From d10e2cdf82e294dc90d284984bef7bd9efdc6a69 Mon Sep 17 00:00:00 2001 From: Stephan Grein Date: Fri, 6 Nov 2020 14:18:50 +0100 Subject: [PATCH 01/58] Update math_vector.h White space removed and header corrected. --- .../math/math_vector_matrix/math_vector.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/ugbase/common/math/math_vector_matrix/math_vector.h b/ugbase/common/math/math_vector_matrix/math_vector.h index b08d73e2b..149646767 100644 --- a/ugbase/common/math/math_vector_matrix/math_vector.h +++ b/ugbase/common/math/math_vector_matrix/math_vector.h @@ -7,7 +7,7 @@ * UG4 is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License version 3 (as published by the * Free Software Foundation) with the following additional attribution - * requirements (according to LGPL/GPL v3 ��7): + * requirements (according to LGPL/GPL v3 §7): * * (1) The following notice must be displayed in the Appropriate Legal Notices * of covered and combined works: "Based on UG4 (www.ug4.org/license)". @@ -20,7 +20,7 @@ * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively * parallel geometric multigrid solver on hierarchically distributed grids. * Computing and visualization in science 16, 4 (2013), 151-164" - * "Vogel, A., Reiter, S., Rupp, M., N��gel, A., and Wittum, G. UG4 -- a novel + * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel * flexible software system for simulating pde based models on high performance * computers. Computing and visualization in science 16, 4 (2013), 165-179" * @@ -101,7 +101,7 @@ class MathVector static const std::size_t Size = N; public: - MathVector() {for(std::size_t i = 0; i < N; ++i) m_data[i] = 0.0;} + MathVector() {for(std::size_t i = 0; i < N; ++i) m_data[i] = 0.0;} MathVector(const value_type& val) {for(std::size_t i = 0; i < N; ++i) m_data[i] = val;} MathVector(const MathVector& v) {assign(v);} @@ -134,7 +134,8 @@ class MathVector MathVector operator- () const { MathVector v; for (std::size_t i = 0; i < N; ++i) v.set_coord(i, -m_data[i]); return v; } // scalar product - value_type operator* (const MathVector& v) const {value_type res = 0.0; for(std::size_t i = 0; i < N; ++i) res += m_data[i] * v.coord(i);return res;} + value_type operator* (const MathVector& v) const {value_type res = + ; for(std::size_t i = 0; i < N; ++i) res += m_data[i] * v.coord(i);return res;} inline std::size_t size() const {return N;} @@ -234,7 +235,7 @@ class MathVector<1, T> static const std::size_t Size = 1; public: - MathVector() {m_data[0] = 0.0; } + MathVector() {m_data[0] = 0.0;} MathVector(value_type x) { m_data[0] = x; } MathVector(const MathVector<1, T>& v) {assign(v);} @@ -298,7 +299,7 @@ class MathVector<2, T> static const std::size_t Size = 2; public: - MathVector() { m_data[0] = m_data[1] = 0.0; } + MathVector() {m_data[0] = m_data[1] = 0.0;} MathVector(const value_type& val) {m_data[0] = m_data[1] = val;} MathVector(value_type x, value_type y) { @@ -370,7 +371,7 @@ class MathVector<3, T> static const std::size_t Size = 3; public: - MathVector() { m_data[0] = m_data[1] = m_data[2] = 0.0; } + MathVector() {m_data[0] = m_data[1] = m_data[2] = 0.0;} MathVector(const value_type& val) {m_data[0] = m_data[1] = m_data[2] = val;} MathVector(value_type x, value_type y, value_type z) { @@ -448,7 +449,7 @@ class MathVector<4, T> static const std::size_t Size = 4; public: - MathVector() {m_data[0] = m_data[1] = m_data[2] = m_data[3] =0.0;} + MathVector() {m_data[0] = m_data[1] = m_data[2] = m_data[3] = 0.0;} MathVector(const value_type& val) {m_data[0] = m_data[1] = m_data[2] = m_data[3] =val;} MathVector(value_type x, value_type y, value_type z, value_type w) { From 6b679c7dec62307bb97941906dc90c83e58a2bbd Mon Sep 17 00:00:00 2001 From: Stephan Grein Date: Tue, 10 Nov 2020 15:50:06 +0100 Subject: [PATCH 02/58] Update math_vector.h --- ugbase/common/math/math_vector_matrix/math_vector.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ugbase/common/math/math_vector_matrix/math_vector.h b/ugbase/common/math/math_vector_matrix/math_vector.h index 149646767..6aa736cf2 100644 --- a/ugbase/common/math/math_vector_matrix/math_vector.h +++ b/ugbase/common/math/math_vector_matrix/math_vector.h @@ -134,8 +134,7 @@ class MathVector MathVector operator- () const { MathVector v; for (std::size_t i = 0; i < N; ++i) v.set_coord(i, -m_data[i]); return v; } // scalar product - value_type operator* (const MathVector& v) const {value_type res = - ; for(std::size_t i = 0; i < N; ++i) res += m_data[i] * v.coord(i);return res;} + value_type operator* (const MathVector& v) const {value_type res = 0.0; for(std::size_t i = 0; i < N; ++i) res += m_data[i] * v.coord(i);return res;} inline std::size_t size() const {return N;} From c4d504ad560cd26c16ea628caa979d5808f8dc7c Mon Sep 17 00:00:00 2001 From: junxiW Date: Mon, 24 Jun 2024 17:22:51 +0200 Subject: [PATCH 03/58] create grid objects directly in ug4 instead of via promesh --- ugbase/lib_grid/tools/creator_grid_util.h | 238 ++++++++++++++++++++++ 1 file changed, 238 insertions(+) create mode 100644 ugbase/lib_grid/tools/creator_grid_util.h diff --git a/ugbase/lib_grid/tools/creator_grid_util.h b/ugbase/lib_grid/tools/creator_grid_util.h new file mode 100644 index 000000000..11df9e6ac --- /dev/null +++ b/ugbase/lib_grid/tools/creator_grid_util.h @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2010-2015: G-CSC, Goethe University Frankfurt + * Authors: Sebastian Reiter, Andreas Vogel, Jan Friebertshäuser + * + * This file is part of UG4. + * + * UG4 is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License version 3 (as published by the + * Free Software Foundation) with the following additional attribution + * requirements (according to LGPL/GPL v3 §7): + * + * (1) The following notice must be displayed in the Appropriate Legal Notices + * of covered and combined works: "Based on UG4 (www.ug4.org/license)". + * + * (2) The following notice must be displayed at a prominent place in the + * terminal output of covered works: "Based on UG4 (www.ug4.org/license)". + * + * (3) The following bibliography is recommended for citation and must be + * preserved in all covered files: + * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively + * parallel geometric multigrid solver on hierarchically distributed grids. + * Computing and visualization in science 16, 4 (2013), 151-164" + * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel + * flexible software system for simulating pde based models on high performance + * computers. Computing and visualization in science 16, 4 (2013), 165-179" + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +#ifndef __H__UG__LIB_GRID__TOOLS__CREATOR_GRID_UTIL__ +#define __H__UG__LIB_GRID__TOOLS__CREATOR_GRID_UTIL__ + +// other lib_discretization headers + + +namespace ug{ +//////////////////////////////////////////////////////////////////////// +/** + * To Create GridObject directly under UG4-C++ + * instead of ProMesh + */ +template +Vertex* CreateVertex(Grid& grid,const TPosition& pos,Grid::VertexAttachmentAccessor >& aaPos ) +{ + RegularVertex* vrt = *grid.create(); + + if(vrt){ + aaPos[vrt] = pos; + } + + return vrt; +} + + + +Edge* CreateEdge(Grid& grid, Vertex* vrts[], const size_t, numVrts){ + //uniquify vrts by hash_value: no + //The vrts can't be simply uniquified by hash_values since it will change the orientation of vrts. + // Hence,it should be generated by aaPos before using this function. + RegularEdge* e = NULL; + + switch(numVrts){ + case 2:{// create edge + if(!grid.get_edge(vrts[0], vrts[1])) + e = *grid.create(ug::EdgeDescriptor(vrts[0], vrts[1])); + else{ + UG_LOG("Can't create edge: RegularEdge already exists.\n"); + } + }break; + + default: + UG_LOG("Can't create edge: Bad number of vertices. 2 are required.\n"); + break; + } + return e; + +} + +Edge* CreateEdge(Grid& grid, Vertex* vrt0, Vertex* vrt1) +{ + RegularEdge* e = NULL; + + uint32 hash0=vrt0->get_hash_value(); + uint32 hash1=vrt1->get_hash_value(); + UG_ASSERT(hash0!=hash1, "Can't create edge: they are identical vertices."); + + Vertex* vrts[2]; + vrts[0]=vrt0; + vrts[1]=vrt1; + // create edge + return CreateEdge(grid, vrts, 2); +} + +/*Edge* CreateEdge(Grid& grid, std::vector vrts){ + size_t numVrts = vrts.num_vertices(); + // vector -> array + for(size_t i=0; i 4){ + UG_ASSERT(numVrts>2 || numVrts<5,"Bad number of vertices! Can't create a face element from " << numVrts << " vertices."); + //return NULL; + //} + + FaceDescriptor fd(numVrts); + for(size_t i = 0; i < numVrts; ++i) + fd.set_vertex(i, vrts[i]); + + if(grid.get_face(fd)){ + UG_LOG("A face connecting the given vertices already exists. Won't create a new one!"); + return NULL; + } + + Face* f = NULL; + switch(numVrts){ + case 3:{// create triangle + f = *grid.create(TriangleDescriptor(vrts[0], vrts[1], vrts[2])); + }break; + + case 4:{// create quadrilateral + f = *grid.create(QuadrilateralDescriptor(vrts[0], vrts[1], + vrts[2], vrts[3])); + }break; + + default: + UG_LOG("Can't create face: Bad number of vertices. 3 or 4 are supported.\n"); + break; + } + + return f; +} + +/*Face* CreateFace(Grid& grid, std::vector vrts){ + size_t numVrts = vrts.num_vertices(); + // vector -> array + for(size_t i=0; i 8){ + UG_ASSERT(numVrts>3 || numVrts<9,"Bad number of vertices! Can't create a volume element from " << numVrts << " vertices."); + + VolumeDescriptor vd(numVrts); + for(size_t i = 0; i < numVrts; ++i) + vd.set_vertex(i, vrts[i]); + + if(grid.get_volume(vd)){ + UG_LOG("A volume connecting the given vertices already exists. Won't create a new one!"); + return NULL; + } + + Volume* v = NULL; + switch(numVrts){ + case 4:{// create tetrahedron + v = *grid.create(TetrahedronDescriptor(vrts[0], vrts[1], + vrts[2], vrts[3])); + }break; + + case 5:{// create pyramid + v = *grid.create(PyramidDescriptor(vrts[0], vrts[1], + vrts[2], vrts[3], vrts[4])); + }break; + + case 6:{// create prism + v = *grid.create(PrismDescriptor(vrts[0], vrts[1], vrts[2], + vrts[3], vrts[4], vrts[5])); + }break; + + case 8:{// create hexahedron + v = *grid.create(HexahedronDescriptor(vrts[0], vrts[1], vrts[2], vrts[3], + vrts[4], vrts[5], vrts[6], vrts[7])); + }break; + + default: + UG_LOG("Can't create volume: Bad number of vertices. 4, 5, 6, and 8 are supported.\n"); + break; + } + + return v; +} + +/*Volume* CreateVolume(Grid& grid, std::vector vrts){ + size_t numVrts = vrts.num_vertices(); + // vector -> array + for(size_t i=0; i //for edges, faces, Volumes. constexpr(TElem:HAS_SIDES) +TElem* CreateGridObject(Grid& grid, +int vrt_indices[], +const size_t numVrts, Grid::VertexAttachmentAccessor >& aaPOS) +*/ + +//pos: 0: upLeft,1:lowLeft, 2: lowRight, 3. upRight +template +void CreatePlane(Grid& grid, + const TPosition& upLeft, + const TPosition& upRight, + const TPosition& lowLeft, + const TPosition& lowRight, + Grid::VertexAttachmentAccessor >& aaPos + bool fill) +{ + Vertex* vrts[4]; + for(size_t i = 0; i < 4; ++i) + vrts[i] = *grid.create(); + + aaPos[vrts[0]] = upLeft; + aaPos[vrts[1]] = lowLeft; + aaPos[vrts[2]] = lowRight; + aaPos[vrts[3]] = upRight; + + if(fill){ + CreateFace(grid, vrts, 4); + }else{ + for(size_t i = 0; i < 4; ++i){ + int i0 = i; + int i1 = (i + 1) % 4; + grid.create(EdgeDescriptor(vrts[i0], vrts[i1])); + } + } +} + + +} + +#endif /* __H__UG__LIB_GRID__TOOLS__CREATOR_GRID_UTIL__*/ \ No newline at end of file From f921106e17622a6cb7c91da994aa4014a9c8e18f Mon Sep 17 00:00:00 2001 From: Markus Date: Wed, 26 Jun 2024 10:28:56 +0200 Subject: [PATCH 04/58] created new branch again for nested Newton, based on actual master added corresponding files --- ugbase/bridge/disc_bridges/algebra_bridge.cpp | 28 ++++ ugbase/lib_disc/CMakeLists.txt | 22 ++++ .../non_linear_operator/line_search.h | 120 +++++++++++++++++- .../newton_solver/nestedNewtonRFSwitch.h | 17 +++ .../newton_solver/nestedNewtonRFSwitch.h.in | 17 +++ .../newton_solver/newton.h | 22 ++++ .../newton_solver/newtonUpdaterGeneric.h | 120 ++++++++++++++++++ .../newton_solver/newton_impl.h | 53 +++++++- 8 files changed, 397 insertions(+), 2 deletions(-) create mode 100644 ugbase/lib_disc/operator/non_linear_operator/newton_solver/nestedNewtonRFSwitch.h create mode 100644 ugbase/lib_disc/operator/non_linear_operator/newton_solver/nestedNewtonRFSwitch.h.in create mode 100644 ugbase/lib_disc/operator/non_linear_operator/newton_solver/newtonUpdaterGeneric.h diff --git a/ugbase/bridge/disc_bridges/algebra_bridge.cpp b/ugbase/bridge/disc_bridges/algebra_bridge.cpp index 1b386d29d..0078524d9 100644 --- a/ugbase/bridge/disc_bridges/algebra_bridge.cpp +++ b/ugbase/bridge/disc_bridges/algebra_bridge.cpp @@ -66,6 +66,14 @@ #include "lib_disc/operator/composite_conv_check.h" #include "lib_disc/spatial_disc/local_to_global/local_to_global_mapper.h" +#include "lib_disc/operator/non_linear_operator/newton_solver/nestedNewtonRFSwitch.h" + +#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE + +#include "lib_disc/operator/non_linear_operator/newton_solver/newtonUpdaterGeneric.h" + +#endif + using namespace std; @@ -265,6 +273,23 @@ static void Algebra(Registry& reg, string parentGroup) .set_construct_as_smart_pointer(true); reg.add_class_to_group(name, "AssembledLinearOperator", tag); } + + +#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE + // generic Newton updater + { + std::string grp = parentGroup; grp.append("/Discretization"); + using T = NewtonUpdaterGeneric; + string name = string("NewtonUpdaterGeneric").append(suffix); + reg.add_class_(name, grp) + .add_constructor() +// .template add_constructor >)>("NewtonUpdaterGeneric") +// .add_method("updateNewton", static_cast (&T::updateNewton)) +// .add_method("updateNewton", static_cast (&T::updateNewton)) + .set_construct_as_smart_pointer(true); + reg.add_class_to_group(name, "NewtonUpdaterGeneric", tag); + } +#endif // NewtonSolver @@ -301,6 +326,9 @@ static void Algebra(Registry& reg, string parentGroup) .add_method("clear_inner_step_update", &T::clear_inner_step_update, "clear inner step update", "") .add_method("add_step_update", &T::add_step_update, "data update called before every Newton step", "") .add_method("clear_step_update", &T::clear_step_update, "clear step update", "") +#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE + .add_method("setNewtonUpdater", &T::setNewtonUpdater, "set the Newton updater", "") +#endif .add_method("config_string", &T::config_string) .set_construct_as_smart_pointer(true); reg.add_class_to_group(name, "NewtonSolver", tag); diff --git a/ugbase/lib_disc/CMakeLists.txt b/ugbase/lib_disc/CMakeLists.txt index f5a4b98f1..ea04f77c3 100644 --- a/ugbase/lib_disc/CMakeLists.txt +++ b/ugbase/lib_disc/CMakeLists.txt @@ -34,6 +34,28 @@ project(P_LIB_DISCRETIZATION) include("../../cmake/ug_includes.cmake") +option(ENABLE_NESTED_NEWTON "If enabled, nested Newton may be used, but needs for specification, else fallback to normal Newton" OFF) +message(STATUS "") +message(STATUS "Info: ${pluginName} options:") +message(STATUS " * ENABLE_NESTED_NEWTON: ${ENABLE_NESTED_NEWTON} (options are: ON, OFF)") + +if( ENABLE_NESTED_NEWTON ) + +set( SET_NESTED_NEWTON 1 ) + +else(ENABLE_NESTED_NEWTON) + +set( SET_NESTED_NEWTON 0) + +endif(ENABLE_NESTED_NEWTON) + +configure_file ( + "${CMAKE_CURRENT_SOURCE_DIR}//operator/non_linear_operator/newton_solver/nestedNewtonRFSwitch.h.in" + "${CMAKE_CURRENT_SOURCE_DIR}//operator/non_linear_operator/newton_solver/nestedNewtonRFSwitch.h" + ) + + + set(srcDiscretization domain.cpp domain_util.cpp diff --git a/ugbase/lib_disc/operator/non_linear_operator/line_search.h b/ugbase/lib_disc/operator/non_linear_operator/line_search.h index 2abbc5c07..75902655c 100644 --- a/ugbase/lib_disc/operator/non_linear_operator/line_search.h +++ b/ugbase/lib_disc/operator/non_linear_operator/line_search.h @@ -38,9 +38,20 @@ #include #include #include +#include #include "common/common.h" +#include "lib_disc/operator/non_linear_operator/newton_solver/nestedNewtonRFSwitch.h" + +#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE + +#include "lib_disc/operator/non_linear_operator/newton_solver/newtonUpdaterGeneric.h" + +#endif + + + namespace ug{ /////////////////////////////////////////////////////////// @@ -93,6 +104,10 @@ class ILineSearch /// virtual destructor virtual ~ILineSearch() {} + +#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE + virtual void setNewtonUpdater( SmartPtr > nU ) = 0; +#endif }; /// standard implementation of the line search based on the "sufficient descent" @@ -108,18 +123,30 @@ class StandardLineSearch : public ILineSearch StandardLineSearch() : m_maxSteps(10), m_lambdaStart(1.0), m_lambdaReduce(0.5), m_alpha(0.25), m_maxDefect(1e+10), m_verbose(true), m_bAcceptBest(false), m_bCheckAll(false), m_offset("") +#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE + , + m_newtonUpdater(new NewtonUpdaterGeneric{}) +#endif {}; /// constructor StandardLineSearch(int maxSteps, number lambdaStart, number lambdaReduce, bool bAcceptBest) : m_maxSteps(maxSteps), m_lambdaStart(lambdaStart), m_lambdaReduce(lambdaReduce), m_alpha(0.25), m_maxDefect(1e+10), m_verbose(true), m_bAcceptBest(bAcceptBest), m_bCheckAll(false), m_offset("") +#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE + , + m_newtonUpdater(new NewtonUpdaterGeneric{}) +#endif {}; /// constructor StandardLineSearch(int maxSteps, number lambdaStart, number lambdaReduce, bool bAcceptBest, bool bCheckAll) : m_maxSteps(maxSteps), m_lambdaStart(lambdaStart), m_lambdaReduce(lambdaReduce), m_alpha(0.25), m_maxDefect(1e+10), m_verbose(true), m_bAcceptBest(bAcceptBest), m_bCheckAll(bCheckAll), m_offset("") +#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE + , + m_newtonUpdater(new NewtonUpdaterGeneric{}) +#endif {}; /// returns information about configuration parameters @@ -188,6 +215,37 @@ class StandardLineSearch : public ILineSearch // loop line search steps for(int k = 1; k <= m_maxSteps; ++k) { +#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE + // try on line u := u - lambda*p + + //if( m_newtonUpdater != NULL ) + //{ + bool acceptedNewtonUpdate = m_newtonUpdater->updateSolution(u, 1.0, u, (-1)*lambda, p); + +// if( ! m_newtonUpdater->updateNewton(u, 1.0, u, (-1)*lambda, p) ) + if( ! acceptedNewtonUpdate ) +// if( m_newtonUpdater->updateNewton(u,p) ) + { + UG_LOG("Update in Line Search did not work.\n"); + norm = std::numeric_limits::max(); + //VecScaleAdd(u, 1.0, u, (-1)*lambda, p); + //return false; + } + else + { + // compute new Defect + spOp->prepare(u); + spOp->apply(d, u); + + // compute new Residuum + norm = d.norm(); + } + //} +// else +// { +// UG_LOG("Please set a Newton updater in Line search"); +// } +#else // try on line u := u - lambda*p VecScaleAdd(u, 1.0, u, (-1)*lambda, p); @@ -198,6 +256,9 @@ class StandardLineSearch : public ILineSearch // compute new Residuum norm = d.norm(); +#endif + + // compute reduction vRho.push_back(norm/norm_old); @@ -254,15 +315,42 @@ class StandardLineSearch : public ILineSearch UG_LOG(m_offset << " ++++ Accept Best: Accepting step " << best+1 << ", Rate = "<< vRho[best] <<".\n"); +#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE + // try on line u := u - lambda*p + + //if( m_newtonUpdater != NULL ) + //{ + if( ! m_newtonUpdater->updateSolution(u, 1.0, s, (-1)*m_lambdaStart*std::pow(m_lambdaReduce, (number)best), p) ) + { + UG_LOG("Update in Line Search kmax did not work.\n"); + + norm = std::numeric_limits::max(); + //return false; + } + else + { + spOp->prepare(u); + spOp->apply(d, u); + + // compute new Residuum + norm = d.norm(); + } + //} +// else +// { +// UG_LOG("Please set a Newton updater in Line search"); +// } +#else // try on line u := u - lambda*p VecScaleAdd(u, 1.0, s, (-1)*m_lambdaStart*std::pow(m_lambdaReduce, (number)best), p); - // compute new Defect spOp->prepare(u); spOp->apply(d, u); // compute new Residuum norm = d.norm(); +#endif + // check if defect-norm is smaller than maximum allowed defect value if (norm > m_maxDefect) @@ -276,8 +364,15 @@ class StandardLineSearch : public ILineSearch break; } +#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE + + // reset u and eventual local variables + m_newtonUpdater->resetSolution(u,s); +#else // reset u u = s; +#endif + } // print end line @@ -288,10 +383,28 @@ class StandardLineSearch : public ILineSearch UG_LOG(m_offset << " ++++ Line Search converged.\n"); } + +#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE + if( ! m_newtonUpdater->tellAndFixUpdateEvents(u) ) + { + UG_LOG("unable to fix local Newton updates" << std::endl ); + return false; + } +#endif // we're done return true; } + +#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE + + virtual void setNewtonUpdater( SmartPtr > nU ) + { + m_newtonUpdater = nU; + } + +#endif + protected: /// solution in line direction vector_type s; @@ -323,6 +436,11 @@ class StandardLineSearch : public ILineSearch /// number of spaces inserted before output std::string m_offset; + +#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE +private: + SmartPtr > m_newtonUpdater; +#endif }; } // end namespace ug diff --git a/ugbase/lib_disc/operator/non_linear_operator/newton_solver/nestedNewtonRFSwitch.h b/ugbase/lib_disc/operator/non_linear_operator/newton_solver/nestedNewtonRFSwitch.h new file mode 100644 index 000000000..39a488d6b --- /dev/null +++ b/ugbase/lib_disc/operator/non_linear_operator/newton_solver/nestedNewtonRFSwitch.h @@ -0,0 +1,17 @@ +/* + * nestedNewtonRFSwitch.h + * + * Created on: 27.07.2021 + * Author: Markus Knodel + */ + +#ifndef UGCORE_UGBASE_NESTEDNEWTONRFSWITCH_H_ +#define UGCORE_UGBASE_NESTEDNEWTONRFSWITCH_H_ + +#ifndef ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE +#define ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE 0 +#endif + + + +#endif /* UGCORE_UGBASE_NESTEDNEWTONRFSWITCH_H_ */ diff --git a/ugbase/lib_disc/operator/non_linear_operator/newton_solver/nestedNewtonRFSwitch.h.in b/ugbase/lib_disc/operator/non_linear_operator/newton_solver/nestedNewtonRFSwitch.h.in new file mode 100644 index 000000000..8add4906f --- /dev/null +++ b/ugbase/lib_disc/operator/non_linear_operator/newton_solver/nestedNewtonRFSwitch.h.in @@ -0,0 +1,17 @@ +/* + * nestedNewtonRFSwitch.h + * + * Created on: 27.07.2021 + * Author: Markus Knodel + */ + +#ifndef UGCORE_UGBASE_NESTEDNEWTONRFSWITCH_H_ +#define UGCORE_UGBASE_NESTEDNEWTONRFSWITCH_H_ + +#ifndef ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE +#define ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE ${SET_NESTED_NEWTON} +#endif + + + +#endif /* UGCORE_UGBASE_NESTEDNEWTONRFSWITCH_H_ */ diff --git a/ugbase/lib_disc/operator/non_linear_operator/newton_solver/newton.h b/ugbase/lib_disc/operator/non_linear_operator/newton_solver/newton.h index 6a50f7df5..10a974002 100644 --- a/ugbase/lib_disc/operator/non_linear_operator/newton_solver/newton.h +++ b/ugbase/lib_disc/operator/non_linear_operator/newton_solver/newton.h @@ -47,6 +47,14 @@ #include "newton_update_interface.h" #include "lib_algebra/operator/debug_writer.h" +#include "nestedNewtonRFSwitch.h" + +#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE + +#include "newtonUpdaterGeneric.h" + +#endif + namespace ug { /// Newton solver for assembling based discretizations @@ -148,6 +156,13 @@ class NewtonSolver void set_reassemble_J_freq(int freq) {m_reassembe_J_freq = freq;}; +#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE + void setNewtonUpdater( SmartPtr > nU ) + { + m_newtonUpdater = nU; + } +#endif + private: /// help functions for debug output /// \{ @@ -189,6 +204,13 @@ class NewtonSolver std::vector m_vNonLinSolverRates; std::vector m_vLinSolverRates; /// \} + +#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE + + SmartPtr > m_newtonUpdater; + +#endif + }; } diff --git a/ugbase/lib_disc/operator/non_linear_operator/newton_solver/newtonUpdaterGeneric.h b/ugbase/lib_disc/operator/non_linear_operator/newton_solver/newtonUpdaterGeneric.h new file mode 100644 index 000000000..f6dacfc82 --- /dev/null +++ b/ugbase/lib_disc/operator/non_linear_operator/newton_solver/newtonUpdaterGeneric.h @@ -0,0 +1,120 @@ +/* + * newtonUpdaterGeneric.h + * + * Created on: 28.07.2021 + * Author: Markus Knodel + */ + +#ifndef UGCORE_UGBASE_LIB_DISC_OPERATOR_NON_LINEAR_OPERATOR_NEWTON_SOLVER_NEWTONUPDATERGENERIC_H_ +#define UGCORE_UGBASE_LIB_DISC_OPERATOR_NON_LINEAR_OPERATOR_NEWTON_SOLVER_NEWTONUPDATERGENERIC_H_ + +#include +#include +#include +#include +#include +#include + +#include "common/common.h" + +namespace ug +{ + +template +class NewtonUpdaterGeneric +{ + +public: + + virtual ~NewtonUpdaterGeneric() {}; + + + using vector_type = TVector; + + virtual bool updateSolution( vector_type & sol, vector_type const & corr, bool signNegative = true ) + { + if( signNegative ) + sol -= corr; + else + sol += corr; + + return true; +// return (*this)(sol, 1, sol, - 1, corr ); + } + + + virtual bool updateSolution( vector_type & solNew, number scaleOldSol, vector_type const & solOld, + number scaleCorr, vector_type const & corr ) + { + VecScaleAdd(solNew, scaleOldSol, solOld, scaleCorr, corr); + + return true; + + } + + virtual bool resetSolution( vector_type & resettedSol, vector_type const & oldSol ) + { + resettedSol = oldSol; + + // reset not only u, but also internal variables if available!!!!! + + return true; + } + + virtual bool tellAndFixUpdateEvents( vector_type const & sol ) + { + return true; + } + +}; + +} + + +#endif /* UGCORE_UGBASE_LIB_DISC_OPERATOR_NON_LINEAR_OPERATOR_NEWTON_SOLVER_NEWTONUPDATERGENERIC_H_ */ + + +// muss noch im Newton und line search irgendwie automatisch so initialisiert werden, aber auf User-Wunsch ueberschrieben +// mit Hilfe von gettern und settern, damit entweder der line search oder der Newton selber sich das vom anderen holen koennen +// und dann muss es soweit registriert werden, wie es noetig ist, damit man von aussen zu greifen kann +// und die abgeleiteten Klassen brauchen ggf einen Konstruktor und so weiter +/// Vector type +//typedef typename TAlgebra::vector_type vector_type; + +// using vector_type = TVector; // typename TAlgebra::vector_type; +// using vec_typ_val_typ = typename vector_type::value_type; + +//typedef TVector vector_type; // typename TAlgebra::vector_type; +//typedef typename vector_type::value_type vec_typ_val_typ; +//typedef typename vector_type::value_type value_type; + +// template //, typename ScalTyp > +// template //, typename ScalTyp > +// bool updateNewton( vector_type & solNew, value_type scaleOldSol, vector_type const & solOld, +// value_type scaleCorr, vector_type const & corr ) +// bool updateNewton( VecTyp & solNew, ScalTyp scaleOldSol, VecTyp const & solOld, +// ScalTyp scaleCorr, VecTyp const & corr ) +// bool updateNewton( VecTyp & solNew, typename VecTyp::value_type scaleOldSol, VecTyp const & solOld, +// typename VecTyp::value_type scaleCorr, VecTyp const & corr ) +// bool updateNewton( vector_type & solNew, ScalTyp scaleOldSol, vector_type const & solOld, +// ScalTyp scaleCorr, vector_type const & corr ) +// static_assert( std::is_same::value, "is ScalType double" ); +// +// static_assert( !std::is_same::value, "! is ScalType number" ); +// +// static_assert( std::is_same::value, "is it value_type" ); +// +// static_assert( std::is_same::value, "is value_type double" ); +// +// static_assert( std::is_same::value, "is value_type number" ); + + // Standard: try on line u := u - lambda*p + // VecScaleAdd(u, 1.0, u, (-1)*lambda, p); + +// typedef typename vector_type::size_type size_type; +//// using size_type = typename vector_type::size_type; +// +// for(size_type i = 0; i < solNew.size(); ++i) +// { +// solNew[i] = scaleOldSol * solOld[i] + scaleCorr * corr[i]; +// } diff --git a/ugbase/lib_disc/operator/non_linear_operator/newton_solver/newton_impl.h b/ugbase/lib_disc/operator/non_linear_operator/newton_solver/newton_impl.h index 11e8ee6f1..3dda607eb 100644 --- a/ugbase/lib_disc/operator/non_linear_operator/newton_solver/newton_impl.h +++ b/ugbase/lib_disc/operator/non_linear_operator/newton_solver/newton_impl.h @@ -35,11 +35,14 @@ #include #include +#include #include "newton.h" #include "lib_disc/function_spaces/grid_function_util.h" #include "common/util/string_util.h" +#include "lib_disc/operator/non_linear_operator/newton_solver/nestedNewtonRFSwitch.h" + #define PROFILE_NEWTON #ifdef PROFILE_NEWTON #define NEWTON_PROFILE_FUNC() PROFILE_FUNC_GROUP("Newton") @@ -67,6 +70,10 @@ NewtonSolver(SmartPtr > LinearSolver, m_reassembe_J_freq(0), m_dgbCall(0), m_lastNumSteps(0) +#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE + , + m_newtonUpdater(new NewtonUpdaterGeneric{}) +#endif {}; template @@ -81,6 +88,10 @@ NewtonSolver() : m_reassembe_J_freq(0), m_dgbCall(0), m_lastNumSteps(0) +#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE + , + m_newtonUpdater(new NewtonUpdaterGeneric{}) +#endif {}; template @@ -95,6 +106,10 @@ NewtonSolver(SmartPtr > N) : m_reassembe_J_freq(0), m_dgbCall(0), m_lastNumSteps(0) +#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE + , + m_newtonUpdater(new NewtonUpdaterGeneric{}) +#endif { init(N); }; @@ -111,6 +126,10 @@ NewtonSolver(SmartPtr > spAss) : m_reassembe_J_freq(0), m_dgbCall(0), m_lastNumSteps(0) +#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE + , + m_newtonUpdater(new NewtonUpdaterGeneric{}) +#endif { m_spAss = spAss; m_N = SmartPtr >(new AssembledOperator(m_spAss)); @@ -277,6 +296,12 @@ bool NewtonSolver::apply(vector_type& u) { m_spLineSearch->set_offset(" # "); NEWTON_PROFILE_BEGIN(NewtonLineSearch); + +#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE + + m_spLineSearch->setNewtonUpdater(m_newtonUpdater); + +#endif if(!m_spLineSearch->search(m_N, u, *spC, *spD, m_spConvCheck->defect())) { UG_LOG("ERROR in 'NewtonSolver::apply': " @@ -288,9 +313,35 @@ bool NewtonSolver::apply(vector_type& u) // No line search: Compute new defect else { +#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE + // update solution + //u -= *spC; +// if( ! (*m_newtonUpdater)() ) + + //bool acceptedNewtonUpdate = m_newtonUpdater->updateNewton(u,*spC); + + //if( ! acceptedNewtonUpdate ) + + if( ! m_newtonUpdater->updateSolution(u,*spC) ) + { + UG_LOG("ERROR in 'NewtonSolver::apply': " + "Newton Update did not work.\n"); + // TODO FIXME was macht conv check update? wie kriege ich hier einfach ein riesiges Residuum rein, ohne was zu rechnen? + return false; + } + + if( ! m_newtonUpdater->tellAndFixUpdateEvents(u) ) + { + UG_LOG("unable to fix local Newton updates" << std::endl ); + return false; + } + + +#else // update solution u -= *spC; - +#endif + // compute new Defect NEWTON_PROFILE_BEGIN(NewtonComputeDefect); m_N->prepare(u); From 0c480898c0cd7edb9cd3aba44af861ba1f90c641 Mon Sep 17 00:00:00 2001 From: Markus Date: Wed, 26 Jun 2024 12:45:53 +0200 Subject: [PATCH 05/58] created arte24 branch unifies updates for vtu reading and for present arte attempts --- ugbase/bridge/grid_bridges/file_io_bridge.cpp | 11 +- .../algorithms/extrusion/expand_layers.cpp | 2898 +++++++++++++++++ .../algorithms/extrusion/expand_layers.h | 8 + ugbase/lib_grid/file_io/file_io_vtu.cpp | 100 +- ugbase/lib_grid/file_io/file_io_vtu.h | 13 + 5 files changed, 3028 insertions(+), 2 deletions(-) diff --git a/ugbase/bridge/grid_bridges/file_io_bridge.cpp b/ugbase/bridge/grid_bridges/file_io_bridge.cpp index f22de584d..0f832ab5c 100644 --- a/ugbase/bridge/grid_bridges/file_io_bridge.cpp +++ b/ugbase/bridge/grid_bridges/file_io_bridge.cpp @@ -35,6 +35,7 @@ #include "lib_grid/multi_grid.h" #include "lib_grid/file_io/file_io.h" #include "lib_grid/file_io/file_io_ugx.h" +#include "lib_grid/file_io/file_io_vtu.h" using namespace std; @@ -77,6 +78,13 @@ bool SaveGridHierarchy(MultiGrid& mg, const char* filename) return SaveGridToFile(mg, mg.get_hierarchy_handler(), filename); } +void SetVTURegionOfInterestIdentifier( char const * regOfInt ) +{ + PROFILE_FUNC_GROUP("grid"); + GridReaderVTU::setRegionOfInterestIdentifier( std::string( regOfInt ) ); + return; +} + void RegisterGridBridge_FileIO(Registry& reg, string parentGroup) { @@ -129,7 +137,8 @@ void RegisterGridBridge_FileIO(Registry& reg, string parentGroup) .add_function("SaveParallelGridLayout", &SaveParallelGridLayout, grp, "", "mg#filename#offset") .add_function("SaveSurfaceViewTransformed", &SaveSurfaceViewTransformed) - .add_function("SaveGridLevelToFile", &SaveGridLevelToFile); + .add_function("SaveGridLevelToFile", &SaveGridLevelToFile) + .add_function("SetVTURegionOfInterestIdentifier", static_cast(&SetVTURegionOfInterestIdentifier) ); } }// end of namespace diff --git a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp index be4c4c03e..727763ef1 100644 --- a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp +++ b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp @@ -39,6 +39,17 @@ #include "lib_grid/grid/grid_util.h" //#include "lib_grid/util/simple_algebra/least_squares_solver.h" +#include +#include +#include +#include +#include +#include +#include + +#include "support.h" + + using namespace std; namespace ug{ @@ -706,6 +717,2893 @@ bool ExpandFractures2d(Grid& grid, SubsetHandler& sh, const vector } +#ifndef NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX +#define NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX 1 +#endif + +#ifndef ANSCHAULICH_ERZEUGE_SUDOS_ANHANG +#define ANSCHAULICH_ERZEUGE_SUDOS_ANHANG 0 +#endif + +#ifndef OLD_PROFREITER_STUFF +#define OLD_PROFREITER_STUFF 0 +#endif + +bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, const vector& fracInfos, + bool expandInnerFracBnds, bool expandOuterFracBnds) +{ + + +// access position attachment + if(!grid.has_vertex_attachment(aPosition)){ + UG_LOG("Error in ExpandFractures 2D Arte: Missing position attachment"); + return false; + } + Grid::VertexAttachmentAccessor aaPos(grid, aPosition); + + if(!grid.option_is_enabled(FACEOPT_AUTOGENERATE_EDGES)){ + UG_LOG("WARNING in Arte 2D CalculateCreaseNormal: grid option FACEOPT_AUTOGENERATE_EDGES autoenabled.\n"); + grid.enable_options(FACEOPT_AUTOGENERATE_EDGES); + } + +// objects for temporary results + FaceDescriptor fd; + vector edges; // used for temporary results. + vector faces; // used for temporary results. + +// vectors that allow to access fracture properties by subset index + vector fracInfosBySubset(sh.num_subsets(), FractureInfo(-1, -1, 0)); + for(size_t i = 0; i < fracInfos.size(); ++i){ + if(fracInfos[i].subsetIndex >= sh.num_subsets()){ + throw(UGError("Bad subsetIndex in given fracInfos.")); + } + + fracInfosBySubset[fracInfos[i].subsetIndex] = fracInfos[i]; + } + +//////////////////////////////// +// Collect surrounding faces of all fractures in a selector +// and select edges and vertices too. + Selector sel(grid); + sel.enable_autoselection(false); + sel.enable_selection_inheritance(false); + +#if OLD_PROFREITER_STUFF + AInt aAdjMarker; // used to mark how many adjacent fractures a vertex has. + // 0: no frac, 1: frac-boundary, >1: inner frac vertex + // TODO FIXME das sieht komisch aus, ist das immer so, wenn z.B. an einer Grenze sich zwei fracs treffen? + grid.attach_to_vertices_dv(aAdjMarker, 0); + Grid::VertexAttachmentAccessor aaMarkVRT(grid, aAdjMarker); + grid.attach_to_edges_dv(aAdjMarker, 0); + Grid::EdgeAttachmentAccessor aaMarkEDGE(grid, aAdjMarker); +#endif + + using IndexType = unsigned short; + using AttVerFracProp = Attachment >; + // attachment pair boundary is fracture, number fractures crossing + + AttVerFracProp aAdjMarkerVFP; + + VertexFractureProperties vfp0( false, 0 ); + // default value: no boundary fracture, no fractures crossing + + grid.attach_to_vertices_dv(aAdjMarkerVFP, vfp0 ); + Grid::VertexAttachmentAccessor aaMarkVrtVFP(grid, aAdjMarkerVFP); + + ABool aAdjMarkerB; // used to know if an edge is frac edge + grid.attach_to_edges_dv(aAdjMarkerB, false); + Grid::EdgeAttachmentAccessor aaMarkEdgeB(grid, aAdjMarkerB); + + + // die Vertizes, Faces und Edges, die mit einer Kluft zu tun haben + + using VertFracTrip = VertexFractureTriple; + + using VecVertFracTrip = std::vector; + + VecVertFracTrip vertexNoInfo; + + using AttVecVertFracTrip = Attachment; + + AttVecVertFracTrip aAdjInfoAVVFT; + + grid.attach_to_vertices_dv( aAdjInfoAVVFT, vertexNoInfo ); + Grid::VertexAttachmentAccessor aaVrtInfoFraTri(grid, aAdjInfoAVVFT ); + + + using VecEdge = std::vector; + using VecFace = std::vector; + + using AttVecEdge = Attachment; + using AttVecFace = Attachment; + + VecEdge noEdge; + VecFace noFace; + AttVecEdge aAdjInfoEdges; + AttVecFace aAdjInfoFaces; + + grid.attach_to_vertices_dv( aAdjInfoEdges, noEdge ); + Grid::VertexAttachmentAccessor aaVrtInfoAssoEdges( grid, aAdjInfoEdges ); + + grid.attach_to_vertices_dv( aAdjInfoFaces, noFace ); + Grid::VertexAttachmentAccessor aaVrtInfoAssoFaces( grid, aAdjInfoFaces ); + + // das ist Käse, ich brauche für jeden Vertex ein Attachment der Form + // class VertexTriple, bzw std vektoren von solchen vertex triplen + // da weiss dann jeder Vertex das triple + // Kante (damit subdom) - Face - normal (von Kante in Face rein) + // dann kann man nämlich anhand des Winkels von zwei Normalen + // von solchen Vertizes bestimmtn, ob sie auf die gleiche Seite der Kante zeigen + // und dann kann man sie mitteln, sofern die Vertizes keine Kreuzungs Vertizes sind + // oder keine äusseren Vertizes - ob sie dsa sind, dafür haben wir schon attachments! + + // TODO FIXME diese komischen accessoren sollen jetzt so zugewiesen + // werden, dass + /* + * jeder Kluftvertex soll wissen, welche Kluftedges ihm anliegen, und welche faces + * jede Kluftedge soll wissen, welche Vertizes ihr anliegen, und welche faces + * jedes Face, das an eine Kluft anliegt, soll wissen, welche Vertizes und Edges + * ihm anliegen + * letzteres muss man vielleicht noch ausdehnen, indem man subdomain indizes + * dazu bringt + * das kann auch notwendig sein fuer alle anderen - wirklich? + * die edges und faces kennen ihre subdomain + * nur beim Vertex kann in Kreuzungspunkten ein Problem sein + * zudem ist die subdomain der faces EGAL, im Zweifel entscheidet die subdomain + * der edges, die anliegen bzw der edge, die anliegt! + * + */ + +// iterate over the given fracture infos and select all fracture edges +// and fracture vertices. + for(size_t i_fi = 0; i_fi < fracInfos.size(); ++i_fi) + { + int fracInd = fracInfos[i_fi].subsetIndex; + + for(EdgeIterator iter = sh.begin(fracInd); iter != sh.end(fracInd); ++iter) + { + // mark edge and vertices + sel.select(*iter); + +#if OLD_PROFREITER_STUFF + aaMarkEDGE[*iter] = 1; +#endif + + aaMarkEdgeB[*iter] = true; + + // select associated vertices + for(size_t i = 0; i < 2; ++i) + { + Vertex* v = (*iter)->vertex(i); + sel.select(v); + + // wird in jedem Fall inkrimiert, da der Vertex auf jeden Fall mit einer Kante einer frac verbunden sein muss, sonst darf der loop gar nicht darüber gehen + aaMarkVrtVFP[v]++; + + if( IsBoundaryVertex2D(grid, v) ) + aaMarkVrtVFP[v].setIsBndFracVertex(); + + +#if OLD_PROFREITER_STUFF + // das ist Sebastians loop, den nicht mehr lassen lassen + // if fracture boundaries are expanded, we'll regard all fracture vertices + // as inner vertices + if(expandInnerFracBnds) + { + if(!expandOuterFracBnds) + { + if(IsBoundaryVertex2D(grid, v)) + aaMarkVRT[v]++; + else + aaMarkVRT[v] = 2; + } + else + aaMarkVRT[v] = 2; + } + else + aaMarkVRT[v]++; +#endif + + } + } + } + + +#if OLD_PROFREITER_STUFF +// Make sure that selected vertices that lie on the boundary of the geometry +// are treated as inner fracture vertices. +// This is only required if frac-boundaries are not expanded anyways. + if(expandOuterFracBnds && !expandInnerFracBnds){ + for(VertexIterator iter = sel.vertices_begin(); + iter != sel.vertices_end(); ++iter) + { + Vertex* v = *iter; + if(aaMarkVRT[v] == 1){ + if(IsBoundaryVertex2D(grid, v)) + aaMarkVRT[v] = 2; + } + } + } + // TODO FIXME was soll das fuer ein Kaese sein? +#endif + + int dbg_flachen_passiert = 0; + + for(VertexIterator iter = sel.begin(); iter != sel.end(); ++iter) + { + + bool wahl = true; + + // so stimmt es vielleicht, aber ist auch ein komischer Fall, innen expandieren und aussen nicht...... die Frage ist, ob es oonst Sinn macht..... + if( expandInnerFracBnds && !expandOuterFracBnds && aaMarkVrtVFP[*iter].getIsBndFracVertex() ) + wahl = false; + + static_assert( std::is_same< decltype(*iter), Vertex * >::value ); + + bool isBnd = aaMarkVrtVFP[ *iter ].getIsBndFracVertex(); + auto numCrosFrac = aaMarkVrtVFP[ *iter ].getNumberCrossingFracsInVertex(); + + if( wahl ) + { + sel.select(grid.associated_edges_begin(*iter), + grid.associated_edges_end(*iter)); + sel.select(grid.associated_faces_begin(*iter), + grid.associated_faces_end(*iter)); + + // TODO FIXME hier ein attachment der associated faces und vertizes, am besten als Klasse, die std vertizes davon frisst, an jeden Vertex anhängen + // so muss man später nicht nochmal über alle Faces und Edges laufen, sondern hat die angehängten schon zur Hand + // im Fall, dass eine Kreuzung vorliegt, das Ganze irgendwann ordnen, dass nebeneinander liegende Faces und edges in eine verkettete Liste kommen + // vielleicht das aber nur bei den Schnittvertizes später + // und vielleicht sollen die Faces Zeiger auf ihre Edges bekommen, und die edges auf die faces, aber wird irgendwann zu wild verzeigert..... + // vielleicht einfach attachment von faces und edges unabhängig an jeden Fracture Vertex...... + + // testen, ob ein Schnittvertex vor liegt, indem die Anzahl der touches getestet wird, anhand einfacher Geometrien testen, was die Anzahl ist + + // mit UG_LOG ausgeben, was die Koordinaten sind, und die Anzahl der hits + + VecFace assFac; + VecEdge assEdg; + +// UG_LOG("----------" << std::endl); + + for( std::vector::iterator iterFac = grid.associated_faces_begin(*iter); iterFac != grid.associated_faces_end(*iter); iterFac++ ) + { + assFac.push_back(*iterFac); +// vector3 facCenter = CalculateCenter( *iterFac, aaPos ); +// UG_LOG("fac center " << facCenter << std::endl); + } + +// UG_LOG("----------" << std::endl); + + for( std::vector::iterator iterEdg = grid.associated_edges_begin(*iter); iterEdg != grid.associated_edges_end(*iter); iterEdg++ ) + { + assEdg.push_back(*iterEdg); + } + + aaVrtInfoAssoFaces[*iter] = assFac; + aaVrtInfoAssoEdges[*iter] = assEdg; + + UG_LOG("marked vertex wahl: " << aaPos[*iter] << " is bnd " << isBnd << " number cross frac " << numCrosFrac << std::endl ); + + // fuer Nicht Boundary Vertizes muessen wir durch 2 teilen, damit wir richtige Anzahl der + // Fracs haben, die durch den spezifischen Vertex durch geht + + } + else + { + UG_LOG("marked vertex unwahl: " << aaPos[*iter] << " is bnd " << isBnd << " number cross frac " << numCrosFrac << std::endl ); + } + + } + + using pairIndDbl = std::pair; + + std::vector< pairIndDbl > fracSubdom_facePerpendMinVal; + + for( auto const & pf: fracInfos ) + { + fracSubdom_facePerpendMinVal.push_back( pairIndDbl( pf.subsetIndex, std::numeric_limits::max() ) ); + } + + T_min minDistPerpOverall( std::numeric_limits::max() ); + +// for( auto fI : fracInfos ) +// for( size_t fraInfInd = 0; fraInfInd < fracInfos.size(); fraInfInd++ ) + for( auto & fsfpmv : fracSubdom_facePerpendMinVal ) + { +// int fracInd = fracInfos[fraInfInd].subsetIndex; +// int fracInd = fI.subsetIndex; + + auto fracInd = fsfpmv.first; + + T_min minDistPerpThisFrac( fsfpmv.second ); + + for(EdgeIterator iterEdg = sh.begin(fracInd); iterEdg != sh.end(fracInd); iterEdg++ ) + { + + // get subdomain of edge + + auto sudoEdg = sh.get_subset_index(*iterEdg); + + static_assert( std::is_same< decltype(sudoEdg), int >::value ); + + // get vertices of edge, always 2 + + std::vector verticesEdg; + + static_assert( std::is_same< Vertex*, decltype( (*iterEdg)->vertex(0) ) >::value ); + + for( size_t i = 0; i < 2; ++i ) + verticesEdg.push_back( (*iterEdg)->vertex(i) ); + + // get attached faces + +#if 0 + std::vector assFace; + + // TODO FIXME dieser loop kann vielleicht vereinfacht werden, wenn dieser ganze loop umgebaut wird + // denn die Vertizes kennen dann die assosciated faces schon + // der Name AssociatedFaceIterator ist sowieso verwirrend, hat mit assosciated nix zu tun, bezieht sich auf alle std Vektoren von Face * + UG_LOG("XXXXXXXXXXXX" << std::endl); + for(Grid::AssociatedFaceIterator iterAFI = grid.associated_faces_begin( verticesEdg[0] ); + iterAFI != grid.associated_faces_end( verticesEdg[0] ); + iterAFI++ ) + { + + if(FaceContains( *iterAFI, *iterEdg )) + { + assFace.push_back( *iterAFI ); + + + vector3 facCenter = CalculateCenter( *iterAFI, aaPos ); + UG_LOG("fac center " << facCenter << std::endl); + + + +// sh.assign_subset( *iterAFI, sh.get_subset_index(*iterEdg)); + } + + } + UG_LOG("XXXXXXXXX" << std::endl); +#else + + std::vector & assFaceVrt0 = aaVrtInfoAssoFaces[verticesEdg[0]]; + + std::vector assFace; + +// static_assert( std::is_same< decltype( aaVrtInfoAssoFaces[verticesEdg[0]] )[0], std::vector >::value ); + //static_assert( std::is_same< decltype( *(aaVrtInfoAssoFaces[verticesEdg[0]]) ), Face * >::value ); + +// UG_LOG("XXXXXXXXXXXX" << std::endl); + + for( auto const & ifa : assFaceVrt0 ) + { + if(FaceContains( ifa, *iterEdg )) + { + assFace.push_back( ifa ); + +// vector3 facCenter = CalculateCenter( ifa, aaPos ); +// UG_LOG("fac center " << facCenter << std::endl); + } + } + +// UG_LOG("XXXXXXXXX" << std::endl); + +#endif + // von hier lernen: + // VecFace & assoFaces = aaVrtInfoAssoFaces[*iterV ist verticesEdg[0] ]; + // for( auto const & ifac : assoFaces ) + // { + // static_assert( std::is_same< decltype( ifac ), Face * const & >::value ); + // } + + + + // compute normal of edge + + std::vector< vector3 > edgeNormals; + + std::vector perpendDistances; + + for( auto const & fac : assFace ) + { + vector3 facCenter = CalculateCenter( fac, aaPos ); + + vector3 perpendicu; + + DropAPerpendicular(perpendicu, facCenter, aaPos[verticesEdg[0]], aaPos[verticesEdg[1]]); + + double perpendDist = VecLength( perpendicu ); // betrag perpendicu + + perpendDistances.push_back( perpendDist ); + + minDistPerpThisFrac( perpendDist ); + + + // vector from projection to center is the unnormalized normal + vector3 tmpN; + + VecSubtract(tmpN, facCenter, perpendicu ); + + VecNormalize(tmpN, tmpN); + + edgeNormals.push_back( tmpN ); + + static_assert( std::is_same< Edge*, decltype(*iterEdg) >::value ); + + static_assert( std::is_same< Face * const &, decltype(fac) >::value ); + static_assert( std::is_same< Face *, decltype( const_cast(fac) ) >::value ); + static_assert( std::is_same< vector3, decltype( tmpN ) >::value ); + + VertFracTrip infoVertizesThisEdge( *iterEdg, fac, tmpN ); + +// UG_LOG("TypE Fac " << typeid(const_cast(fac) ).name() << std::endl); +// UG_LOG("TypE Edg " << typeid( *iterEdg ).name() << std::endl); +// UG_LOG("TypE Vec " << typeid( tmpN ).name() << std::endl); + + + for( auto const & v : verticesEdg ) + { + static_assert( std::is_same< decltype(v), Vertex * const & >::value ); + static_assert( std::is_same< decltype(const_cast(v)), Vertex * >::value ); + aaVrtInfoFraTri[v].push_back( infoVertizesThisEdge ); + +// VecVertFracTrip allInfosVrtxThisEdg = aaVrtInfoFraTri[v]; + +// static_assert( std::is_same< decltype( aaVrtInfoFraTri[v] ), VecVertFracTrip >::value ); + +// UG_LOG("type Fac " << typeid( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getFace() ).name() << std::endl); +// UG_LOG("type Edg " << typeid( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getEdge() ).name() << std::endl); +// UG_LOG("type Vec " << typeid( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getNormal() ).name() << std::endl); + + static_assert( std::is_same< decltype( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getFace() ), Face * >::value ); + static_assert( std::is_same< decltype( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getEdge() ), Edge * >::value ); + static_assert( std::is_same< decltype( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getNormal() ), vector3 const >::value ); + } + + } + + // damit speichern wir die plus und minus Normale, und das ist alles, und auch + // gleich wieder weg + // TODO FIXME besser, wir speichern die gemittelte Normale an den Vertizes + // vielleihct als attachment pair, das die subdom kennt der frac und die Normale dazu? + // ziemlich nutzlos, die Normale wie hier gemacht in einen kurzen Vektor zu speichern, der schnell + // wieder weg ist...... + // wir brauchen alle Normalen zu jeder fracture an jedem fracture Vertex, also die Mittelung vermutlich + // diese Mittelung kann aber erst stattfinden, wenn wir nachher über die vertizes loopen, + // hier kennen wir nur die Vertizes, die an derselben Edge anliegen + + UG_LOG("EDGE NORMALS: " << sh.get_subset_index(*iterEdg) << " -> "); + + int j = 0; + + for( auto const & en: edgeNormals ) + { + + for( size_t i = 0; i < 3; i++ ) + UG_LOG( en[i] << ", " ); + + + UG_LOG(" --- " << perpendDistances[j] << " ///////// " ); + + j++; + } + + UG_LOG(std::endl); + + } + + fsfpmv.second = minDistPerpThisFrac(); + + minDistPerpOverall( fsfpmv.second ); + + UG_LOG("first " << fsfpmv.first << " second " << fsfpmv.second << std::endl); + } + + for( auto const & fsfpmv : fracSubdom_facePerpendMinVal ) + { + UG_LOG("min dist sd " << fsfpmv.first << " -> " << fsfpmv.second << std::endl ); + } + + UG_LOG("overall min dist " << minDistPerpOverall() << std::endl); + + + + // von Sebastian teilweise das Prinzip übernommen, dass die Faces wissen können, was ihre neuen Vertizes sein sollen + // create new vertices + + // we have to associate a vector of vertices with each node in the fracture. + // since an empty vector is quite small, we can associate one with each vertex in + // the whole grid. This could be optimized if required, by using subset attachments. + + // TODO FIXME es reicht vielleicht, hier statt einem Vektor einfach nur einen Vertex * zu storen + using AttVrtVec = Attachment >; + AttVrtVec attVrtVec; + + // we associate a vector of vertices for each face adjacent to the frac. + // it will store a set of vertices. An entry contains the new vertex, if the + // corresponding vertex is an inner fracture vertex, and NULL if not. + grid.attach_to_faces(attVrtVec); + Grid::FaceAttachmentAccessor aaVrtVecFace(grid, attVrtVec); + + + // iterate over all surrounding faces to enable face changes, this loop taken from SR but shortened + for(FaceIterator iter_sf = sel.faces_begin(); iter_sf != sel.faces_end(); ++iter_sf) + { + Face* sf = *iter_sf; + + std::vector& newVrts = aaVrtVecFace[sf]; + newVrts.resize(sf->num_vertices()); + + for(size_t i_vrt = 0; i_vrt < sf->num_vertices(); ++i_vrt) + { + newVrts[i_vrt] = NULL; + } + // erstmal so tun, als ob keine neuen Vertizes erzeugt werden an den alten Vertizes + } + + + // attachment to allow fracture vertizes to know the newly created vertizes + // due to extrusion which are related to them, in connection with + // the normals which are an average of the related edges and the faces + // defining the original normal + + // usage: store edges and associated faces in SAME order in std vectors! + using ExpandVertexMultiplett = VertexFractureTriple< std::vector, std::vector, vector3 >; + // holds the averaged normal of the related edges and their corresponding faces which give direction + + using VecExpandVertexMultiplett = std::vector; + + + VecExpandVertexMultiplett vertexMultiplettEmpty; + + using AttVecExpandVertexMultiplett = Attachment; + + AttVecExpandVertexMultiplett aAdjInfoVVEVM; + + grid.attach_to_vertices_dv( aAdjInfoVVEVM, vertexMultiplettEmpty ); + Grid::VertexAttachmentAccessor aaVrtExpMP(grid, aAdjInfoVVEVM ); + + + + // am Ende dieser Prozedur sollten alle Vertizes wissen, welche Tripel vom Typ Edge - Face - Normal zum Face hin an ihnen angelagert sind + + // damit weiss, wenn es stimmt, jeder Vertex, der an einer Fracture ist, wieviele Schnittpunkte von Fractures er hat, + // ob er ein boundary vertex ist, und was für einen Vektor von Tripeln an ihm angehängt sind + // die subdomain der Fracture muss anhand der subdomain der edge bestimmt werden immer + + UG_LOG("loop over all marked vertizes " << std::endl); + + int dbg_vertizesPassiert = 0; + + // jetzt können wir alle Vertizes ablaufen und an ihnen neue Vertizes erzeugen, die anhand der gemittelten Normalen von den Vertizes weg gehen + // ob zwei anhängende Faces auf der gleichen Seite liegen, wenn es kein Schnittvertex von zwei oder mehr Klüften ist + // das kann man anhand des Winkels zwischen zwei face Normalen unterscheiden vermutlich + // dabei müssen die edges sowieso disjunkt sein, sonst ist man sowieso sicher auf verschiedenen Seiten + // wenn wir es mit einem boundary Vertex zu tun haben, müssen wir weiter überlegen, wie wir die Verschiebung auf die äussere Kante projizieren + // muss auch mit dem Winkel zu tun haben + for(VertexIterator iterV = sel.begin(); iterV != sel.end(); ++iterV) + { + + // POsition dieses Vertex + vector3 posOldVrt = aaPos[*iterV]; + + // vielleicht muss man, wenn die neuen Vertizes da sind, diese auch gleich mit den umliegenden Knoten per neuer Kanten verbinden + // und die neuen faces erzeugen nach Löschen der alten? + // oder alle neuen Vertizes wie bei Prof Reiter in einen std Vektor, der als attachment den bisherigen Face Vertizes angehängt wird + // und Edge Vernichtung und Erzeugung neuer edges und faces wie bei Prof Reiter in Folgeschritten? + + VecVertFracTrip & vecVertFracTrip = aaVrtInfoFraTri[*iterV]; + + std::vector & allAssoEdges = aaVrtInfoAssoEdges[*iterV]; + + static_assert( std::is_same< decltype( vecVertFracTrip[ vecVertFracTrip.size() - 1 ].getFace() ), Face * >::value ); + static_assert( std::is_same< decltype( vecVertFracTrip[ vecVertFracTrip.size() - 1 ].getEdge() ), Edge * >::value ); + static_assert( std::is_same< decltype( vecVertFracTrip[ vecVertFracTrip.size() - 1 ].getNormal() ), vector3 const >::value ); + + for( auto const & vft : vecVertFracTrip ) + { + static_assert( std::is_same< decltype( vft.getFace() ), Face * >::value ); + static_assert( std::is_same< decltype( vft.getEdge() ), Edge * >::value ); + static_assert( std::is_same< decltype( vft.getNormal() ), vector3 const >::value ); + + Face * f = vft.getFace(); + Edge * e = vft.getEdge(); + vector3 n = vft.getNormal(); + + } + + using VvftIterator = VecVertFracTrip::iterator; + + VecFace & assoFaces = aaVrtInfoAssoFaces[*iterV]; + // TODO FIXME hier braucht man das nicht zu ordnen + // aber bei Kreuzpunkten von Klueften muss es so geordnet werden, wie es nebeneinander liegt + // bei den Edges gibt es auch die benachbarten, und die edges haben das attachment, ob sie Kluftedges sind + +// for( auto const & ifac : assoFaces ) +// { +// static_assert( std::is_same< decltype( ifac ), Face * const & >::value ); +// } + + + + // Anzahl der Kreuzungspunkte auslesen und danach unterscheiden, erstmal keine Kreuzung! TODO FIXME + + // irgendwie muessen wir diese Infos jetzt verwerten, um als erstes neue Vertizes zu erzeugen, anfangs für eine Kluft nur + // und danach die alten Edges und faces löschen und an neuer Stelle neu erzeugen, plus die sowieso neuen, + // oder Edges verschieben, wenn es möglich ist, die Vertizes zu verschieben, und die Edges und in Folge faces passen sich an, + // dann müssen nur die neuen edges und faces neu erzeugt werden + // verschieben der Position des Vertex löst Kaskade aus, dass Edge und Face auch verschoben werden, kann also angewendet werden + // allerdings Problem, dass die Vertizes dafür verdoppelt werden müssen und die Kanten, sonst kann man sie nicht nach aussen verschieben + // also doch komplette Neuerzeugung vermutlich..... oder doppeltes Klonen, und das alte bleibt in der Mitte..... + + vector3 posThisVrt = aaPos[*iterV]; + + UG_LOG("vertex at " << posThisVrt << std::endl ); + + bool vrtxIsBndVrt = aaMarkVrtVFP[*iterV].getIsBndFracVertex(); + // alternativ wäre möglich: IsBoundaryVertex2D(grid, *iterV) + + UG_LOG("is bndry " << vrtxIsBndVrt << std::endl); + + IndexType numFracsCrossAtVrt = aaMarkVrtVFP[*iterV].getNumberCrossingFracsInVertex(); + + UG_LOG("number crossing fracs " << numFracsCrossAtVrt << std::endl); + + size_t numbAttTripl = vecVertFracTrip.size(); + + UG_LOG("sizes of vft " << numbAttTripl << std::endl ); + + if( ! vrtxIsBndVrt ) + { + + if( numFracsCrossAtVrt < 1 ) + { + UG_THROW("no fracs crossing but marked vertex? << std::endl"); + } + + if( numFracsCrossAtVrt == 1 ) // free line of fracture, no crossing point, not at boundary + { + // in this case, we have two attached edges, and each of these edges has two attached faces + // the faces have a naormal, and based on the normal, we can decide which faces belong to the same side of the edges + + + if( numbAttTripl != 4 ) + { + UG_THROW("Anzahl der angehaengten Triples kann nicht stimmen, Vertex einer Kluft ohne Schnittpunkte, nicht am Rand " << std::endl); + } + + // Zuordnung der Edges und Faces, die auf der gleichen Seite der fracture sind + + // und gleich auch Erzeugung der neuen Knoten, die dann + // in einem Doublett zusammen mit ihren Normalen an die alten Vertizes + // angehängt werden; der Winkel zur Normalen hilft später, die Seite + // heraus zu finden, Seite von den Edges + + + + int dbg_iteratorAblaufen = 0; + +#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX + + int dbg_laenge = 0; + + for( auto const & vft : vecVertFracTrip ) + { + dbg_laenge++; + + UG_LOG("VERTEXFRACTRIP" << std::endl); + + vector3 ve = vft.getNormal(); + + UG_LOG("NORMAL " << ve << std::endl); + + UG_LOG("laenge " << dbg_laenge << std::endl ); + } + + + UG_LOG("SINGLE" << std::endl); + + + for( VvftIterator vvftOne = vecVertFracTrip.begin(); + vvftOne != vecVertFracTrip.end() - 1; + vvftOne++ + ) + { + + + Edge * edgeOne = vvftOne->getEdge(); + vector3 nOne = vvftOne->getNormal(); + + + for( VvftIterator vvftTwo = vvftOne + 1; + vvftTwo != vecVertFracTrip.end(); + vvftTwo++ + ) + { + Edge * edgeTwo = vvftTwo->getEdge(); + vector3 nTwo = vvftTwo->getNormal(); + + number cosinus = VecDot( nOne, nTwo ); + if( edgeOne != edgeTwo ) + { + UG_LOG("COSI between " << nOne << " and " << nTwo << " -> " << cosinus << std::endl ); + } + + } + } + + UG_LOG("SINGLE END" << std::endl); + + int dbg_laenge_eins = 0; + +#endif + + + for( VvftIterator vvftOne = vecVertFracTrip.begin(); + vvftOne != vecVertFracTrip.end() - 1; + vvftOne++ + ) + { + +#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX + dbg_laenge_eins++; + + if( dbg_laenge_eins > dbg_laenge ) + { + break; + } + + int dbg_laenge_zwei = dbg_laenge_eins; +#endif + int dbg_zweiterIteratorAblaufen = 0; + + vector3 nOne = vvftOne->getNormal(); + + Edge * edgeOne = vvftOne->getEdge(); + + + + for( VvftIterator vvftTwo = vvftOne + 1; + vvftTwo != vecVertFracTrip.end(); + vvftTwo++ + ) + { + +#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX + dbg_laenge_zwei++; + + if( dbg_laenge_zwei > dbg_laenge ) + { + break; + } + + UG_LOG("NORMAL ONE " << vvftOne->getNormal() << std::endl); + UG_LOG("NORMAL TWO " << vvftTwo->getNormal() << std::endl); + UG_LOG("LAENGE EINZ ZWO " << dbg_laenge_eins << " " << dbg_laenge_zwei << std::endl ); +#endif + + // dieselben brauchen wir nicht vergleichen + if( vvftOne == vvftTwo ) + { + // sollte nie vorkommen! + UG_THROW("Unsinn " << std::endl); + } + else + { + + Edge * edgeTwo = vvftTwo->getEdge(); + + // noch testen, ob nicht die Kante dieselbe ist, geht das? + // bei der gleichen Ecke ist es unnötig, da es gegensätzlich sein muss + + + + if( edgeOne != edgeTwo ) + { + + std::vector nextFracVrt; + + IndexType foundThisVrtOne = 0; + + for( size_t i = 0; i < 2; ++i ) + { + Vertex * vrtEdgEnd = edgeOne->vertex(i); + + if( vrtEdgEnd == *iterV ) + { + foundThisVrtOne++; + } + else + { + nextFracVrt.push_back( vrtEdgEnd ); + } + + } + + if( foundThisVrtOne != 1 ) + { + UG_THROW("zu viel zu wenig vertizex one " << std::endl); + } + + + IndexType foundThisVrtTwo = 0; + + for( size_t i = 0; i < 2; ++i ) + { + Vertex * vrtEdgEnd = edgeTwo->vertex(i); + + if( vrtEdgEnd == *iterV ) + { + foundThisVrtTwo++; + } + else + { + nextFracVrt.push_back( vrtEdgEnd ); + } + + } + + if( foundThisVrtTwo != 1 ) + { + UG_THROW("zu viel zu wenig vertizex two " << std::endl); + } + + + + vector3 nTwo = vvftTwo->getNormal(); + + number cosinus = VecDot( nOne, nTwo ); + +// bool vz = ! std::signbit(cosinus); + + UG_LOG("cosinus " << dbg_vertizesPassiert << " between " << nOne << " and " << nTwo << " -> " << cosinus << std::endl ); + //UG_LOG("sign between " << nOne << " and " << nTwo << " -> " << vz << std::endl ); + + + + if( cosinus > 0 ) + { + // gleiche Seite vermutet + + // sind die edges dieselben? pruefen! gleiche unnoetig - wird oben schon abgefragt + + // Klasse schreiben, die als attachment an einen Fracture-Vertex + // die neuen Vertizes samt ihrer gemittelten Normalen speichert + // also std::vector von dieser neuen Klasse als Vertex attachment + + + // average the normals + + vector3 normSum; + + VecAdd( normSum, nOne, nTwo ); + + vector3 normSumNormed; + + VecNormalize(normSumNormed, normSum); + + UG_LOG("averaged normal " << normSumNormed << std::endl); + + std::vector attEdg; + std::vector attFac; + + attEdg.push_back( edgeOne ); + attEdg.push_back( edgeTwo ); + + Face * facOne = vvftOne->getFace(); + Face * facTwo = vvftTwo->getFace(); + + attFac.push_back( facOne ); + attFac.push_back( facTwo ); + + // jetzt neuen Vertex erzeugen in Richtung der Normalen + // sonst ist das attachment Schwachsinn! + + vector3 posNewVrt; + + vector3 moveVrt; + + auto subsIndEdgOne = sh.get_subset_index(edgeOne); + + auto subsIndEdgTwo = sh.get_subset_index(edgeTwo); + + + if( subsIndEdgOne != subsIndEdgTwo ) + { + UG_THROW("subsets passen nicht" << std::endl ); + } + + + + + number width = fracInfosBySubset.at(subsIndEdgOne).width; + + // der Faktor ist Käse und muss noch aus den Eingaben übernommen werden + VecScale(moveVrt, normSumNormed, width/2. ); + + VecAdd(posNewVrt, posOldVrt, moveVrt ); + + UG_LOG("neuer Vertex " << posNewVrt << std::endl ); + + // TODO FIXME hier ist das PROBLEM, SEGFAULT durch create regular vertex + + Vertex * newShiftVrtx = *grid.create(); + aaPos[newShiftVrtx] = posNewVrt; + + sh.assign_subset(newShiftVrtx, subsIndEdgOne ); + + + + // fuer was braucheh wir das eigentlich? selber schon vergessen..... + + ExpandVertexMultiplett vrtMtpl( attEdg, attFac, normSumNormed ); + + aaVrtExpMP[ *iterV ].push_back( vrtMtpl ); + + + + // alle anhängenden faces müssen noch zu wissen bekommen + // dass es diesen neuen Vertex gibt, nicht nur die + // an den edges anhängenden + // vielleicht gibt es einen Loop über attached faces des + // Vertex, für die schon bekannten direkt angehängten klar + // wenn auch dort vermerkt werden muss im Attachment von Seb + // bei den anderen, die keine Edge haben von der Kluft + // da muss man die Normale ins Zentrum bestimmen + // um heraus zu finden, ob sie auf dieser seite sind + // am besten dann das Attachment der faces für vertizes + // von Seb recyclen + + // loop über assosciated faces des vertex am besten + // vermutlich auch noch assosciated edges, um + // zu markieren, welche weg fallen sollen, wenn + // nicht von Kluft selber, sondern quasi verschoben + // und neu erzeugt + + int dbg_FaceIterator = 0; + +#if 0 +// for( auto iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ ) + for( std::vector::iterator iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ ) + { + bool isFromFrac = false; + +// for( std::vector::iterator iterF2 = attFac.begin(); iterF2 != attFac.end(); iterF2++ ) +// { +// static_assert( std::is_same< decltype( *iterF2 ), decltype ( *iterFac ) >::value ); +// +// } + + int dbg_innterFacFracIt = 0; + + for( auto const & facFrac : attFac ) + { + + +// UG_LOG("type iter facFrac " << typeid( facFrac ).name() << std::endl); +// +// UG_LOG("type iter Fac " << typeid( *iterFac ).name() << std::endl); + + static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype ( *iterFac ) >::value ); + + + + + if( *iterFac == facFrac ) + { + isFromFrac = true; + + static_assert( std::is_same< decltype( const_cast(facFrac) ), Face * & >::value ); + static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype( * iterFac ) >::value ); + + } + } + + bool atRightSide = false; + + if( isFromFrac ) + atRightSide = true; + + if( !isFromFrac ) + { + // check if on same side of edge where the normal points to: compute cosinus between vector of face center + // perpendicular to the edge + // TODO FIXME + // KAESE!!! + + vector3 facCenter = CalculateCenter( *iterFac, aaPos ); + + vector3 perpendicu; + + if( nextFracVrt.size() != 2 ) + { + UG_THROW("komische Groesse" << std::endl); + } + + DropAPerpendicular(perpendicu, facCenter, aaPos[nextFracVrt[0]], aaPos[nextFracVrt[1]]); + + vector3 tmpN; + + VecSubtract(tmpN, facCenter, perpendicu ); + + VecNormalize(tmpN, tmpN); + + UG_LOG("Normale zum Face ist " << tmpN << std::endl); + + number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, normSumNormed ); + + UG_LOG("Cosinus zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); + + if( cosBetwFracEdgAndDirection2Face > 0 ) + { + UG_LOG("assuming face to be on richt side" << std::endl); + + atRightSide = true; + +#if ANSCHAULICH_ERZEUGE_SUDOS_ANHANG + + Vertex * otherFacCent = *grid.create(); + aaPos[otherFacCent] = facCenter; + sh.assign_subset(otherFacCent, 5 ); + + Vertex * pp = *grid.create(); + aaPos[pp] = perpendicu; + sh.assign_subset(pp, 6 ); + + sh.assign_subset(*iterFac,7); +#endif + + } + else + { + UG_LOG("assuming face to be on wrong side" << std::endl); + } + +// if( dbg_flachen_passiert == 0 ) +// { +// UG_LOG("passiert " << dbg_flachen_passiert << std::endl); +// +// Vertex * otherFacCent = *grid.create(); +// aaPos[otherFacCent] = facCenter; +// sh.assign_subset(otherFacCent, 5 ); +// +// Vertex * pp = *grid.create(); +// aaPos[pp] = perpendicu; +// sh.assign_subset(pp, 6 ); +// +// sh.assign_subset(*iterFac,7); +// +// +// sh.assign_subset(*iterFac,3); +// +// UG_LOG("is from frac " << isFromFrac << std::endl); +// +// return true; +// } + + + dbg_flachen_passiert++; + } + + + if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein + { + + + // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! + vector& newVrts4Fac = aaVrtVecFace[ * iterFac ]; + + IndexType vrtxFnd = 0; + + for(size_t indVrt = 0; indVrt < (*iterFac)->num_vertices(); indVrt++ ) + { + Vertex* facVrt = (*iterFac)->vertex(indVrt); + + if( facVrt == *iterV ) + { + newVrts4Fac[ indVrt ] = newShiftVrtx; + // UG_LOG("vertex found " << indVrt << std::endl ); + vrtxFnd++; + } + } + + + if( vrtxFnd <= 0 ) + { + UG_THROW("vertex not found!" << std::endl); + } + else if( vrtxFnd > 1 ) + { + UG_THROW("vertex zu oft gefunden " << vrtxFnd << std::endl ); + } + else if ( vrtxFnd == 1 ) + { + // UG_LOG("vertex found abgeschlossen" << std::endl); + } + else + { + UG_THROW("vertex finden komisch " << std::endl); + } + + + } + + dbg_innterFacFracIt++; + + + +// +// +// if( ! isFromFrac ) +// { +// // Vektor zum Zentrum von KNoten aus berechnen und Winkel zur Normalen bestimmen zur Unterscheidung der Seite +// // wenn auf richtiger Seite, zuweisen +// } + + dbg_FaceIterator++; + + } +#else +// std::vector & assFaceVrt = aaVrtInfoAssoFaces[*iterV]; + + // VecFace & assoFaces = aaVrtInfoAssoFaces[*iterV]; + // TODO FIXME hier braucht man das nicht zu ordnen + // aber bei Kreuzpunkten von Klueften muss es so geordnet werden, wie es nebeneinander liegt + // bei den Edges gibt es auch die benachbarten, und die edges haben das attachment, ob sie Kluftedges sind + + // for( auto const & ifac : assoFaces ) + // { + // static_assert( std::is_same< decltype( ifac ), Face * const & >::value ); + // + // // TODO FIXME folgenden loop durch diesen ersetzen + // // Achtung: Zeigerproblematik, Referenzen, etc..... + // // *iterFac ersetzen durch ifac vermutlich, aber wer weiss + // } + + + // for( auto iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ ) + //for( std::vector::iterator iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ ) + for( auto const & ifac : assoFaces ) + { + bool isFromFrac = false; + + + int dbg_innterFacFracIt = 0; + + for( auto const & facFrac : attFac ) + { + +// static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype ( ifac ) >::value ); + static_assert( std::is_same< decltype( (facFrac) ), decltype ( ifac ) >::value ); + + if( ifac == facFrac ) + { + isFromFrac = true; + +// static_assert( std::is_same< decltype( const_cast(facFrac) ), Face * & >::value ); + static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value ); +// static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype( ifac ) >::value ); + static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value ); + + } + } + + bool atRightSide = false; + + if( isFromFrac ) + atRightSide = true; + + if( !isFromFrac ) + { + // check if on same side of edge where the normal points to: compute cosinus between vector of face center + // perpendicular to the edge + + vector3 facCenter = CalculateCenter( ifac, aaPos ); + + vector3 perpendicu; + + if( nextFracVrt.size() != 2 ) + { + UG_THROW("komische Groesse" << std::endl); + } + + DropAPerpendicular(perpendicu, facCenter, aaPos[nextFracVrt[0]], aaPos[nextFracVrt[1]]); + + vector3 tmpN; + + VecSubtract(tmpN, facCenter, perpendicu ); + + VecNormalize(tmpN, tmpN); + + UG_LOG("Normale zum Face ist " << tmpN << std::endl); + + number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, normSumNormed ); + + UG_LOG("Cosinus zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); + + if( cosBetwFracEdgAndDirection2Face > 0 ) + { + UG_LOG("assuming face to be on richt side" << std::endl); + + atRightSide = true; + +#if ANSCHAULICH_ERZEUGE_SUDOS_ANHANG + + Vertex * otherFacCent = *grid.create(); + aaPos[otherFacCent] = facCenter; + sh.assign_subset(otherFacCent, 5 ); + + Vertex * pp = *grid.create(); + aaPos[pp] = perpendicu; + sh.assign_subset(pp, 6 ); + + sh.assign_subset(*iterFac,7); +#endif + + } + else + { + UG_LOG("assuming face to be on wrong side" << std::endl); + } + + + dbg_flachen_passiert++; + } + + + if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein + { + + // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! + vector& newVrts4Fac = aaVrtVecFace[ ifac ]; + + IndexType vrtxFnd = 0; + + for(size_t indVrt = 0; indVrt < (ifac)->num_vertices(); indVrt++ ) + { + Vertex* facVrt = (ifac)->vertex(indVrt); + + if( facVrt == *iterV ) + { + newVrts4Fac[ indVrt ] = newShiftVrtx; + vrtxFnd++; + } + } + + + if( vrtxFnd <= 0 ) + { + UG_THROW("vertex not found!" << std::endl); + } + else if( vrtxFnd > 1 ) + { + UG_THROW("vertex zu oft gefunden " << vrtxFnd << std::endl ); + } + else if ( vrtxFnd == 1 ) + { + } + else + { + UG_THROW("vertex finden komisch " << std::endl); + } + + + } + + dbg_innterFacFracIt++; + + + + dbg_FaceIterator++; + + } + +#endif + + + + } + else + { + // andere Seite vermutet, nichts tun! + } + + + + } + + + } + + dbg_zweiterIteratorAblaufen++; + + } + + dbg_iteratorAblaufen++; + + } + + +// // Ziel: die beiden parallelen Normalen mitteln, und in die jeweiligen beiden Richtungen je einen neuen Vertex erzeugen +// // irgendwie muss der Vertex oder die Edge besser sogar wissen, dass sie einen neuen Verschiebevertex bekommen hat +// // denn später müssen neue Edges und neue Faces basierend auf den neuen Vertizes erzeugt werden +// // vielleicht braucht die edge und das face ein Attachment, das ihnen das sagt, ähnlihc wie VertexTrible std Vektoren? +// +// +// + + + UG_LOG("END THIS VERTEX NORMAL COSINE" << std::endl); + + + + } + else // fractures are crossing, numFracsCrossAtVrt > 1 + { + + IndexType countedCrossingFracEdgs = 0; + + // TODO FIXME kreuzende Fractures im Innenraum -> Arte in Reinform implementieren + + // verkettete Liste der anhängenden fractures in Reihenfolge + // der Anhängung mit INfo, ob eine Kluft vorliegt + +// for( auto const & attVFT : vecVertFracTrip } + for( auto const & attVFT : vecVertFracTrip ) + { + Edge * edg = attVFT.getEdge(); + Face * fac = attVFT.getFace(); + vector3 nv = attVFT.getNormal(); + } + + // hier werden ALLE attached Faces benötigt, auch die, die zwischen den direkt an den fractures liegenden Faces sind + for( auto const & ifac : assoFaces ) + { + + } + + // copies of all faces and of fractured ones + + auto vVFT = vecVertFracTrip; // caution: COPY, not reference! + auto aF = assoFaces; // caution: COPY, not reference! + + UG_LOG("Gesamtanzahl faces um Knoten " << aF.size() << std::endl ); + + // TODO FIXME erstmal die ganzen anhaengenden Faces ordnen, dass wir wissen, in welcher Reihenfolge wir durchlaufen muessen + // jede Edge hat ein bool attachment schon, das weiss, ob sie Fracture edge ist oder nicht + // Reihenfolge der faces und die edges auch dazu, vielleicht neues Triple oder dergleiche, dabei zwei edges und zwei normals + // und wie gesagt, die edges wissen, ob sie fractures sind, dazu keine neuen Variablen notwendig + + using VertexOfFaceInfo = VertexFractureTriple< std::pair, Face*, std::pair >; + // all edges of the attached face - must always be two, the face itself, and the normal vectors of the face in direction of the two edges + // the size of the normal vector vector also must be two + // however, if an edge of the face is not a fracture edge, we do not compute the normal, but assign zero as norm + // for those edges and faces which are Kluft edges, we assign the normal known from the info computed before, vertex fracture triple + + using VecVertexOfFaceInfo = std::vector; + + VecVertexOfFaceInfo orderedFaces; + + using SegmentsFractExtrus = std::vector; + + SegmentsFractExtrus segments; + // single components always from one fracture edge to the next one + + VecVertexOfFaceInfo segmentPart; + + // note: we do not attach this info to the vertex, as we only need it local; in principle, in case of further need, it would + // be usful to establish some sort of attachment + + if( vVFT.size() == 0 ) + UG_THROW("vertex frac triple zu klein an Kreuzung " << std::endl); + + // we start with the first fracture face edge stuff, copy it, and delete this immidiately + VertFracTrip startVertFracTrip = vVFT[0]; + + vVFT.erase(vVFT.begin()); + + bool atFirstTriple = true; + + Face* fracFac = startVertFracTrip.getFace(); + Edge* fracEdg = startVertFracTrip.getEdge(); + vector3 fracNorm = startVertFracTrip.getNormal(); + + Edge* originalStartEdge = startVertFracTrip.getEdge(); + + if( fracEdg != 0 ) + { + countedCrossingFracEdgs++; + } + + // do not change this pointer + Edge* startEdg = fracEdg; + Face* startFace = fracFac; + +// for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); ) +// { +// if( *itFac == fracFac ) +// { +// itFac = aF.erase(itFac); +// break; +// } +// } + + vector3 startNormal = fracNorm; + +// vector3 nuVe(0,0,0); +// IndexType fndCommEdg = 0; +// +// std::pair assoEdg2Fac; +// std::pair assoNorm2Fac; // will stay zero vector in case that next face contains no frac, i.e. if next edge no fracture edge +// +// Edge* nextEdge = NULL; +// +// assoEdg2Fac.first = fracEdg; +// assoNorm2Fac.first = fracNorm; +// +// assoEdg2Fac.second = NULL; // muss noch modifiziert werden +// assoNorm2Fac.second = nuVe; // wird nur modifiziert, wenn die zweite Ecke eine Kluftecke ist von dem face ebenso + + + // now need to find the second edge and figure out if it is fracture + +// Face* nextFace = NULL; +// +// +// for( auto const & iE : allAssoEdges ) // werden nicht gelöscht, deswegen Zugriff auf attachment direkt +// { +// if( FaceContains(fracFac, iE) ) +// { +// fndCommEdg++; +// if( iE != startEdg ) +// { +// nextEdge = iE; +// assoEdg2Fac.second = iE; +// } +// } +// +// if( fndCommEdg != 2 ) +// { +// UG_THROW("komische Anzahl gemeinsamer Ecke " << fndCommEdg << std::endl); +// } +// +// if( nextEdge == NULL ) +// { +// UG_THROW("wieso keine zweite Ecke gefunden???? " << std::endl); +// } +// +// } +// +// if( assoEdg2Fac.second == NULL ) +// { +// UG_THROW("null immer noch?" << std::endl); +// } +// assoEdg2Fac.push_back(nextEdge); + + Face* nextFace = NULL; + + UG_LOG("Gesamtanzahl faces um Knoten vor while " << aF.size() << std::endl ); + + + while( aF.size() != 0 ) + { + + UG_LOG("Gesamtanzahl faces um Knoten Anfang while " << aF.size() << std::endl ); + + + Face* face2Append = startFace; + Edge* startEdg2Append = startEdg; + + + IndexType fndCommEdg = 0; + vector3 nuVe(0,0,0); + + Edge* nextEdge = NULL; + + std::pair edge2Append( startEdg2Append, nextEdge ); + std::pair normal2Append( startNormal, nuVe ); + +// for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); ) +// { +// if( *itFac == startFace ) +// { +// itFac = aF.erase(itFac); +// break; +// } +// } +// + + // if start face and start edge from a triple, then has to be erased this triple, exept for the entire start, as already erased + if( ! atFirstTriple ) + { + for( VecVertFracTrip::iterator itAttVFT = vVFT.begin(); itAttVFT != vVFT.end(); itAttVFT++ ) + { + auto vft = *itAttVFT; + + Edge * edgIt = vft.getEdge(); + + Face * facIt = vft.getFace(); + + if( edgIt == startEdg && facIt == startFace ) + { + // the first edge if from a fracture and the face is connected to it + + vVFT.erase(itAttVFT); + + normal2Append.first = vft.getNormal(); + + if( ! FaceContains( facIt, startEdg )) + { + UG_THROW("Face does not contain start edge of its edge" << std::endl); + } + + break; + } + } + + } + else // we can save the investigation if we have a triple, and we do not need to erase, as already erased..... + { + atFirstTriple = false; + } + + + for( auto const & iE : allAssoEdges ) // werden nicht gelöscht, deswegen Zugriff auf attachment direkt + { + if( FaceContains(face2Append, iE) ) + { + fndCommEdg++; + + if( iE != startEdg ) + { + nextEdge = iE; + + edge2Append.second = iE; + +// if( edge2Append.second != nextEdge || edge2Append.second != iE ) +// { +// UG_THROW("wieso wird die naechste Ecke nicht uebertragen?" << std::endl ); +// } + + //assoEdg2Fac.second = iE; + } + } + + + } + + if( fndCommEdg != 2 ) + { + UG_THROW("komische Anzahl gemeinsamer Ecke " << fndCommEdg << std::endl); + } + + if( nextEdge == NULL ) + { + UG_THROW("wieso keine zweite Ecke gefunden???? " << std::endl); + } + + if( edge2Append.first == NULL || edge2Append.second == NULL ) + { + UG_THROW("null immer noch?" << std::endl); + } + + // erase the face from the list + + IndexType faceFound = 0; + + for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ ) + { + Face * iFa = *itFac; + + if( iFa == startFace && FaceContains( iFa, nextEdge ) && FaceContains(iFa, startEdg)) + { + faceFound++; + } + } + + int totalSubsNum = sh.num_subsets(); + + int newSubsToAdd = totalSubsNum; + + if( faceFound != 1 ) + { + + + sh.assign_subset(startFace,newSubsToAdd++); + sh.assign_subset(startEdg,newSubsToAdd++); + sh.assign_subset(nextEdge,newSubsToAdd++); + + int faNum = aF.size(); + + UG_LOG("Gesamtzahl faces vor Absturz " << faNum << std::endl); + + UG_LOG("Gesicht in falscher Anztahl gefunden " << faceFound << std::endl); + +// return true; + + + + UG_THROW("Gesicht in falscher Anztahl gefunden " << faceFound << std::endl); + } + else + { +// sh.assign_subset(startFace,newSubsToAdd++); +// sh.assign_subset(startEdg,newSubsToAdd++); +// sh.assign_subset(nextEdge,newSubsToAdd++); + + int faNum = aF.size(); + + UG_LOG("Gesamtzahl faces ohne Absturz " << faNum << std::endl); + + } + + for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ ) + { + Face * iFa = *itFac; + + if( iFa == startFace && FaceContains( iFa, nextEdge ) && FaceContains(iFa, startEdg) ) + { + aF.erase(itFac); + break; + } + } + + + + + bool sndEdgIsFracEdgeAlso = aaMarkEdgeB[nextEdge]; + + bool tripFound = false; + + if( sndEdgIsFracEdgeAlso ) + { + + if( nextEdge != originalStartEdge ) + countedCrossingFracEdgs++; + + // we need to have a look for the next triple + + // check if the next normal is a frac normal which contains the face as well + + for( VecVertFracTrip::iterator itAttVFT = vVFT.begin(); itAttVFT != vVFT.end(); itAttVFT++ ) + { + auto vft = *itAttVFT; + + Edge * edgIt = vft.getEdge(); + + Face * facIt = vft.getFace(); + + if( edgIt == nextEdge && facIt == face2Append ) + { + // the second edge if from a fracture and the face is connected to it + + tripFound = true; + + vVFT.erase(itAttVFT); + + normal2Append.second = vft.getNormal(); + + if( ! FaceContains( facIt, nextEdge )) + { + UG_THROW("Face does not contain edge of its edge" << std::endl); + } + + break; + } + } + + } + + if( ! tripFound && sndEdgIsFracEdgeAlso ) + { + UG_THROW("Triple nicht gefunden trotz markierter Edge" << std::endl); + } + + +// for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ ) +// { +// if( FaceContains( *itFac, nextEdge ) ) +// { +// Face * facFnd = *itFac; +// aF.erase(itFac); +// +// faceEras = true; +// // check if +//// for( VecVertFracTrip::iterator itAttVFT = vVFT.begin(); itAttVFT != vVFT.end(); itAttVFT++ ) +//// { +//// Face * facTrip = itAttVFT->getFace(); +//// +//// if( facTrip == facFnd ) +//// { +//// VertFracTrip fndVFT = *itAttVFT; +////// vVFT.erase(itAttVFT); +//// +//// normal2Append.second = fndVFT.getNormal(); +//// +//// Edge * edgTrip = fndVFT.getEdge(); +//// +//// if( edgTrip != nextEdge ) +//// { +//// UG_THROW("Ecken Denkfehler" << std::endl); +//// } +//// +//// break; +//// } +//// } +// +// break; +// } +// } + + // check if aF or vVFT still contain the former or the next face - must not be the case! TODO FIXME + + VertexOfFaceInfo vOFI( edge2Append, face2Append, normal2Append ); + + orderedFaces.push_back( vOFI ); + + segmentPart.push_back( vOFI ); + + if( sndEdgIsFracEdgeAlso ) + { + segments.push_back( segmentPart ); + + segmentPart.clear(); + } + + + // what is next face, what is next edge? + // wie kriegen wir es hin, auch das nächste Triple zu erasen, wenn es jetzt kommt als nächstes? + + + startNormal = nuVe; + startEdg = nextEdge; + + if( aF.size() == 0 ) + { + if( nextEdge != originalStartEdge ) + { + UG_THROW("Gesichter leer, aber keine Anfangsecke gefunden" << std::endl); + } + else + { + break; // while loop zu Ende, raus aus dem while loop, den Rest nicht mehr machen, würde schief gehen zwingendermassen + } + + } + + + // TODO FIXME bleibt noch das nächste Gesicht heraus zu finden, dafür kommt eigentlich nur noch eines in Frage, da das zweite Gesicht vom edge + // geloescht sein muss in aF, es muss das einzig übrige face sein, das die jetzt start edge enthält, davon darf es nur eines geben, wir löschen aber noch nicht + + IndexType nextFaceFound = 0; + + for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ ) + { + Face * iFa = *itFac; + + if( FaceContains(iFa, startEdg ) ) + { + nextFaceFound++; + } + } + + if( nextFaceFound != 1 ) + { + UG_THROW("folgendes Gesicht in falscher Anztahl gefunden " << nextFaceFound << std::endl); + } + + for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ ) + { + Face * iFa = *itFac; + + if( FaceContains(iFa, startEdg ) ) + { +// aF.erase(itFac); + startFace = iFa; + break; + } + } + + + } + + if( vVFT.size() != 0 ) + { + UG_THROW("not all triples found! " << std::endl); + } + + if( aF.size() != 0 ) + UG_THROW("not all faces found " << std::endl); + + if( startEdg != originalStartEdge ) + { + UG_THROW("wir sind nicht am Anfang wieder angekommen" << std::endl); + } + + if( 2 * numFracsCrossAtVrt != countedCrossingFracEdgs ) + { + + UG_LOG("gezaehlt und nicht gleiche Kreuzungszahl " << numFracsCrossAtVrt << " " << countedCrossingFracEdgs << std::endl); + +// return true; + + UG_THROW("gezaehlt und nicht gleiche Kreuzungszahl" << std::endl); + } + + if( segmentPart.size() != 0 ) + { + UG_THROW("die Segmentteile muessen alle verarbeitet sein" << std::endl); + } + + UG_LOG("Kreislauf geschlossen" << std::endl); + + + // test if the segments and their partition produce sumething useful, for debug purposes + + // bis hier vermutlich sinnvoll + + // als nächstes muss man die Klassen von durch Klüften abgetrennten ordered Faces durchgehen, und die Verschiebevertizes erzeugen + // als nächstes die verschiedenen Sektionen durch gehen, eventuell nochmal extra Objekte dafür erzeugen + // oder gleich beim Durchgehen die neuen Vertizes erzeugen, Startsignal durch ein Face mit erster Edge KLuft, und dann die nächste + // Kluftedge finden, egal ob vom gleihen face oder von einem späteren face im kreis + + // now figure out to which face this next edge belongs, and if this is a fracture edge, then we have the triple and the normal info + // else we let the normal zero + + // figure out if second edge is also frac edge, i.e. if it belongs to an edge of the remaining vVFT elements + // first easily asking if it is marked as frac edge, simplifies research + + // in principle from here on need to loop through all triples and through all faces, find out some way to construct next edge and to + // build one element after the other of the ordered faces vector, still even the first element is not completed + + // TODO FIXME kreuzende Fractures im Innenraum -> Arte in Reinform implementieren + // later assign somehow next edge to start edge, or use new variable, when we have figured out next face + // at end, chech if we have arrived again at original first edge + + + +// if( !sndEdgIsFracEdgeAlso ) +// { +// ; // normal remains zero vector +// }sh + + int totalSubsNum = sh.num_subsets(); + +// int newSubsToAdd = totalSubsNum; + +// for( VertexOfFaceInfo const & vertFracInfo : orderedFaces ) +// { +//// Face * fa = vertFracInfo.getFace(); +//// +//// sh.assign_subset(fa,newSubsToAdd++); +// } + + number totAnglsEdg = 0; + number totAnglsNrm = 0; + + for( VecVertexOfFaceInfo const & segPart : segments ) + { +// newSubsToAdd++; + + IndexType numbTriangs = segPart.size(); + + if( numbAttTripl == 0 ) + { + UG_THROW("zu wenig Dreiecke " << std::endl); + } + + VertexOfFaceInfo const & vFISBegin = segPart[0]; + VertexOfFaceInfo const & vFISEnd = segPart[numbTriangs-1]; + + std::pair edgesBegin = vFISBegin.getEdge(); + std::pair edgesEnd = vFISEnd.getEdge(); + + std::pair normalBegin = vFISBegin.getNormal(); + std::pair normalEnd = vFISEnd.getNormal(); + + Edge* edgeFracOne = edgesBegin.first; + Edge* edgeFracTwo = edgesEnd.second; + + vector3 normalFracOne = normalBegin.first; + vector3 normalFracTwo = normalEnd.second; + +// sh.assign_subset(edgeFracOne, newSubsToAdd); +// +// if( edgeFracTwo != originalStartEdge ) +// sh.assign_subset(edgeFracTwo, newSubsToAdd); + +// vertFracInfoSeg const & vFISBeg = + + // neue Punkte erzeugen + + number cosBetweenNormals = VecDot( normalFracOne, normalFracTwo ); + + // create normal vectors into direction of relevant edges + + vector3 alongEdgeOne; + vector3 alongEdgeTwo; + + Vertex * vrtEdgeOneBegin = NULL; + Vertex * vrtEdgeTwoBegin = NULL; + Vertex * vrtEdgeOneEnd = NULL; + Vertex * vrtEdgeTwoEnd = NULL; + + + for( size_t i = 0; i < 2; ++i ) + { + Vertex * vrtFromEdgeOne = edgeFracOne->vertex(i); + Vertex * vrtFromEdgeTwo = edgeFracTwo->vertex(i); + + if( vrtFromEdgeOne == *iterV ) + { + vrtEdgeOneBegin = vrtFromEdgeOne; + } + else + { + vrtEdgeOneEnd = vrtFromEdgeOne; + } + + if( vrtFromEdgeTwo == *iterV ) + { + vrtEdgeTwoBegin = vrtFromEdgeTwo; + } + else + { + vrtEdgeTwoEnd = vrtFromEdgeTwo; + } + + } + + if( vrtEdgeOneBegin == NULL || vrtEdgeTwoBegin == NULL || vrtEdgeOneEnd == NULL || vrtEdgeTwoEnd == NULL ) + { + UG_THROW("lauter Nullen vertizes" << std::endl); + } + + vector3 fracVrtPos = aaPos[*iterV]; + + vector3 fracEdgOneEndPos = aaPos[ vrtEdgeOneEnd ]; + vector3 fracEdgTwoEndPos = aaPos[ vrtEdgeTwoEnd ]; + + vector3 directionEdgOne; + VecSubtract(directionEdgOne, fracEdgOneEndPos, fracVrtPos); + + vector3 directionEdgTwo; + VecSubtract(directionEdgTwo, fracEdgTwoEndPos, fracVrtPos); + + vector3 nrmdVecEdgOne; + VecNormalize(nrmdVecEdgOne, directionEdgOne); + + vector3 nrmdVecEdgTwo; + VecNormalize(nrmdVecEdgTwo, directionEdgTwo); + + number cosBetweenEdges = VecDot(nrmdVecEdgOne,nrmdVecEdgTwo); + + number angleEdges = std::acos( cosBetweenEdges ); + number angleNormls = std::acos( cosBetweenNormals ); + + totAnglsEdg += angleEdges; + totAnglsNrm += angleNormls; + + UG_LOG("cosinus Edges Normals " << cosBetweenEdges << " " << cosBetweenNormals << std::endl); + UG_LOG("angles edges normals " << angleEdges << " " << angleNormls << std::endl); + + // prject normal 1 onto edge 2 and normal 2 on edge 1, scale with width one half resp with width two half + + + number cosBetweenNrmFraOneEdgTwo = VecDot(normalFracOne,nrmdVecEdgTwo); + number cosBetweenNrmFraTwoEdgOne = VecDot(normalFracTwo,nrmdVecEdgOne); + + vector3 projectNrmFraOneToEdgTwoDirection; + VecScale(projectNrmFraOneToEdgTwoDirection, nrmdVecEdgTwo, 1./cosBetweenNrmFraOneEdgTwo); + + vector3 projectNrmFraTwoToEdgOneDirection; + VecScale(projectNrmFraTwoToEdgOneDirection, nrmdVecEdgOne, 1./cosBetweenNrmFraTwoEdgOne); + + auto subsIndFracOne = sh.get_subset_index(edgeFracOne); + auto subsIndFracTwo = sh.get_subset_index(edgeFracTwo); + + number shiftOne = fracInfosBySubset.at( subsIndFracOne ).width / 2. ; + number shiftTwo = fracInfosBySubset.at( subsIndFracTwo ).width / 2. ; + + vector3 shiftAlongEdgeTwo; + VecScale(shiftAlongEdgeTwo, projectNrmFraOneToEdgTwoDirection, shiftOne); + + vector3 shiftAlongEdgeOne; + VecScale(shiftAlongEdgeOne, projectNrmFraTwoToEdgOneDirection, shiftTwo); + + vector3 shiftPart; + VecAdd(shiftPart, fracVrtPos, shiftAlongEdgeTwo); + + vector3 posNewVrt; + VecAdd( posNewVrt, shiftPart, shiftAlongEdgeOne); + + UG_LOG("neuer Vertex Kreuzung " << posNewVrt << std::endl ); + + Vertex * newShiftVrtx = *grid.create(); + aaPos[newShiftVrtx] = posNewVrt; + +// sh.assign_subset(newShiftVrtx, newSubsToAdd ); + + + for( VertexOfFaceInfo const & vertFracInfoSeg : segPart ) + { + Face * fac = vertFracInfoSeg.getFace(); + +// sh.assign_subset(fa,newSubsToAdd); + + + // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! + vector& newVrts4Fac = aaVrtVecFace[ fac ]; + + IndexType vrtxFnd = 0; + + for(size_t indVrt = 0; indVrt < (fac)->num_vertices(); indVrt++ ) + { + Vertex* facVrt = (fac)->vertex(indVrt); + + if( facVrt == *iterV ) + { + newVrts4Fac[ indVrt ] = newShiftVrtx; + vrtxFnd++; + } + } + + + if( vrtxFnd <= 0 ) + { + UG_THROW("vertex not found kreuzung!" << std::endl); + } + else if( vrtxFnd > 1 ) + { + UG_THROW("vertex zu oft gefunden kreuzung " << vrtxFnd << std::endl ); + } + else if ( vrtxFnd == 1 ) + { + } + else + { + UG_THROW("vertex finden komisch kreuzung " << std::endl); + } + + } + } + + UG_LOG("sum angles edges normals " << totAnglsEdg << " " << totAnglsNrm << std::endl); + +// return true; + +#if 0 + // das folgende ist vermutlich Unsinn TODO FIXME, waren wohl Versuche am Anfang..... nochmal prüfen!!!! + + // get starting point of the "rotation" around the vertex where fractures are crossing +// for( auto & attVFT : vVFT ) // not const, as we need to erase found elements! + for( VecVertFracTrip::iterator itAttVFT = vVFT.begin(); itAttVFT != vVFT.end(); ) + { + Face * facAtVrtWithFrac = itAttVFT->getFace(); + + bool facFound = false; + +// for( auto const & ifac : assoFaces ) // not const, as we need to erase found elements! + for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); ) + { + if( *itFac == facAtVrtWithFrac ) + { + // found a starting face + // copy first the found info, then delete the original one + auto attVFTCop = *itAttVFT; // copy, not reference! + + vVFT.erase(itAttVFT); + aF.erase(itFac); + + // TODO FIXME erase ifac and attVFT, how to do? + + Face * startFace = facAtVrtWithFrac; + + // now determine the common edge(s), the first edge of the vector must be a frac edge, the second one might be one + + Edge * startEdg = attVFTCop.getEdge(); + + // unnecessary check, but for test purposes at beginning, later should be removed + if( !FaceContains(facAtVrtWithFrac, startEdg )) + { + UG_THROW("face hat ecke nicht, die es haben soll" << std::endl); + } + + // loop around the edges of the ifac face attached to the vertex + + // determin second edge of the startFace, not stored in the vecVertFracTrip information + // check number of common edges containing the same vertex + + IndexType fndCommEdg = 0; + std::vector assoEdg2Fac; + + assoEdg2Fac.push_back( startEdg ); + + std::vector assoNorm; + + vector3 norm2Frac = attVFTCop.getNormal(); + + Edge * secondEdge; + secondEdge = NULL; + + for( auto const & iE : allAssoEdges ) // werden nicht gelöscht, deswegen Zugriff auf attachment direkt + { + if( FaceContains(facAtVrtWithFrac, iE) ) + { + fndCommEdg++; + if( iE != startEdg ) + { + secondEdge = iE; + } + } + + if( fndCommEdg != 2 ) + { + UG_THROW("komische Anzahl gemeinsamer Ecke " << fndCommEdg << std::endl); + } + + if( secondEdge == NULL ) + { + UG_THROW("wieso keine zweite Ecke gefunden???? " << std::endl); + } + + assoEdg2Fac.push_back(secondEdge); + + // check, if second edge belongs to anothter fracture fac, i.e. if it is also a fracture edge + + // check if second edge is edge of a fracture face, i.e. either this edge, or another one is from a fracture + + bool scndEdgIsFracEdg = aaMarkEdgeB[secondEdge]; + + if( scndEdgIsFracEdg ) + { + // TODO FIXME figure out second vertex fracture info, in this case, we have found the next part of the chain! + + for( VecVertFracTrip::iterator itAttVFTTwo = vVFT.begin(); itAttVFTTwo != vVFT.end(); ) + { + // need to erase also this element soon, also in the list of all attached elements + + Face* vFTTwoFac = itAttVFTTwo->getFace(); + + if( FaceContains( vFTTwoFac, secondEdge)) + { + auto vVFT2 = *itAttVFTTwo; + vVFT.erase( itAttVFTTwo ); + + Face * nextFace = vFTTwoFac; + + if( secondEdge != vVFT2.getEdge() ) + { + UG_THROW("Ecke nicht Ecke " << std::endl); + } + + + } + } + } + else // find the next attached face, either from the + { + + } + } + + break; + } + + if( ! facFound ) + { + UG_THROW("Gesicht unauffindbar" << std::endl); + } + + break; + } + } + + while( vVFT.size() != 0 ) + { + while( aF.size() != 0 ) + { + + } + } + +#endif + + + } + + } +// // // different treatment for boundary vertizes + else + { + + // TODO FIXME es muss wohl noch ein Problem mit den Verschiebungen bei boundary Vertizes geben..... + // TODO FIXME XXXXXXXXXXXXXX hier sind wir + + + if( numFracsCrossAtVrt < 1 ) + { + UG_THROW("no fracs crossing but marked vertex at boundary? << std::endl"); + } + + if( numFracsCrossAtVrt == 1 ) // no crossing point at boundary + { + // in this case, we have ONE attached edges, the edges has two attached faces + // the faces have a naormal, and based on the normal, we can decide which faces belong to the same side of the edges + + if( numbAttTripl != 2 ) + { + UG_THROW("Anzahl der angehaengten Triples kann nicht stimmen, Vertex einer Kluft ohne Schnittpunkte am Rand " << std::endl); + } + + // Zuordnung der Edges und Faces, die auf der gleichen Seite der fracture sind + + // und gleich auch Erzeugung der neuen Knoten, die dann + // in einem Doublett zusammen mit ihren Normalen an die alten Vertizes + // angehängt werden; der Winkel zur Normalen hilft später, die Seite + // heraus zu finden, Seite von den Edges + + // get edges adjacent to this vertex which lie on the boundary of the domain + + std::vector adjBndEdgs; + +// std::vector & allAssoEdges = aaVrtInfoAssoEdges[*iterV]; + +// for( std::vector::iterator iterBVEdg = grid.associated_edges_begin(*iterV); iterBVEdg != grid.associated_edges_end(*iterV); iterBVEdg++ ) +// { +// if( IsBoundaryEdge2D(grid,*iterBVEdg) ) +// { +// adjBndEdgs.push_back( *iterBVEdg ); +// } +// } + for( auto const & iBVE : allAssoEdges ) + { + if( IsBoundaryEdge2D(grid, iBVE ) ) + { + adjBndEdgs.push_back( iBVE ); + } + } + + // to compute the normals, compute the vector of the edge and normalize it + std::vector bndEdgeDirection; + + for( auto const & bE : adjBndEdgs ) + { + + // get vertices, i.e. get seocnd vertex, first one must be known + +// std::vector verticesEdg; + + static_assert( std::is_same< Edge* const &, decltype( bE ) >::value ); + + static_assert( std::is_same< Vertex*, decltype( bE->vertex(0) ) >::value ); + + IndexType fndIV = 0; + + Vertex * vrtOtherEdg; + vrtOtherEdg = NULL; + + for( size_t i = 0; i < 2; ++i ) + { +// verticesEdg.push_back( adjBndEdgs.vertex(i) ); + + Vertex * vrtOfEdg = bE->vertex(i); + + if( vrtOfEdg == *iterV ) + { + fndIV++; + } + else + { + vrtOtherEdg = vrtOfEdg; + } + } + + vector3 posOtherVrt = aaPos[vrtOtherEdg]; + + UG_LOG("BOUNDARY EDGE VERTIZES " << posOldVrt << ", " << posOtherVrt << std::endl); + + vector3 fromIterV2Other; + + VecSubtract(fromIterV2Other, posOtherVrt, posOldVrt); + + vector3 nV; + + VecNormalize(nV, fromIterV2Other); + + bndEdgeDirection.push_back(nV); + } + + + +#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX + + IndexType dbg_lim = vecVertFracTrip.size(); + + int dbg_cnt = 0; +#endif + + for( VvftIterator vvftAtBnd = vecVertFracTrip.begin(); + vvftAtBnd != vecVertFracTrip.end(); + vvftAtBnd++ + ) + { +#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX + + if( dbg_lim == dbg_cnt ) + { + UG_LOG("DARF NICHT SEIN" << std::endl); + break; + } + + dbg_cnt++; +#endif + + // Ziel: den parallelen Anteil der Normalen auf die jeweilige Randkante projizieren + + vector3 nrmEdg = vvftAtBnd->getNormal(); + + Edge * edgeOfFrac = vvftAtBnd->getEdge(); + + // figure out the adjoint boundary edge into the same direction + + // the normal in both directions have to be compared with the vectors in direction of boundary edges + for( auto bED : bndEdgeDirection ) + { + // check orientation of boundary edges wrt the normals + + number cosinus = VecDot( nrmEdg, bED ); + + UG_LOG("BOUNDARY COSINUS between " << nrmEdg << " and " << bED << " -> " << cosinus << std::endl); + + if( cosinus > 0 ) + { + // gleiche Seite vermutet + + // muessen wissen, wie lange das gestreckt werden soll + + vector3 alongEdgV; + + auto subsIndEdgOF = sh.get_subset_index(edgeOfFrac); + + number width = fracInfosBySubset.at(subsIndEdgOF).width; + + number scal = width / 2. / cosinus; + + VecScale( alongEdgV, bED, scal ); + + vector3 posNewVrtOnBnd; + + VecAdd(posNewVrtOnBnd, posOldVrt, alongEdgV ); + + UG_LOG("neuer Vertex Edge " << posNewVrtOnBnd << std::endl ); + + Vertex * newShiftEdgVrtx = *grid.create(); + aaPos[newShiftEdgVrtx] = posNewVrtOnBnd; + + sh.assign_subset(newShiftEdgVrtx, subsIndEdgOF ); + + std::vector attEdg; + std::vector attFac; + + attEdg.push_back(edgeOfFrac); + + Face * facFrac = vvftAtBnd->getFace(); + + attFac.push_back( facFrac ); + + // we store the boundary edge direction for boundary verzizes rather than the normal, in contrast to inner vertizes, where we store the averaged normal + ExpandVertexMultiplett vrtMtpl( attEdg, attFac, bED ); + + aaVrtExpMP[ *iterV ].push_back( vrtMtpl ); + +#if 0 + // the attached faces need to know that they need a new vertex to be shifted + for( std::vector::iterator iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ ) + { + bool isFromFrac = false; + + for( auto const & facFrac : attFac ) + { + if( *iterFac == facFrac ) + { + isFromFrac = true; + } + } + + bool atRightSide = false; + + if( isFromFrac ) + atRightSide = true; + + if( !isFromFrac ) + { + + // check if on same side of edge where the normal points to: compute cosinus between vector of face center + // perpendicular to the edge + // TODO FIXME + + vector3 facCenter = CalculateCenter( *iterFac, aaPos ); + + vector3 perpendicu; + + DropAPerpendicular(perpendicu, facCenter, aaPos[edgeOfFrac->vertex(0)], aaPos[edgeOfFrac->vertex(1)]); + + vector3 tmpN; + + VecSubtract(tmpN, facCenter, perpendicu ); + + VecNormalize(tmpN, tmpN); + + UG_LOG("Normale Boundary zum Face ist " << tmpN << std::endl); + + number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, nrmEdg ); + + UG_LOG("Cosinus Boundary zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); + + if( cosBetwFracEdgAndDirection2Face > 0 ) + { + UG_LOG("assuming boundary face to be on richt side" << std::endl); + + atRightSide = true; + +#if ANSCHAULICH_ERZEUGE_SUDOS_ANHANG + Vertex * otherFacCent = *grid.create(); + aaPos[otherFacCent] = facCenter; + sh.assign_subset(otherFacCent, 5 ); + + Vertex * pp = *grid.create(); + aaPos[pp] = perpendicu; + sh.assign_subset(pp, 6 ); + + sh.assign_subset(*iterFac,7); +#endif + + + } + else + { + UG_LOG("assuming boundary face to be on wrong side" << std::endl); + } + + } + + if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein + { + + + vector& newVrts4Fac = aaVrtVecFace[ * iterFac ]; + + IndexType vrtxFnd = 0; + + for(size_t indVrt = 0; indVrt < (*iterFac)->num_vertices(); indVrt++ ) + { + Vertex* facVrt = (*iterFac)->vertex(indVrt); + + if( facVrt == *iterV ) + { + newVrts4Fac[ indVrt ] = newShiftEdgVrtx; + vrtxFnd++; + } + } + + + + if( vrtxFnd <= 0 ) + { + UG_THROW("vertex not found bnd!" << std::endl); + } + else if( vrtxFnd > 1 ) + { + UG_THROW("vertex zu oft gefunden bnd " << vrtxFnd << std::endl ); + } + else if ( vrtxFnd == 1 ) + { +// UG_LOG("vertex found abgeschlossen" << std::endl); + } + else + { + UG_THROW("vertex finden bnd komisch " << std::endl); + } + } + + } +#else + for( auto const & ifac : assoFaces ) + { + bool isFromFrac = false; + + for( auto const & facFrac : attFac ) + { + if( ifac == facFrac ) + { + isFromFrac = true; + } + } + + bool atRightSide = false; + + if( isFromFrac ) + atRightSide = true; + + if( !isFromFrac ) + { + + // check if on same side of edge where the normal points to: compute cosinus between vector of face center + // perpendicular to the edge + // TODO FIXME + + vector3 facCenter = CalculateCenter( ifac, aaPos ); + + vector3 perpendicu; + + DropAPerpendicular(perpendicu, facCenter, aaPos[edgeOfFrac->vertex(0)], aaPos[edgeOfFrac->vertex(1)]); + + vector3 tmpN; + + VecSubtract(tmpN, facCenter, perpendicu ); + + VecNormalize(tmpN, tmpN); + + UG_LOG("Normale Boundary zum Face ist " << tmpN << std::endl); + + number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, nrmEdg ); + + UG_LOG("Cosinus Boundary zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); + + if( cosBetwFracEdgAndDirection2Face > 0 ) + { + UG_LOG("assuming boundary face to be on richt side" << std::endl); + + atRightSide = true; + +#if ANSCHAULICH_ERZEUGE_SUDOS_ANHANG + Vertex * otherFacCent = *grid.create(); + aaPos[otherFacCent] = facCenter; + sh.assign_subset(otherFacCent, 5 ); + + Vertex * pp = *grid.create(); + aaPos[pp] = perpendicu; + sh.assign_subset(pp, 6 ); + + sh.assign_subset(*iterFac,7); +#endif + + + } + else + { + UG_LOG("assuming boundary face to be on wrong side" << std::endl); + } + + } + + if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein + { + + + vector& newVrts4Fac = aaVrtVecFace[ ifac ]; + + IndexType vrtxFnd = 0; + + for(size_t indVrt = 0; indVrt < (ifac)->num_vertices(); indVrt++ ) + { + Vertex* facVrt = (ifac)->vertex(indVrt); + + if( facVrt == *iterV ) + { + newVrts4Fac[ indVrt ] = newShiftEdgVrtx; + vrtxFnd++; + } + } + + + + if( vrtxFnd <= 0 ) + { + UG_THROW("vertex not found bnd!" << std::endl); + } + else if( vrtxFnd > 1 ) + { + UG_THROW("vertex zu oft gefunden bnd " << vrtxFnd << std::endl ); + } + else if ( vrtxFnd == 1 ) + { +// UG_LOG("vertex found abgeschlossen" << std::endl); + } + else + { + UG_THROW("vertex finden bnd komisch " << std::endl); + } + } + } + +#endif + + + + } + } + } + + } + else // fractures are crossing at boundary even + { + + } + + + UG_LOG("END THIS BOUNDARY VERTEX" << std::endl); + } + + dbg_vertizesPassiert++; + + } + + +// // neue Vertizes in der Entfernung der Klüfte von den Klüften weg erzeugen, +// // basierend auf den Normalen multipliziert mit der halben Kluftdicke +// //für eine Kluft erstmal nur +// // die neuen Kanten und Faces erzeugen, die alten falschen Kanten löschen und ebenso die alten Faces +// // später auf mehr Klüfte ausdehnen, mit Problemstelle Kreuzung, aber erst, wenn eine Kluft funktioniert +// + + // jetzt Seb Sachen beinahe unverändert + + //////////////////////////////// + // create new elements + + // first we create new edges from selected ones which are connected to + // inner vertices. This allows to preserve old subsets. + // Since we have to make sure that we use the right vertices, + // we have to iterate over the selected faces and perform all actions on the edges + // of those faces. + for(FaceIterator iter_sf = sel.faces_begin(); iter_sf != sel.faces_end(); ++iter_sf) + { + Face* sf = *iter_sf; + // check for each edge whether it has to be copied. + for(size_t i_edge = 0; i_edge < sf->num_edges(); ++i_edge) + { + Edge* e = grid.get_edge(sf, i_edge); + + if(sel.is_selected(e)) + { + // check the associated vertices through the volumes aaVrtVecVol attachment. + // If at least one has an associated new vertex and if no edge between the + // new vertices already exists, we'll create the new edge. + size_t ind0 = i_edge; + size_t ind1 = (i_edge + 1) % sf->num_edges(); + + Vertex* nv0 = (aaVrtVecFace[sf])[ind0]; + Vertex* nv1 = (aaVrtVecFace[sf])[ind1]; + + if(nv0 || nv1) + { + // if one vertex has no associated new one, then we use the vertex itself + if(!nv0) + nv0 = sf->vertex(ind0); + if(!nv1) + nv1 = sf->vertex(ind1); + + // create the new edge if it not already exists. + if(!grid.get_edge(nv0, nv1)) + grid.create_by_cloning(e, EdgeDescriptor(nv0, nv1), e); + } + } + } + } + + std::vector newFaces; + std::vector subsOfNewFaces; + + // iterate over all surrounding faces and create new vertices. + // Since faces are replaced on the fly, we have to take care with the iterator. + for(FaceIterator iter_sf = sel.faces_begin(); iter_sf != sel.faces_end();) + { + Face* sf = *iter_sf; + ++iter_sf; + + vector newVrts = aaVrtVecFace[sf]; + + // all new vertices have been assigned to newVrts. + // Note that if newVrts[i] == NULL, then we have to take the + // old vertex sf->vertex(i). + // now expand the fracture edges of sf to faces. + for(size_t i_vrt = 0; i_vrt < sf->num_vertices(); ++i_vrt) + { + size_t iv1 = i_vrt; + size_t iv2 = (i_vrt + 1) % sf->num_vertices(); + + Edge* tEdge = grid.get_edge(sf->vertex(iv1), sf->vertex(iv2)); + + if(tEdge) + { + if( aaMarkEdgeB[tEdge] ) + { + Face* expFace = NULL; + if(newVrts[iv1] && newVrts[iv2]) + { + // create a new quadrilateral + expFace = *grid.create( + QuadrilateralDescriptor(sf->vertex(iv1), sf->vertex(iv2), + newVrts[iv2], newVrts[iv1])); + } + else if(newVrts[iv1]) + { + // create a new triangle + expFace = *grid.create( + TriangleDescriptor(sf->vertex(iv1), sf->vertex(iv2), newVrts[iv1])); + } + else if(newVrts[iv2]) + { + // create a new triangle + expFace = *grid.create( + TriangleDescriptor(sf->vertex(iv1), sf->vertex(iv2), newVrts[iv2])); + } + else + { + // this code-block should never be entered. If it is entered then + // we selected the wrong faces. This is would be a BUG!!! + // remove the temporary attachments and throw an error + + // remove the temporary attachments +#if OLD_PROFREITER_STUFF + grid.detach_from_vertices(aAdjMarker); + grid.detach_from_edges(aAdjMarker); +#endif + grid.detach_from_vertices(aAdjMarkerVFP); + grid.detach_from_edges(aAdjMarkerB); + + grid.detach_from_vertices( aAdjInfoAVVFT ); + grid.detach_from_faces(attVrtVec); + + grid.detach_from_vertices( aAdjInfoEdges ); + grid.detach_from_vertices( aAdjInfoFaces ); + + + // TODO FIXME auch die weiteren Marker und INfos, alle Attachments, detachen!!!! + + throw(UGError("Implementation error in ExpandFractures2d Arte.")); + } + + // TODO FIXME selektion closen irgendwie, damit auch alle Randkanten zum subset gehoeren!!! + + sh.assign_subset(expFace, fracInfosBySubset.at(sh.get_subset_index(tEdge)).newSubsetIndex); + + int subs = fracInfosBySubset.at(sh.get_subset_index(tEdge)).newSubsetIndex; + + subsOfNewFaces.push_back( subs ); + + newFaces.push_back( expFace ); + } + } + } + + + + + // now set up a new face descriptor and replace the face. + if(fd.num_vertices() != sf->num_vertices()) + fd.set_num_vertices(sf->num_vertices()); + + for(size_t i_vrt = 0; i_vrt < sf->num_vertices(); ++i_vrt) + { + if(newVrts[i_vrt]) + fd.set_vertex(i_vrt, newVrts[i_vrt]); + else + fd.set_vertex(i_vrt, sf->vertex(i_vrt)); + } + + grid.create_by_cloning(sf, fd, sf); + grid.erase(sf); + } + + // we have to clean up unused edges. + // All selected edges with mark 0 have to be deleted. + for(EdgeIterator iter = sel.edges_begin(); iter != sel.edges_end();) + { + // be careful with the iterator + Edge* e = *iter; + ++iter; + + if(!aaMarkEdgeB[e]) + grid.erase(e); + } + + if( subsOfNewFaces.size() != newFaces.size() ) + { + UG_THROW("andere zahl neue faces als subdoms " << std::endl); + } + + IndexType nfn = 0; + + for( auto const & nf : newFaces ) + { + for(size_t i_edge = 0; i_edge < nf->num_edges(); ++i_edge) + { + Edge* edg = grid.get_edge(nf, i_edge); + + sh.assign_subset( edg, subsOfNewFaces[nfn] ); + } + + nfn++; + } + + // TODO FIXME sollen die Boundary Edges zur boundary gehören, oder zur Kluft? + // TODO FIXME wie ist es mit den Knoten, sind die alle richtig zugewiesen bezüglich subset? + + // remove the temporary attachments + +#if OLD_PROFREITER_STUFF + grid.detach_from_vertices(aAdjMarker); + grid.detach_from_edges(aAdjMarker); +#endif + grid.detach_from_vertices(aAdjMarkerVFP); + grid.detach_from_edges(aAdjMarkerB); + + grid.detach_from_vertices( aAdjInfoAVVFT ); + grid.detach_from_faces(attVrtVec); + + grid.detach_from_vertices( aAdjInfoEdges ); + grid.detach_from_vertices(aAdjInfoFaces ); + + + // TODO FIXME alles detachen, was noch attached ist, da ist einiges hinzu gekommen! + + + return true; + + // ENDE NEUES ZEUG SELEKTION + + + + + + + +#if OLD_PROFREITER_STUFF + // TODO FIXME von diesem Loop kann man noch für oben die calculate crease normal lernen, vielleicht minimal abgewandelt, vielleicht exakt gleich + + // a callback that returns true if the edge is a fracture edge, neues System + AttachmentUnequal > isFracEdgeB(aaMarkEdgeB, false); + + // iterate over all surrounding faces and create new vertices. + for(FaceIterator iter_sf = sel.faces_begin(); iter_sf != sel.faces_end(); ++iter_sf) + { + Face* sf = *iter_sf; + + // check for each vertex whether it lies in the fracture + // (aaMarkVRT > 1 in this case) + // if so, we have to copy or create a vertex from/in aaVrtVec[vrt] which is + // associated with the crease normal on the side of sf. + for(size_t i_vrt = 0; i_vrt < sf->num_vertices(); ++i_vrt) + { + Vertex* vrt = sf->vertex(i_vrt); + if(aaMarkVRT[vrt] > 1) + { + // calculate the normal on this side of the frac + // TODO FIXME so eine Funktion brauchen wir vielleicht oben auch zur Vereinfachung des Codes!!! + vector3 n_v2 = CalculateCreaseNormal(grid, sf, vrt, isFracEdgeB, aaPos); + // das calculate crease normal scheint mir ein Schwachsinn zu sein + // aber vielleicht doch nicht? + + UG_LOG("calculated crease normal v2: " << n_v2 << endl); + + } + } +#endif + + + + + + + +} + + + /** Selects all involved geometic objects and assigns marks to them. * If required, som edges may be split, so that we always operate * on a fully expandable fracture. diff --git a/ugbase/lib_grid/algorithms/extrusion/expand_layers.h b/ugbase/lib_grid/algorithms/extrusion/expand_layers.h index 667d6e359..6819d60c7 100644 --- a/ugbase/lib_grid/algorithms/extrusion/expand_layers.h +++ b/ugbase/lib_grid/algorithms/extrusion/expand_layers.h @@ -75,6 +75,14 @@ bool ExpandFractures2d(Grid& grid, SubsetHandler& sh, const std::vector& fracInfos, bool expandInnerFracBnds, bool expandOuterFracBnds); +/** + * 2 dimensional fracture expansion for finite extensions, using the Arte algorithm + * + */ +bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, + const std::vector& fracInfos, + bool expandInnerFracBnds, bool expandOuterFracBnds); + /** * This algorithm indirectly uses Grid::mark. diff --git a/ugbase/lib_grid/file_io/file_io_vtu.cpp b/ugbase/lib_grid/file_io/file_io_vtu.cpp index cd9fa2577..ac8ee9d5b 100644 --- a/ugbase/lib_grid/file_io/file_io_vtu.cpp +++ b/ugbase/lib_grid/file_io/file_io_vtu.cpp @@ -31,6 +31,8 @@ */ #include "file_io_vtu.h" +#include +#include using namespace std; using namespace rapidxml; @@ -411,7 +413,8 @@ GridReaderVTU::~GridReaderVTU() { } - +#if 0 +// original function bool GridReaderVTU:: parse_file(const char* filename) { @@ -442,6 +445,81 @@ parse_file(const char* filename) // notify derived classes that a new document has been parsed. return new_document_parsed(); } +#else + +bool GridReaderVTU:: +parse_file(const char* filename) +{ + ifstream in(filename, ios::binary); + if(!in) + return false; + + m_filename = filename; + +// get the length of the file + streampos posStart = in.tellg(); + in.seekg(0, ios_base::end); + streampos posEnd = in.tellg(); + streamsize size = posEnd - posStart; + +// go back to the start of the file + in.seekg(posStart); + + char * fileContentOriginal = new char[size + 1]; + + in.read(fileContentOriginal,size); + fileContentOriginal[size] = 0; + in.close(); + + std::string fiCo2Str(fileContentOriginal); + + delete [] fileContentOriginal; + fileContentOriginal = NULL; + + std::string regInf("RegionInfo"); + + if ( fiCo2Str.find(regInf) == std::string::npos && fiCo2Str.find(m_regionOfInterest) != std::string::npos ) + { + // we need to insert the additional string + + std::string regInfLines; + + regInfLines.append( "\n\n"); + + regInfLines.append( "" ); + + std::string insAft( "" ); + + size_t cedava = fiCo2Str.find( insAft ); + + if( cedava == std::string::npos ) + return false; + + size_t insVal = cedava + insAft.size(); + + fiCo2Str.insert( insVal, regInfLines ); + + } + + char* fileContent = m_doc.allocate_string(0, fiCo2Str.size() ); + + strcpy(fileContent, fiCo2Str.c_str()); + + +// parse the xml-data + m_doc.parse<0>(fileContent); + +// notify derived classes that a new document has been parsed. + return new_document_parsed(); +} + +#endif + + bool GridReaderVTU:: new_document_parsed() @@ -461,6 +539,7 @@ new_document_parsed() m_entries.push_back(GridEntry(curNode)); GridEntry& gridEntry = m_entries.back(); + // collect associated subset handlers xml_node<>* curSHNode = curNode->first_node("RegionInfo"); while(curSHNode){ @@ -569,6 +648,14 @@ subset_handler(ISubsetHandler& shOut, vector subsetIndices; read_scalar_data(subsetIndices, regionDataNode, true); + if( subsetIndices.size() != cells.size() ) + { + vector subsetIndicesDbl; + read_scalar_data(subsetIndicesDbl, regionDataNode, true); + + trafoDblVec2Int( subsetIndicesDbl, subsetIndices ); + } + UG_COND_THROW(subsetIndices.size() != cells.size(), "Mismatch regarding number of cells and number of region-indices!"); @@ -772,6 +859,17 @@ create_cells(std::vector& cellsOut, return true; } +void GridReaderVTU:: +trafoDblVec2Int( std::vector const & dblVec, std::vector & intVec ) +{ + intVec = std::vector(); + + for( auto d : dblVec ) + { + intVec.push_back( static_cast( d ) ); + } +} + xml_node<>* GridReaderVTU:: find_child_node_by_argument_value(rapidxml::xml_node<>* parent, diff --git a/ugbase/lib_grid/file_io/file_io_vtu.h b/ugbase/lib_grid/file_io/file_io_vtu.h index 3aa18aa3d..a02aaaa84 100644 --- a/ugbase/lib_grid/file_io/file_io_vtu.h +++ b/ugbase/lib_grid/file_io/file_io_vtu.h @@ -220,6 +220,12 @@ class GridReaderVTU size_t refGridIndex, size_t subsetHandlerIndex); + static std::string const getRegionOfInterestIdentifyer() + { return m_regionOfInterest; } + + static void setRegionOfInterestIdentifier( std::string const & regOfInt ) + { m_regionOfInterest = regOfInt; } + protected: struct SubsetHandlerEntry { @@ -269,6 +275,8 @@ class GridReaderVTU rapidxml::xml_node<>* dataNode, bool clearData = true); + void trafoDblVec2Int( std::vector const & dblVec, std::vector & intVec ); + template void check_indices(std::vector& inds, size_t first, size_t num, size_t max); @@ -286,6 +294,11 @@ class GridReaderVTU /// holds grids which already have been created std::vector m_entries; + + + + inline static std::string m_regionOfInterest = "regions"; // ProMesh standard, in Braunschweig case often "Material Id", but not always + }; }// end of namespace From 75af9e445a8b1c856a450aee61d1c2a44cac19b0 Mon Sep 17 00:00:00 2001 From: Markus Date: Wed, 26 Jun 2024 15:39:49 +0200 Subject: [PATCH 06/58] =?UTF-8?q?Vorbedigung=20f=C3=BCr=20endende=20Kl?= =?UTF-8?q?=C3=BCfte=20innendrin,=20mit=20oder=20ohne=20Kreuzung=20mit=20a?= =?UTF-8?q?nderen=202D=20Fall?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../algorithms/extrusion/expand_layers.cpp | 40 ++++++++++++------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp index 727763ef1..687a6ae30 100644 --- a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp +++ b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp @@ -941,7 +941,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, const vector::value ); bool isBnd = aaMarkVrtVFP[ *iter ].getIsBndFracVertex(); - auto numCrosFrac = aaMarkVrtVFP[ *iter ].getNumberCrossingFracsInVertex(); + auto numCrosFrac = aaMarkVrtVFP[ *iter ].getNumberFracEdgesInVertex(); if( wahl ) { @@ -987,6 +987,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, const vector 1 + else if( numFracsCrossAtVrt == 3 ) + { + // one fracture end point at another facture passing by + // TODO FIXME + } + else // two fractures completely crossing, numFracsCrossAtVrt > 3 { IndexType countedCrossingFracEdgs = 0; @@ -2521,15 +2532,15 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, const vector Date: Wed, 26 Jun 2024 16:53:23 +0200 Subject: [PATCH 07/58] pbs generic scheduler: fix processor and nodes --- scripts/shell/schedulers/pbs-generic | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/shell/schedulers/pbs-generic b/scripts/shell/schedulers/pbs-generic index 6e0299eb7..74170d6b2 100755 --- a/scripts/shell/schedulers/pbs-generic +++ b/scripts/shell/schedulers/pbs-generic @@ -34,7 +34,7 @@ function UJS_Submit # PBSnodes="-l select=$nnodes:node_type=rome:mpiprocs=$nppn" - PBSnodes="" + PBSnodes="-l select=$nnodes:ncpus=$nppn:mpiprocs=$nppn" if [ -z "$queue" ]; then @@ -82,7 +82,7 @@ function UJS_Submit exit fi jobid=`echo $jobid | sed 's/\([0-9]*\).*/\1/'` - fi + fi } From 2ae70d8f3117984fa3377b03d5a6ee4868ff9576 Mon Sep 17 00:00:00 2001 From: Markus Date: Thu, 27 Jun 2024 18:05:01 +0200 Subject: [PATCH 08/58] Einbauen von innerem Kluftende 2D --- .../algorithms/extrusion/expand_layers.cpp | 366 ++++++++++++++++++ 1 file changed, 366 insertions(+) diff --git a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp index 687a6ae30..72646084f 100644 --- a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp +++ b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp @@ -1366,6 +1366,370 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, const vector dbg_laenge ) + { + break; + } + +#endif + + vector3 nV = vvftV->getNormal(); + + Edge * edgeV = vvftV->getEdge(); + + + +#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX + + UG_LOG("NORMAL " << vvftV->getNormal() << std::endl); + UG_LOG("LAENGE EINZ " << dbg_laenge_eins << std::endl ); +#endif + + Vertex * nextFracVrt; + + IndexType foundThisVrt = 0; + + for( size_t i = 0; i < 2; ++i ) + { + Vertex * vrtEdgEnd = edgeV->vertex(i); + + if( vrtEdgEnd == *iterV ) + { + foundThisVrt++; + } + else + { + nextFracVrt = vrtEdgEnd ; + } + + } + + if( foundThisVrt != 1 ) + { + UG_THROW("zu viel zu wenig vertizex one " << std::endl); + } + + + + // Klasse schreiben, die als attachment an einen Fracture-Vertex + // die neuen Vertizes samt ihrer gemittelten Normalen speichert + // also std::vector von dieser neuen Klasse als Vertex attachment + + std::vector attEdg; + std::vector attFac; + + attEdg.push_back( edgeV ); + + Face * facV = vvftV->getFace(); + + attFac.push_back( facV ); + + // jetzt neuen Vertex erzeugen in Richtung der Normalen + // sonst ist das attachment Schwachsinn! + + vector3 posNewVrt; + + vector3 moveVrt; + + auto subsIndEdgV = sh.get_subset_index(edgeV); + + number width = fracInfosBySubset.at(subsIndEdgV).width; + + static constexpr bool expandInnerVertizes = true; + + if( expandInnerVertizes ) + { + // der Faktor ist Käse und muss noch aus den Eingaben übernommen werden + VecScale(moveVrt, nV, width/2. ); + } + else + { + // auf Annes Wunsch hin werden die Normalen innendrin an einer endenen Kluft zu Null gesetzt + + VecScale(moveVrt, nV, 0. ); + + } + + VecAdd(posNewVrt, posOldVrt, moveVrt ); + + UG_LOG("neuer Vertex " << posNewVrt << std::endl ); + + // TODO FIXME hier ist das PROBLEM, SEGFAULT durch create regular vertex + + + + Vertex * newShiftVrtx = *grid.create(); + aaPos[newShiftVrtx] = posNewVrt; + + sh.assign_subset(newShiftVrtx, subsIndEdgV ); + + + + // fuer was braucheh wir das eigentlich? selber schon vergessen..... + + ExpandVertexMultiplett vrtMtpl( attEdg, attFac, nV ); + + aaVrtExpMP[ *iterV ].push_back( vrtMtpl ); + + + + // alle anhängenden faces müssen noch zu wissen bekommen + // dass es diesen neuen Vertex gibt, nicht nur die + // an den edges anhängenden + // vielleicht gibt es einen Loop über attached faces des + // Vertex, für die schon bekannten direkt angehängten klar + // wenn auch dort vermerkt werden muss im Attachment von Seb + // bei den anderen, die keine Edge haben von der Kluft + // da muss man die Normale ins Zentrum bestimmen + // um heraus zu finden, ob sie auf dieser seite sind + // am besten dann das Attachment der faces für vertizes + // von Seb recyclen + + // loop über assosciated faces des vertex am besten + // vermutlich auch noch assosciated edges, um + // zu markieren, welche weg fallen sollen, wenn + // nicht von Kluft selber, sondern quasi verschoben + // und neu erzeugt + + int dbg_FaceIterator = 0; + + + + for( auto const & ifac : assoFaces ) + { + bool isFromFrac = false; + + for( auto const & facFrac : attFac ) + { + +// static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype ( ifac ) >::value ); + static_assert( std::is_same< decltype( (facFrac) ), decltype ( ifac ) >::value ); + + if( ifac == facFrac ) + { + isFromFrac = true; + +// static_assert( std::is_same< decltype( const_cast(facFrac) ), Face * & >::value ); + static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value ); +// static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype( ifac ) >::value ); + static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value ); + + } + } + + + bool atRightSide = false; + + if( isFromFrac ) + atRightSide = true; + + if( !isFromFrac ) + { + // check if on same side of edge where the normal points to: compute cosinus between vector of face center + // perpendicular to the edge + + + + + vector3 facCenter = CalculateCenter( ifac, aaPos ); + + vector3 perpendicu; + + +// UG_LOG("pos 0 " << aaPos[nextFracVrt[0]] << std::endl); +// UG_LOG("pos 1 " << aaPos[*iterV] << std::endl); +// UG_LOG("fac ce " << facCenter << std::endl); + + DropAPerpendicular(perpendicu, facCenter, aaPos[nextFracVrt], aaPos[*iterV]); + +// if( dbg_FaceIterator == 1 ) +// { +// UG_LOG("huhu a0" << std::endl); +// return true; +// } + + + vector3 tmpN; + + VecSubtract(tmpN, facCenter, perpendicu ); + + VecNormalize(tmpN, tmpN); + + UG_LOG("Normale zum Face ist " << tmpN << std::endl); + + number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, nV ); + + UG_LOG("Cosinus zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); + +// if( dbg_FaceIterator == 1 ) +// { +// UG_LOG("huhu a" << std::endl); +//// return true; +// } + + + if( cosBetwFracEdgAndDirection2Face > 0 ) + { + UG_LOG("assuming face to be on richt side" << std::endl); + + atRightSide = true; + +#if ANSCHAULICH_ERZEUGE_SUDOS_ANHANG + + Vertex * otherFacCent = *grid.create(); + aaPos[otherFacCent] = facCenter; + sh.assign_subset(otherFacCent, 6 ); + + Vertex * pp = *grid.create(); + aaPos[pp] = perpendicu; + sh.assign_subset(pp, 7 ); + + sh.assign_subset(ifac,8); + +#endif + + } + else + { + UG_LOG("assuming face to be on wrong side" << std::endl); + } + + + dbg_flachen_passiert++; + } + + +// if( dbg_FaceIterator == 1 ) +// { +// UG_LOG("huhu b" << std::endl); +//// return true; +// } + + + + if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein + { + + // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! + vector& newVrts4Fac = aaVrtVecFace[ ifac ]; + + IndexType vrtxFnd = 0; + + for(size_t indVrt = 0; indVrt < (ifac)->num_vertices(); indVrt++ ) + { + Vertex* facVrt = (ifac)->vertex(indVrt); + + if( facVrt == *iterV ) + { + newVrts4Fac[ indVrt ] = newShiftVrtx; + vrtxFnd++; + } + } + + + if( vrtxFnd <= 0 ) + { + UG_THROW("vertex not found!" << std::endl); + } + else if( vrtxFnd > 1 ) + { + UG_THROW("vertex zu oft gefunden " << vrtxFnd << std::endl ); + } + else if ( vrtxFnd == 1 ) + { + } + else + { + UG_THROW("vertex finden komisch " << std::endl); + } + + + } + + dbg_FaceIterator++; + + } + + + + + + + + + } + + + + dbg_iteratorAblaufen++; + + + +// // Ziel: die beiden parallelen Normalen mitteln, und in die jeweiligen beiden Richtungen je einen neuen Vertex erzeugen +// // irgendwie muss der Vertex oder die Edge besser sogar wissen, dass sie einen neuen Verschiebevertex bekommen hat +// // denn später müssen neue Edges und neue Faces basierend auf den neuen Vertizes erzeugt werden +// // vielleicht braucht die edge und das face ein Attachment, das ihnen das sagt, ähnlihc wie VertexTrible std Vektoren? +// +// +// + + + + UG_LOG("END THIS VERTEX NORMAL INNER ENDING CLEFT" << std::endl); + + } if( numFracsCrossAtVrt == 2 ) // free line of fracture, no crossing point, not at boundary @@ -3359,6 +3723,8 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, const vector Date: Tue, 9 Jul 2024 13:54:25 +0200 Subject: [PATCH 09/58] Reparatur von Verbesserungsversuchen --- .../algorithms/extrusion/expand_layers.cpp | 56 +++++++++++++------ 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp index 72646084f..65d008def 100644 --- a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp +++ b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp @@ -733,6 +733,11 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, const vector Date: Tue, 9 Jul 2024 14:18:40 +0200 Subject: [PATCH 10/58] =?UTF-8?q?unn=C3=B6tige=20Umwege=20f=C3=BCr=20ausge?= =?UTF-8?q?dehnte=20inneren=20Enden=20auskommentiert?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../algorithms/extrusion/expand_layers.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp index 65d008def..49ee960f8 100644 --- a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp +++ b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp @@ -733,7 +733,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, const vector Date: Tue, 9 Jul 2024 16:03:34 +0200 Subject: [PATCH 11/58] innere Enden von Faces funktioniert --- .../algorithms/extrusion/expand_layers.cpp | 115 +++++++++++++----- 1 file changed, 82 insertions(+), 33 deletions(-) diff --git a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp index 49ee960f8..79aa775ad 100644 --- a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp +++ b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp @@ -949,6 +949,11 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, const vector::iterator iterEdg = grid.associated_edges_begin(*iter); iterEdg != grid.associated_edges_end(*iter); iterEdg++ ) { assEdg.push_back(*iterEdg); +// sh.assign_subset(*iterEdg,10); } aaVrtInfoAssoFaces[*iter] = assFac; @@ -1012,6 +1020,8 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, const vector; std::vector< pairIndDbl > fracSubdom_facePerpendMinVal; @@ -1103,6 +1113,26 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, const vector & assFaceVrt1 = aaVrtInfoAssoFaces[verticesEdg[1]]; + + for( auto const & ifa : assFaceVrt1 ) + { + if(FaceContains( ifa, *iterEdg )) + { + bool faceContained = false; + + for( auto const & afa : assFace ) + { + if( afa == ifa ) + faceContained = true; + } + + if( !faceContained ) + assFace.push_back( ifa ); + } + } + + // UG_LOG("XXXXXXXXX" << std::endl); #endif @@ -1380,9 +1410,15 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, const vector newFaces; std::vector subsOfNewFaces; @@ -3846,39 +3888,46 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, const vector Date: Tue, 9 Jul 2024 16:43:36 +0200 Subject: [PATCH 12/58] =?UTF-8?q?Abzweigungspunkt=20f=C3=BCr=20T=20Kreuzun?= =?UTF-8?q?g=20identifiziert?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../algorithms/extrusion/expand_layers.cpp | 385 ++++++------------ 1 file changed, 135 insertions(+), 250 deletions(-) diff --git a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp index 79aa775ad..e2b356285 100644 --- a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp +++ b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp @@ -1805,7 +1805,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, const vector 3 + else // two fractures completely crossing, numFracsCrossAtVrt >= 3, i.e. T crossing and two fractures completely crossing { + // TODO FIXME in case of three fractures, we have to use the method for eine durchgehende fracture + // auf der Seite, wo die zweite fracture NICHT rein geht + IndexType countedCrossingFracEdgs = 0; // TODO FIXME kreuzende Fractures im Innenraum -> Arte in Reinform implementieren @@ -2491,7 +2489,6 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, const vector::iterator itFac = aF.begin(); itFac != aF.end(); ) -// { -// if( *itFac == fracFac ) -// { -// itFac = aF.erase(itFac); -// break; -// } -// } - vector3 startNormal = fracNorm; -// vector3 nuVe(0,0,0); -// IndexType fndCommEdg = 0; -// -// std::pair assoEdg2Fac; -// std::pair assoNorm2Fac; // will stay zero vector in case that next face contains no frac, i.e. if next edge no fracture edge -// -// Edge* nextEdge = NULL; -// -// assoEdg2Fac.first = fracEdg; -// assoNorm2Fac.first = fracNorm; -// -// assoEdg2Fac.second = NULL; // muss noch modifiziert werden -// assoNorm2Fac.second = nuVe; // wird nur modifiziert, wenn die zweite Ecke eine Kluftecke ist von dem face ebenso - - - // now need to find the second edge and figure out if it is fracture - -// Face* nextFace = NULL; -// -// -// for( auto const & iE : allAssoEdges ) // werden nicht gelöscht, deswegen Zugriff auf attachment direkt -// { -// if( FaceContains(fracFac, iE) ) -// { -// fndCommEdg++; -// if( iE != startEdg ) -// { -// nextEdge = iE; -// assoEdg2Fac.second = iE; -// } -// } -// -// if( fndCommEdg != 2 ) -// { -// UG_THROW("komische Anzahl gemeinsamer Ecke " << fndCommEdg << std::endl); -// } -// -// if( nextEdge == NULL ) -// { -// UG_THROW("wieso keine zweite Ecke gefunden???? " << std::endl); -// } -// -// } -// -// if( assoEdg2Fac.second == NULL ) -// { -// UG_THROW("null immer noch?" << std::endl); -// } -// assoEdg2Fac.push_back(nextEdge); - Face* nextFace = NULL; UG_LOG("Gesamtanzahl faces um Knoten vor while " << aF.size() << std::endl ); @@ -2646,15 +2580,6 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, const vector edge2Append( startEdg2Append, nextEdge ); std::pair normal2Append( startNormal, nuVe ); -// for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); ) -// { -// if( *itFac == startFace ) -// { -// itFac = aF.erase(itFac); -// break; -// } -// } -// // if start face and start edge from a triple, then has to be erased this triple, exept for the entire start, as already erased if( ! atFirstTriple ) @@ -2703,12 +2628,6 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, const vector::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ ) -// { -// if( FaceContains( *itFac, nextEdge ) ) -// { -// Face * facFnd = *itFac; -// aF.erase(itFac); -// -// faceEras = true; -// // check if -//// for( VecVertFracTrip::iterator itAttVFT = vVFT.begin(); itAttVFT != vVFT.end(); itAttVFT++ ) -//// { -//// Face * facTrip = itAttVFT->getFace(); -//// -//// if( facTrip == facFnd ) -//// { -//// VertFracTrip fndVFT = *itAttVFT; -////// vVFT.erase(itAttVFT); -//// -//// normal2Append.second = fndVFT.getNormal(); -//// -//// Edge * edgTrip = fndVFT.getEdge(); -//// -//// if( edgTrip != nextEdge ) -//// { -//// UG_THROW("Ecken Denkfehler" << std::endl); -//// } -//// -//// break; -//// } -//// } -// -// break; -// } -// } - - // check if aF or vVFT still contain the former or the next face - must not be the case! TODO FIXME + // check if aF or vVFT still contain the former or the next face - must not be the case! VertexOfFaceInfo vOFI( edge2Append, face2Append, normal2Append ); @@ -2915,7 +2799,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, const vectorvertex(i); - Vertex * vrtFromEdgeTwo = edgeFracTwo->vertex(i); + number cosBetweenNormals = VecDot( normalFracOne, normalFracTwo ); - if( vrtFromEdgeOne == *iterV ) - { - vrtEdgeOneBegin = vrtFromEdgeOne; - } - else - { - vrtEdgeOneEnd = vrtFromEdgeOne; - } - if( vrtFromEdgeTwo == *iterV ) + // create normal vectors into direction of relevant edges + + vector3 alongEdgeOne; + vector3 alongEdgeTwo; + + Vertex * vrtEdgeOneBegin = NULL; + Vertex * vrtEdgeTwoBegin = NULL; + Vertex * vrtEdgeOneEnd = NULL; + Vertex * vrtEdgeTwoEnd = NULL; + + + for( size_t i = 0; i < 2; ++i ) { - vrtEdgeTwoBegin = vrtFromEdgeTwo; + Vertex * vrtFromEdgeOne = edgeFracOne->vertex(i); + Vertex * vrtFromEdgeTwo = edgeFracTwo->vertex(i); + + if( vrtFromEdgeOne == *iterV ) + { + vrtEdgeOneBegin = vrtFromEdgeOne; + } + else + { + vrtEdgeOneEnd = vrtFromEdgeOne; + } + + if( vrtFromEdgeTwo == *iterV ) + { + vrtEdgeTwoBegin = vrtFromEdgeTwo; + } + else + { + vrtEdgeTwoEnd = vrtFromEdgeTwo; + } + } - else + + if( vrtEdgeOneBegin == NULL || vrtEdgeTwoBegin == NULL || vrtEdgeOneEnd == NULL || vrtEdgeTwoEnd == NULL ) { - vrtEdgeTwoEnd = vrtFromEdgeTwo; + UG_THROW("lauter Nullen vertizes" << std::endl); } - } + vector3 fracVrtPos = aaPos[*iterV]; - if( vrtEdgeOneBegin == NULL || vrtEdgeTwoBegin == NULL || vrtEdgeOneEnd == NULL || vrtEdgeTwoEnd == NULL ) - { - UG_THROW("lauter Nullen vertizes" << std::endl); - } + vector3 fracEdgOneEndPos = aaPos[ vrtEdgeOneEnd ]; + vector3 fracEdgTwoEndPos = aaPos[ vrtEdgeTwoEnd ]; - vector3 fracVrtPos = aaPos[*iterV]; + vector3 directionEdgOne; + VecSubtract(directionEdgOne, fracEdgOneEndPos, fracVrtPos); - vector3 fracEdgOneEndPos = aaPos[ vrtEdgeOneEnd ]; - vector3 fracEdgTwoEndPos = aaPos[ vrtEdgeTwoEnd ]; + vector3 directionEdgTwo; + VecSubtract(directionEdgTwo, fracEdgTwoEndPos, fracVrtPos); - vector3 directionEdgOne; - VecSubtract(directionEdgOne, fracEdgOneEndPos, fracVrtPos); + vector3 nrmdVecEdgOne; + VecNormalize(nrmdVecEdgOne, directionEdgOne); - vector3 directionEdgTwo; - VecSubtract(directionEdgTwo, fracEdgTwoEndPos, fracVrtPos); + vector3 nrmdVecEdgTwo; + VecNormalize(nrmdVecEdgTwo, directionEdgTwo); - vector3 nrmdVecEdgOne; - VecNormalize(nrmdVecEdgOne, directionEdgOne); + number cosBetweenEdges = VecDot(nrmdVecEdgOne,nrmdVecEdgTwo); - vector3 nrmdVecEdgTwo; - VecNormalize(nrmdVecEdgTwo, directionEdgTwo); + number angleEdges = std::acos( cosBetweenEdges ); + number angleNormls = std::acos( cosBetweenNormals ); - number cosBetweenEdges = VecDot(nrmdVecEdgOne,nrmdVecEdgTwo); + totAnglsEdg += angleEdges; + totAnglsNrm += angleNormls; - number angleEdges = std::acos( cosBetweenEdges ); - number angleNormls = std::acos( cosBetweenNormals ); + UG_LOG("cosinus Edges Normals " << cosBetweenEdges << " " << cosBetweenNormals << std::endl); + UG_LOG("angles edges normals " << angleEdges << " " << angleNormls << std::endl); - totAnglsEdg += angleEdges; - totAnglsNrm += angleNormls; + // prject normal 1 onto edge 2 and normal 2 on edge 1, scale with width one half resp with width two half - UG_LOG("cosinus Edges Normals " << cosBetweenEdges << " " << cosBetweenNormals << std::endl); - UG_LOG("angles edges normals " << angleEdges << " " << angleNormls << std::endl); - // prject normal 1 onto edge 2 and normal 2 on edge 1, scale with width one half resp with width two half + number cosBetweenNrmFraOneEdgTwo = VecDot(normalFracOne,nrmdVecEdgTwo); + number cosBetweenNrmFraTwoEdgOne = VecDot(normalFracTwo,nrmdVecEdgOne); + vector3 projectNrmFraOneToEdgTwoDirection; + VecScale(projectNrmFraOneToEdgTwoDirection, nrmdVecEdgTwo, 1./cosBetweenNrmFraOneEdgTwo); - number cosBetweenNrmFraOneEdgTwo = VecDot(normalFracOne,nrmdVecEdgTwo); - number cosBetweenNrmFraTwoEdgOne = VecDot(normalFracTwo,nrmdVecEdgOne); + vector3 projectNrmFraTwoToEdgOneDirection; + VecScale(projectNrmFraTwoToEdgOneDirection, nrmdVecEdgOne, 1./cosBetweenNrmFraTwoEdgOne); - vector3 projectNrmFraOneToEdgTwoDirection; - VecScale(projectNrmFraOneToEdgTwoDirection, nrmdVecEdgTwo, 1./cosBetweenNrmFraOneEdgTwo); + // auto subsIndFracOne = sh.get_subset_index(edgeFracOne); + // auto subsIndFracTwo = sh.get_subset_index(edgeFracTwo); - vector3 projectNrmFraTwoToEdgOneDirection; - VecScale(projectNrmFraTwoToEdgOneDirection, nrmdVecEdgOne, 1./cosBetweenNrmFraTwoEdgOne); + number shiftOne = fracInfosBySubset.at( subsIndFracOne ).width / 2. ; + number shiftTwo = fracInfosBySubset.at( subsIndFracTwo ).width / 2. ; - auto subsIndFracOne = sh.get_subset_index(edgeFracOne); - auto subsIndFracTwo = sh.get_subset_index(edgeFracTwo); + vector3 shiftAlongEdgeTwo; + VecScale(shiftAlongEdgeTwo, projectNrmFraOneToEdgTwoDirection, shiftOne); - number shiftOne = fracInfosBySubset.at( subsIndFracOne ).width / 2. ; - number shiftTwo = fracInfosBySubset.at( subsIndFracTwo ).width / 2. ; + vector3 shiftAlongEdgeOne; + VecScale(shiftAlongEdgeOne, projectNrmFraTwoToEdgOneDirection, shiftTwo); - vector3 shiftAlongEdgeTwo; - VecScale(shiftAlongEdgeTwo, projectNrmFraOneToEdgTwoDirection, shiftOne); + vector3 shiftPart; + VecAdd(shiftPart, fracVrtPos, shiftAlongEdgeTwo); - vector3 shiftAlongEdgeOne; - VecScale(shiftAlongEdgeOne, projectNrmFraTwoToEdgOneDirection, shiftTwo); + vector3 posNewVrt; + VecAdd( posNewVrt, shiftPart, shiftAlongEdgeOne); - vector3 shiftPart; - VecAdd(shiftPart, fracVrtPos, shiftAlongEdgeTwo); + UG_LOG("neuer Vertex Kreuzung " << posNewVrt << std::endl ); - vector3 posNewVrt; - VecAdd( posNewVrt, shiftPart, shiftAlongEdgeOne); + Vertex * newShiftVrtx = *grid.create(); + aaPos[newShiftVrtx] = posNewVrt; - UG_LOG("neuer Vertex Kreuzung " << posNewVrt << std::endl ); + // sh.assign_subset(newShiftVrtx, newSubsToAdd ); - Vertex * newShiftVrtx = *grid.create(); - aaPos[newShiftVrtx] = posNewVrt; -// sh.assign_subset(newShiftVrtx, newSubsToAdd ); + for( VertexOfFaceInfo const & vertFracInfoSeg : segPart ) + { + Face * fac = vertFracInfoSeg.getFace(); + // sh.assign_subset(fa,newSubsToAdd); - for( VertexOfFaceInfo const & vertFracInfoSeg : segPart ) - { - Face * fac = vertFracInfoSeg.getFace(); -// sh.assign_subset(fa,newSubsToAdd); + // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! + vector& newVrts4Fac = aaVrtVecFace[ fac ]; + IndexType vrtxFnd = 0; - // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! - vector& newVrts4Fac = aaVrtVecFace[ fac ]; + for(size_t indVrt = 0; indVrt < (fac)->num_vertices(); indVrt++ ) + { + Vertex* facVrt = (fac)->vertex(indVrt); - IndexType vrtxFnd = 0; + if( facVrt == *iterV ) + { + newVrts4Fac[ indVrt ] = newShiftVrtx; + vrtxFnd++; + } + } - for(size_t indVrt = 0; indVrt < (fac)->num_vertices(); indVrt++ ) - { - Vertex* facVrt = (fac)->vertex(indVrt); - if( facVrt == *iterV ) + if( vrtxFnd <= 0 ) + { + UG_THROW("vertex not found kreuzung!" << std::endl); + } + else if( vrtxFnd > 1 ) { - newVrts4Fac[ indVrt ] = newShiftVrtx; - vrtxFnd++; + UG_THROW("vertex zu oft gefunden kreuzung " << vrtxFnd << std::endl ); + } + else if ( vrtxFnd == 1 ) + { + } + else + { + UG_THROW("vertex finden komisch kreuzung " << std::endl); } - } - - if( vrtxFnd <= 0 ) - { - UG_THROW("vertex not found kreuzung!" << std::endl); - } - else if( vrtxFnd > 1 ) - { - UG_THROW("vertex zu oft gefunden kreuzung " << vrtxFnd << std::endl ); - } - else if ( vrtxFnd == 1 ) - { } - else - { - UG_THROW("vertex finden komisch kreuzung " << std::endl); - } - } } From 071b3e878537fdd0f0433e7dc576dd67f7f5085d Mon Sep 17 00:00:00 2001 From: Markus Date: Tue, 9 Jul 2024 16:58:44 +0200 Subject: [PATCH 13/58] Vereinheitlichung Expansion durchgehende Kluftseite Funktion begonnen --- .../algorithms/extrusion/expand_layers.cpp | 249 +++++++++++++++++- 1 file changed, 245 insertions(+), 4 deletions(-) diff --git a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp index e2b356285..0a16d599d 100644 --- a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp +++ b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp @@ -716,6 +716,247 @@ bool ExpandFractures2d(Grid& grid, SubsetHandler& sh, const vector return true; } +using VertFracTrip = VertexFractureTriple; + +using VecVertFracTrip = std::vector; + +using VvftIterator = VecVertFracTrip::iterator; + + +bool expandSingleFractureAtGivenSide( vector3 const & nOne, vector3 const & nTwo, + Edge * const edgeOne, Edge * const edgeTwo, + VvftIterator const & vvftOne, VvftIterator const & vvftTwo + ) +{ + // gleiche Seite vermutet oder gegeben + + // average the normals + + vector3 normSum; + + VecAdd( normSum, nOne, nTwo ); + + vector3 normSumNormed; + + VecNormalize(normSumNormed, normSum); + + UG_LOG("averaged normal " << normSumNormed << std::endl); + + std::vector attEdg; + std::vector attFac; + + attEdg.push_back( edgeOne ); + attEdg.push_back( edgeTwo ); + + Face * facOne = vvftOne->getFace(); + Face * facTwo = vvftTwo->getFace(); +// +// attFac.push_back( facOne ); +// attFac.push_back( facTwo ); +// +// // jetzt neuen Vertex erzeugen in Richtung der Normalen +// // sonst ist das attachment Schwachsinn! +// +// vector3 posNewVrt; +// +// vector3 moveVrt; +// +// auto subsIndEdgOne = sh.get_subset_index(edgeOne); +// +// auto subsIndEdgTwo = sh.get_subset_index(edgeTwo); +// +// +// if( subsIndEdgOne != subsIndEdgTwo ) +// { +// UG_THROW("subsets passen nicht" << std::endl ); +// } +// +// +// +// +// number width = fracInfosBySubset.at(subsIndEdgOne).width; +// +// // der Faktor ist Käse und muss noch aus den Eingaben übernommen werden +// VecScale(moveVrt, normSumNormed, width/2. ); +// +// VecAdd(posNewVrt, posOldVrt, moveVrt ); +// +// UG_LOG("neuer Vertex " << posNewVrt << std::endl ); +// +// // TODO FIXME hier ist das PROBLEM, SEGFAULT durch create regular vertex +// +// Vertex * newShiftVrtx = *grid.create(); +// aaPos[newShiftVrtx] = posNewVrt; +// +// sh.assign_subset(newShiftVrtx, subsIndEdgOne ); +// +// +// +// // fuer was braucheh wir das eigentlich? selber schon vergessen..... +// +// ExpandVertexMultiplett vrtMtpl( attEdg, attFac, normSumNormed ); +// +// aaVrtExpMP[ *iterV ].push_back( vrtMtpl ); +// +// +// +// // alle anhängenden faces müssen noch zu wissen bekommen +// // dass es diesen neuen Vertex gibt, nicht nur die +// // an den edges anhängenden +// // vielleicht gibt es einen Loop über attached faces des +// // Vertex, für die schon bekannten direkt angehängten klar +// // wenn auch dort vermerkt werden muss im Attachment von Seb +// // bei den anderen, die keine Edge haben von der Kluft +// // da muss man die Normale ins Zentrum bestimmen +// // um heraus zu finden, ob sie auf dieser seite sind +// // am besten dann das Attachment der faces für vertizes +// // von Seb recyclen +// +// // loop über assosciated faces des vertex am besten +// // vermutlich auch noch assosciated edges, um +// // zu markieren, welche weg fallen sollen, wenn +// // nicht von Kluft selber, sondern quasi verschoben +// // und neu erzeugt +// +// int dbg_FaceIterator = 0; +// +// for( auto const & ifac : assoFaces ) +// { +// bool isFromFrac = false; +// +// +// int dbg_innterFacFracIt = 0; +// +// for( auto const & facFrac : attFac ) +// { +// +// static_assert( std::is_same< decltype( (facFrac) ), decltype ( ifac ) >::value ); +// +// if( ifac == facFrac ) +// { +// isFromFrac = true; +// +// static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value ); +// static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value ); +// +// } +// } +// +// bool atRightSide = false; +// +// if( isFromFrac ) +// atRightSide = true; +// +// if( !isFromFrac ) +// { +// // check if on same side of edge where the normal points to: compute cosinus between vector of face center +// // perpendicular to the edge +// +// vector3 facCenter = CalculateCenter( ifac, aaPos ); +// +// vector3 perpendicu; +// +// if( nextFracVrt.size() != 2 ) +// { +// UG_THROW("komische Groesse" << std::endl); +// } +// +// DropAPerpendicular(perpendicu, facCenter, aaPos[nextFracVrt[0]], aaPos[nextFracVrt[1]]); +// +// vector3 tmpN; +// +// VecSubtract(tmpN, facCenter, perpendicu ); +// +// VecNormalize(tmpN, tmpN); +// +// UG_LOG("Normale zum Face ist " << tmpN << std::endl); +// +// number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, normSumNormed ); +// +// UG_LOG("Cosinus zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); +// +// if( cosBetwFracEdgAndDirection2Face > 0 ) +// { +// UG_LOG("assuming face to be on richt side" << std::endl); +// +// atRightSide = true; +// +//#if ANSCHAULICH_ERZEUGE_SUDOS_ANHANG +// +// Vertex * otherFacCent = *grid.create(); +// aaPos[otherFacCent] = facCenter; +// sh.assign_subset(otherFacCent, 5 ); +// +// Vertex * pp = *grid.create(); +// aaPos[pp] = perpendicu; +// sh.assign_subset(pp, 6 ); +// +// sh.assign_subset(*iterFac,7); +//#endif +// +// } +// else +// { +// UG_LOG("assuming face to be on wrong side" << std::endl); +// } +// +// +// dbg_flachen_passiert++; +// } +// +// +// if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein +// { +// +// // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! +// vector& newVrts4Fac = aaVrtVecFace[ ifac ]; +// +// IndexType vrtxFnd = 0; +// +// for(size_t indVrt = 0; indVrt < (ifac)->num_vertices(); indVrt++ ) +// { +// Vertex* facVrt = (ifac)->vertex(indVrt); +// +// if( facVrt == *iterV ) +// { +// newVrts4Fac[ indVrt ] = newShiftVrtx; +// vrtxFnd++; +// } +// } +// +// +// if( vrtxFnd <= 0 ) +// { +// UG_THROW("vertex not found!" << std::endl); +// } +// else if( vrtxFnd > 1 ) +// { +// UG_THROW("vertex zu oft gefunden " << vrtxFnd << std::endl ); +// } +// else if ( vrtxFnd == 1 ) +// { +// } +// else +// { +// UG_THROW("vertex finden komisch " << std::endl); +// } +// +// +// } +// +// dbg_innterFacFracIt++; +// +// +// +// dbg_FaceIterator++; +// +// } + + + return true; + + +} #ifndef NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX #define NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX 1 @@ -802,9 +1043,9 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, const vector; - - using VecVertFracTrip = std::vector; +// using VertFracTrip = VertexFractureTriple; +// +// using VecVertFracTrip = std::vector; VecVertFracTrip vertexNoInfo; @@ -1359,7 +1600,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, const vector Date: Tue, 9 Jul 2024 17:16:46 +0200 Subject: [PATCH 14/58] Auslagerungsfunktion geschrieben --- .../algorithms/extrusion/expand_layers.cpp | 413 +++++++++--------- 1 file changed, 206 insertions(+), 207 deletions(-) diff --git a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp index 0a16d599d..7ede241b4 100644 --- a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp +++ b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp @@ -722,10 +722,23 @@ using VecVertFracTrip = std::vector; using VvftIterator = VecVertFracTrip::iterator; +using AttVrtVec = Attachment >; +using IndexType = unsigned short; + +template bool expandSingleFractureAtGivenSide( vector3 const & nOne, vector3 const & nTwo, Edge * const edgeOne, Edge * const edgeTwo, - VvftIterator const & vvftOne, VvftIterator const & vvftTwo + VvftIterator const & vvftOne, VvftIterator const & vvftTwo, + vector const & fracInfosBySubset, + vector3 const & posOldVrt, + Grid::VertexAttachmentAccessor & aaPos, + Grid & grid, SubsetHandler & sh, + ASOF const & assoFaces, + std::vector const & nextFracVrt, + Grid::FaceAttachmentAccessor & aaVrtVecFace, + int & dbg_flachen_passiert, + Vertex * iterV ) { // gleiche Seite vermutet oder gegeben @@ -750,211 +763,197 @@ bool expandSingleFractureAtGivenSide( vector3 const & nOne, vector3 const & nTwo Face * facOne = vvftOne->getFace(); Face * facTwo = vvftTwo->getFace(); -// -// attFac.push_back( facOne ); -// attFac.push_back( facTwo ); -// -// // jetzt neuen Vertex erzeugen in Richtung der Normalen -// // sonst ist das attachment Schwachsinn! -// -// vector3 posNewVrt; -// -// vector3 moveVrt; -// -// auto subsIndEdgOne = sh.get_subset_index(edgeOne); -// -// auto subsIndEdgTwo = sh.get_subset_index(edgeTwo); -// -// -// if( subsIndEdgOne != subsIndEdgTwo ) -// { -// UG_THROW("subsets passen nicht" << std::endl ); -// } -// -// -// -// -// number width = fracInfosBySubset.at(subsIndEdgOne).width; -// -// // der Faktor ist Käse und muss noch aus den Eingaben übernommen werden -// VecScale(moveVrt, normSumNormed, width/2. ); -// -// VecAdd(posNewVrt, posOldVrt, moveVrt ); -// -// UG_LOG("neuer Vertex " << posNewVrt << std::endl ); -// -// // TODO FIXME hier ist das PROBLEM, SEGFAULT durch create regular vertex -// -// Vertex * newShiftVrtx = *grid.create(); -// aaPos[newShiftVrtx] = posNewVrt; -// -// sh.assign_subset(newShiftVrtx, subsIndEdgOne ); -// -// -// -// // fuer was braucheh wir das eigentlich? selber schon vergessen..... -// -// ExpandVertexMultiplett vrtMtpl( attEdg, attFac, normSumNormed ); -// -// aaVrtExpMP[ *iterV ].push_back( vrtMtpl ); -// -// -// -// // alle anhängenden faces müssen noch zu wissen bekommen -// // dass es diesen neuen Vertex gibt, nicht nur die -// // an den edges anhängenden -// // vielleicht gibt es einen Loop über attached faces des -// // Vertex, für die schon bekannten direkt angehängten klar -// // wenn auch dort vermerkt werden muss im Attachment von Seb -// // bei den anderen, die keine Edge haben von der Kluft -// // da muss man die Normale ins Zentrum bestimmen -// // um heraus zu finden, ob sie auf dieser seite sind -// // am besten dann das Attachment der faces für vertizes -// // von Seb recyclen -// -// // loop über assosciated faces des vertex am besten -// // vermutlich auch noch assosciated edges, um -// // zu markieren, welche weg fallen sollen, wenn -// // nicht von Kluft selber, sondern quasi verschoben -// // und neu erzeugt -// -// int dbg_FaceIterator = 0; -// -// for( auto const & ifac : assoFaces ) -// { -// bool isFromFrac = false; -// -// -// int dbg_innterFacFracIt = 0; -// -// for( auto const & facFrac : attFac ) -// { -// -// static_assert( std::is_same< decltype( (facFrac) ), decltype ( ifac ) >::value ); -// -// if( ifac == facFrac ) -// { -// isFromFrac = true; -// -// static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value ); -// static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value ); -// -// } -// } -// -// bool atRightSide = false; -// -// if( isFromFrac ) -// atRightSide = true; -// -// if( !isFromFrac ) -// { -// // check if on same side of edge where the normal points to: compute cosinus between vector of face center -// // perpendicular to the edge -// -// vector3 facCenter = CalculateCenter( ifac, aaPos ); -// -// vector3 perpendicu; -// -// if( nextFracVrt.size() != 2 ) -// { -// UG_THROW("komische Groesse" << std::endl); -// } -// -// DropAPerpendicular(perpendicu, facCenter, aaPos[nextFracVrt[0]], aaPos[nextFracVrt[1]]); -// -// vector3 tmpN; -// -// VecSubtract(tmpN, facCenter, perpendicu ); -// -// VecNormalize(tmpN, tmpN); -// -// UG_LOG("Normale zum Face ist " << tmpN << std::endl); -// -// number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, normSumNormed ); -// -// UG_LOG("Cosinus zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); -// -// if( cosBetwFracEdgAndDirection2Face > 0 ) -// { -// UG_LOG("assuming face to be on richt side" << std::endl); -// -// atRightSide = true; -// -//#if ANSCHAULICH_ERZEUGE_SUDOS_ANHANG -// -// Vertex * otherFacCent = *grid.create(); -// aaPos[otherFacCent] = facCenter; -// sh.assign_subset(otherFacCent, 5 ); -// -// Vertex * pp = *grid.create(); -// aaPos[pp] = perpendicu; -// sh.assign_subset(pp, 6 ); -// -// sh.assign_subset(*iterFac,7); -//#endif -// -// } -// else -// { -// UG_LOG("assuming face to be on wrong side" << std::endl); -// } -// -// -// dbg_flachen_passiert++; -// } -// -// -// if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein -// { -// -// // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! -// vector& newVrts4Fac = aaVrtVecFace[ ifac ]; -// -// IndexType vrtxFnd = 0; -// -// for(size_t indVrt = 0; indVrt < (ifac)->num_vertices(); indVrt++ ) -// { -// Vertex* facVrt = (ifac)->vertex(indVrt); -// -// if( facVrt == *iterV ) -// { -// newVrts4Fac[ indVrt ] = newShiftVrtx; -// vrtxFnd++; -// } -// } -// -// -// if( vrtxFnd <= 0 ) -// { -// UG_THROW("vertex not found!" << std::endl); -// } -// else if( vrtxFnd > 1 ) -// { -// UG_THROW("vertex zu oft gefunden " << vrtxFnd << std::endl ); -// } -// else if ( vrtxFnd == 1 ) -// { -// } -// else -// { -// UG_THROW("vertex finden komisch " << std::endl); -// } -// -// -// } -// -// dbg_innterFacFracIt++; -// -// -// -// dbg_FaceIterator++; -// -// } + attFac.push_back( facOne ); + attFac.push_back( facTwo ); - return true; + // jetzt neuen Vertex erzeugen in Richtung der Normalen + // sonst ist das attachment Schwachsinn! + + vector3 posNewVrt; + + vector3 moveVrt; + + auto subsIndEdgOne = sh.get_subset_index(edgeOne); + + auto subsIndEdgTwo = sh.get_subset_index(edgeTwo); + + if( subsIndEdgOne != subsIndEdgTwo ) + { + UG_THROW("subsets passen nicht Vereinheitlichung" << std::endl ); + } + + number width = fracInfosBySubset.at(subsIndEdgOne).width; + + // der Faktor ist Käse und muss noch aus den Eingaben übernommen werden + VecScale(moveVrt, normSumNormed, width/2. ); + + VecAdd(posNewVrt, posOldVrt, moveVrt ); + + UG_LOG("neuer Vertex " << posNewVrt << std::endl ); + + // TODO FIXME hier ist das PROBLEM, SEGFAULT durch create regular vertex + + Vertex * newShiftVrtx = *grid.create(); + aaPos[newShiftVrtx] = posNewVrt; + + sh.assign_subset(newShiftVrtx, subsIndEdgOne ); + + + + // alle anhängenden faces müssen noch zu wissen bekommen + // dass es diesen neuen Vertex gibt, nicht nur die + // an den edges anhängenden + // vielleicht gibt es einen Loop über attached faces des + // Vertex, für die schon bekannten direkt angehängten klar + // wenn auch dort vermerkt werden muss im Attachment von Seb + // bei den anderen, die keine Edge haben von der Kluft + // da muss man die Normale ins Zentrum bestimmen + // um heraus zu finden, ob sie auf dieser seite sind + // am besten dann das Attachment der faces für vertizes + // von Seb recyclen + + // loop über assosciated faces des vertex am besten + // vermutlich auch noch assosciated edges, um + // zu markieren, welche weg fallen sollen, wenn + // nicht von Kluft selber, sondern quasi verschoben + // und neu erzeugt + + int dbg_FaceIterator = 0; + + for( auto const & ifac : assoFaces ) + { + bool isFromFrac = false; + + int dbg_innterFacFracIt = 0; + + for( auto const & facFrac : attFac ) + { + + static_assert( std::is_same< decltype( (facFrac) ), decltype ( ifac ) >::value ); + + if( ifac == facFrac ) + { + isFromFrac = true; + + static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value ); + static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value ); + + } + } + + bool atRightSide = false; + + if( isFromFrac ) + atRightSide = true; + + if( !isFromFrac ) + { + // check if on same side of edge where the normal points to: compute cosinus between vector of face center + // perpendicular to the edge + + vector3 facCenter = CalculateCenter( ifac, aaPos ); + vector3 perpendicu; + + if( nextFracVrt.size() != 2 ) + { + UG_THROW("komische Groesse" << std::endl); + } + + DropAPerpendicular(perpendicu, facCenter, aaPos[nextFracVrt[0]], aaPos[nextFracVrt[1]]); + + vector3 tmpN; + + VecSubtract(tmpN, facCenter, perpendicu ); + + VecNormalize(tmpN, tmpN); + + UG_LOG("Normale zum Face ist " << tmpN << std::endl); + + number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, normSumNormed ); + + UG_LOG("Cosinus zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); + + if( cosBetwFracEdgAndDirection2Face > 0 ) + { + UG_LOG("assuming face to be on richt side" << std::endl); + + atRightSide = true; + +#if ANSCHAULICH_ERZEUGE_SUDOS_ANHANG + + Vertex * otherFacCent = *grid.create(); + aaPos[otherFacCent] = facCenter; + sh.assign_subset(otherFacCent, 5 ); + + Vertex * pp = *grid.create(); + aaPos[pp] = perpendicu; + sh.assign_subset(pp, 6 ); + + sh.assign_subset(*iterFac,7); +#endif + + } + else + { + UG_LOG("assuming face to be on wrong side" << std::endl); + } + + + dbg_flachen_passiert++; + } + + + if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein + { + + // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! + vector& newVrts4Fac = aaVrtVecFace[ ifac ]; + + IndexType vrtxFnd = 0; + + for(size_t indVrt = 0; indVrt < (ifac)->num_vertices(); indVrt++ ) + { + Vertex* facVrt = (ifac)->vertex(indVrt); + + if( facVrt == iterV ) + { + newVrts4Fac[ indVrt ] = newShiftVrtx; + vrtxFnd++; + } + } + + + if( vrtxFnd <= 0 ) + { + UG_THROW("vertex not found!" << std::endl); + } + else if( vrtxFnd > 1 ) + { + UG_THROW("vertex zu oft gefunden " << vrtxFnd << std::endl ); + } + else if ( vrtxFnd == 1 ) + { + } + else + { + UG_THROW("vertex finden komisch " << std::endl); + } + + + } + + dbg_innterFacFracIt++; + + + + dbg_FaceIterator++; + + } + + + return true; } @@ -970,7 +969,7 @@ bool expandSingleFractureAtGivenSide( vector3 const & nOne, vector3 const & nTwo #define OLD_PROFREITER_STUFF 0 #endif -bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, const vector& fracInfos, +bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector const & fracInfos, bool expandInnerFracBnds, bool expandOuterFracBnds) { @@ -1024,7 +1023,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, const vector aaMarkEDGE(grid, aAdjMarker); #endif - using IndexType = unsigned short; +// using IndexType = unsigned short; using AttVerFracProp = Attachment >; // attachment pair boundary is fracture, number fractures crossing @@ -1503,8 +1502,8 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, const vector >; + // es reicht vielleicht, hier statt einem Vektor einfach nur einen Vertex * zu storen +// using AttVrtVec = Attachment >; AttVrtVec attVrtVec; // we associate a vector of vertices for each face adjacent to the frac. From 2994ed2e1e33ad99d6f9355e1fced5506691a606 Mon Sep 17 00:00:00 2001 From: Markus Date: Tue, 9 Jul 2024 18:09:29 +0200 Subject: [PATCH 15/58] T Kreuzung funktioniert jetzt auch, wenn auch noch mit Keilen --- .../algorithms/extrusion/expand_layers.cpp | 120 ++++++++++++++---- 1 file changed, 96 insertions(+), 24 deletions(-) diff --git a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp index 7ede241b4..63ef385e1 100644 --- a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp +++ b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp @@ -718,29 +718,35 @@ bool ExpandFractures2d(Grid& grid, SubsetHandler& sh, const vector using VertFracTrip = VertexFractureTriple; -using VecVertFracTrip = std::vector; +//using VecVertFracTrip = std::vector; -using VvftIterator = VecVertFracTrip::iterator; +//using VvftIterator = VecVertFracTrip::iterator; using AttVrtVec = Attachment >; +using VertexOfFaceInfo = VertexFractureTriple< std::pair, Face*, std::pair >; + + using IndexType = unsigned short; template bool expandSingleFractureAtGivenSide( vector3 const & nOne, vector3 const & nTwo, - Edge * const edgeOne, Edge * const edgeTwo, - VvftIterator const & vvftOne, VvftIterator const & vvftTwo, + Edge * edgeOne, Edge * edgeTwo, + Face * facOne, Face * facTwo, vector const & fracInfosBySubset, vector3 const & posOldVrt, Grid::VertexAttachmentAccessor & aaPos, Grid & grid, SubsetHandler & sh, - ASOF const & assoFaces, + ASOF const & assoFaces + , std::vector const & nextFracVrt, Grid::FaceAttachmentAccessor & aaVrtVecFace, int & dbg_flachen_passiert, Vertex * iterV ) { + +#if 1 // gleiche Seite vermutet oder gegeben // average the normals @@ -761,9 +767,6 @@ bool expandSingleFractureAtGivenSide( vector3 const & nOne, vector3 const & nTwo attEdg.push_back( edgeOne ); attEdg.push_back( edgeTwo ); - Face * facOne = vvftOne->getFace(); - Face * facTwo = vvftTwo->getFace(); - attFac.push_back( facOne ); attFac.push_back( facTwo ); @@ -951,7 +954,7 @@ bool expandSingleFractureAtGivenSide( vector3 const & nOne, vector3 const & nTwo dbg_FaceIterator++; } - +#endif return true; @@ -1044,7 +1047,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c // using VertFracTrip = VertexFractureTriple; // -// using VecVertFracTrip = std::vector; + using VecVertFracTrip = std::vector; VecVertFracTrip vertexNoInfo; @@ -1599,7 +1602,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c } -// using VvftIterator = VecVertFracTrip::iterator; + using VvftIterator = VecVertFracTrip::iterator; VecFace & assoFaces = aaVrtInfoAssoFaces[*iterV]; // TODO FIXME hier braucht man das nicht zu ordnen @@ -2739,7 +2742,6 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c // // hier werden ALLE attached Faces benötigt, auch die, die zwischen den direkt an den fractures liegenden Faces sind // // copies of all faces and of fractured ones - auto vVFT = vecVertFracTrip; // caution: COPY, not reference! auto aF = assoFaces; // caution: COPY, not reference! @@ -3156,35 +3158,105 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c auto subsIndFracOne = sh.get_subset_index(edgeFracOne); auto subsIndFracTwo = sh.get_subset_index(edgeFracTwo); + vector3 normalFracOne = normalBegin.first; + vector3 normalFracTwo = normalEnd.second; +// sh.assign_subset(edgeFracOne, newSubsToAdd); +// +// if( edgeFracTwo != originalStartEdge ) +// sh.assign_subset(edgeFracTwo, newSubsToAdd); + + // neue Punkte erzeugen + + number cosBetweenNormals = VecDot( normalFracOne, normalFracTwo ); if( subsIndFracOne == subsIndFracTwo ) { + if( numFracsCrossAtVrt != 3 ) + { + UG_THROW("Fracture Segment an beiden Seiten gleiche sudo, aber keine T Kreuzung?" << std::endl); + } + // dieselben Methoden wie im Fall von einer durchgehenden Kluft an einem Vertex, dort kopieren // bzw Funktion schreiben, die beides macht // TODO FIXME irgendwie muss hier der Fall abgezweigt werden, dass wir auf der durchgehenden Seite einer Kluft sind // wenn wir eine T-Kreuzung haben - // XXXXXXXXXXXXXXXXX hier kritischer Punkt aktuell + // HHHHHHHHHHHH hier kritischer Punkt aktuell + std::vector nextFracVrt; - } - else - { + IndexType foundThisVrtOne = 0; - vector3 normalFracOne = normalBegin.first; - vector3 normalFracTwo = normalEnd.second; + for( size_t i = 0; i < 2; ++i ) + { + Vertex * vrtEdgEnd = edgeFracOne->vertex(i); - // sh.assign_subset(edgeFracOne, newSubsToAdd); - // - // if( edgeFracTwo != originalStartEdge ) - // sh.assign_subset(edgeFracTwo, newSubsToAdd); + if( vrtEdgEnd == *iterV ) + { + foundThisVrtOne++; + } + else + { + nextFracVrt.push_back( vrtEdgEnd ); + } - // neue Punkte erzeugen + } - number cosBetweenNormals = VecDot( normalFracOne, normalFracTwo ); + if( foundThisVrtOne != 1 ) + { + UG_THROW("zu viel zu wenig vertizex one " << std::endl); + } + IndexType foundThisVrtTwo = 0; + + for( size_t i = 0; i < 2; ++i ) + { + Vertex * vrtEdgEnd = edgeFracTwo->vertex(i); + + if( vrtEdgEnd == *iterV ) + { + foundThisVrtTwo++; + } + else + { + nextFracVrt.push_back( vrtEdgEnd ); + } + + } + + if( foundThisVrtTwo != 1 ) + { + UG_THROW("zu viel zu wenig vertizex two " << std::endl); + } + + Face * faceBegin = vFISBegin.getFace(); + Face * faceEnd = vFISEnd.getFace(); + + + + expandSingleFractureAtGivenSide( normalFracTwo, normalFracTwo, + edgeFracOne, edgeFracTwo, + faceBegin, faceEnd, + fracInfosBySubset, + posOldVrt, + aaPos, + grid, sh, + assoFaces + , + nextFracVrt, + aaVrtVecFace, + dbg_flachen_passiert, + *iterV + ); + + + + } + else + { + // create normal vectors into direction of relevant edges vector3 alongEdgeOne; From 33187850848542b099795bbce320379c78c7841b Mon Sep 17 00:00:00 2001 From: Markus Date: Tue, 9 Jul 2024 18:52:35 +0200 Subject: [PATCH 16/58] Auslagerung in Zusatzfunk zwecks Vermeiden von copy and paste aber zu viele Argumente bei dieser Funktion..... --- .../algorithms/extrusion/expand_layers.cpp | 30 +++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp index 63ef385e1..a07a4f39f 100644 --- a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp +++ b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp @@ -737,8 +737,7 @@ bool expandSingleFractureAtGivenSide( vector3 const & nOne, vector3 const & nTwo vector3 const & posOldVrt, Grid::VertexAttachmentAccessor & aaPos, Grid & grid, SubsetHandler & sh, - ASOF const & assoFaces - , + ASOF const & assoFaces, std::vector const & nextFracVrt, Grid::FaceAttachmentAccessor & aaVrtVecFace, int & dbg_flachen_passiert, @@ -2252,6 +2251,27 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c // die neuen Vertizes samt ihrer gemittelten Normalen speichert // also std::vector von dieser neuen Klasse als Vertex attachment +#if 1 + + Face * facOne = vvftOne->getFace(); + Face * facTwo = vvftTwo->getFace(); + + expandSingleFractureAtGivenSide( nOne, nTwo, + edgeOne, edgeTwo, + facOne, facTwo, + fracInfosBySubset, + posOldVrt, + aaPos, + grid, sh, + assoFaces + , + nextFracVrt, + aaVrtVecFace, + dbg_flachen_passiert, + *iterV + ); + +#else // average the normals @@ -2271,8 +2291,8 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c attEdg.push_back( edgeOne ); attEdg.push_back( edgeTwo ); - Face * facOne = vvftOne->getFace(); - Face * facTwo = vvftTwo->getFace(); +// Face * facOne = vvftOne->getFace(); +// Face * facTwo = vvftTwo->getFace(); attFac.push_back( facOne ); attFac.push_back( facTwo ); @@ -2681,7 +2701,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c #endif - +#endif } else From 79e85b749845f2714c7762db5085ab2ae42de446 Mon Sep 17 00:00:00 2001 From: Markus Date: Tue, 9 Jul 2024 19:06:12 +0200 Subject: [PATCH 17/58] KluftInnen Erzeugung mit DiamantInnen als Ziel --- .../lib_grid/algorithms/extrusion/expand_layers.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp index a07a4f39f..b47ce9f8b 100644 --- a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp +++ b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp @@ -3200,9 +3200,8 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c // dieselben Methoden wie im Fall von einer durchgehenden Kluft an einem Vertex, dort kopieren // bzw Funktion schreiben, die beides macht - // TODO FIXME irgendwie muss hier der Fall abgezweigt werden, dass wir auf der durchgehenden Seite einer Kluft sind + // hier wird der Fall abgezweigt, dass wir auf der durchgehenden Seite einer Kluft sind // wenn wir eine T-Kreuzung haben - // HHHHHHHHHHHH hier kritischer Punkt aktuell std::vector nextFracVrt; @@ -4199,8 +4198,12 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c nfn++; } - // TODO FIXME sollen die Boundary Edges zur boundary gehören, oder zur Kluft? - // TODO FIXME wie ist es mit den Knoten, sind die alle richtig zugewiesen bezüglich subset? + // sollen die Boundary Edges zur boundary gehören, oder zur Kluft? + // wie ist es mit den Knoten, sind die alle richtig zugewiesen bezüglich subset? + + // TODO FIXME HHHHHHHHHHHHHHHHHH + // jetzt muss noch der Diamant erzeugt werden + // Ziel: KluftInnen erzeugen // remove the temporary attachments From ee16da29b2d0b3e8583840294869668f0ed83294 Mon Sep 17 00:00:00 2001 From: junxiW Date: Wed, 10 Jul 2024 15:18:19 +0200 Subject: [PATCH 18/58] correcte function inputs for creating plane and edge. --- ugbase/lib_grid/tools/creator_grid_util.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/ugbase/lib_grid/tools/creator_grid_util.h b/ugbase/lib_grid/tools/creator_grid_util.h index 11df9e6ac..f3676644d 100644 --- a/ugbase/lib_grid/tools/creator_grid_util.h +++ b/ugbase/lib_grid/tools/creator_grid_util.h @@ -40,7 +40,9 @@ namespace ug{ //////////////////////////////////////////////////////////////////////// /** * To Create GridObject directly under UG4-C++ - * instead of ProMesh + * instead of ProMesh: + * + * Functions are copied from plugins/ProMesh/tools/grid_generation_tools.cpp */ template Vertex* CreateVertex(Grid& grid,const TPosition& pos,Grid::VertexAttachmentAccessor >& aaPos ) @@ -56,7 +58,7 @@ Vertex* CreateVertex(Grid& grid,const TPosition& pos,Grid::VertexAttachmentAcces -Edge* CreateEdge(Grid& grid, Vertex* vrts[], const size_t, numVrts){ +Edge* CreateEdge(Grid& grid, Vertex* vrts[], const size_t numVrts){ //uniquify vrts by hash_value: no //The vrts can't be simply uniquified by hash_values since it will change the orientation of vrts. // Hence,it should be generated by aaPos before using this function. @@ -144,7 +146,7 @@ Face* CreateFace(Grid& grid, Vertex* vrts[], const size_t numVrts){ //return CreateFace(grid, avrts, numVrts); }*/ -Volume* CreateVolume(Grid& grid, Vertex* vrts, const size_t numVrts){ +Volume* CreateVolume(Grid& grid, Vertex* vrts[], const size_t numVrts){ //if(numVrts < 4 || numVrts > 8){ UG_ASSERT(numVrts>3 || numVrts<9,"Bad number of vertices! Can't create a volume element from " << numVrts << " vertices."); @@ -209,7 +211,7 @@ void CreatePlane(Grid& grid, const TPosition& upRight, const TPosition& lowLeft, const TPosition& lowRight, - Grid::VertexAttachmentAccessor >& aaPos + Grid::VertexAttachmentAccessor >& aaPos, bool fill) { Vertex* vrts[4]; From 4ba5ddbbc7969d0961a4781e79763ff75a29fcb3 Mon Sep 17 00:00:00 2001 From: Arne Naegel Date: Wed, 10 Jul 2024 17:28:36 +0200 Subject: [PATCH 19/58] Undo 8de72de4182eed7dd9e67e5050384537bbdb502d --- ugbase/bridge/disc_bridges/algebra_bridge.cpp | 28 ---- ugbase/lib_disc/CMakeLists.txt | 22 ---- .../non_linear_operator/line_search.h | 120 +----------------- .../newton_solver/nestedNewtonRFSwitch.h | 17 --- .../newton_solver/nestedNewtonRFSwitch.h.in | 17 --- .../newton_solver/newton.h | 22 ---- .../newton_solver/newtonUpdaterGeneric.h | 120 ------------------ .../newton_solver/newton_impl.h | 53 +------- 8 files changed, 2 insertions(+), 397 deletions(-) delete mode 100644 ugbase/lib_disc/operator/non_linear_operator/newton_solver/nestedNewtonRFSwitch.h delete mode 100644 ugbase/lib_disc/operator/non_linear_operator/newton_solver/nestedNewtonRFSwitch.h.in delete mode 100644 ugbase/lib_disc/operator/non_linear_operator/newton_solver/newtonUpdaterGeneric.h diff --git a/ugbase/bridge/disc_bridges/algebra_bridge.cpp b/ugbase/bridge/disc_bridges/algebra_bridge.cpp index 0078524d9..1b386d29d 100644 --- a/ugbase/bridge/disc_bridges/algebra_bridge.cpp +++ b/ugbase/bridge/disc_bridges/algebra_bridge.cpp @@ -66,14 +66,6 @@ #include "lib_disc/operator/composite_conv_check.h" #include "lib_disc/spatial_disc/local_to_global/local_to_global_mapper.h" -#include "lib_disc/operator/non_linear_operator/newton_solver/nestedNewtonRFSwitch.h" - -#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE - -#include "lib_disc/operator/non_linear_operator/newton_solver/newtonUpdaterGeneric.h" - -#endif - using namespace std; @@ -273,23 +265,6 @@ static void Algebra(Registry& reg, string parentGroup) .set_construct_as_smart_pointer(true); reg.add_class_to_group(name, "AssembledLinearOperator", tag); } - - -#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE - // generic Newton updater - { - std::string grp = parentGroup; grp.append("/Discretization"); - using T = NewtonUpdaterGeneric; - string name = string("NewtonUpdaterGeneric").append(suffix); - reg.add_class_(name, grp) - .add_constructor() -// .template add_constructor >)>("NewtonUpdaterGeneric") -// .add_method("updateNewton", static_cast (&T::updateNewton)) -// .add_method("updateNewton", static_cast (&T::updateNewton)) - .set_construct_as_smart_pointer(true); - reg.add_class_to_group(name, "NewtonUpdaterGeneric", tag); - } -#endif // NewtonSolver @@ -326,9 +301,6 @@ static void Algebra(Registry& reg, string parentGroup) .add_method("clear_inner_step_update", &T::clear_inner_step_update, "clear inner step update", "") .add_method("add_step_update", &T::add_step_update, "data update called before every Newton step", "") .add_method("clear_step_update", &T::clear_step_update, "clear step update", "") -#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE - .add_method("setNewtonUpdater", &T::setNewtonUpdater, "set the Newton updater", "") -#endif .add_method("config_string", &T::config_string) .set_construct_as_smart_pointer(true); reg.add_class_to_group(name, "NewtonSolver", tag); diff --git a/ugbase/lib_disc/CMakeLists.txt b/ugbase/lib_disc/CMakeLists.txt index ea04f77c3..f5a4b98f1 100644 --- a/ugbase/lib_disc/CMakeLists.txt +++ b/ugbase/lib_disc/CMakeLists.txt @@ -34,28 +34,6 @@ project(P_LIB_DISCRETIZATION) include("../../cmake/ug_includes.cmake") -option(ENABLE_NESTED_NEWTON "If enabled, nested Newton may be used, but needs for specification, else fallback to normal Newton" OFF) -message(STATUS "") -message(STATUS "Info: ${pluginName} options:") -message(STATUS " * ENABLE_NESTED_NEWTON: ${ENABLE_NESTED_NEWTON} (options are: ON, OFF)") - -if( ENABLE_NESTED_NEWTON ) - -set( SET_NESTED_NEWTON 1 ) - -else(ENABLE_NESTED_NEWTON) - -set( SET_NESTED_NEWTON 0) - -endif(ENABLE_NESTED_NEWTON) - -configure_file ( - "${CMAKE_CURRENT_SOURCE_DIR}//operator/non_linear_operator/newton_solver/nestedNewtonRFSwitch.h.in" - "${CMAKE_CURRENT_SOURCE_DIR}//operator/non_linear_operator/newton_solver/nestedNewtonRFSwitch.h" - ) - - - set(srcDiscretization domain.cpp domain_util.cpp diff --git a/ugbase/lib_disc/operator/non_linear_operator/line_search.h b/ugbase/lib_disc/operator/non_linear_operator/line_search.h index 75902655c..2abbc5c07 100644 --- a/ugbase/lib_disc/operator/non_linear_operator/line_search.h +++ b/ugbase/lib_disc/operator/non_linear_operator/line_search.h @@ -38,20 +38,9 @@ #include #include #include -#include #include "common/common.h" -#include "lib_disc/operator/non_linear_operator/newton_solver/nestedNewtonRFSwitch.h" - -#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE - -#include "lib_disc/operator/non_linear_operator/newton_solver/newtonUpdaterGeneric.h" - -#endif - - - namespace ug{ /////////////////////////////////////////////////////////// @@ -104,10 +93,6 @@ class ILineSearch /// virtual destructor virtual ~ILineSearch() {} - -#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE - virtual void setNewtonUpdater( SmartPtr > nU ) = 0; -#endif }; /// standard implementation of the line search based on the "sufficient descent" @@ -123,30 +108,18 @@ class StandardLineSearch : public ILineSearch StandardLineSearch() : m_maxSteps(10), m_lambdaStart(1.0), m_lambdaReduce(0.5), m_alpha(0.25), m_maxDefect(1e+10), m_verbose(true), m_bAcceptBest(false), m_bCheckAll(false), m_offset("") -#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE - , - m_newtonUpdater(new NewtonUpdaterGeneric{}) -#endif {}; /// constructor StandardLineSearch(int maxSteps, number lambdaStart, number lambdaReduce, bool bAcceptBest) : m_maxSteps(maxSteps), m_lambdaStart(lambdaStart), m_lambdaReduce(lambdaReduce), m_alpha(0.25), m_maxDefect(1e+10), m_verbose(true), m_bAcceptBest(bAcceptBest), m_bCheckAll(false), m_offset("") -#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE - , - m_newtonUpdater(new NewtonUpdaterGeneric{}) -#endif {}; /// constructor StandardLineSearch(int maxSteps, number lambdaStart, number lambdaReduce, bool bAcceptBest, bool bCheckAll) : m_maxSteps(maxSteps), m_lambdaStart(lambdaStart), m_lambdaReduce(lambdaReduce), m_alpha(0.25), m_maxDefect(1e+10), m_verbose(true), m_bAcceptBest(bAcceptBest), m_bCheckAll(bCheckAll), m_offset("") -#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE - , - m_newtonUpdater(new NewtonUpdaterGeneric{}) -#endif {}; /// returns information about configuration parameters @@ -215,37 +188,6 @@ class StandardLineSearch : public ILineSearch // loop line search steps for(int k = 1; k <= m_maxSteps; ++k) { -#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE - // try on line u := u - lambda*p - - //if( m_newtonUpdater != NULL ) - //{ - bool acceptedNewtonUpdate = m_newtonUpdater->updateSolution(u, 1.0, u, (-1)*lambda, p); - -// if( ! m_newtonUpdater->updateNewton(u, 1.0, u, (-1)*lambda, p) ) - if( ! acceptedNewtonUpdate ) -// if( m_newtonUpdater->updateNewton(u,p) ) - { - UG_LOG("Update in Line Search did not work.\n"); - norm = std::numeric_limits::max(); - //VecScaleAdd(u, 1.0, u, (-1)*lambda, p); - //return false; - } - else - { - // compute new Defect - spOp->prepare(u); - spOp->apply(d, u); - - // compute new Residuum - norm = d.norm(); - } - //} -// else -// { -// UG_LOG("Please set a Newton updater in Line search"); -// } -#else // try on line u := u - lambda*p VecScaleAdd(u, 1.0, u, (-1)*lambda, p); @@ -256,9 +198,6 @@ class StandardLineSearch : public ILineSearch // compute new Residuum norm = d.norm(); -#endif - - // compute reduction vRho.push_back(norm/norm_old); @@ -315,42 +254,15 @@ class StandardLineSearch : public ILineSearch UG_LOG(m_offset << " ++++ Accept Best: Accepting step " << best+1 << ", Rate = "<< vRho[best] <<".\n"); -#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE - // try on line u := u - lambda*p - - //if( m_newtonUpdater != NULL ) - //{ - if( ! m_newtonUpdater->updateSolution(u, 1.0, s, (-1)*m_lambdaStart*std::pow(m_lambdaReduce, (number)best), p) ) - { - UG_LOG("Update in Line Search kmax did not work.\n"); - - norm = std::numeric_limits::max(); - //return false; - } - else - { - spOp->prepare(u); - spOp->apply(d, u); - - // compute new Residuum - norm = d.norm(); - } - //} -// else -// { -// UG_LOG("Please set a Newton updater in Line search"); -// } -#else // try on line u := u - lambda*p VecScaleAdd(u, 1.0, s, (-1)*m_lambdaStart*std::pow(m_lambdaReduce, (number)best), p); + // compute new Defect spOp->prepare(u); spOp->apply(d, u); // compute new Residuum norm = d.norm(); -#endif - // check if defect-norm is smaller than maximum allowed defect value if (norm > m_maxDefect) @@ -364,15 +276,8 @@ class StandardLineSearch : public ILineSearch break; } -#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE - - // reset u and eventual local variables - m_newtonUpdater->resetSolution(u,s); -#else // reset u u = s; -#endif - } // print end line @@ -383,28 +288,10 @@ class StandardLineSearch : public ILineSearch UG_LOG(m_offset << " ++++ Line Search converged.\n"); } - -#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE - if( ! m_newtonUpdater->tellAndFixUpdateEvents(u) ) - { - UG_LOG("unable to fix local Newton updates" << std::endl ); - return false; - } -#endif // we're done return true; } - -#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE - - virtual void setNewtonUpdater( SmartPtr > nU ) - { - m_newtonUpdater = nU; - } - -#endif - protected: /// solution in line direction vector_type s; @@ -436,11 +323,6 @@ class StandardLineSearch : public ILineSearch /// number of spaces inserted before output std::string m_offset; - -#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE -private: - SmartPtr > m_newtonUpdater; -#endif }; } // end namespace ug diff --git a/ugbase/lib_disc/operator/non_linear_operator/newton_solver/nestedNewtonRFSwitch.h b/ugbase/lib_disc/operator/non_linear_operator/newton_solver/nestedNewtonRFSwitch.h deleted file mode 100644 index 39a488d6b..000000000 --- a/ugbase/lib_disc/operator/non_linear_operator/newton_solver/nestedNewtonRFSwitch.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * nestedNewtonRFSwitch.h - * - * Created on: 27.07.2021 - * Author: Markus Knodel - */ - -#ifndef UGCORE_UGBASE_NESTEDNEWTONRFSWITCH_H_ -#define UGCORE_UGBASE_NESTEDNEWTONRFSWITCH_H_ - -#ifndef ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE -#define ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE 0 -#endif - - - -#endif /* UGCORE_UGBASE_NESTEDNEWTONRFSWITCH_H_ */ diff --git a/ugbase/lib_disc/operator/non_linear_operator/newton_solver/nestedNewtonRFSwitch.h.in b/ugbase/lib_disc/operator/non_linear_operator/newton_solver/nestedNewtonRFSwitch.h.in deleted file mode 100644 index 8add4906f..000000000 --- a/ugbase/lib_disc/operator/non_linear_operator/newton_solver/nestedNewtonRFSwitch.h.in +++ /dev/null @@ -1,17 +0,0 @@ -/* - * nestedNewtonRFSwitch.h - * - * Created on: 27.07.2021 - * Author: Markus Knodel - */ - -#ifndef UGCORE_UGBASE_NESTEDNEWTONRFSWITCH_H_ -#define UGCORE_UGBASE_NESTEDNEWTONRFSWITCH_H_ - -#ifndef ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE -#define ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE ${SET_NESTED_NEWTON} -#endif - - - -#endif /* UGCORE_UGBASE_NESTEDNEWTONRFSWITCH_H_ */ diff --git a/ugbase/lib_disc/operator/non_linear_operator/newton_solver/newton.h b/ugbase/lib_disc/operator/non_linear_operator/newton_solver/newton.h index 10a974002..6a50f7df5 100644 --- a/ugbase/lib_disc/operator/non_linear_operator/newton_solver/newton.h +++ b/ugbase/lib_disc/operator/non_linear_operator/newton_solver/newton.h @@ -47,14 +47,6 @@ #include "newton_update_interface.h" #include "lib_algebra/operator/debug_writer.h" -#include "nestedNewtonRFSwitch.h" - -#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE - -#include "newtonUpdaterGeneric.h" - -#endif - namespace ug { /// Newton solver for assembling based discretizations @@ -156,13 +148,6 @@ class NewtonSolver void set_reassemble_J_freq(int freq) {m_reassembe_J_freq = freq;}; -#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE - void setNewtonUpdater( SmartPtr > nU ) - { - m_newtonUpdater = nU; - } -#endif - private: /// help functions for debug output /// \{ @@ -204,13 +189,6 @@ class NewtonSolver std::vector m_vNonLinSolverRates; std::vector m_vLinSolverRates; /// \} - -#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE - - SmartPtr > m_newtonUpdater; - -#endif - }; } diff --git a/ugbase/lib_disc/operator/non_linear_operator/newton_solver/newtonUpdaterGeneric.h b/ugbase/lib_disc/operator/non_linear_operator/newton_solver/newtonUpdaterGeneric.h deleted file mode 100644 index f6dacfc82..000000000 --- a/ugbase/lib_disc/operator/non_linear_operator/newton_solver/newtonUpdaterGeneric.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * newtonUpdaterGeneric.h - * - * Created on: 28.07.2021 - * Author: Markus Knodel - */ - -#ifndef UGCORE_UGBASE_LIB_DISC_OPERATOR_NON_LINEAR_OPERATOR_NEWTON_SOLVER_NEWTONUPDATERGENERIC_H_ -#define UGCORE_UGBASE_LIB_DISC_OPERATOR_NON_LINEAR_OPERATOR_NEWTON_SOLVER_NEWTONUPDATERGENERIC_H_ - -#include -#include -#include -#include -#include -#include - -#include "common/common.h" - -namespace ug -{ - -template -class NewtonUpdaterGeneric -{ - -public: - - virtual ~NewtonUpdaterGeneric() {}; - - - using vector_type = TVector; - - virtual bool updateSolution( vector_type & sol, vector_type const & corr, bool signNegative = true ) - { - if( signNegative ) - sol -= corr; - else - sol += corr; - - return true; -// return (*this)(sol, 1, sol, - 1, corr ); - } - - - virtual bool updateSolution( vector_type & solNew, number scaleOldSol, vector_type const & solOld, - number scaleCorr, vector_type const & corr ) - { - VecScaleAdd(solNew, scaleOldSol, solOld, scaleCorr, corr); - - return true; - - } - - virtual bool resetSolution( vector_type & resettedSol, vector_type const & oldSol ) - { - resettedSol = oldSol; - - // reset not only u, but also internal variables if available!!!!! - - return true; - } - - virtual bool tellAndFixUpdateEvents( vector_type const & sol ) - { - return true; - } - -}; - -} - - -#endif /* UGCORE_UGBASE_LIB_DISC_OPERATOR_NON_LINEAR_OPERATOR_NEWTON_SOLVER_NEWTONUPDATERGENERIC_H_ */ - - -// muss noch im Newton und line search irgendwie automatisch so initialisiert werden, aber auf User-Wunsch ueberschrieben -// mit Hilfe von gettern und settern, damit entweder der line search oder der Newton selber sich das vom anderen holen koennen -// und dann muss es soweit registriert werden, wie es noetig ist, damit man von aussen zu greifen kann -// und die abgeleiteten Klassen brauchen ggf einen Konstruktor und so weiter -/// Vector type -//typedef typename TAlgebra::vector_type vector_type; - -// using vector_type = TVector; // typename TAlgebra::vector_type; -// using vec_typ_val_typ = typename vector_type::value_type; - -//typedef TVector vector_type; // typename TAlgebra::vector_type; -//typedef typename vector_type::value_type vec_typ_val_typ; -//typedef typename vector_type::value_type value_type; - -// template //, typename ScalTyp > -// template //, typename ScalTyp > -// bool updateNewton( vector_type & solNew, value_type scaleOldSol, vector_type const & solOld, -// value_type scaleCorr, vector_type const & corr ) -// bool updateNewton( VecTyp & solNew, ScalTyp scaleOldSol, VecTyp const & solOld, -// ScalTyp scaleCorr, VecTyp const & corr ) -// bool updateNewton( VecTyp & solNew, typename VecTyp::value_type scaleOldSol, VecTyp const & solOld, -// typename VecTyp::value_type scaleCorr, VecTyp const & corr ) -// bool updateNewton( vector_type & solNew, ScalTyp scaleOldSol, vector_type const & solOld, -// ScalTyp scaleCorr, vector_type const & corr ) -// static_assert( std::is_same::value, "is ScalType double" ); -// -// static_assert( !std::is_same::value, "! is ScalType number" ); -// -// static_assert( std::is_same::value, "is it value_type" ); -// -// static_assert( std::is_same::value, "is value_type double" ); -// -// static_assert( std::is_same::value, "is value_type number" ); - - // Standard: try on line u := u - lambda*p - // VecScaleAdd(u, 1.0, u, (-1)*lambda, p); - -// typedef typename vector_type::size_type size_type; -//// using size_type = typename vector_type::size_type; -// -// for(size_type i = 0; i < solNew.size(); ++i) -// { -// solNew[i] = scaleOldSol * solOld[i] + scaleCorr * corr[i]; -// } diff --git a/ugbase/lib_disc/operator/non_linear_operator/newton_solver/newton_impl.h b/ugbase/lib_disc/operator/non_linear_operator/newton_solver/newton_impl.h index 3dda607eb..11e8ee6f1 100644 --- a/ugbase/lib_disc/operator/non_linear_operator/newton_solver/newton_impl.h +++ b/ugbase/lib_disc/operator/non_linear_operator/newton_solver/newton_impl.h @@ -35,14 +35,11 @@ #include #include -#include #include "newton.h" #include "lib_disc/function_spaces/grid_function_util.h" #include "common/util/string_util.h" -#include "lib_disc/operator/non_linear_operator/newton_solver/nestedNewtonRFSwitch.h" - #define PROFILE_NEWTON #ifdef PROFILE_NEWTON #define NEWTON_PROFILE_FUNC() PROFILE_FUNC_GROUP("Newton") @@ -70,10 +67,6 @@ NewtonSolver(SmartPtr > LinearSolver, m_reassembe_J_freq(0), m_dgbCall(0), m_lastNumSteps(0) -#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE - , - m_newtonUpdater(new NewtonUpdaterGeneric{}) -#endif {}; template @@ -88,10 +81,6 @@ NewtonSolver() : m_reassembe_J_freq(0), m_dgbCall(0), m_lastNumSteps(0) -#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE - , - m_newtonUpdater(new NewtonUpdaterGeneric{}) -#endif {}; template @@ -106,10 +95,6 @@ NewtonSolver(SmartPtr > N) : m_reassembe_J_freq(0), m_dgbCall(0), m_lastNumSteps(0) -#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE - , - m_newtonUpdater(new NewtonUpdaterGeneric{}) -#endif { init(N); }; @@ -126,10 +111,6 @@ NewtonSolver(SmartPtr > spAss) : m_reassembe_J_freq(0), m_dgbCall(0), m_lastNumSteps(0) -#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE - , - m_newtonUpdater(new NewtonUpdaterGeneric{}) -#endif { m_spAss = spAss; m_N = SmartPtr >(new AssembledOperator(m_spAss)); @@ -296,12 +277,6 @@ bool NewtonSolver::apply(vector_type& u) { m_spLineSearch->set_offset(" # "); NEWTON_PROFILE_BEGIN(NewtonLineSearch); - -#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE - - m_spLineSearch->setNewtonUpdater(m_newtonUpdater); - -#endif if(!m_spLineSearch->search(m_N, u, *spC, *spD, m_spConvCheck->defect())) { UG_LOG("ERROR in 'NewtonSolver::apply': " @@ -313,35 +288,9 @@ bool NewtonSolver::apply(vector_type& u) // No line search: Compute new defect else { -#if ENABLE_NESTED_NEWTON_RESOLFUNC_UPDATE - // update solution - //u -= *spC; -// if( ! (*m_newtonUpdater)() ) - - //bool acceptedNewtonUpdate = m_newtonUpdater->updateNewton(u,*spC); - - //if( ! acceptedNewtonUpdate ) - - if( ! m_newtonUpdater->updateSolution(u,*spC) ) - { - UG_LOG("ERROR in 'NewtonSolver::apply': " - "Newton Update did not work.\n"); - // TODO FIXME was macht conv check update? wie kriege ich hier einfach ein riesiges Residuum rein, ohne was zu rechnen? - return false; - } - - if( ! m_newtonUpdater->tellAndFixUpdateEvents(u) ) - { - UG_LOG("unable to fix local Newton updates" << std::endl ); - return false; - } - - -#else // update solution u -= *spC; -#endif - + // compute new Defect NEWTON_PROFILE_BEGIN(NewtonComputeDefect); m_N->prepare(u); From 1bd57e2f9f0915b0d103ae28e199fed1d0991d7f Mon Sep 17 00:00:00 2001 From: Arne Naegel Date: Wed, 10 Jul 2024 17:29:53 +0200 Subject: [PATCH 20/58] Revert "KluftInnen Erzeugung mit DiamantInnen als Ziel" This reverts commit 79e85b749845f2714c7762db5085ab2ae42de446. --- .../lib_grid/algorithms/extrusion/expand_layers.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp index b47ce9f8b..a07a4f39f 100644 --- a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp +++ b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp @@ -3200,8 +3200,9 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c // dieselben Methoden wie im Fall von einer durchgehenden Kluft an einem Vertex, dort kopieren // bzw Funktion schreiben, die beides macht - // hier wird der Fall abgezweigt, dass wir auf der durchgehenden Seite einer Kluft sind + // TODO FIXME irgendwie muss hier der Fall abgezweigt werden, dass wir auf der durchgehenden Seite einer Kluft sind // wenn wir eine T-Kreuzung haben + // HHHHHHHHHHHH hier kritischer Punkt aktuell std::vector nextFracVrt; @@ -4198,12 +4199,8 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c nfn++; } - // sollen die Boundary Edges zur boundary gehören, oder zur Kluft? - // wie ist es mit den Knoten, sind die alle richtig zugewiesen bezüglich subset? - - // TODO FIXME HHHHHHHHHHHHHHHHHH - // jetzt muss noch der Diamant erzeugt werden - // Ziel: KluftInnen erzeugen + // TODO FIXME sollen die Boundary Edges zur boundary gehören, oder zur Kluft? + // TODO FIXME wie ist es mit den Knoten, sind die alle richtig zugewiesen bezüglich subset? // remove the temporary attachments From 3f4e1bc7e1495b4b908e1f3faf4dd3723948041c Mon Sep 17 00:00:00 2001 From: Arne Naegel Date: Wed, 10 Jul 2024 17:42:50 +0200 Subject: [PATCH 21/58] Merge --- ugbase/bridge/grid_bridges/file_io_bridge.cpp | 11 +- .../algorithms/extrusion/expand_layers.cpp | 12 +-- .../algorithms/extrusion/expand_layers.h | 8 -- ugbase/lib_grid/file_io/file_io_vtu.cpp | 100 +----------------- ugbase/lib_grid/file_io/file_io_vtu.h | 13 --- 5 files changed, 3 insertions(+), 141 deletions(-) diff --git a/ugbase/bridge/grid_bridges/file_io_bridge.cpp b/ugbase/bridge/grid_bridges/file_io_bridge.cpp index 0f832ab5c..f22de584d 100644 --- a/ugbase/bridge/grid_bridges/file_io_bridge.cpp +++ b/ugbase/bridge/grid_bridges/file_io_bridge.cpp @@ -35,7 +35,6 @@ #include "lib_grid/multi_grid.h" #include "lib_grid/file_io/file_io.h" #include "lib_grid/file_io/file_io_ugx.h" -#include "lib_grid/file_io/file_io_vtu.h" using namespace std; @@ -78,13 +77,6 @@ bool SaveGridHierarchy(MultiGrid& mg, const char* filename) return SaveGridToFile(mg, mg.get_hierarchy_handler(), filename); } -void SetVTURegionOfInterestIdentifier( char const * regOfInt ) -{ - PROFILE_FUNC_GROUP("grid"); - GridReaderVTU::setRegionOfInterestIdentifier( std::string( regOfInt ) ); - return; -} - void RegisterGridBridge_FileIO(Registry& reg, string parentGroup) { @@ -137,8 +129,7 @@ void RegisterGridBridge_FileIO(Registry& reg, string parentGroup) .add_function("SaveParallelGridLayout", &SaveParallelGridLayout, grp, "", "mg#filename#offset") .add_function("SaveSurfaceViewTransformed", &SaveSurfaceViewTransformed) - .add_function("SaveGridLevelToFile", &SaveGridLevelToFile) - .add_function("SetVTURegionOfInterestIdentifier", static_cast(&SetVTURegionOfInterestIdentifier) ); + .add_function("SaveGridLevelToFile", &SaveGridLevelToFile); } }// end of namespace diff --git a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp index a07a4f39f..58d5b052b 100644 --- a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp +++ b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp @@ -39,17 +39,6 @@ #include "lib_grid/grid/grid_util.h" //#include "lib_grid/util/simple_algebra/least_squares_solver.h" -#include -#include -#include -#include -#include -#include -#include - -#include "support.h" - - using namespace std; namespace ug{ @@ -716,6 +705,7 @@ bool ExpandFractures2d(Grid& grid, SubsetHandler& sh, const vector return true; } + using VertFracTrip = VertexFractureTriple; //using VecVertFracTrip = std::vector; diff --git a/ugbase/lib_grid/algorithms/extrusion/expand_layers.h b/ugbase/lib_grid/algorithms/extrusion/expand_layers.h index 6819d60c7..667d6e359 100644 --- a/ugbase/lib_grid/algorithms/extrusion/expand_layers.h +++ b/ugbase/lib_grid/algorithms/extrusion/expand_layers.h @@ -75,14 +75,6 @@ bool ExpandFractures2d(Grid& grid, SubsetHandler& sh, const std::vector& fracInfos, bool expandInnerFracBnds, bool expandOuterFracBnds); -/** - * 2 dimensional fracture expansion for finite extensions, using the Arte algorithm - * - */ -bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, - const std::vector& fracInfos, - bool expandInnerFracBnds, bool expandOuterFracBnds); - /** * This algorithm indirectly uses Grid::mark. diff --git a/ugbase/lib_grid/file_io/file_io_vtu.cpp b/ugbase/lib_grid/file_io/file_io_vtu.cpp index ac8ee9d5b..cd9fa2577 100644 --- a/ugbase/lib_grid/file_io/file_io_vtu.cpp +++ b/ugbase/lib_grid/file_io/file_io_vtu.cpp @@ -31,8 +31,6 @@ */ #include "file_io_vtu.h" -#include -#include using namespace std; using namespace rapidxml; @@ -413,8 +411,7 @@ GridReaderVTU::~GridReaderVTU() { } -#if 0 -// original function + bool GridReaderVTU:: parse_file(const char* filename) { @@ -445,81 +442,6 @@ parse_file(const char* filename) // notify derived classes that a new document has been parsed. return new_document_parsed(); } -#else - -bool GridReaderVTU:: -parse_file(const char* filename) -{ - ifstream in(filename, ios::binary); - if(!in) - return false; - - m_filename = filename; - -// get the length of the file - streampos posStart = in.tellg(); - in.seekg(0, ios_base::end); - streampos posEnd = in.tellg(); - streamsize size = posEnd - posStart; - -// go back to the start of the file - in.seekg(posStart); - - char * fileContentOriginal = new char[size + 1]; - - in.read(fileContentOriginal,size); - fileContentOriginal[size] = 0; - in.close(); - - std::string fiCo2Str(fileContentOriginal); - - delete [] fileContentOriginal; - fileContentOriginal = NULL; - - std::string regInf("RegionInfo"); - - if ( fiCo2Str.find(regInf) == std::string::npos && fiCo2Str.find(m_regionOfInterest) != std::string::npos ) - { - // we need to insert the additional string - - std::string regInfLines; - - regInfLines.append( "\n\n"); - - regInfLines.append( "" ); - - std::string insAft( "" ); - - size_t cedava = fiCo2Str.find( insAft ); - - if( cedava == std::string::npos ) - return false; - - size_t insVal = cedava + insAft.size(); - - fiCo2Str.insert( insVal, regInfLines ); - - } - - char* fileContent = m_doc.allocate_string(0, fiCo2Str.size() ); - - strcpy(fileContent, fiCo2Str.c_str()); - - -// parse the xml-data - m_doc.parse<0>(fileContent); - -// notify derived classes that a new document has been parsed. - return new_document_parsed(); -} - -#endif - - bool GridReaderVTU:: new_document_parsed() @@ -539,7 +461,6 @@ new_document_parsed() m_entries.push_back(GridEntry(curNode)); GridEntry& gridEntry = m_entries.back(); - // collect associated subset handlers xml_node<>* curSHNode = curNode->first_node("RegionInfo"); while(curSHNode){ @@ -648,14 +569,6 @@ subset_handler(ISubsetHandler& shOut, vector subsetIndices; read_scalar_data(subsetIndices, regionDataNode, true); - if( subsetIndices.size() != cells.size() ) - { - vector subsetIndicesDbl; - read_scalar_data(subsetIndicesDbl, regionDataNode, true); - - trafoDblVec2Int( subsetIndicesDbl, subsetIndices ); - } - UG_COND_THROW(subsetIndices.size() != cells.size(), "Mismatch regarding number of cells and number of region-indices!"); @@ -859,17 +772,6 @@ create_cells(std::vector& cellsOut, return true; } -void GridReaderVTU:: -trafoDblVec2Int( std::vector const & dblVec, std::vector & intVec ) -{ - intVec = std::vector(); - - for( auto d : dblVec ) - { - intVec.push_back( static_cast( d ) ); - } -} - xml_node<>* GridReaderVTU:: find_child_node_by_argument_value(rapidxml::xml_node<>* parent, diff --git a/ugbase/lib_grid/file_io/file_io_vtu.h b/ugbase/lib_grid/file_io/file_io_vtu.h index a02aaaa84..3aa18aa3d 100644 --- a/ugbase/lib_grid/file_io/file_io_vtu.h +++ b/ugbase/lib_grid/file_io/file_io_vtu.h @@ -220,12 +220,6 @@ class GridReaderVTU size_t refGridIndex, size_t subsetHandlerIndex); - static std::string const getRegionOfInterestIdentifyer() - { return m_regionOfInterest; } - - static void setRegionOfInterestIdentifier( std::string const & regOfInt ) - { m_regionOfInterest = regOfInt; } - protected: struct SubsetHandlerEntry { @@ -275,8 +269,6 @@ class GridReaderVTU rapidxml::xml_node<>* dataNode, bool clearData = true); - void trafoDblVec2Int( std::vector const & dblVec, std::vector & intVec ); - template void check_indices(std::vector& inds, size_t first, size_t num, size_t max); @@ -294,11 +286,6 @@ class GridReaderVTU /// holds grids which already have been created std::vector m_entries; - - - - inline static std::string m_regionOfInterest = "regions"; // ProMesh standard, in Braunschweig case often "Material Id", but not always - }; }// end of namespace From 07c5bdf083e77b4a11d9e7d576feb43eb0d90a2c Mon Sep 17 00:00:00 2001 From: Arne Naegel Date: Wed, 10 Jul 2024 17:45:20 +0200 Subject: [PATCH 22/58] Revert "Merge commit '79e85b749845f2714c7762db5085ab2ae42de446'" This reverts commit 793182bfa7ab5404d32944c21783d2eaab6d67f1, reversing changes made to ee16da29b2d0b3e8583840294869668f0ed83294. --- ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp index 58d5b052b..ab7ba4d3a 100644 --- a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp +++ b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp @@ -706,6 +706,7 @@ bool ExpandFractures2d(Grid& grid, SubsetHandler& sh, const vector } + using VertFracTrip = VertexFractureTriple; //using VecVertFracTrip = std::vector; @@ -4263,6 +4264,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c + /** Selects all involved geometic objects and assigns marks to them. * If required, som edges may be split, so that we always operate * on a fully expandable fracture. From 4991e81b13d77194faff24913b839b489aef2dbd Mon Sep 17 00:00:00 2001 From: Arne Naegel Date: Thu, 11 Jul 2024 06:34:31 +0200 Subject: [PATCH 23/58] Revert to old version (before arte merge) --- .../algorithms/extrusion/expand_layers.cpp | 3560 ----------------- 1 file changed, 3560 deletions(-) diff --git a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp index ab7ba4d3a..0db34358a 100644 --- a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp +++ b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp @@ -705,3566 +705,6 @@ bool ExpandFractures2d(Grid& grid, SubsetHandler& sh, const vector return true; } - - -using VertFracTrip = VertexFractureTriple; - -//using VecVertFracTrip = std::vector; - -//using VvftIterator = VecVertFracTrip::iterator; - -using AttVrtVec = Attachment >; - -using VertexOfFaceInfo = VertexFractureTriple< std::pair, Face*, std::pair >; - - -using IndexType = unsigned short; - -template -bool expandSingleFractureAtGivenSide( vector3 const & nOne, vector3 const & nTwo, - Edge * edgeOne, Edge * edgeTwo, - Face * facOne, Face * facTwo, - vector const & fracInfosBySubset, - vector3 const & posOldVrt, - Grid::VertexAttachmentAccessor & aaPos, - Grid & grid, SubsetHandler & sh, - ASOF const & assoFaces, - std::vector const & nextFracVrt, - Grid::FaceAttachmentAccessor & aaVrtVecFace, - int & dbg_flachen_passiert, - Vertex * iterV - ) -{ - -#if 1 - // gleiche Seite vermutet oder gegeben - - // average the normals - - vector3 normSum; - - VecAdd( normSum, nOne, nTwo ); - - vector3 normSumNormed; - - VecNormalize(normSumNormed, normSum); - - UG_LOG("averaged normal " << normSumNormed << std::endl); - - std::vector attEdg; - std::vector attFac; - - attEdg.push_back( edgeOne ); - attEdg.push_back( edgeTwo ); - - attFac.push_back( facOne ); - attFac.push_back( facTwo ); - - // jetzt neuen Vertex erzeugen in Richtung der Normalen - // sonst ist das attachment Schwachsinn! - - vector3 posNewVrt; - - vector3 moveVrt; - - auto subsIndEdgOne = sh.get_subset_index(edgeOne); - - auto subsIndEdgTwo = sh.get_subset_index(edgeTwo); - - if( subsIndEdgOne != subsIndEdgTwo ) - { - UG_THROW("subsets passen nicht Vereinheitlichung" << std::endl ); - } - - number width = fracInfosBySubset.at(subsIndEdgOne).width; - - // der Faktor ist Käse und muss noch aus den Eingaben übernommen werden - VecScale(moveVrt, normSumNormed, width/2. ); - - VecAdd(posNewVrt, posOldVrt, moveVrt ); - - UG_LOG("neuer Vertex " << posNewVrt << std::endl ); - - // TODO FIXME hier ist das PROBLEM, SEGFAULT durch create regular vertex - - Vertex * newShiftVrtx = *grid.create(); - aaPos[newShiftVrtx] = posNewVrt; - - sh.assign_subset(newShiftVrtx, subsIndEdgOne ); - - - - // alle anhängenden faces müssen noch zu wissen bekommen - // dass es diesen neuen Vertex gibt, nicht nur die - // an den edges anhängenden - // vielleicht gibt es einen Loop über attached faces des - // Vertex, für die schon bekannten direkt angehängten klar - // wenn auch dort vermerkt werden muss im Attachment von Seb - // bei den anderen, die keine Edge haben von der Kluft - // da muss man die Normale ins Zentrum bestimmen - // um heraus zu finden, ob sie auf dieser seite sind - // am besten dann das Attachment der faces für vertizes - // von Seb recyclen - - // loop über assosciated faces des vertex am besten - // vermutlich auch noch assosciated edges, um - // zu markieren, welche weg fallen sollen, wenn - // nicht von Kluft selber, sondern quasi verschoben - // und neu erzeugt - - int dbg_FaceIterator = 0; - - for( auto const & ifac : assoFaces ) - { - bool isFromFrac = false; - - int dbg_innterFacFracIt = 0; - - for( auto const & facFrac : attFac ) - { - - static_assert( std::is_same< decltype( (facFrac) ), decltype ( ifac ) >::value ); - - if( ifac == facFrac ) - { - isFromFrac = true; - - static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value ); - static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value ); - - } - } - - bool atRightSide = false; - - if( isFromFrac ) - atRightSide = true; - - if( !isFromFrac ) - { - // check if on same side of edge where the normal points to: compute cosinus between vector of face center - // perpendicular to the edge - - vector3 facCenter = CalculateCenter( ifac, aaPos ); - - vector3 perpendicu; - - if( nextFracVrt.size() != 2 ) - { - UG_THROW("komische Groesse" << std::endl); - } - - DropAPerpendicular(perpendicu, facCenter, aaPos[nextFracVrt[0]], aaPos[nextFracVrt[1]]); - - vector3 tmpN; - - VecSubtract(tmpN, facCenter, perpendicu ); - - VecNormalize(tmpN, tmpN); - - UG_LOG("Normale zum Face ist " << tmpN << std::endl); - - number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, normSumNormed ); - - UG_LOG("Cosinus zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); - - if( cosBetwFracEdgAndDirection2Face > 0 ) - { - UG_LOG("assuming face to be on richt side" << std::endl); - - atRightSide = true; - -#if ANSCHAULICH_ERZEUGE_SUDOS_ANHANG - - Vertex * otherFacCent = *grid.create(); - aaPos[otherFacCent] = facCenter; - sh.assign_subset(otherFacCent, 5 ); - - Vertex * pp = *grid.create(); - aaPos[pp] = perpendicu; - sh.assign_subset(pp, 6 ); - - sh.assign_subset(*iterFac,7); -#endif - - } - else - { - UG_LOG("assuming face to be on wrong side" << std::endl); - } - - - dbg_flachen_passiert++; - } - - - if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein - { - - // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! - vector& newVrts4Fac = aaVrtVecFace[ ifac ]; - - IndexType vrtxFnd = 0; - - for(size_t indVrt = 0; indVrt < (ifac)->num_vertices(); indVrt++ ) - { - Vertex* facVrt = (ifac)->vertex(indVrt); - - if( facVrt == iterV ) - { - newVrts4Fac[ indVrt ] = newShiftVrtx; - vrtxFnd++; - } - } - - - if( vrtxFnd <= 0 ) - { - UG_THROW("vertex not found!" << std::endl); - } - else if( vrtxFnd > 1 ) - { - UG_THROW("vertex zu oft gefunden " << vrtxFnd << std::endl ); - } - else if ( vrtxFnd == 1 ) - { - } - else - { - UG_THROW("vertex finden komisch " << std::endl); - } - - - } - - dbg_innterFacFracIt++; - - - - dbg_FaceIterator++; - - } -#endif - - return true; - -} - -#ifndef NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX -#define NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX 1 -#endif - -#ifndef ANSCHAULICH_ERZEUGE_SUDOS_ANHANG -#define ANSCHAULICH_ERZEUGE_SUDOS_ANHANG 0 -#endif - -#ifndef OLD_PROFREITER_STUFF -#define OLD_PROFREITER_STUFF 0 -#endif - -bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector const & fracInfos, - bool expandInnerFracBnds, bool expandOuterFracBnds) -{ - -// static constexpr bool dehneInnereKluftGrenzpunkteAus = false; - -// expandInnerFracBnds = false; - -// expandOuterFracBnds = true; - -// access position attachment - if(!grid.has_vertex_attachment(aPosition)){ - UG_LOG("Error in ExpandFractures 2D Arte: Missing position attachment"); - return false; - } - Grid::VertexAttachmentAccessor aaPos(grid, aPosition); - - if(!grid.option_is_enabled(FACEOPT_AUTOGENERATE_EDGES)){ - UG_LOG("WARNING in Arte 2D CalculateCreaseNormal: grid option FACEOPT_AUTOGENERATE_EDGES autoenabled.\n"); - grid.enable_options(FACEOPT_AUTOGENERATE_EDGES); - } - -// objects for temporary results - FaceDescriptor fd; - vector edges; // used for temporary results. - vector faces; // used for temporary results. - -// vectors that allow to access fracture properties by subset index - vector fracInfosBySubset(sh.num_subsets(), FractureInfo(-1, -1, 0)); - for(size_t i = 0; i < fracInfos.size(); ++i){ - if(fracInfos[i].subsetIndex >= sh.num_subsets()){ - throw(UGError("Bad subsetIndex in given fracInfos.")); - } - - fracInfosBySubset[fracInfos[i].subsetIndex] = fracInfos[i]; - } - -//////////////////////////////// -// Collect surrounding faces of all fractures in a selector -// and select edges and vertices too. - Selector sel(grid); - sel.enable_autoselection(false); - sel.enable_selection_inheritance(false); - -#if OLD_PROFREITER_STUFF - AInt aAdjMarker; // used to mark how many adjacent fractures a vertex has. - // 0: no frac, 1: frac-boundary, >1: inner frac vertex - // TODO FIXME das sieht komisch aus, ist das immer so, wenn z.B. an einer Grenze sich zwei fracs treffen? - grid.attach_to_vertices_dv(aAdjMarker, 0); - Grid::VertexAttachmentAccessor aaMarkVRT(grid, aAdjMarker); - grid.attach_to_edges_dv(aAdjMarker, 0); - Grid::EdgeAttachmentAccessor aaMarkEDGE(grid, aAdjMarker); -#endif - -// using IndexType = unsigned short; - using AttVerFracProp = Attachment >; - // attachment pair boundary is fracture, number fractures crossing - - AttVerFracProp aAdjMarkerVFP; - - VertexFractureProperties vfp0( false, 0 ); - // default value: no boundary fracture, no fractures crossing - - grid.attach_to_vertices_dv(aAdjMarkerVFP, vfp0 ); - Grid::VertexAttachmentAccessor aaMarkVrtVFP(grid, aAdjMarkerVFP); - - ABool aAdjMarkerB; // used to know if an edge is frac edge - grid.attach_to_edges_dv(aAdjMarkerB, false); - Grid::EdgeAttachmentAccessor aaMarkEdgeB(grid, aAdjMarkerB); - - - // die Vertizes, Faces und Edges, die mit einer Kluft zu tun haben - -// using VertFracTrip = VertexFractureTriple; -// - using VecVertFracTrip = std::vector; - - VecVertFracTrip vertexNoInfo; - - using AttVecVertFracTrip = Attachment; - - AttVecVertFracTrip aAdjInfoAVVFT; - - grid.attach_to_vertices_dv( aAdjInfoAVVFT, vertexNoInfo ); - Grid::VertexAttachmentAccessor aaVrtInfoFraTri(grid, aAdjInfoAVVFT ); - - - using VecEdge = std::vector; - using VecFace = std::vector; - - using AttVecEdge = Attachment; - using AttVecFace = Attachment; - - VecEdge noEdge; - VecFace noFace; - AttVecEdge aAdjInfoEdges; - AttVecFace aAdjInfoFaces; - - grid.attach_to_vertices_dv( aAdjInfoEdges, noEdge ); - Grid::VertexAttachmentAccessor aaVrtInfoAssoEdges( grid, aAdjInfoEdges ); - - grid.attach_to_vertices_dv( aAdjInfoFaces, noFace ); - Grid::VertexAttachmentAccessor aaVrtInfoAssoFaces( grid, aAdjInfoFaces ); - - // das ist Käse, ich brauche für jeden Vertex ein Attachment der Form - // class VertexTriple, bzw std vektoren von solchen vertex triplen - // da weiss dann jeder Vertex das triple - // Kante (damit subdom) - Face - normal (von Kante in Face rein) - // dann kann man nämlich anhand des Winkels von zwei Normalen - // von solchen Vertizes bestimmtn, ob sie auf die gleiche Seite der Kante zeigen - // und dann kann man sie mitteln, sofern die Vertizes keine Kreuzungs Vertizes sind - // oder keine äusseren Vertizes - ob sie dsa sind, dafür haben wir schon attachments! - - // TODO FIXME diese komischen accessoren sollen jetzt so zugewiesen - // werden, dass - /* - * jeder Kluftvertex soll wissen, welche Kluftedges ihm anliegen, und welche faces - * jede Kluftedge soll wissen, welche Vertizes ihr anliegen, und welche faces - * jedes Face, das an eine Kluft anliegt, soll wissen, welche Vertizes und Edges - * ihm anliegen - * letzteres muss man vielleicht noch ausdehnen, indem man subdomain indizes - * dazu bringt - * das kann auch notwendig sein fuer alle anderen - wirklich? - * die edges und faces kennen ihre subdomain - * nur beim Vertex kann in Kreuzungspunkten ein Problem sein - * zudem ist die subdomain der faces EGAL, im Zweifel entscheidet die subdomain - * der edges, die anliegen bzw der edge, die anliegt! - * - */ - -// iterate over the given fracture infos and select all fracture edges -// and fracture vertices. - for(size_t i_fi = 0; i_fi < fracInfos.size(); ++i_fi) - { - int fracInd = fracInfos[i_fi].subsetIndex; - - for(EdgeIterator iter = sh.begin(fracInd); iter != sh.end(fracInd); ++iter) - { - // mark edge and vertices - sel.select(*iter); - -#if OLD_PROFREITER_STUFF - aaMarkEDGE[*iter] = 1; -#endif - - aaMarkEdgeB[*iter] = true; - - // select associated vertices - for(size_t i = 0; i < 2; ++i) - { - Vertex* v = (*iter)->vertex(i); - sel.select(v); - - // wird in jedem Fall inkrimiert, da der Vertex auf jeden Fall mit einer Kante einer frac verbunden sein muss, sonst darf der loop gar nicht darüber gehen - aaMarkVrtVFP[v]++; - - if( IsBoundaryVertex2D(grid, v) ) - aaMarkVrtVFP[v].setIsBndFracVertex(); - - -#if OLD_PROFREITER_STUFF - // das ist Sebastians loop, den nicht mehr lassen lassen - // if fracture boundaries are expanded, we'll regard all fracture vertices - // as inner vertices - if(expandInnerFracBnds) - { - if(!expandOuterFracBnds) - { - if(IsBoundaryVertex2D(grid, v)) - aaMarkVRT[v]++; - else - aaMarkVRT[v] = 2; - } - else - aaMarkVRT[v] = 2; - } - else - aaMarkVRT[v]++; -#endif - - } - } - } - - -#if OLD_PROFREITER_STUFF -// Make sure that selected vertices that lie on the boundary of the geometry -// are treated as inner fracture vertices. -// This is only required if frac-boundaries are not expanded anyways. - if(expandOuterFracBnds && !expandInnerFracBnds){ - for(VertexIterator iter = sel.vertices_begin(); - iter != sel.vertices_end(); ++iter) - { - Vertex* v = *iter; - if(aaMarkVRT[v] == 1){ - if(IsBoundaryVertex2D(grid, v)) - aaMarkVRT[v] = 2; - } - } - } - // TODO FIXME was soll das fuer ein Kaese sein? -#endif - - int dbg_flachen_passiert = 0; - - for(VertexIterator iter = sel.begin(); iter != sel.end(); ++iter) - { - - bool wahl = true; - - - // so stimmt es vielleicht, aber ist auch ein komischer Fall, innen expandieren und aussen nicht...... die Frage ist, ob es oonst Sinn macht..... - if( expandInnerFracBnds && !expandOuterFracBnds && aaMarkVrtVFP[*iter].getIsBndFracVertex() ) - wahl = false; - - static_assert( std::is_same< decltype(*iter), Vertex * >::value ); - - bool isBnd = aaMarkVrtVFP[ *iter ].getIsBndFracVertex(); - auto numCrosFrac = aaMarkVrtVFP[ *iter ].getNumberFracEdgesInVertex(); - - if( ! isBnd && numCrosFrac == 1 ) - { - wahl = false; - } - -// if( ! dehneInnereKluftGrenzpunkteAus ) -// { -// if( numCrosFrac == 1 ) // inner frac boundary vertex -// { -// wahl = false; -// } -// } - - - if( wahl ) - { - sel.select(grid.associated_edges_begin(*iter), - grid.associated_edges_end(*iter)); - sel.select(grid.associated_faces_begin(*iter), - grid.associated_faces_end(*iter)); - - // TODO FIXME hier ein attachment der associated faces und vertizes, am besten als Klasse, die std vertizes davon frisst, an jeden Vertex anhängen - // so muss man später nicht nochmal über alle Faces und Edges laufen, sondern hat die angehängten schon zur Hand - // im Fall, dass eine Kreuzung vorliegt, das Ganze irgendwann ordnen, dass nebeneinander liegende Faces und edges in eine verkettete Liste kommen - // vielleicht das aber nur bei den Schnittvertizes später - // und vielleicht sollen die Faces Zeiger auf ihre Edges bekommen, und die edges auf die faces, aber wird irgendwann zu wild verzeigert..... - // vielleicht einfach attachment von faces und edges unabhängig an jeden Fracture Vertex...... - - // testen, ob ein Schnittvertex vor liegt, indem die Anzahl der touches getestet wird, anhand einfacher Geometrien testen, was die Anzahl ist - - // mit UG_LOG ausgeben, was die Koordinaten sind, und die Anzahl der hits - - VecFace assFac; - VecEdge assEdg; - -// UG_LOG("----------" << std::endl); - - for( std::vector::iterator iterFac = grid.associated_faces_begin(*iter); iterFac != grid.associated_faces_end(*iter); iterFac++ ) - { - assFac.push_back(*iterFac); -// vector3 facCenter = CalculateCenter( *iterFac, aaPos ); -// UG_LOG("fac center " << facCenter << std::endl); - -// sh.assign_subset(*iterFac, 10); - } - -// UG_LOG("----------" << std::endl); - - for( std::vector::iterator iterEdg = grid.associated_edges_begin(*iter); iterEdg != grid.associated_edges_end(*iter); iterEdg++ ) - { - assEdg.push_back(*iterEdg); -// sh.assign_subset(*iterEdg,10); - } - - aaVrtInfoAssoFaces[*iter] = assFac; - aaVrtInfoAssoEdges[*iter] = assEdg; - - UG_LOG("marked vertex wahl: " << aaPos[*iter] << " is bnd " << isBnd << " number cross frac " << numCrosFrac << std::endl ); - - // fuer Nicht Boundary Vertizes muessen wir durch 2 teilen, damit wir richtige Anzahl der - // Fracs haben, die durch den spezifischen Vertex durch geht - // FALSCH war mal so, ist schon abgestellt, es wird angezeigt, wieviele Ecken von Kanten rein kommen - - } - else - { - UG_LOG("marked vertex unwahl: " << aaPos[*iter] << " is bnd " << isBnd << " number cross frac " << numCrosFrac << std::endl ); - } - - } - -// return true; - - using pairIndDbl = std::pair; - - std::vector< pairIndDbl > fracSubdom_facePerpendMinVal; - - for( auto const & pf: fracInfos ) - { - fracSubdom_facePerpendMinVal.push_back( pairIndDbl( pf.subsetIndex, std::numeric_limits::max() ) ); - } - - T_min minDistPerpOverall( std::numeric_limits::max() ); - -// for( auto fI : fracInfos ) -// for( size_t fraInfInd = 0; fraInfInd < fracInfos.size(); fraInfInd++ ) - for( auto & fsfpmv : fracSubdom_facePerpendMinVal ) - { -// int fracInd = fracInfos[fraInfInd].subsetIndex; -// int fracInd = fI.subsetIndex; - - auto fracInd = fsfpmv.first; - - T_min minDistPerpThisFrac( fsfpmv.second ); - - for(EdgeIterator iterEdg = sh.begin(fracInd); iterEdg != sh.end(fracInd); iterEdg++ ) - { - - // get subdomain of edge - - auto sudoEdg = sh.get_subset_index(*iterEdg); - - static_assert( std::is_same< decltype(sudoEdg), int >::value ); - - // get vertices of edge, always 2 - - std::vector verticesEdg; - - static_assert( std::is_same< Vertex*, decltype( (*iterEdg)->vertex(0) ) >::value ); - - for( size_t i = 0; i < 2; ++i ) - verticesEdg.push_back( (*iterEdg)->vertex(i) ); - - // get attached faces - -#if 0 - std::vector assFace; - - // TODO FIXME dieser loop kann vielleicht vereinfacht werden, wenn dieser ganze loop umgebaut wird - // denn die Vertizes kennen dann die assosciated faces schon - // der Name AssociatedFaceIterator ist sowieso verwirrend, hat mit assosciated nix zu tun, bezieht sich auf alle std Vektoren von Face * - UG_LOG("XXXXXXXXXXXX" << std::endl); - for(Grid::AssociatedFaceIterator iterAFI = grid.associated_faces_begin( verticesEdg[0] ); - iterAFI != grid.associated_faces_end( verticesEdg[0] ); - iterAFI++ ) - { - - if(FaceContains( *iterAFI, *iterEdg )) - { - assFace.push_back( *iterAFI ); - - - vector3 facCenter = CalculateCenter( *iterAFI, aaPos ); - UG_LOG("fac center " << facCenter << std::endl); - - - -// sh.assign_subset( *iterAFI, sh.get_subset_index(*iterEdg)); - } - - } - UG_LOG("XXXXXXXXX" << std::endl); -#else - - std::vector & assFaceVrt0 = aaVrtInfoAssoFaces[verticesEdg[0]]; - - std::vector assFace; - -// static_assert( std::is_same< decltype( aaVrtInfoAssoFaces[verticesEdg[0]] )[0], std::vector >::value ); - //static_assert( std::is_same< decltype( *(aaVrtInfoAssoFaces[verticesEdg[0]]) ), Face * >::value ); - -// UG_LOG("XXXXXXXXXXXX" << std::endl); - - for( auto const & ifa : assFaceVrt0 ) - { - if(FaceContains( ifa, *iterEdg )) - { - assFace.push_back( ifa ); - -// vector3 facCenter = CalculateCenter( ifa, aaPos ); -// UG_LOG("fac center " << facCenter << std::endl); - } - } - - std::vector & assFaceVrt1 = aaVrtInfoAssoFaces[verticesEdg[1]]; - - for( auto const & ifa : assFaceVrt1 ) - { - if(FaceContains( ifa, *iterEdg )) - { - bool faceContained = false; - - for( auto const & afa : assFace ) - { - if( afa == ifa ) - faceContained = true; - } - - if( !faceContained ) - assFace.push_back( ifa ); - } - } - - -// UG_LOG("XXXXXXXXX" << std::endl); - -#endif - // von hier lernen: - // VecFace & assoFaces = aaVrtInfoAssoFaces[*iterV ist verticesEdg[0] ]; - // for( auto const & ifac : assoFaces ) - // { - // static_assert( std::is_same< decltype( ifac ), Face * const & >::value ); - // } - - - - // compute normal of edge - - std::vector< vector3 > edgeNormals; - - std::vector perpendDistances; - - for( auto const & fac : assFace ) - { - vector3 facCenter = CalculateCenter( fac, aaPos ); - - vector3 perpendicu; - - DropAPerpendicular(perpendicu, facCenter, aaPos[verticesEdg[0]], aaPos[verticesEdg[1]]); - - double perpendDist = VecLength( perpendicu ); // betrag perpendicu - - perpendDistances.push_back( perpendDist ); - - minDistPerpThisFrac( perpendDist ); - - - // vector from projection to center is the unnormalized normal - vector3 tmpN; - - VecSubtract(tmpN, facCenter, perpendicu ); - - VecNormalize(tmpN, tmpN); - - edgeNormals.push_back( tmpN ); - - static_assert( std::is_same< Edge*, decltype(*iterEdg) >::value ); - - static_assert( std::is_same< Face * const &, decltype(fac) >::value ); - static_assert( std::is_same< Face *, decltype( const_cast(fac) ) >::value ); - static_assert( std::is_same< vector3, decltype( tmpN ) >::value ); - - VertFracTrip infoVertizesThisEdge( *iterEdg, fac, tmpN ); - -// UG_LOG("TypE Fac " << typeid(const_cast(fac) ).name() << std::endl); -// UG_LOG("TypE Edg " << typeid( *iterEdg ).name() << std::endl); -// UG_LOG("TypE Vec " << typeid( tmpN ).name() << std::endl); - - - for( auto const & v : verticesEdg ) - { - static_assert( std::is_same< decltype(v), Vertex * const & >::value ); - static_assert( std::is_same< decltype(const_cast(v)), Vertex * >::value ); - aaVrtInfoFraTri[v].push_back( infoVertizesThisEdge ); - -// VecVertFracTrip allInfosVrtxThisEdg = aaVrtInfoFraTri[v]; - -// static_assert( std::is_same< decltype( aaVrtInfoFraTri[v] ), VecVertFracTrip >::value ); - -// UG_LOG("type Fac " << typeid( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getFace() ).name() << std::endl); -// UG_LOG("type Edg " << typeid( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getEdge() ).name() << std::endl); -// UG_LOG("type Vec " << typeid( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getNormal() ).name() << std::endl); - - static_assert( std::is_same< decltype( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getFace() ), Face * >::value ); - static_assert( std::is_same< decltype( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getEdge() ), Edge * >::value ); - static_assert( std::is_same< decltype( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getNormal() ), vector3 const >::value ); - } - - } - - // damit speichern wir die plus und minus Normale, und das ist alles, und auch - // gleich wieder weg - // TODO FIXME besser, wir speichern die gemittelte Normale an den Vertizes - // vielleihct als attachment pair, das die subdom kennt der frac und die Normale dazu? - // ziemlich nutzlos, die Normale wie hier gemacht in einen kurzen Vektor zu speichern, der schnell - // wieder weg ist...... - // wir brauchen alle Normalen zu jeder fracture an jedem fracture Vertex, also die Mittelung vermutlich - // diese Mittelung kann aber erst stattfinden, wenn wir nachher über die vertizes loopen, - // hier kennen wir nur die Vertizes, die an derselben Edge anliegen - - UG_LOG("EDGE NORMALS: " << sh.get_subset_index(*iterEdg) << " -> "); - - int j = 0; - - for( auto const & en: edgeNormals ) - { - - for( size_t i = 0; i < 3; i++ ) - UG_LOG( en[i] << ", " ); - - - UG_LOG(" --- " << perpendDistances[j] << " ///////// " ); - - j++; - } - - UG_LOG(std::endl); - - } - - fsfpmv.second = minDistPerpThisFrac(); - - minDistPerpOverall( fsfpmv.second ); - - UG_LOG("first " << fsfpmv.first << " second " << fsfpmv.second << std::endl); - } - - for( auto const & fsfpmv : fracSubdom_facePerpendMinVal ) - { - UG_LOG("min dist sd " << fsfpmv.first << " -> " << fsfpmv.second << std::endl ); - } - - UG_LOG("overall min dist " << minDistPerpOverall() << std::endl); - - - - // von Sebastian teilweise das Prinzip übernommen, dass die Faces wissen können, was ihre neuen Vertizes sein sollen - // create new vertices - - // we have to associate a vector of vertices with each node in the fracture. - // since an empty vector is quite small, we can associate one with each vertex in - // the whole grid. This could be optimized if required, by using subset attachments. - - // es reicht vielleicht, hier statt einem Vektor einfach nur einen Vertex * zu storen -// using AttVrtVec = Attachment >; - AttVrtVec attVrtVec; - - // we associate a vector of vertices for each face adjacent to the frac. - // it will store a set of vertices. An entry contains the new vertex, if the - // corresponding vertex is an inner fracture vertex, and NULL if not. - grid.attach_to_faces(attVrtVec); - Grid::FaceAttachmentAccessor aaVrtVecFace(grid, attVrtVec); - - - // iterate over all surrounding faces to enable face changes, this loop taken from SR but shortened - for(FaceIterator iter_sf = sel.faces_begin(); iter_sf != sel.faces_end(); ++iter_sf) - { - Face* sf = *iter_sf; - - std::vector& newVrts = aaVrtVecFace[sf]; - newVrts.resize(sf->num_vertices()); - - for(size_t i_vrt = 0; i_vrt < sf->num_vertices(); ++i_vrt) - { - newVrts[i_vrt] = NULL; - } - // erstmal so tun, als ob keine neuen Vertizes erzeugt werden an den alten Vertizes - } - - - // attachment to allow fracture vertizes to know the newly created vertizes - // due to extrusion which are related to them, in connection with - // the normals which are an average of the related edges and the faces - // defining the original normal - - // usage: store edges and associated faces in SAME order in std vectors! - using ExpandVertexMultiplett = VertexFractureTriple< std::vector, std::vector, vector3 >; - // holds the averaged normal of the related edges and their corresponding faces which give direction - - using VecExpandVertexMultiplett = std::vector; - - - VecExpandVertexMultiplett vertexMultiplettEmpty; - - using AttVecExpandVertexMultiplett = Attachment; - - AttVecExpandVertexMultiplett aAdjInfoVVEVM; - - grid.attach_to_vertices_dv( aAdjInfoVVEVM, vertexMultiplettEmpty ); - Grid::VertexAttachmentAccessor aaVrtExpMP(grid, aAdjInfoVVEVM ); - - - - // am Ende dieser Prozedur sollten alle Vertizes wissen, welche Tripel vom Typ Edge - Face - Normal zum Face hin an ihnen angelagert sind - - // damit weiss, wenn es stimmt, jeder Vertex, der an einer Fracture ist, wieviele Schnittpunkte von Fractures er hat, - // ob er ein boundary vertex ist, und was für einen Vektor von Tripeln an ihm angehängt sind - // die subdomain der Fracture muss anhand der subdomain der edge bestimmt werden immer - - UG_LOG("loop over all marked vertizes " << std::endl); - - int dbg_vertizesPassiert = 0; - - // jetzt können wir alle Vertizes ablaufen und an ihnen neue Vertizes erzeugen, die anhand der gemittelten Normalen von den Vertizes weg gehen - // ob zwei anhängende Faces auf der gleichen Seite liegen, wenn es kein Schnittvertex von zwei oder mehr Klüften ist - // das kann man anhand des Winkels zwischen zwei face Normalen unterscheiden vermutlich - // dabei müssen die edges sowieso disjunkt sein, sonst ist man sowieso sicher auf verschiedenen Seiten - // wenn wir es mit einem boundary Vertex zu tun haben, müssen wir weiter überlegen, wie wir die Verschiebung auf die äussere Kante projizieren - // muss auch mit dem Winkel zu tun haben - for(VertexIterator iterV = sel.begin(); iterV != sel.end(); ++iterV) - { - - // POsition dieses Vertex - vector3 posOldVrt = aaPos[*iterV]; - - // vielleicht muss man, wenn die neuen Vertizes da sind, diese auch gleich mit den umliegenden Knoten per neuer Kanten verbinden - // und die neuen faces erzeugen nach Löschen der alten? - // oder alle neuen Vertizes wie bei Prof Reiter in einen std Vektor, der als attachment den bisherigen Face Vertizes angehängt wird - // und Edge Vernichtung und Erzeugung neuer edges und faces wie bei Prof Reiter in Folgeschritten? - - VecVertFracTrip & vecVertFracTrip = aaVrtInfoFraTri[*iterV]; - - std::vector & allAssoEdges = aaVrtInfoAssoEdges[*iterV]; - - static_assert( std::is_same< decltype( vecVertFracTrip[ vecVertFracTrip.size() - 1 ].getFace() ), Face * >::value ); - static_assert( std::is_same< decltype( vecVertFracTrip[ vecVertFracTrip.size() - 1 ].getEdge() ), Edge * >::value ); - static_assert( std::is_same< decltype( vecVertFracTrip[ vecVertFracTrip.size() - 1 ].getNormal() ), vector3 const >::value ); - - for( auto const & vft : vecVertFracTrip ) - { - static_assert( std::is_same< decltype( vft.getFace() ), Face * >::value ); - static_assert( std::is_same< decltype( vft.getEdge() ), Edge * >::value ); - static_assert( std::is_same< decltype( vft.getNormal() ), vector3 const >::value ); - - Face * f = vft.getFace(); - Edge * e = vft.getEdge(); - vector3 n = vft.getNormal(); - - } - - using VvftIterator = VecVertFracTrip::iterator; - - VecFace & assoFaces = aaVrtInfoAssoFaces[*iterV]; - // TODO FIXME hier braucht man das nicht zu ordnen - // aber bei Kreuzpunkten von Klueften muss es so geordnet werden, wie es nebeneinander liegt - // bei den Edges gibt es auch die benachbarten, und die edges haben das attachment, ob sie Kluftedges sind - -// for( auto const & ifac : assoFaces ) -// { -// static_assert( std::is_same< decltype( ifac ), Face * const & >::value ); -// } - - - - // Anzahl der Kreuzungspunkte auslesen und danach unterscheiden, erstmal keine Kreuzung! TODO FIXME - - // irgendwie muessen wir diese Infos jetzt verwerten, um als erstes neue Vertizes zu erzeugen, anfangs für eine Kluft nur - // und danach die alten Edges und faces löschen und an neuer Stelle neu erzeugen, plus die sowieso neuen, - // oder Edges verschieben, wenn es möglich ist, die Vertizes zu verschieben, und die Edges und in Folge faces passen sich an, - // dann müssen nur die neuen edges und faces neu erzeugt werden - // verschieben der Position des Vertex löst Kaskade aus, dass Edge und Face auch verschoben werden, kann also angewendet werden - // allerdings Problem, dass die Vertizes dafür verdoppelt werden müssen und die Kanten, sonst kann man sie nicht nach aussen verschieben - // also doch komplette Neuerzeugung vermutlich..... oder doppeltes Klonen, und das alte bleibt in der Mitte..... - - vector3 posThisVrt = aaPos[*iterV]; - - UG_LOG("vertex at " << posThisVrt << std::endl ); - - bool vrtxIsBndVrt = aaMarkVrtVFP[*iterV].getIsBndFracVertex(); - // alternativ wäre möglich: IsBoundaryVertex2D(grid, *iterV) - - UG_LOG("is bndry " << vrtxIsBndVrt << std::endl); - - IndexType numFracsCrossAtVrt = aaMarkVrtVFP[*iterV].getNumberFracEdgesInVertex(); - - UG_LOG("number crossing fracs " << numFracsCrossAtVrt << std::endl); - - size_t numbAttTripl = vecVertFracTrip.size(); - - UG_LOG("sizes of vft " << numbAttTripl << std::endl ); - - if( ! vrtxIsBndVrt ) - { - - if( numFracsCrossAtVrt < 1 ) - { - UG_THROW("no fracs crossing but marked vertex? << std::endl"); - } - else if( numFracsCrossAtVrt == 1 ) - { - -// if( numbAttTripl != 0 ) -// { -// UG_THROW("Anzahl der angehaengten Triples kann nicht stimmen, Vertex einer Kluft ohne Schnittpunkte, nicht am Rand, Kluftende " << std::endl); -// } - - - - UG_LOG("END THIS VERTEX NORMAL INNER ENDING CLEFT" << std::endl); - - -// if( ! dehneInnereKluftGrenzpunkteAus ) -// { -// break; -// } - // inner vertex where fracture ends - // TODO FIXME - - // in this case, we have two attached edges, and each of these edges has two attached faces - // the faces have a naormal, and based on the normal, we can decide which faces belong to the same side of the edges - -#if 0 - - if( numbAttTripl != 2 ) - { - UG_THROW("Anzahl der angehaengten Triples kann nicht stimmen, Vertex einer Kluft ohne Schnittpunkte, nicht am Rand, Kluftende " << std::endl); - } - - // Zuordnung der Edges und Faces, die auf der gleichen Seite der fracture sind - - // und gleich auch Erzeugung der neuen Knoten, die dann - // in einem Doublett zusammen mit ihren Normalen an die alten Vertizes - // angehängt werden; der Winkel zur Normalen hilft später, die Seite - // heraus zu finden, Seite von den Edges - - int dbg_iteratorAblaufen = 0; - - -#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX - - int dbg_laenge = 0; - - for( auto const & vft : vecVertFracTrip ) - { - dbg_laenge++; - - UG_LOG("VERTEXFRACTRIP" << std::endl); - - vector3 ve = vft.getNormal(); - - UG_LOG("NORMAL " << ve << std::endl); - - UG_LOG("laenge " << dbg_laenge << std::endl ); - } - - int dbg_laenge_eins = 0; - -#endif - - - - for( VvftIterator vvftV = vecVertFracTrip.begin(); - vvftV != vecVertFracTrip.end(); - vvftV++ - ) - { - -#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX - dbg_laenge_eins++; - - if( dbg_laenge_eins > dbg_laenge ) - { - break; - } - -#endif - - vector3 nV = vvftV->getNormal(); - - Edge * edgeV = vvftV->getEdge(); - - - -#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX - - UG_LOG("NORMAL " << vvftV->getNormal() << std::endl); - UG_LOG("LAENGE EINZ " << dbg_laenge_eins << std::endl ); -#endif - - Vertex * nextFracVrt; - - IndexType foundThisVrt = 0; - - for( size_t i = 0; i < 2; ++i ) - { - Vertex * vrtEdgEnd = edgeV->vertex(i); - - if( vrtEdgEnd == *iterV ) - { - foundThisVrt++; - } - else - { - nextFracVrt = vrtEdgEnd ; - } - - } - - if( foundThisVrt != 1 ) - { - UG_THROW("zu viel zu wenig vertizex one " << std::endl); - } - - - - // Klasse schreiben, die als attachment an einen Fracture-Vertex - // die neuen Vertizes samt ihrer gemittelten Normalen speichert - // also std::vector von dieser neuen Klasse als Vertex attachment - - std::vector attEdg; - std::vector attFac; - - attEdg.push_back( edgeV ); - - Face * facV = vvftV->getFace(); - - attFac.push_back( facV ); - - // jetzt neuen Vertex erzeugen in Richtung der Normalen - // sonst ist das attachment Schwachsinn! - - vector3 posNewVrt; - - vector3 moveVrt; - - auto subsIndEdgV = sh.get_subset_index(edgeV); - - number width = fracInfosBySubset.at(subsIndEdgV).width; - -// if( expandInnerFracBnds ) -// { -// // der Faktor ist Käse und muss noch aus den Eingaben übernommen werden -// VecScale(moveVrt, nV, width/2. ); -// } -// else -// { -// // auf Annes Wunsch hin werden die Normalen innendrin an einer endenen Kluft zu Null gesetzt -// -// VecScale(moveVrt, nV, 0. ); -// -// } - - VecScale(moveVrt, nV, width/2. ); - - VecAdd(posNewVrt, posOldVrt, moveVrt ); - - UG_LOG("neuer Vertex " << posNewVrt << std::endl ); - - // TODO FIXME hier ist das PROBLEM, SEGFAULT durch create regular vertex - - - - Vertex * newShiftVrtx = *grid.create(); - aaPos[newShiftVrtx] = posNewVrt; - - sh.assign_subset(newShiftVrtx, subsIndEdgV ); - - - - // fuer was braucheh wir das eigentlich? selber schon vergessen..... - - ExpandVertexMultiplett vrtMtpl( attEdg, attFac, nV ); - - aaVrtExpMP[ *iterV ].push_back( vrtMtpl ); - - - - // alle anhängenden faces müssen noch zu wissen bekommen - // dass es diesen neuen Vertex gibt, nicht nur die - // an den edges anhängenden - // vielleicht gibt es einen Loop über attached faces des - // Vertex, für die schon bekannten direkt angehängten klar - // wenn auch dort vermerkt werden muss im Attachment von Seb - // bei den anderen, die keine Edge haben von der Kluft - // da muss man die Normale ins Zentrum bestimmen - // um heraus zu finden, ob sie auf dieser seite sind - // am besten dann das Attachment der faces für vertizes - // von Seb recyclen - - // loop über assosciated faces des vertex am besten - // vermutlich auch noch assosciated edges, um - // zu markieren, welche weg fallen sollen, wenn - // nicht von Kluft selber, sondern quasi verschoben - // und neu erzeugt - - int dbg_FaceIterator = 0; - - - - for( auto const & ifac : assoFaces ) - { - bool isFromFrac = false; - - for( auto const & facFrac : attFac ) - { - -// static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype ( ifac ) >::value ); - static_assert( std::is_same< decltype( (facFrac) ), decltype ( ifac ) >::value ); - - if( ifac == facFrac ) - { - isFromFrac = true; - -// static_assert( std::is_same< decltype( const_cast(facFrac) ), Face * & >::value ); - static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value ); -// static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype( ifac ) >::value ); - static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value ); - - } - } - - - bool atRightSide = false; - - if( isFromFrac ) - atRightSide = true; - - if( !isFromFrac ) - { - // check if on same side of edge where the normal points to: compute cosinus between vector of face center - // perpendicular to the edge - - - - - vector3 facCenter = CalculateCenter( ifac, aaPos ); - - vector3 perpendicu; - - -// UG_LOG("pos 0 " << aaPos[nextFracVrt[0]] << std::endl); -// UG_LOG("pos 1 " << aaPos[*iterV] << std::endl); -// UG_LOG("fac ce " << facCenter << std::endl); - - DropAPerpendicular(perpendicu, facCenter, aaPos[nextFracVrt], aaPos[*iterV]); - -// if( dbg_FaceIterator == 1 ) -// { -// UG_LOG("huhu a0" << std::endl); -// return true; -// } - - - vector3 tmpN; - - VecSubtract(tmpN, facCenter, perpendicu ); - - VecNormalize(tmpN, tmpN); - - UG_LOG("Normale zum Face ist " << tmpN << std::endl); - - number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, nV ); - - UG_LOG("Cosinus zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); - -// if( dbg_FaceIterator == 1 ) -// { -// UG_LOG("huhu a" << std::endl); -//// return true; -// } - - - if( cosBetwFracEdgAndDirection2Face > 0 ) - { - UG_LOG("assuming face to be on richt side" << std::endl); - - atRightSide = true; - -#if ANSCHAULICH_ERZEUGE_SUDOS_ANHANG - - Vertex * otherFacCent = *grid.create(); - aaPos[otherFacCent] = facCenter; - sh.assign_subset(otherFacCent, 6 ); - - Vertex * pp = *grid.create(); - aaPos[pp] = perpendicu; - sh.assign_subset(pp, 7 ); - - sh.assign_subset(ifac,8); - -#endif - - } - else - { - UG_LOG("assuming face to be on wrong side" << std::endl); - } - - - dbg_flachen_passiert++; - } - - -// if( dbg_FaceIterator == 1 ) -// { -// UG_LOG("huhu b" << std::endl); -//// return true; -// } - - - - if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein - { - - // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! - vector& newVrts4Fac = aaVrtVecFace[ ifac ]; - - IndexType vrtxFnd = 0; - - for(size_t indVrt = 0; indVrt < (ifac)->num_vertices(); indVrt++ ) - { - Vertex* facVrt = (ifac)->vertex(indVrt); - - if( facVrt == *iterV ) - { - newVrts4Fac[ indVrt ] = newShiftVrtx; - vrtxFnd++; - } - } - - - if( vrtxFnd <= 0 ) - { - UG_THROW("vertex not found!" << std::endl); - } - else if( vrtxFnd > 1 ) - { - UG_THROW("vertex zu oft gefunden " << vrtxFnd << std::endl ); - } - else if ( vrtxFnd == 1 ) - { - } - else - { - UG_THROW("vertex finden komisch " << std::endl); - } - - - } - - dbg_FaceIterator++; - - } - - - - - - - - - } - - - - dbg_iteratorAblaufen++; - - - -// // Ziel: die beiden parallelen Normalen mitteln, und in die jeweiligen beiden Richtungen je einen neuen Vertex erzeugen -// // irgendwie muss der Vertex oder die Edge besser sogar wissen, dass sie einen neuen Verschiebevertex bekommen hat -// // denn später müssen neue Edges und neue Faces basierend auf den neuen Vertizes erzeugt werden -// // vielleicht braucht die edge und das face ein Attachment, das ihnen das sagt, ähnlihc wie VertexTrible std Vektoren? -// -// -// - UG_LOG("END THIS VERTEX NORMAL INNER ENDING CLEFT" << std::endl); - -#endif - - -// return true; - - - } - else if( numFracsCrossAtVrt == 2 ) // free line of fracture, no crossing point, not at boundary - { - // in this case, we have two attached edges, and each of these edges has two attached faces - // the faces have a naormal, and based on the normal, we can decide which faces belong to the same side of the edges - - - if( numbAttTripl != 4 ) - { - - UG_LOG("NUMBER OF TRIPLETTS " << numbAttTripl << std::endl); - -// return true; - - UG_THROW("Anzahl der angehaengten Triples kann nicht stimmen, Vertex einer Kluft ohne Schnittpunkte, nicht am Rand " << std::endl); - } - - // Zuordnung der Edges und Faces, die auf der gleichen Seite der fracture sind - - // und gleich auch Erzeugung der neuen Knoten, die dann - // in einem Doublett zusammen mit ihren Normalen an die alten Vertizes - // angehängt werden; der Winkel zur Normalen hilft später, die Seite - // heraus zu finden, Seite von den Edges - - - - int dbg_iteratorAblaufen = 0; - -#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX - - int dbg_laenge = 0; - - for( auto const & vft : vecVertFracTrip ) - { - dbg_laenge++; - - UG_LOG("VERTEXFRACTRIP" << std::endl); - - vector3 ve = vft.getNormal(); - - UG_LOG("NORMAL " << ve << std::endl); - - UG_LOG("laenge " << dbg_laenge << std::endl ); - } - - - UG_LOG("SINGLE" << std::endl); - - - for( VvftIterator vvftOne = vecVertFracTrip.begin(); - vvftOne != vecVertFracTrip.end() - 1; - vvftOne++ - ) - { - - - Edge * edgeOne = vvftOne->getEdge(); - vector3 nOne = vvftOne->getNormal(); - - - for( VvftIterator vvftTwo = vvftOne + 1; - vvftTwo != vecVertFracTrip.end(); - vvftTwo++ - ) - { - Edge * edgeTwo = vvftTwo->getEdge(); - vector3 nTwo = vvftTwo->getNormal(); - - number cosinus = VecDot( nOne, nTwo ); - if( edgeOne != edgeTwo ) - { - UG_LOG("COSI between " << nOne << " and " << nTwo << " -> " << cosinus << std::endl ); - } - - } - } - - UG_LOG("SINGLE END" << std::endl); - - int dbg_laenge_eins = 0; - -#endif - - - for( VvftIterator vvftOne = vecVertFracTrip.begin(); - vvftOne != vecVertFracTrip.end() - 1; - vvftOne++ - ) - { - -#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX - dbg_laenge_eins++; - - if( dbg_laenge_eins > dbg_laenge ) - { - break; - } - - int dbg_laenge_zwei = dbg_laenge_eins; -#endif - int dbg_zweiterIteratorAblaufen = 0; - - vector3 nOne = vvftOne->getNormal(); - - Edge * edgeOne = vvftOne->getEdge(); - - - - for( VvftIterator vvftTwo = vvftOne + 1; - vvftTwo != vecVertFracTrip.end(); - vvftTwo++ - ) - { - -#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX - dbg_laenge_zwei++; - - if( dbg_laenge_zwei > dbg_laenge ) - { - break; - } - - UG_LOG("NORMAL ONE " << vvftOne->getNormal() << std::endl); - UG_LOG("NORMAL TWO " << vvftTwo->getNormal() << std::endl); - UG_LOG("LAENGE EINZ ZWO " << dbg_laenge_eins << " " << dbg_laenge_zwei << std::endl ); -#endif - - // dieselben brauchen wir nicht vergleichen - if( vvftOne == vvftTwo ) - { - // sollte nie vorkommen! - UG_THROW("Unsinn " << std::endl); - } - else - { - - Edge * edgeTwo = vvftTwo->getEdge(); - - // noch testen, ob nicht die Kante dieselbe ist, geht das? - // bei der gleichen Ecke ist es unnötig, da es gegensätzlich sein muss - - - - if( edgeOne != edgeTwo ) - { - - std::vector nextFracVrt; - - IndexType foundThisVrtOne = 0; - - for( size_t i = 0; i < 2; ++i ) - { - Vertex * vrtEdgEnd = edgeOne->vertex(i); - - if( vrtEdgEnd == *iterV ) - { - foundThisVrtOne++; - } - else - { - nextFracVrt.push_back( vrtEdgEnd ); - } - - } - - if( foundThisVrtOne != 1 ) - { - UG_THROW("zu viel zu wenig vertizex one " << std::endl); - } - - - IndexType foundThisVrtTwo = 0; - - for( size_t i = 0; i < 2; ++i ) - { - Vertex * vrtEdgEnd = edgeTwo->vertex(i); - - if( vrtEdgEnd == *iterV ) - { - foundThisVrtTwo++; - } - else - { - nextFracVrt.push_back( vrtEdgEnd ); - } - - } - - if( foundThisVrtTwo != 1 ) - { - UG_THROW("zu viel zu wenig vertizex two " << std::endl); - } - - - - vector3 nTwo = vvftTwo->getNormal(); - - number cosinus = VecDot( nOne, nTwo ); - -// bool vz = ! std::signbit(cosinus); - - UG_LOG("cosinus " << dbg_vertizesPassiert << " between " << nOne << " and " << nTwo << " -> " << cosinus << std::endl ); - //UG_LOG("sign between " << nOne << " and " << nTwo << " -> " << vz << std::endl ); - - - - if( cosinus > 0 ) - { - // gleiche Seite vermutet - - // sind die edges dieselben? pruefen! gleiche unnoetig - wird oben schon abgefragt - - // Klasse schreiben, die als attachment an einen Fracture-Vertex - // die neuen Vertizes samt ihrer gemittelten Normalen speichert - // also std::vector von dieser neuen Klasse als Vertex attachment - -#if 1 - - Face * facOne = vvftOne->getFace(); - Face * facTwo = vvftTwo->getFace(); - - expandSingleFractureAtGivenSide( nOne, nTwo, - edgeOne, edgeTwo, - facOne, facTwo, - fracInfosBySubset, - posOldVrt, - aaPos, - grid, sh, - assoFaces - , - nextFracVrt, - aaVrtVecFace, - dbg_flachen_passiert, - *iterV - ); - -#else - - // average the normals - - vector3 normSum; - - VecAdd( normSum, nOne, nTwo ); - - vector3 normSumNormed; - - VecNormalize(normSumNormed, normSum); - - UG_LOG("averaged normal " << normSumNormed << std::endl); - - std::vector attEdg; - std::vector attFac; - - attEdg.push_back( edgeOne ); - attEdg.push_back( edgeTwo ); - -// Face * facOne = vvftOne->getFace(); -// Face * facTwo = vvftTwo->getFace(); - - attFac.push_back( facOne ); - attFac.push_back( facTwo ); - - // jetzt neuen Vertex erzeugen in Richtung der Normalen - // sonst ist das attachment Schwachsinn! - - vector3 posNewVrt; - - vector3 moveVrt; - - auto subsIndEdgOne = sh.get_subset_index(edgeOne); - - auto subsIndEdgTwo = sh.get_subset_index(edgeTwo); - - - if( subsIndEdgOne != subsIndEdgTwo ) - { - UG_THROW("subsets passen nicht" << std::endl ); - } - - - - - number width = fracInfosBySubset.at(subsIndEdgOne).width; - - // der Faktor ist Käse und muss noch aus den Eingaben übernommen werden - VecScale(moveVrt, normSumNormed, width/2. ); - - VecAdd(posNewVrt, posOldVrt, moveVrt ); - - UG_LOG("neuer Vertex " << posNewVrt << std::endl ); - - // TODO FIXME hier ist das PROBLEM, SEGFAULT durch create regular vertex - - Vertex * newShiftVrtx = *grid.create(); - aaPos[newShiftVrtx] = posNewVrt; - - sh.assign_subset(newShiftVrtx, subsIndEdgOne ); - - - - // fuer was braucheh wir das eigentlich? selber schon vergessen..... - - ExpandVertexMultiplett vrtMtpl( attEdg, attFac, normSumNormed ); - - aaVrtExpMP[ *iterV ].push_back( vrtMtpl ); - - - - // alle anhängenden faces müssen noch zu wissen bekommen - // dass es diesen neuen Vertex gibt, nicht nur die - // an den edges anhängenden - // vielleicht gibt es einen Loop über attached faces des - // Vertex, für die schon bekannten direkt angehängten klar - // wenn auch dort vermerkt werden muss im Attachment von Seb - // bei den anderen, die keine Edge haben von der Kluft - // da muss man die Normale ins Zentrum bestimmen - // um heraus zu finden, ob sie auf dieser seite sind - // am besten dann das Attachment der faces für vertizes - // von Seb recyclen - - // loop über assosciated faces des vertex am besten - // vermutlich auch noch assosciated edges, um - // zu markieren, welche weg fallen sollen, wenn - // nicht von Kluft selber, sondern quasi verschoben - // und neu erzeugt - - int dbg_FaceIterator = 0; - -#if 0 -// for( auto iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ ) - for( std::vector::iterator iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ ) - { - bool isFromFrac = false; - -// for( std::vector::iterator iterF2 = attFac.begin(); iterF2 != attFac.end(); iterF2++ ) -// { -// static_assert( std::is_same< decltype( *iterF2 ), decltype ( *iterFac ) >::value ); -// -// } - - int dbg_innterFacFracIt = 0; - - for( auto const & facFrac : attFac ) - { - - -// UG_LOG("type iter facFrac " << typeid( facFrac ).name() << std::endl); -// -// UG_LOG("type iter Fac " << typeid( *iterFac ).name() << std::endl); - - static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype ( *iterFac ) >::value ); - - - - - if( *iterFac == facFrac ) - { - isFromFrac = true; - - static_assert( std::is_same< decltype( const_cast(facFrac) ), Face * & >::value ); - static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype( * iterFac ) >::value ); - - } - } - - bool atRightSide = false; - - if( isFromFrac ) - atRightSide = true; - - if( !isFromFrac ) - { - // check if on same side of edge where the normal points to: compute cosinus between vector of face center - // perpendicular to the edge - // TODO FIXME - // KAESE!!! - - vector3 facCenter = CalculateCenter( *iterFac, aaPos ); - - vector3 perpendicu; - - if( nextFracVrt.size() != 2 ) - { - UG_THROW("komische Groesse" << std::endl); - } - - DropAPerpendicular(perpendicu, facCenter, aaPos[nextFracVrt[0]], aaPos[nextFracVrt[1]]); - - vector3 tmpN; - - VecSubtract(tmpN, facCenter, perpendicu ); - - VecNormalize(tmpN, tmpN); - - UG_LOG("Normale zum Face ist " << tmpN << std::endl); - - number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, normSumNormed ); - - UG_LOG("Cosinus zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); - - if( cosBetwFracEdgAndDirection2Face > 0 ) - { - UG_LOG("assuming face to be on richt side" << std::endl); - - atRightSide = true; - -#if ANSCHAULICH_ERZEUGE_SUDOS_ANHANG - - Vertex * otherFacCent = *grid.create(); - aaPos[otherFacCent] = facCenter; - sh.assign_subset(otherFacCent, 5 ); - - Vertex * pp = *grid.create(); - aaPos[pp] = perpendicu; - sh.assign_subset(pp, 6 ); - - sh.assign_subset(*iterFac,7); -#endif - - } - else - { - UG_LOG("assuming face to be on wrong side" << std::endl); - } - -// if( dbg_flachen_passiert == 0 ) -// { -// UG_LOG("passiert " << dbg_flachen_passiert << std::endl); -// -// Vertex * otherFacCent = *grid.create(); -// aaPos[otherFacCent] = facCenter; -// sh.assign_subset(otherFacCent, 5 ); -// -// Vertex * pp = *grid.create(); -// aaPos[pp] = perpendicu; -// sh.assign_subset(pp, 6 ); -// -// sh.assign_subset(*iterFac,7); -// -// -// sh.assign_subset(*iterFac,3); -// -// UG_LOG("is from frac " << isFromFrac << std::endl); -// -// return true; -// } - - - dbg_flachen_passiert++; - } - - - if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein - { - - - // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! - vector& newVrts4Fac = aaVrtVecFace[ * iterFac ]; - - IndexType vrtxFnd = 0; - - for(size_t indVrt = 0; indVrt < (*iterFac)->num_vertices(); indVrt++ ) - { - Vertex* facVrt = (*iterFac)->vertex(indVrt); - - if( facVrt == *iterV ) - { - newVrts4Fac[ indVrt ] = newShiftVrtx; - // UG_LOG("vertex found " << indVrt << std::endl ); - vrtxFnd++; - } - } - - - if( vrtxFnd <= 0 ) - { - UG_THROW("vertex not found!" << std::endl); - } - else if( vrtxFnd > 1 ) - { - UG_THROW("vertex zu oft gefunden " << vrtxFnd << std::endl ); - } - else if ( vrtxFnd == 1 ) - { - // UG_LOG("vertex found abgeschlossen" << std::endl); - } - else - { - UG_THROW("vertex finden komisch " << std::endl); - } - - - } - - dbg_innterFacFracIt++; - - - -// -// -// if( ! isFromFrac ) -// { -// // Vektor zum Zentrum von KNoten aus berechnen und Winkel zur Normalen bestimmen zur Unterscheidung der Seite -// // wenn auf richtiger Seite, zuweisen -// } - - dbg_FaceIterator++; - - } -#else -// std::vector & assFaceVrt = aaVrtInfoAssoFaces[*iterV]; - - // VecFace & assoFaces = aaVrtInfoAssoFaces[*iterV]; - // TODO FIXME hier braucht man das nicht zu ordnen - // aber bei Kreuzpunkten von Klueften muss es so geordnet werden, wie es nebeneinander liegt - // bei den Edges gibt es auch die benachbarten, und die edges haben das attachment, ob sie Kluftedges sind - - // for( auto const & ifac : assoFaces ) - // { - // static_assert( std::is_same< decltype( ifac ), Face * const & >::value ); - // - // // TODO FIXME folgenden loop durch diesen ersetzen - // // Achtung: Zeigerproblematik, Referenzen, etc..... - // // *iterFac ersetzen durch ifac vermutlich, aber wer weiss - // } - - - // for( auto iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ ) - //for( std::vector::iterator iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ ) - for( auto const & ifac : assoFaces ) - { - bool isFromFrac = false; - - - int dbg_innterFacFracIt = 0; - - for( auto const & facFrac : attFac ) - { - -// static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype ( ifac ) >::value ); - static_assert( std::is_same< decltype( (facFrac) ), decltype ( ifac ) >::value ); - - if( ifac == facFrac ) - { - isFromFrac = true; - -// static_assert( std::is_same< decltype( const_cast(facFrac) ), Face * & >::value ); - static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value ); -// static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype( ifac ) >::value ); - static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value ); - - } - } - - bool atRightSide = false; - - if( isFromFrac ) - atRightSide = true; - - if( !isFromFrac ) - { - // check if on same side of edge where the normal points to: compute cosinus between vector of face center - // perpendicular to the edge - - vector3 facCenter = CalculateCenter( ifac, aaPos ); - - vector3 perpendicu; - - if( nextFracVrt.size() != 2 ) - { - UG_THROW("komische Groesse" << std::endl); - } - - DropAPerpendicular(perpendicu, facCenter, aaPos[nextFracVrt[0]], aaPos[nextFracVrt[1]]); - - vector3 tmpN; - - VecSubtract(tmpN, facCenter, perpendicu ); - - VecNormalize(tmpN, tmpN); - - UG_LOG("Normale zum Face ist " << tmpN << std::endl); - - number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, normSumNormed ); - - UG_LOG("Cosinus zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); - - if( cosBetwFracEdgAndDirection2Face > 0 ) - { - UG_LOG("assuming face to be on richt side" << std::endl); - - atRightSide = true; - -#if ANSCHAULICH_ERZEUGE_SUDOS_ANHANG - - Vertex * otherFacCent = *grid.create(); - aaPos[otherFacCent] = facCenter; - sh.assign_subset(otherFacCent, 5 ); - - Vertex * pp = *grid.create(); - aaPos[pp] = perpendicu; - sh.assign_subset(pp, 6 ); - - sh.assign_subset(*iterFac,7); -#endif - - } - else - { - UG_LOG("assuming face to be on wrong side" << std::endl); - } - - - dbg_flachen_passiert++; - } - - - if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein - { - - // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! - vector& newVrts4Fac = aaVrtVecFace[ ifac ]; - - IndexType vrtxFnd = 0; - - for(size_t indVrt = 0; indVrt < (ifac)->num_vertices(); indVrt++ ) - { - Vertex* facVrt = (ifac)->vertex(indVrt); - - if( facVrt == *iterV ) - { - newVrts4Fac[ indVrt ] = newShiftVrtx; - vrtxFnd++; - } - } - - - if( vrtxFnd <= 0 ) - { - UG_THROW("vertex not found!" << std::endl); - } - else if( vrtxFnd > 1 ) - { - UG_THROW("vertex zu oft gefunden " << vrtxFnd << std::endl ); - } - else if ( vrtxFnd == 1 ) - { - } - else - { - UG_THROW("vertex finden komisch " << std::endl); - } - - - } - - dbg_innterFacFracIt++; - - - - dbg_FaceIterator++; - - } - -#endif - -#endif - - } - else - { - // andere Seite vermutet, nichts tun! - } - - - - } - - - } - - dbg_zweiterIteratorAblaufen++; - - } - - dbg_iteratorAblaufen++; - - } - - -// // Ziel: die beiden parallelen Normalen mitteln, und in die jeweiligen beiden Richtungen je einen neuen Vertex erzeugen -// // irgendwie muss der Vertex oder die Edge besser sogar wissen, dass sie einen neuen Verschiebevertex bekommen hat -// // denn später müssen neue Edges und neue Faces basierend auf den neuen Vertizes erzeugt werden -// // vielleicht braucht die edge und das face ein Attachment, das ihnen das sagt, ähnlihc wie VertexTrible std Vektoren? -// -// -// - - - UG_LOG("END THIS VERTEX NORMAL COSINE" << std::endl); - - - - } - else // two fractures completely crossing, numFracsCrossAtVrt >= 3, i.e. T crossing and two fractures completely crossing - { - - // TODO FIXME in case of three fractures, we have to use the method for eine durchgehende fracture - // auf der Seite, wo die zweite fracture NICHT rein geht - - IndexType countedCrossingFracEdgs = 0; - - // TODO FIXME kreuzende Fractures im Innenraum -> Arte in Reinform implementieren - - // verkettete Liste der anhängenden fractures in Reihenfolge - // der Anhängung mit INfo, ob eine Kluft vorliegt - - for( auto const & attVFT : vecVertFracTrip ) - { - Edge * edg = attVFT.getEdge(); - Face * fac = attVFT.getFace(); - vector3 nv = attVFT.getNormal(); - } - -// // hier werden ALLE attached Faces benötigt, auch die, die zwischen den direkt an den fractures liegenden Faces sind -// - // copies of all faces and of fractured ones - auto vVFT = vecVertFracTrip; // caution: COPY, not reference! - auto aF = assoFaces; // caution: COPY, not reference! - - UG_LOG("Gesamtanzahl faces um Knoten " << aF.size() << std::endl ); - - // erstmal die ganzen anhaengenden Faces ordnen, dass wir wissen, in welcher Reihenfolge wir durchlaufen muessen - // jede Edge hat ein bool attachment schon, das weiss, ob sie Fracture edge ist oder nicht - // Reihenfolge der faces und die edges auch dazu, vielleicht neues Triple oder dergleiche, dabei zwei edges und zwei normals - // und wie gesagt, die edges wissen, ob sie fractures sind, dazu keine neuen Variablen notwendig - - using VertexOfFaceInfo = VertexFractureTriple< std::pair, Face*, std::pair >; - // all edges of the attached face - must always be two, the face itself, and the normal vectors of the face in direction of the two edges - // the size of the normal vector vector also must be two - // however, if an edge of the face is not a fracture edge, we do not compute the normal, but assign zero as norm - // for those edges and faces which are Kluft edges, we assign the normal known from the info computed before, vertex fracture triple - - using VecVertexOfFaceInfo = std::vector; - - VecVertexOfFaceInfo orderedFaces; - - using SegmentsFractExtrus = std::vector; - - SegmentsFractExtrus segments; - // single components always from one fracture edge to the next one - - VecVertexOfFaceInfo segmentPart; - - // note: we do not attach this info to the vertex, as we only need it local; in principle, in case of further need, it would - // be usful to establish some sort of attachment - - if( vVFT.size() == 0 ) - UG_THROW("vertex frac triple zu klein an Kreuzung " << std::endl); - - // we start with the first fracture face edge stuff, copy it, and delete this immidiately - VertFracTrip startVertFracTrip = vVFT[0]; - - vVFT.erase(vVFT.begin()); - - bool atFirstTriple = true; - - Face* fracFac = startVertFracTrip.getFace(); - Edge* fracEdg = startVertFracTrip.getEdge(); - vector3 fracNorm = startVertFracTrip.getNormal(); - - Edge* originalStartEdge = startVertFracTrip.getEdge(); - - if( fracEdg != 0 ) - { - countedCrossingFracEdgs++; - } - - // do not change this pointer - Edge* startEdg = fracEdg; - Face* startFace = fracFac; - - vector3 startNormal = fracNorm; - - Face* nextFace = NULL; - - UG_LOG("Gesamtanzahl faces um Knoten vor while " << aF.size() << std::endl ); - - - while( aF.size() != 0 ) - { - - UG_LOG("Gesamtanzahl faces um Knoten Anfang while " << aF.size() << std::endl ); - - - Face* face2Append = startFace; - Edge* startEdg2Append = startEdg; - - - IndexType fndCommEdg = 0; - vector3 nuVe(0,0,0); - - Edge* nextEdge = NULL; - - std::pair edge2Append( startEdg2Append, nextEdge ); - std::pair normal2Append( startNormal, nuVe ); - - - // if start face and start edge from a triple, then has to be erased this triple, exept for the entire start, as already erased - if( ! atFirstTriple ) - { - for( VecVertFracTrip::iterator itAttVFT = vVFT.begin(); itAttVFT != vVFT.end(); itAttVFT++ ) - { - auto vft = *itAttVFT; - - Edge * edgIt = vft.getEdge(); - - Face * facIt = vft.getFace(); - - if( edgIt == startEdg && facIt == startFace ) - { - // the first edge if from a fracture and the face is connected to it - - vVFT.erase(itAttVFT); - - normal2Append.first = vft.getNormal(); - - if( ! FaceContains( facIt, startEdg )) - { - UG_THROW("Face does not contain start edge of its edge" << std::endl); - } - - break; - } - } - - } - else // we can save the investigation if we have a triple, and we do not need to erase, as already erased..... - { - atFirstTriple = false; - } - - - for( auto const & iE : allAssoEdges ) // werden nicht gelöscht, deswegen Zugriff auf attachment direkt - { - if( FaceContains(face2Append, iE) ) - { - fndCommEdg++; - - if( iE != startEdg ) - { - nextEdge = iE; - - edge2Append.second = iE; - - } - } - - - } - - if( fndCommEdg != 2 ) - { - UG_THROW("komische Anzahl gemeinsamer Ecke " << fndCommEdg << std::endl); - } - - if( nextEdge == NULL ) - { - UG_THROW("wieso keine zweite Ecke gefunden???? " << std::endl); - } - - if( edge2Append.first == NULL || edge2Append.second == NULL ) - { - UG_THROW("null immer noch?" << std::endl); - } - - // erase the face from the list - - IndexType faceFound = 0; - - for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ ) - { - Face * iFa = *itFac; - - if( iFa == startFace && FaceContains( iFa, nextEdge ) && FaceContains(iFa, startEdg)) - { - faceFound++; - } - } - - int totalSubsNum = sh.num_subsets(); - - int newSubsToAdd = totalSubsNum; - - if( faceFound != 1 ) - { - - - sh.assign_subset(startFace,newSubsToAdd++); - sh.assign_subset(startEdg,newSubsToAdd++); - sh.assign_subset(nextEdge,newSubsToAdd++); - - int faNum = aF.size(); - - UG_LOG("Gesamtzahl faces vor Absturz " << faNum << std::endl); - - UG_LOG("Gesicht in falscher Anztahl gefunden " << faceFound << std::endl); - -// return true; - - - - UG_THROW("Gesicht in falscher Anztahl gefunden " << faceFound << std::endl); - } - else - { -// sh.assign_subset(startFace,newSubsToAdd++); -// sh.assign_subset(startEdg,newSubsToAdd++); -// sh.assign_subset(nextEdge,newSubsToAdd++); - - int faNum = aF.size(); - - UG_LOG("Gesamtzahl faces ohne Absturz " << faNum << std::endl); - - } - - for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ ) - { - Face * iFa = *itFac; - - if( iFa == startFace && FaceContains( iFa, nextEdge ) && FaceContains(iFa, startEdg) ) - { - aF.erase(itFac); - break; - } - } - - - - - bool sndEdgIsFracEdgeAlso = aaMarkEdgeB[nextEdge]; - - bool tripFound = false; - - if( sndEdgIsFracEdgeAlso ) - { - - if( nextEdge != originalStartEdge ) - countedCrossingFracEdgs++; - - // we need to have a look for the next triple - - // check if the next normal is a frac normal which contains the face as well - - for( VecVertFracTrip::iterator itAttVFT = vVFT.begin(); itAttVFT != vVFT.end(); itAttVFT++ ) - { - auto vft = *itAttVFT; - - Edge * edgIt = vft.getEdge(); - - Face * facIt = vft.getFace(); - - if( edgIt == nextEdge && facIt == face2Append ) - { - // the second edge if from a fracture and the face is connected to it - - tripFound = true; - - vVFT.erase(itAttVFT); - - normal2Append.second = vft.getNormal(); - - if( ! FaceContains( facIt, nextEdge )) - { - UG_THROW("Face does not contain edge of its edge" << std::endl); - } - - break; - } - } - - } - - if( ! tripFound && sndEdgIsFracEdgeAlso ) - { - UG_THROW("Triple nicht gefunden trotz markierter Edge" << std::endl); - } - - - // check if aF or vVFT still contain the former or the next face - must not be the case! - - VertexOfFaceInfo vOFI( edge2Append, face2Append, normal2Append ); - - orderedFaces.push_back( vOFI ); - - segmentPart.push_back( vOFI ); - - if( sndEdgIsFracEdgeAlso ) - { - segments.push_back( segmentPart ); - - segmentPart.clear(); - } - - - // what is next face, what is next edge? - // wie kriegen wir es hin, auch das nächste Triple zu erasen, wenn es jetzt kommt als nächstes? - - - startNormal = nuVe; - startEdg = nextEdge; - - if( aF.size() == 0 ) - { - if( nextEdge != originalStartEdge ) - { - UG_THROW("Gesichter leer, aber keine Anfangsecke gefunden" << std::endl); - } - else - { - break; // while loop zu Ende, raus aus dem while loop, den Rest nicht mehr machen, würde schief gehen zwingendermassen - } - - } - - - // bleibt noch das nächste Gesicht heraus zu finden, dafür kommt eigentlich nur noch eines in Frage, da das zweite Gesicht vom edge - // geloescht sein muss in aF, es muss das einzig übrige face sein, das die jetzt start edge enthält, davon darf es nur eines geben, wir löschen aber noch nicht - - IndexType nextFaceFound = 0; - - for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ ) - { - Face * iFa = *itFac; - - if( FaceContains(iFa, startEdg ) ) - { - nextFaceFound++; - } - } - - if( nextFaceFound != 1 ) - { - UG_THROW("folgendes Gesicht in falscher Anztahl gefunden " << nextFaceFound << std::endl); - } - - for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ ) - { - Face * iFa = *itFac; - - if( FaceContains(iFa, startEdg ) ) - { - startFace = iFa; - break; - } - } - - - } - - if( vVFT.size() != 0 ) - { - UG_THROW("not all triples found! " << std::endl); - } - - if( aF.size() != 0 ) - UG_THROW("not all faces found " << std::endl); - - if( startEdg != originalStartEdge ) - { - UG_THROW("wir sind nicht am Anfang wieder angekommen" << std::endl); - } - - - if( segmentPart.size() != 0 ) - { - UG_THROW("die Segmentteile muessen alle verarbeitet sein" << std::endl); - } - - UG_LOG("Kreislauf geschlossen" << std::endl); - - - // test if the segments and their partition produce sumething useful, for debug purposes - - // als nächstes muss man die Klassen von durch Klüften abgetrennten ordered Faces durchgehen, und die Verschiebevertizes erzeugen - // als nächstes die verschiedenen Sektionen durch gehen, eventuell nochmal extra Objekte dafür erzeugen - // oder gleich beim Durchgehen die neuen Vertizes erzeugen, Startsignal durch ein Face mit erster Edge KLuft, und dann die nächste - // Kluftedge finden, egal ob vom gleihen face oder von einem späteren face im kreis - - // now figure out to which face this next edge belongs, and if this is a fracture edge, then we have the triple and the normal info - // else we let the normal zero - - // figure out if second edge is also frac edge, i.e. if it belongs to an edge of the remaining vVFT elements - // first easily asking if it is marked as frac edge, simplifies research - - // in principle from here on need to loop through all triples and through all faces, find out some way to construct next edge and to - // build one element after the other of the ordered faces vector, still even the first element is not completed - - // TODO FIXME kreuzende Fractures im Innenraum -> Arte in Reinform implementieren - // later assign somehow next edge to start edge, or use new variable, when we have figured out next face - // at end, chech if we have arrived again at original first edge - - - int totalSubsNum = sh.num_subsets(); - -// int newSubsToAdd = totalSubsNum; - -// for( VertexOfFaceInfo const & vertFracInfo : orderedFaces ) -// { -//// Face * fa = vertFracInfo.getFace(); -//// -//// sh.assign_subset(fa,newSubsToAdd++); -// } - - number totAnglsEdg = 0; - number totAnglsNrm = 0; - - for( VecVertexOfFaceInfo const & segPart : segments ) - { -// newSubsToAdd++; - - IndexType numbTriangs = segPart.size(); - - if( numbAttTripl == 0 ) - { - UG_THROW("zu wenig Dreiecke " << std::endl); - } - - VertexOfFaceInfo const & vFISBegin = segPart[0]; - VertexOfFaceInfo const & vFISEnd = segPart[numbTriangs-1]; - - std::pair edgesBegin = vFISBegin.getEdge(); - std::pair edgesEnd = vFISEnd.getEdge(); - - std::pair normalBegin = vFISBegin.getNormal(); - std::pair normalEnd = vFISEnd.getNormal(); - - Edge* edgeFracOne = edgesBegin.first; - Edge* edgeFracTwo = edgesEnd.second; - - auto subsIndFracOne = sh.get_subset_index(edgeFracOne); - auto subsIndFracTwo = sh.get_subset_index(edgeFracTwo); - - vector3 normalFracOne = normalBegin.first; - vector3 normalFracTwo = normalEnd.second; - -// sh.assign_subset(edgeFracOne, newSubsToAdd); -// -// if( edgeFracTwo != originalStartEdge ) -// sh.assign_subset(edgeFracTwo, newSubsToAdd); - - // neue Punkte erzeugen - - number cosBetweenNormals = VecDot( normalFracOne, normalFracTwo ); - - if( subsIndFracOne == subsIndFracTwo ) - { - if( numFracsCrossAtVrt != 3 ) - { - UG_THROW("Fracture Segment an beiden Seiten gleiche sudo, aber keine T Kreuzung?" << std::endl); - } - - // dieselben Methoden wie im Fall von einer durchgehenden Kluft an einem Vertex, dort kopieren - // bzw Funktion schreiben, die beides macht - - // TODO FIXME irgendwie muss hier der Fall abgezweigt werden, dass wir auf der durchgehenden Seite einer Kluft sind - // wenn wir eine T-Kreuzung haben - // HHHHHHHHHHHH hier kritischer Punkt aktuell - - std::vector nextFracVrt; - - IndexType foundThisVrtOne = 0; - - for( size_t i = 0; i < 2; ++i ) - { - Vertex * vrtEdgEnd = edgeFracOne->vertex(i); - - if( vrtEdgEnd == *iterV ) - { - foundThisVrtOne++; - } - else - { - nextFracVrt.push_back( vrtEdgEnd ); - } - - } - - if( foundThisVrtOne != 1 ) - { - UG_THROW("zu viel zu wenig vertizex one " << std::endl); - } - - - IndexType foundThisVrtTwo = 0; - - for( size_t i = 0; i < 2; ++i ) - { - Vertex * vrtEdgEnd = edgeFracTwo->vertex(i); - - if( vrtEdgEnd == *iterV ) - { - foundThisVrtTwo++; - } - else - { - nextFracVrt.push_back( vrtEdgEnd ); - } - - } - - if( foundThisVrtTwo != 1 ) - { - UG_THROW("zu viel zu wenig vertizex two " << std::endl); - } - - Face * faceBegin = vFISBegin.getFace(); - Face * faceEnd = vFISEnd.getFace(); - - - - expandSingleFractureAtGivenSide( normalFracTwo, normalFracTwo, - edgeFracOne, edgeFracTwo, - faceBegin, faceEnd, - fracInfosBySubset, - posOldVrt, - aaPos, - grid, sh, - assoFaces - , - nextFracVrt, - aaVrtVecFace, - dbg_flachen_passiert, - *iterV - ); - - - - } - else - { - - // create normal vectors into direction of relevant edges - - vector3 alongEdgeOne; - vector3 alongEdgeTwo; - - Vertex * vrtEdgeOneBegin = NULL; - Vertex * vrtEdgeTwoBegin = NULL; - Vertex * vrtEdgeOneEnd = NULL; - Vertex * vrtEdgeTwoEnd = NULL; - - - for( size_t i = 0; i < 2; ++i ) - { - Vertex * vrtFromEdgeOne = edgeFracOne->vertex(i); - Vertex * vrtFromEdgeTwo = edgeFracTwo->vertex(i); - - if( vrtFromEdgeOne == *iterV ) - { - vrtEdgeOneBegin = vrtFromEdgeOne; - } - else - { - vrtEdgeOneEnd = vrtFromEdgeOne; - } - - if( vrtFromEdgeTwo == *iterV ) - { - vrtEdgeTwoBegin = vrtFromEdgeTwo; - } - else - { - vrtEdgeTwoEnd = vrtFromEdgeTwo; - } - - } - - if( vrtEdgeOneBegin == NULL || vrtEdgeTwoBegin == NULL || vrtEdgeOneEnd == NULL || vrtEdgeTwoEnd == NULL ) - { - UG_THROW("lauter Nullen vertizes" << std::endl); - } - - vector3 fracVrtPos = aaPos[*iterV]; - - vector3 fracEdgOneEndPos = aaPos[ vrtEdgeOneEnd ]; - vector3 fracEdgTwoEndPos = aaPos[ vrtEdgeTwoEnd ]; - - vector3 directionEdgOne; - VecSubtract(directionEdgOne, fracEdgOneEndPos, fracVrtPos); - - vector3 directionEdgTwo; - VecSubtract(directionEdgTwo, fracEdgTwoEndPos, fracVrtPos); - - vector3 nrmdVecEdgOne; - VecNormalize(nrmdVecEdgOne, directionEdgOne); - - vector3 nrmdVecEdgTwo; - VecNormalize(nrmdVecEdgTwo, directionEdgTwo); - - number cosBetweenEdges = VecDot(nrmdVecEdgOne,nrmdVecEdgTwo); - - number angleEdges = std::acos( cosBetweenEdges ); - number angleNormls = std::acos( cosBetweenNormals ); - - totAnglsEdg += angleEdges; - totAnglsNrm += angleNormls; - - UG_LOG("cosinus Edges Normals " << cosBetweenEdges << " " << cosBetweenNormals << std::endl); - UG_LOG("angles edges normals " << angleEdges << " " << angleNormls << std::endl); - - // prject normal 1 onto edge 2 and normal 2 on edge 1, scale with width one half resp with width two half - - - number cosBetweenNrmFraOneEdgTwo = VecDot(normalFracOne,nrmdVecEdgTwo); - number cosBetweenNrmFraTwoEdgOne = VecDot(normalFracTwo,nrmdVecEdgOne); - - vector3 projectNrmFraOneToEdgTwoDirection; - VecScale(projectNrmFraOneToEdgTwoDirection, nrmdVecEdgTwo, 1./cosBetweenNrmFraOneEdgTwo); - - vector3 projectNrmFraTwoToEdgOneDirection; - VecScale(projectNrmFraTwoToEdgOneDirection, nrmdVecEdgOne, 1./cosBetweenNrmFraTwoEdgOne); - - // auto subsIndFracOne = sh.get_subset_index(edgeFracOne); - // auto subsIndFracTwo = sh.get_subset_index(edgeFracTwo); - - number shiftOne = fracInfosBySubset.at( subsIndFracOne ).width / 2. ; - number shiftTwo = fracInfosBySubset.at( subsIndFracTwo ).width / 2. ; - - vector3 shiftAlongEdgeTwo; - VecScale(shiftAlongEdgeTwo, projectNrmFraOneToEdgTwoDirection, shiftOne); - - vector3 shiftAlongEdgeOne; - VecScale(shiftAlongEdgeOne, projectNrmFraTwoToEdgOneDirection, shiftTwo); - - vector3 shiftPart; - VecAdd(shiftPart, fracVrtPos, shiftAlongEdgeTwo); - - vector3 posNewVrt; - VecAdd( posNewVrt, shiftPart, shiftAlongEdgeOne); - - UG_LOG("neuer Vertex Kreuzung " << posNewVrt << std::endl ); - - Vertex * newShiftVrtx = *grid.create(); - aaPos[newShiftVrtx] = posNewVrt; - - // sh.assign_subset(newShiftVrtx, newSubsToAdd ); - - - for( VertexOfFaceInfo const & vertFracInfoSeg : segPart ) - { - Face * fac = vertFracInfoSeg.getFace(); - - // sh.assign_subset(fa,newSubsToAdd); - - - // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! - vector& newVrts4Fac = aaVrtVecFace[ fac ]; - - IndexType vrtxFnd = 0; - - for(size_t indVrt = 0; indVrt < (fac)->num_vertices(); indVrt++ ) - { - Vertex* facVrt = (fac)->vertex(indVrt); - - if( facVrt == *iterV ) - { - newVrts4Fac[ indVrt ] = newShiftVrtx; - vrtxFnd++; - } - } - - - if( vrtxFnd <= 0 ) - { - UG_THROW("vertex not found kreuzung!" << std::endl); - } - else if( vrtxFnd > 1 ) - { - UG_THROW("vertex zu oft gefunden kreuzung " << vrtxFnd << std::endl ); - } - else if ( vrtxFnd == 1 ) - { - } - else - { - UG_THROW("vertex finden komisch kreuzung " << std::endl); - } - - } - } - } - - UG_LOG("sum angles edges normals " << totAnglsEdg << " " << totAnglsNrm << std::endl); - -// return true; - -#if 0 - // das folgende ist vermutlich Unsinn TODO FIXME, waren wohl Versuche am Anfang..... nochmal prüfen!!!! - - // get starting point of the "rotation" around the vertex where fractures are crossing -// for( auto & attVFT : vVFT ) // not const, as we need to erase found elements! - for( VecVertFracTrip::iterator itAttVFT = vVFT.begin(); itAttVFT != vVFT.end(); ) - { - Face * facAtVrtWithFrac = itAttVFT->getFace(); - - bool facFound = false; - -// for( auto const & ifac : assoFaces ) // not const, as we need to erase found elements! - for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); ) - { - if( *itFac == facAtVrtWithFrac ) - { - // found a starting face - // copy first the found info, then delete the original one - auto attVFTCop = *itAttVFT; // copy, not reference! - - vVFT.erase(itAttVFT); - aF.erase(itFac); - - // TODO FIXME erase ifac and attVFT, how to do? - - Face * startFace = facAtVrtWithFrac; - - // now determine the common edge(s), the first edge of the vector must be a frac edge, the second one might be one - - Edge * startEdg = attVFTCop.getEdge(); - - // unnecessary check, but for test purposes at beginning, later should be removed - if( !FaceContains(facAtVrtWithFrac, startEdg )) - { - UG_THROW("face hat ecke nicht, die es haben soll" << std::endl); - } - - // loop around the edges of the ifac face attached to the vertex - - // determin second edge of the startFace, not stored in the vecVertFracTrip information - // check number of common edges containing the same vertex - - IndexType fndCommEdg = 0; - std::vector assoEdg2Fac; - - assoEdg2Fac.push_back( startEdg ); - - std::vector assoNorm; - - vector3 norm2Frac = attVFTCop.getNormal(); - - Edge * secondEdge; - secondEdge = NULL; - - for( auto const & iE : allAssoEdges ) // werden nicht gelöscht, deswegen Zugriff auf attachment direkt - { - if( FaceContains(facAtVrtWithFrac, iE) ) - { - fndCommEdg++; - if( iE != startEdg ) - { - secondEdge = iE; - } - } - - if( fndCommEdg != 2 ) - { - UG_THROW("komische Anzahl gemeinsamer Ecke " << fndCommEdg << std::endl); - } - - if( secondEdge == NULL ) - { - UG_THROW("wieso keine zweite Ecke gefunden???? " << std::endl); - } - - assoEdg2Fac.push_back(secondEdge); - - // check, if second edge belongs to anothter fracture fac, i.e. if it is also a fracture edge - - // check if second edge is edge of a fracture face, i.e. either this edge, or another one is from a fracture - - bool scndEdgIsFracEdg = aaMarkEdgeB[secondEdge]; - - if( scndEdgIsFracEdg ) - { - // TODO FIXME figure out second vertex fracture info, in this case, we have found the next part of the chain! - - for( VecVertFracTrip::iterator itAttVFTTwo = vVFT.begin(); itAttVFTTwo != vVFT.end(); ) - { - // need to erase also this element soon, also in the list of all attached elements - - Face* vFTTwoFac = itAttVFTTwo->getFace(); - - if( FaceContains( vFTTwoFac, secondEdge)) - { - auto vVFT2 = *itAttVFTTwo; - vVFT.erase( itAttVFTTwo ); - - Face * nextFace = vFTTwoFac; - - if( secondEdge != vVFT2.getEdge() ) - { - UG_THROW("Ecke nicht Ecke " << std::endl); - } - - - } - } - } - else // find the next attached face, either from the - { - - } - } - - break; - } - - if( ! facFound ) - { - UG_THROW("Gesicht unauffindbar" << std::endl); - } - - break; - } - } - - while( vVFT.size() != 0 ) - { - while( aF.size() != 0 ) - { - - } - } - -#endif - - - } - - } -// // // different treatment for boundary vertizes - else - { - - // TODO FIXME es muss wohl noch ein Problem mit den Verschiebungen bei boundary Vertizes geben..... - // TODO FIXME XXXXXXXXXXXXXX hier sind wir - - - if( numFracsCrossAtVrt < 1 ) - { - UG_THROW("no fracs crossing but marked vertex at boundary? << std::endl"); - } - else if( numFracsCrossAtVrt == 1 ) // no crossing point at boundary - { - // in this case, we have ONE attached edges, the edges has two attached faces - // the faces have a normal, and based on the normal, we can decide which faces belong to the same side of the edges - - if( numbAttTripl != 2 ) - { - UG_THROW("Anzahl der angehaengten Triples kann nicht stimmen, Vertex einer Kluft ohne Schnittpunkte am Rand " << std::endl); - } - - // Zuordnung der Edges und Faces, die auf der gleichen Seite der fracture sind - - // und gleich auch Erzeugung der neuen Knoten, die dann - // in einem Doublett zusammen mit ihren Normalen an die alten Vertizes - // angehängt werden; der Winkel zur Normalen hilft später, die Seite - // heraus zu finden, Seite von den Edges - - // get edges adjacent to this vertex which lie on the boundary of the domain - - std::vector adjBndEdgs; - -// std::vector & allAssoEdges = aaVrtInfoAssoEdges[*iterV]; - -// for( std::vector::iterator iterBVEdg = grid.associated_edges_begin(*iterV); iterBVEdg != grid.associated_edges_end(*iterV); iterBVEdg++ ) -// { -// if( IsBoundaryEdge2D(grid,*iterBVEdg) ) -// { -// adjBndEdgs.push_back( *iterBVEdg ); -// } -// } - for( auto const & iBVE : allAssoEdges ) - { - if( IsBoundaryEdge2D(grid, iBVE ) ) - { - adjBndEdgs.push_back( iBVE ); - } - } - - // to compute the normals, compute the vector of the edge and normalize it - std::vector bndEdgeDirection; - - for( auto const & bE : adjBndEdgs ) - { - - // get vertices, i.e. get seocnd vertex, first one must be known - -// std::vector verticesEdg; - - static_assert( std::is_same< Edge* const &, decltype( bE ) >::value ); - - static_assert( std::is_same< Vertex*, decltype( bE->vertex(0) ) >::value ); - - IndexType fndIV = 0; - - Vertex * vrtOtherEdg; - vrtOtherEdg = NULL; - - for( size_t i = 0; i < 2; ++i ) - { -// verticesEdg.push_back( adjBndEdgs.vertex(i) ); - - Vertex * vrtOfEdg = bE->vertex(i); - - if( vrtOfEdg == *iterV ) - { - fndIV++; - } - else - { - vrtOtherEdg = vrtOfEdg; - } - } - - vector3 posOtherVrt = aaPos[vrtOtherEdg]; - - UG_LOG("BOUNDARY EDGE VERTIZES " << posOldVrt << ", " << posOtherVrt << std::endl); - - vector3 fromIterV2Other; - - VecSubtract(fromIterV2Other, posOtherVrt, posOldVrt); - - vector3 nV; - - VecNormalize(nV, fromIterV2Other); - - bndEdgeDirection.push_back(nV); - } - - - -#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX - - IndexType dbg_lim = vecVertFracTrip.size(); - - int dbg_cnt = 0; -#endif - - for( VvftIterator vvftAtBnd = vecVertFracTrip.begin(); - vvftAtBnd != vecVertFracTrip.end(); - vvftAtBnd++ - ) - { -#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX - - if( dbg_lim == dbg_cnt ) - { - UG_LOG("DARF NICHT SEIN" << std::endl); - break; - } - - dbg_cnt++; -#endif - - // Ziel: den parallelen Anteil der Normalen auf die jeweilige Randkante projizieren - - vector3 nrmEdg = vvftAtBnd->getNormal(); - - Edge * edgeOfFrac = vvftAtBnd->getEdge(); - - // figure out the adjoint boundary edge into the same direction - - // the normal in both directions have to be compared with the vectors in direction of boundary edges - for( auto bED : bndEdgeDirection ) - { - // check orientation of boundary edges wrt the normals - - number cosinus = VecDot( nrmEdg, bED ); - - UG_LOG("BOUNDARY COSINUS between " << nrmEdg << " and " << bED << " -> " << cosinus << std::endl); - - if( cosinus > 0 ) - { - // gleiche Seite vermutet - - // muessen wissen, wie lange das gestreckt werden soll - - vector3 alongEdgV; - - auto subsIndEdgOF = sh.get_subset_index(edgeOfFrac); - - number width = fracInfosBySubset.at(subsIndEdgOF).width; - - number scal = width / 2. / cosinus; - - VecScale( alongEdgV, bED, scal ); - - vector3 posNewVrtOnBnd; - - VecAdd(posNewVrtOnBnd, posOldVrt, alongEdgV ); - - UG_LOG("neuer Vertex Edge " << posNewVrtOnBnd << std::endl ); - - Vertex * newShiftEdgVrtx = *grid.create(); - aaPos[newShiftEdgVrtx] = posNewVrtOnBnd; - - sh.assign_subset(newShiftEdgVrtx, subsIndEdgOF ); - - std::vector attEdg; - std::vector attFac; - - attEdg.push_back(edgeOfFrac); - - Face * facFrac = vvftAtBnd->getFace(); - - attFac.push_back( facFrac ); - - // we store the boundary edge direction for boundary verzizes rather than the normal, in contrast to inner vertizes, where we store the averaged normal - ExpandVertexMultiplett vrtMtpl( attEdg, attFac, bED ); - - aaVrtExpMP[ *iterV ].push_back( vrtMtpl ); - -#if 0 - // the attached faces need to know that they need a new vertex to be shifted - for( std::vector::iterator iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ ) - { - bool isFromFrac = false; - - for( auto const & facFrac : attFac ) - { - if( *iterFac == facFrac ) - { - isFromFrac = true; - } - } - - bool atRightSide = false; - - if( isFromFrac ) - atRightSide = true; - - if( !isFromFrac ) - { - - // check if on same side of edge where the normal points to: compute cosinus between vector of face center - // perpendicular to the edge - // TODO FIXME - - vector3 facCenter = CalculateCenter( *iterFac, aaPos ); - - vector3 perpendicu; - - DropAPerpendicular(perpendicu, facCenter, aaPos[edgeOfFrac->vertex(0)], aaPos[edgeOfFrac->vertex(1)]); - - vector3 tmpN; - - VecSubtract(tmpN, facCenter, perpendicu ); - - VecNormalize(tmpN, tmpN); - - UG_LOG("Normale Boundary zum Face ist " << tmpN << std::endl); - - number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, nrmEdg ); - - UG_LOG("Cosinus Boundary zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); - - if( cosBetwFracEdgAndDirection2Face > 0 ) - { - UG_LOG("assuming boundary face to be on richt side" << std::endl); - - atRightSide = true; - -#if ANSCHAULICH_ERZEUGE_SUDOS_ANHANG - Vertex * otherFacCent = *grid.create(); - aaPos[otherFacCent] = facCenter; - sh.assign_subset(otherFacCent, 5 ); - - Vertex * pp = *grid.create(); - aaPos[pp] = perpendicu; - sh.assign_subset(pp, 6 ); - - sh.assign_subset(*iterFac,7); -#endif - - - } - else - { - UG_LOG("assuming boundary face to be on wrong side" << std::endl); - } - - } - - if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein - { - - - vector& newVrts4Fac = aaVrtVecFace[ * iterFac ]; - - IndexType vrtxFnd = 0; - - for(size_t indVrt = 0; indVrt < (*iterFac)->num_vertices(); indVrt++ ) - { - Vertex* facVrt = (*iterFac)->vertex(indVrt); - - if( facVrt == *iterV ) - { - newVrts4Fac[ indVrt ] = newShiftEdgVrtx; - vrtxFnd++; - } - } - - - - if( vrtxFnd <= 0 ) - { - UG_THROW("vertex not found bnd!" << std::endl); - } - else if( vrtxFnd > 1 ) - { - UG_THROW("vertex zu oft gefunden bnd " << vrtxFnd << std::endl ); - } - else if ( vrtxFnd == 1 ) - { -// UG_LOG("vertex found abgeschlossen" << std::endl); - } - else - { - UG_THROW("vertex finden bnd komisch " << std::endl); - } - } - - } -#else - for( auto const & ifac : assoFaces ) - { - bool isFromFrac = false; - - for( auto const & facFrac : attFac ) - { - if( ifac == facFrac ) - { - isFromFrac = true; - } - } - - bool atRightSide = false; - - if( isFromFrac ) - atRightSide = true; - - if( !isFromFrac ) - { - - // check if on same side of edge where the normal points to: compute cosinus between vector of face center - // perpendicular to the edge - // TODO FIXME - - vector3 facCenter = CalculateCenter( ifac, aaPos ); - - vector3 perpendicu; - - DropAPerpendicular(perpendicu, facCenter, aaPos[edgeOfFrac->vertex(0)], aaPos[edgeOfFrac->vertex(1)]); - - vector3 tmpN; - - VecSubtract(tmpN, facCenter, perpendicu ); - - VecNormalize(tmpN, tmpN); - - UG_LOG("Normale Boundary zum Face ist " << tmpN << std::endl); - - number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, nrmEdg ); - - UG_LOG("Cosinus Boundary zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); - - if( cosBetwFracEdgAndDirection2Face > 0 ) - { - UG_LOG("assuming boundary face to be on richt side" << std::endl); - - atRightSide = true; - -#if ANSCHAULICH_ERZEUGE_SUDOS_ANHANG - Vertex * otherFacCent = *grid.create(); - aaPos[otherFacCent] = facCenter; - sh.assign_subset(otherFacCent, 5 ); - - Vertex * pp = *grid.create(); - aaPos[pp] = perpendicu; - sh.assign_subset(pp, 6 ); - - sh.assign_subset(*iterFac,7); -#endif - - - } - else - { - UG_LOG("assuming boundary face to be on wrong side" << std::endl); - } - - } - - if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein - { - - - vector& newVrts4Fac = aaVrtVecFace[ ifac ]; - - IndexType vrtxFnd = 0; - - for(size_t indVrt = 0; indVrt < (ifac)->num_vertices(); indVrt++ ) - { - Vertex* facVrt = (ifac)->vertex(indVrt); - - if( facVrt == *iterV ) - { - newVrts4Fac[ indVrt ] = newShiftEdgVrtx; - vrtxFnd++; - } - } - - - - if( vrtxFnd <= 0 ) - { - UG_THROW("vertex not found bnd!" << std::endl); - } - else if( vrtxFnd > 1 ) - { - UG_THROW("vertex zu oft gefunden bnd " << vrtxFnd << std::endl ); - } - else if ( vrtxFnd == 1 ) - { -// UG_LOG("vertex found abgeschlossen" << std::endl); - } - else - { - UG_THROW("vertex finden bnd komisch " << std::endl); - } - } - } - -#endif - - - - } - } - } - - } - else // fractures are crossing at boundary even - { - - } - - - UG_LOG("END THIS BOUNDARY VERTEX" << std::endl); - } - - dbg_vertizesPassiert++; - - } - - -// // neue Vertizes in der Entfernung der Klüfte von den Klüften weg erzeugen, -// // basierend auf den Normalen multipliziert mit der halben Kluftdicke -// //für eine Kluft erstmal nur -// // die neuen Kanten und Faces erzeugen, die alten falschen Kanten löschen und ebenso die alten Faces -// // später auf mehr Klüfte ausdehnen, mit Problemstelle Kreuzung, aber erst, wenn eine Kluft funktioniert -// - -// return true; - - // jetzt Seb Sachen beinahe unverändert - - //////////////////////////////// - // create new elements - - // first we create new edges from selected ones which are connected to - // inner vertices. This allows to preserve old subsets. - // Since we have to make sure that we use the right vertices, - // we have to iterate over the selected faces and perform all actions on the edges - // of those faces. - for(FaceIterator iter_sf = sel.faces_begin(); iter_sf != sel.faces_end(); ++iter_sf) - { - Face* sf = *iter_sf; - // check for each edge whether it has to be copied. - for(size_t i_edge = 0; i_edge < sf->num_edges(); ++i_edge) - { - Edge* e = grid.get_edge(sf, i_edge); - - if(sel.is_selected(e)) - { - // check the associated vertices through the volumes aaVrtVecVol attachment. - // If at least one has an associated new vertex and if no edge between the - // new vertices already exists, we'll create the new edge. - size_t ind0 = i_edge; - size_t ind1 = (i_edge + 1) % sf->num_edges(); - - Vertex* nv0 = (aaVrtVecFace[sf])[ind0]; - Vertex* nv1 = (aaVrtVecFace[sf])[ind1]; - - if(nv0 || nv1) - { - // if one vertex has no associated new one, then we use the vertex itself - if(!nv0) - nv0 = sf->vertex(ind0); - if(!nv1) - nv1 = sf->vertex(ind1); - - // create the new edge if it not already exists. - if(!grid.get_edge(nv0, nv1)) - grid.create_by_cloning(e, EdgeDescriptor(nv0, nv1), e); - } - } - } - } - - - std::vector newFaces; - std::vector subsOfNewFaces; - - // iterate over all surrounding faces and create new vertices. - // Since faces are replaced on the fly, we have to take care with the iterator. - for(FaceIterator iter_sf = sel.faces_begin(); iter_sf != sel.faces_end();) - { - Face* sf = *iter_sf; - ++iter_sf; - - vector newVrts = aaVrtVecFace[sf]; - - // all new vertices have been assigned to newVrts. - // Note that if newVrts[i] == NULL, then we have to take the - // old vertex sf->vertex(i). - // now expand the fracture edges of sf to faces. - for(size_t i_vrt = 0; i_vrt < sf->num_vertices(); ++i_vrt) - { - size_t iv1 = i_vrt; - size_t iv2 = (i_vrt + 1) % sf->num_vertices(); - - Edge* tEdge = grid.get_edge(sf->vertex(iv1), sf->vertex(iv2)); - - if(tEdge) - { - if( aaMarkEdgeB[tEdge] ) - { - Face* expFace = NULL; - if(newVrts[iv1] && newVrts[iv2]) - { - // create a new quadrilateral - expFace = *grid.create( - QuadrilateralDescriptor(sf->vertex(iv1), sf->vertex(iv2), - newVrts[iv2], newVrts[iv1])); - } - else if(newVrts[iv1]) - { - // create a new triangle - expFace = *grid.create( - TriangleDescriptor(sf->vertex(iv1), sf->vertex(iv2), newVrts[iv1])); - } - else if(newVrts[iv2]) - { - // create a new triangle - expFace = *grid.create( - TriangleDescriptor(sf->vertex(iv1), sf->vertex(iv2), newVrts[iv2])); - } - else - { - -//// sh.assign_subset(*iter_sf,10); -//// sh.assign_subset(tEdge,11); -// -// return true; -// // this code-block should never be entered. If it is entered then -// // we selected the wrong faces. This is would be a BUG!!! -// // remove the temporary attachments and throw an error -// -// // remove the temporary attachments -//#if OLD_PROFREITER_STUFF -// grid.detach_from_vertices(aAdjMarker); -// grid.detach_from_edges(aAdjMarker); -//#endif -// grid.detach_from_vertices(aAdjMarkerVFP); -// grid.detach_from_edges(aAdjMarkerB); -// -// grid.detach_from_vertices( aAdjInfoAVVFT ); -// grid.detach_from_faces(attVrtVec); -// -// grid.detach_from_vertices( aAdjInfoEdges ); -// grid.detach_from_vertices( aAdjInfoFaces ); -// -// -// // TODO FIXME auch die weiteren Marker und INfos, alle Attachments, detachen!!!! -// -// throw(UGError("Implementation error in ExpandFractures2d Arte.")); - } - - // TODO FIXME selektion closen irgendwie, damit auch alle Randkanten zum subset gehoeren!!! - - if( expFace ) - { - sh.assign_subset(expFace, fracInfosBySubset.at(sh.get_subset_index(tEdge)).newSubsetIndex); - - int subs = fracInfosBySubset.at(sh.get_subset_index(tEdge)).newSubsetIndex; - - subsOfNewFaces.push_back( subs ); - - newFaces.push_back( expFace ); - } - } - } - } - - - - - // now set up a new face descriptor and replace the face. - if(fd.num_vertices() != sf->num_vertices()) - fd.set_num_vertices(sf->num_vertices()); - - for(size_t i_vrt = 0; i_vrt < sf->num_vertices(); ++i_vrt) - { - if(newVrts[i_vrt]) - fd.set_vertex(i_vrt, newVrts[i_vrt]); - else - fd.set_vertex(i_vrt, sf->vertex(i_vrt)); - } - - grid.create_by_cloning(sf, fd, sf); - grid.erase(sf); - } - - // we have to clean up unused edges. - // All selected edges with mark 0 have to be deleted. - for(EdgeIterator iter = sel.edges_begin(); iter != sel.edges_end();) - { - // be careful with the iterator - Edge* e = *iter; - ++iter; - - if(!aaMarkEdgeB[e]) - grid.erase(e); - } - - if( subsOfNewFaces.size() != newFaces.size() ) - { - UG_THROW("andere zahl neue faces als subdoms " << std::endl); - } - - IndexType nfn = 0; - - for( auto const & nf : newFaces ) - { - for(size_t i_edge = 0; i_edge < nf->num_edges(); ++i_edge) - { - Edge* edg = grid.get_edge(nf, i_edge); - - sh.assign_subset( edg, subsOfNewFaces[nfn] ); - } - - nfn++; - } - - // TODO FIXME sollen die Boundary Edges zur boundary gehören, oder zur Kluft? - // TODO FIXME wie ist es mit den Knoten, sind die alle richtig zugewiesen bezüglich subset? - - // remove the temporary attachments - -#if OLD_PROFREITER_STUFF - grid.detach_from_vertices(aAdjMarker); - grid.detach_from_edges(aAdjMarker); -#endif - grid.detach_from_vertices(aAdjMarkerVFP); - grid.detach_from_edges(aAdjMarkerB); - - grid.detach_from_vertices( aAdjInfoAVVFT ); - grid.detach_from_faces(attVrtVec); - - grid.detach_from_vertices( aAdjInfoEdges ); - grid.detach_from_vertices(aAdjInfoFaces ); - - - // TODO FIXME alles detachen, was noch attached ist, da ist einiges hinzu gekommen! - - - return true; - - // ENDE NEUES ZEUG SELEKTION - - - - - - - -#if OLD_PROFREITER_STUFF - // TODO FIXME von diesem Loop kann man noch für oben die calculate crease normal lernen, vielleicht minimal abgewandelt, vielleicht exakt gleich - - // a callback that returns true if the edge is a fracture edge, neues System - AttachmentUnequal > isFracEdgeB(aaMarkEdgeB, false); - - // iterate over all surrounding faces and create new vertices. - for(FaceIterator iter_sf = sel.faces_begin(); iter_sf != sel.faces_end(); ++iter_sf) - { - Face* sf = *iter_sf; - - // check for each vertex whether it lies in the fracture - // (aaMarkVRT > 1 in this case) - // if so, we have to copy or create a vertex from/in aaVrtVec[vrt] which is - // associated with the crease normal on the side of sf. - for(size_t i_vrt = 0; i_vrt < sf->num_vertices(); ++i_vrt) - { - Vertex* vrt = sf->vertex(i_vrt); - if(aaMarkVRT[vrt] > 1) - { - // calculate the normal on this side of the frac - // TODO FIXME so eine Funktion brauchen wir vielleicht oben auch zur Vereinfachung des Codes!!! - vector3 n_v2 = CalculateCreaseNormal(grid, sf, vrt, isFracEdgeB, aaPos); - // das calculate crease normal scheint mir ein Schwachsinn zu sein - // aber vielleicht doch nicht? - - UG_LOG("calculated crease normal v2: " << n_v2 << endl); - - } - } -#endif - - - - - - - -} - - - - /** Selects all involved geometic objects and assigns marks to them. * If required, som edges may be split, so that we always operate * on a fully expandable fracture. From e4ff2400be0ead8b6c2ba90ab67a5107f4aa9d0f Mon Sep 17 00:00:00 2001 From: Arne Naegel Date: Thu, 11 Jul 2024 09:09:50 +0200 Subject: [PATCH 24/58] Update jenkins-trigger.yml: Jenkins interval: 5', start_timeout: 30' --- .github/workflows/jenkins-trigger.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/jenkins-trigger.yml b/.github/workflows/jenkins-trigger.yml index eabbb5328..866ae01a2 100644 --- a/.github/workflows/jenkins-trigger.yml +++ b/.github/workflows/jenkins-trigger.yml @@ -22,4 +22,5 @@ jobs: username: ${{ secrets.JENKINS_USER }} api_token: ${{ secrets.JENKINS_TOKEN }} timeout: "3600" - interval: "300" + interval: "60" + start_timeout: "1800" From 0e9b49a4349a4f36996f780d7c0dda02f6661d22 Mon Sep 17 00:00:00 2001 From: Arne Naegel Date: Thu, 11 Jul 2024 09:11:06 +0200 Subject: [PATCH 25/58] Update jenkins-trigger.yml: start_timeout: 1h --- .github/workflows/jenkins-trigger.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/jenkins-trigger.yml b/.github/workflows/jenkins-trigger.yml index 866ae01a2..f9f51f276 100644 --- a/.github/workflows/jenkins-trigger.yml +++ b/.github/workflows/jenkins-trigger.yml @@ -23,4 +23,4 @@ jobs: api_token: ${{ secrets.JENKINS_TOKEN }} timeout: "3600" interval: "60" - start_timeout: "1800" + start_timeout: "3600" From 141f816895ef42334aa05f5fbee765b34a6be04c Mon Sep 17 00:00:00 2001 From: Arne Naegel Date: Thu, 11 Jul 2024 09:47:31 +0200 Subject: [PATCH 26/58] Create jenkins-trigger2.yml (new trigger) --- .github/workflows/jenkins-trigger2.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .github/workflows/jenkins-trigger2.yml diff --git a/.github/workflows/jenkins-trigger2.yml b/.github/workflows/jenkins-trigger2.yml new file mode 100644 index 000000000..dc6d89fb2 --- /dev/null +++ b/.github/workflows/jenkins-trigger2.yml @@ -0,0 +1,14 @@ +jobs: + trigger-a-jenkins-job: + runs-on: ubuntu-latest + steps: + - id: triggerjenkinsjob + uses: mickeygoussetorg/trigger-jenkins-job@v1 + with: + jenkins-server: ${{ secrets.JENKINS_URL }} # URL of the jenkins server. ex: http://myjenkins.acme.com:8080 + jenkins-job: "mySampleApp" # The name of the jenkins job to run + jenkins-username: ${{ secrets.JENKINS_USER }} # user name for accessing jenkins + jenkins-pat: ${{ secrets.JENKINS_TOKEN }} # personal Access token for accessing Jenkins + poll-time: 10 # how often (seconds) to poll the jenkins server for results + timeout-value: 3600 # How long (seconds) to poll before timing out the action + verbose: true # true/false - turns on extra logging From 9551be7323665031e9eab0051798f9c9f1740c2b Mon Sep 17 00:00:00 2001 From: Arne Naegel Date: Thu, 11 Jul 2024 09:54:16 +0200 Subject: [PATCH 27/58] Update jenkins-trigger2.yml --- .github/workflows/jenkins-trigger2.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/jenkins-trigger2.yml b/.github/workflows/jenkins-trigger2.yml index dc6d89fb2..e13cc49ac 100644 --- a/.github/workflows/jenkins-trigger2.yml +++ b/.github/workflows/jenkins-trigger2.yml @@ -6,7 +6,7 @@ jobs: uses: mickeygoussetorg/trigger-jenkins-job@v1 with: jenkins-server: ${{ secrets.JENKINS_URL }} # URL of the jenkins server. ex: http://myjenkins.acme.com:8080 - jenkins-job: "mySampleApp" # The name of the jenkins job to run + jenkins-job: "ug-build-pipeline" # The name of the jenkins job to run jenkins-username: ${{ secrets.JENKINS_USER }} # user name for accessing jenkins jenkins-pat: ${{ secrets.JENKINS_TOKEN }} # personal Access token for accessing Jenkins poll-time: 10 # how often (seconds) to poll the jenkins server for results From bb6e8c160282a0e60aed14281a9386ec0bf2859b Mon Sep 17 00:00:00 2001 From: Arne Naegel Date: Thu, 11 Jul 2024 09:56:02 +0200 Subject: [PATCH 28/58] Update jenkins-trigger2.yml --- .github/workflows/jenkins-trigger2.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/jenkins-trigger2.yml b/.github/workflows/jenkins-trigger2.yml index e13cc49ac..fdf01ea0c 100644 --- a/.github/workflows/jenkins-trigger2.yml +++ b/.github/workflows/jenkins-trigger2.yml @@ -1,3 +1,10 @@ +on: + # Triggers the workflow on push or pull request events but only for the main branch + push: + branches: [ master ] + pull_request: + branches: [ master ] + jobs: trigger-a-jenkins-job: runs-on: ubuntu-latest From e0d40097c44725f7511976f2a1b724e45e516e92 Mon Sep 17 00:00:00 2001 From: Arne Naegel Date: Thu, 11 Jul 2024 09:59:41 +0200 Subject: [PATCH 29/58] Update jenkins-trigger2.yml: poll every 2 mins --- .github/workflows/jenkins-trigger2.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/jenkins-trigger2.yml b/.github/workflows/jenkins-trigger2.yml index fdf01ea0c..b547145b1 100644 --- a/.github/workflows/jenkins-trigger2.yml +++ b/.github/workflows/jenkins-trigger2.yml @@ -16,6 +16,6 @@ jobs: jenkins-job: "ug-build-pipeline" # The name of the jenkins job to run jenkins-username: ${{ secrets.JENKINS_USER }} # user name for accessing jenkins jenkins-pat: ${{ secrets.JENKINS_TOKEN }} # personal Access token for accessing Jenkins - poll-time: 10 # how often (seconds) to poll the jenkins server for results + poll-time: 120 # how often (seconds) to poll the jenkins server for results timeout-value: 3600 # How long (seconds) to poll before timing out the action verbose: true # true/false - turns on extra logging From 4f242632aff225f99fe1d6da70abe9c5b09c7760 Mon Sep 17 00:00:00 2001 From: Arne Naegel Date: Thu, 11 Jul 2024 10:01:28 +0200 Subject: [PATCH 30/58] Update jenkins-trigger2.yml --- .github/workflows/jenkins-trigger2.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/jenkins-trigger2.yml b/.github/workflows/jenkins-trigger2.yml index b547145b1..fdf01ea0c 100644 --- a/.github/workflows/jenkins-trigger2.yml +++ b/.github/workflows/jenkins-trigger2.yml @@ -16,6 +16,6 @@ jobs: jenkins-job: "ug-build-pipeline" # The name of the jenkins job to run jenkins-username: ${{ secrets.JENKINS_USER }} # user name for accessing jenkins jenkins-pat: ${{ secrets.JENKINS_TOKEN }} # personal Access token for accessing Jenkins - poll-time: 120 # how often (seconds) to poll the jenkins server for results + poll-time: 10 # how often (seconds) to poll the jenkins server for results timeout-value: 3600 # How long (seconds) to poll before timing out the action verbose: true # true/false - turns on extra logging From 776c187afc1b3a5696d57cca2843ab9cad6a6d32 Mon Sep 17 00:00:00 2001 From: Arne Naegel Date: Thu, 11 Jul 2024 10:02:39 +0200 Subject: [PATCH 31/58] Update jenkins-trigger2.yml --- .github/workflows/jenkins-trigger2.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/jenkins-trigger2.yml b/.github/workflows/jenkins-trigger2.yml index fdf01ea0c..61ad72d33 100644 --- a/.github/workflows/jenkins-trigger2.yml +++ b/.github/workflows/jenkins-trigger2.yml @@ -16,6 +16,6 @@ jobs: jenkins-job: "ug-build-pipeline" # The name of the jenkins job to run jenkins-username: ${{ secrets.JENKINS_USER }} # user name for accessing jenkins jenkins-pat: ${{ secrets.JENKINS_TOKEN }} # personal Access token for accessing Jenkins - poll-time: 10 # how often (seconds) to poll the jenkins server for results + poll-time: 90 # how often (seconds) to poll the jenkins server for results timeout-value: 3600 # How long (seconds) to poll before timing out the action verbose: true # true/false - turns on extra logging From 0eedc2438e7487534facfad377e959802cb62fe0 Mon Sep 17 00:00:00 2001 From: Arne Naegel Date: Thu, 11 Jul 2024 10:35:17 +0200 Subject: [PATCH 32/58] Update jenkins-trigger2.yml --- .github/workflows/jenkins-trigger2.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/jenkins-trigger2.yml b/.github/workflows/jenkins-trigger2.yml index 61ad72d33..22a904a70 100644 --- a/.github/workflows/jenkins-trigger2.yml +++ b/.github/workflows/jenkins-trigger2.yml @@ -1,3 +1,5 @@ +name: Trigger Jenkins CI +# Controls when the workflow will run on: # Triggers the workflow on push or pull request events but only for the main branch push: From 1e80ffb53a1fbc97b343a10da9d3855dccb7b4b2 Mon Sep 17 00:00:00 2001 From: Arne Naegel Date: Thu, 11 Jul 2024 10:36:09 +0200 Subject: [PATCH 33/58] Delete .github/workflows/jenkins-trigger.yml --- .github/workflows/jenkins-trigger.yml | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100644 .github/workflows/jenkins-trigger.yml diff --git a/.github/workflows/jenkins-trigger.yml b/.github/workflows/jenkins-trigger.yml deleted file mode 100644 index f9f51f276..000000000 --- a/.github/workflows/jenkins-trigger.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Trigger Jenkins CI -# Controls when the workflow will run -on: - # Triggers the workflow on push or pull request events but only for the main branch - push: - branches: [ master ] - pull_request: - branches: [ master ] - -# A workflow run is made up of one or more jobs that can run sequentially or in parallel -jobs: - # This workflow contains a single job called "build" - build: - name: Build - runs-on: ubuntu-latest - steps: - - name: Trigger jenkins job - uses: anaegel/jenkins-githubaction@master - with: - url: ${{ secrets.JENKINS_URL }} - job_name: ug-build-pipeline - username: ${{ secrets.JENKINS_USER }} - api_token: ${{ secrets.JENKINS_TOKEN }} - timeout: "3600" - interval: "60" - start_timeout: "3600" From 799e16dea70aa63a4aafd99ff36cd16f95893722 Mon Sep 17 00:00:00 2001 From: Arne Naegel Date: Thu, 11 Jul 2024 10:36:22 +0200 Subject: [PATCH 34/58] Rename jenkins-trigger2.yml to jenkins-trigger.yml --- .github/workflows/{jenkins-trigger2.yml => jenkins-trigger.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{jenkins-trigger2.yml => jenkins-trigger.yml} (100%) diff --git a/.github/workflows/jenkins-trigger2.yml b/.github/workflows/jenkins-trigger.yml similarity index 100% rename from .github/workflows/jenkins-trigger2.yml rename to .github/workflows/jenkins-trigger.yml From 9a75dc916939953c2464fbb6adae2561b83a9356 Mon Sep 17 00:00:00 2001 From: Arne Naegel Date: Thu, 11 Jul 2024 10:55:15 +0200 Subject: [PATCH 35/58] Update jenkins-trigger.yml --- .github/workflows/jenkins-trigger.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/jenkins-trigger.yml b/.github/workflows/jenkins-trigger.yml index 22a904a70..239b3bbaa 100644 --- a/.github/workflows/jenkins-trigger.yml +++ b/.github/workflows/jenkins-trigger.yml @@ -1,4 +1,5 @@ name: Trigger Jenkins CI + # Controls when the workflow will run on: # Triggers the workflow on push or pull request events but only for the main branch @@ -8,7 +9,7 @@ on: branches: [ master ] jobs: - trigger-a-jenkins-job: + trigger-jenkins-job: runs-on: ubuntu-latest steps: - id: triggerjenkinsjob From 4fb345c5abbb4d913b8d26458b283e9d796ccf9f Mon Sep 17 00:00:00 2001 From: Markus Date: Tue, 9 Jul 2024 19:06:12 +0200 Subject: [PATCH 36/58] KluftInnen Erzeugung mit DiamantInnen als Ziel (cherry picked from commit 79e85b749845f2714c7762db5085ab2ae42de446) --- .../lib_grid/algorithms/extrusion/expand_layers.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp index a07a4f39f..b47ce9f8b 100644 --- a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp +++ b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp @@ -3200,9 +3200,8 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c // dieselben Methoden wie im Fall von einer durchgehenden Kluft an einem Vertex, dort kopieren // bzw Funktion schreiben, die beides macht - // TODO FIXME irgendwie muss hier der Fall abgezweigt werden, dass wir auf der durchgehenden Seite einer Kluft sind + // hier wird der Fall abgezweigt, dass wir auf der durchgehenden Seite einer Kluft sind // wenn wir eine T-Kreuzung haben - // HHHHHHHHHHHH hier kritischer Punkt aktuell std::vector nextFracVrt; @@ -4199,8 +4198,12 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c nfn++; } - // TODO FIXME sollen die Boundary Edges zur boundary gehören, oder zur Kluft? - // TODO FIXME wie ist es mit den Knoten, sind die alle richtig zugewiesen bezüglich subset? + // sollen die Boundary Edges zur boundary gehören, oder zur Kluft? + // wie ist es mit den Knoten, sind die alle richtig zugewiesen bezüglich subset? + + // TODO FIXME HHHHHHHHHHHHHHHHHH + // jetzt muss noch der Diamant erzeugt werden + // Ziel: KluftInnen erzeugen // remove the temporary attachments From b549ab10c608ad67dde1079fcd7af45b4be80709 Mon Sep 17 00:00:00 2001 From: Markus Date: Wed, 10 Jul 2024 23:29:12 +0200 Subject: [PATCH 37/58] vergessene Datei addiert (cherry picked from commit 76f9b81e47a878d09c2c26cc01084ad3c6060971) --- .../lib_grid/algorithms/extrusion/support.h | 270 ++++++++++++++++++ 1 file changed, 270 insertions(+) create mode 100644 ugbase/lib_grid/algorithms/extrusion/support.h diff --git a/ugbase/lib_grid/algorithms/extrusion/support.h b/ugbase/lib_grid/algorithms/extrusion/support.h new file mode 100644 index 000000000..a424f010e --- /dev/null +++ b/ugbase/lib_grid/algorithms/extrusion/support.h @@ -0,0 +1,270 @@ +#ifndef __SUPPORT_H__ +#define __SUPPORT_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + ////////////////////////////////////////////////////////////////////////////// + +// class to help count and store a bool and a number of templete type +// comparable to std::pair but more dedicated to the specific aim + + template< typename T > + class VertexFractureProperties + { + public: + + VertexFractureProperties( bool isBndFracVertex, T numberCrossingFracsInVertex ) + : m_isBndFracVertex(isBndFracVertex), m_numberCountedFracsInVertex(numberCrossingFracsInVertex) + { + }; + + + VertexFractureProperties() + : VertexFractureProperties( false, 0 ) + { + }; + + void setIsBndFracVertex( bool iBDV = true ) + { + m_isBndFracVertex = iBDV; + } + + void setNumberCrossingFracsInVertex( T const & nCFIV ) + { + m_numberCountedFracsInVertex = nCFIV; + } + + bool getIsBndFracVertex() + { + return m_isBndFracVertex; + } + +// T getCountedNumberFracsInVertex() +// { +// return m_numberCountedFracsInVertex; +// } + + + T getNumberFracEdgesInVertex() + { + return m_numberCountedFracsInVertex; + } + +// T getNumberCrossingFracsInVertex() +// { +// if( m_isBndFracVertex ) +// return m_numberCountedFracsInVertex; +// +// // for inner vertices, each edge passed when +// // fractures are counted along their edges +// // that the vertizes get hit twice for each fracture run +// // only for boundary vertices, this happens only once per fracture +// T multipeInnerHits = 2; +// +// T rest = m_numberCountedFracsInVertex % multipeInnerHits; +// +// if( rest != 0 ) +// { +//// UG_THROW("Expand layers: rest division frac counting not zero " << m_numberCountedFracsInVertex << std::endl); +// +// throw std::runtime_error("error"); +// +// return 0; +// } +// +// return m_numberCountedFracsInVertex / multipeInnerHits; +// } + + VertexFractureProperties & operator++( int a ) + { + m_numberCountedFracsInVertex++; + return *this; + } + + + private: + bool m_isBndFracVertex; + T m_numberCountedFracsInVertex; + }; + + ////////////////////////////////////////////////////////////////////////////// + +// a class to store a matrix with two indices + +template< typename I, typename D, +typename std::enable_if::value, int>::type = 0, +typename std::enable_if::value, int>::type = 0 +//, typename std::conditional_t, char, D> + > +class MatrixTwoIndices +{ +public: + + // standard constructor + MatrixTwoIndices() : x_degree(-1), y_degree(-1) {}; + + // constructor, wants to know the degrees + MatrixTwoIndices( I _x_degree_, I _y_degree_, D defVal = 0 ) + : x_degree(_x_degree_), y_degree(_y_degree_) + { values = std::vector( (_x_degree_)*(_y_degree_), defVal ); } + + // asking for a special element, cout << object(i,j) ... + D const operator()( I i, I j ) const + { + assert( x_degree > 0 && y_degree > 0 ); + return values[ j*(x_degree) + i ]; + } + + // giving a special element a special value , object(i,j) = xx -> values[...] = xx + D & operator()( I i, I j ) + { + assert( x_degree > 0 && y_degree > 0 ); + return values[ j*(x_degree) + i ]; + } + +private: + + std::vector values; + I x_degree, y_degree; // the degree of the polynom in x and y + + }; + +// std::vector minDist2Center(fracInfos.size(), std::numeric_limits); +// matrix, wo auch index drin ist der subdom + +// MatrixTwoIndices mat_fracInd_minFacePep( fracInfos.size(), 100 ); +// MatrixTwoIndices mat_fracInd_minFacePep( fracInfos.size(), std::numeric_limits::max() ); + //MatrixTwoIndices mat_fracInd_minFacePep( fracInfos.size(), std::numeric_limits ); + +// MatrixTwoIndices mat_fracInd_minFacePep( 30, 20, std::numeric_limits::max() ); +// +// class bla{ +// +// }; +// +// bla blubb; +// +// MatrixTwoIndices mat_by( 30, 20, blubb ); + + +///////////////////////////////////////////////////////////////////////////// + + +template +class T_min +{ + +public: + // constructor, initializes minval (cause the first told is in this + // moment the maximum) + T_min( T val ) : minval( val ) {}; + + // tells the minimal value + T const operator()() const { return minval; }; + + // wants to know values, saves the minimum + void operator()(T val) + { if( minval > val ) minval = val; }; + + +protected: + + T minval; + +private: + + T_min() {}; +}; + +////////////////////////////////////////////////////////////////////// + + +template < +typename ECKENTYP, +typename GESICHTSTYP, +typename SENKRECHTENTYP +> +class VertexFractureTriple +{ + +public: + + VertexFractureTriple( ECKENTYP const & edge, GESICHTSTYP const & face, SENKRECHTENTYP const & normal ) + : m_edge(edge), m_face(face), m_normal(normal) + { + }; + + ECKENTYP const getEdge() const { return m_edge; } + + GESICHTSTYP const getFace() const { return m_face; } + + SENKRECHTENTYP const getNormal() const { return m_normal; } + +private: + + ECKENTYP m_edge; + GESICHTSTYP m_face; + SENKRECHTENTYP m_normal; + + VertexFractureTriple() + {}; + +}; + + +////////////////////////////////////////////////////////////////// + +template < typename VRT, typename IndTyp > //, typename EDG > +class CrossingVertexInfo +{ +public: + + CrossingVertexInfo( VRT const & crossVrt, IndTyp numbCrossFracs ) + : m_crossVrt(crossVrt), m_numbCrossFracs( numbCrossFracs ), m_vecShiftedVrts(std::vector()) + //,m_vecOrigEdges(std::vector()) + { + + } + + VRT getCrossVertex() const { return m_crossVrt; } + + IndTyp getNumbCrossFracs() const { return m_numbCrossFracs; } + + void addShiftVrtx( VRT const & vrt ) + { + m_vecShiftedVrts.push_back(vrt); + } + +// void addOriginalFracEdge( EDG const & edg ) { m_vecOrigEdges.push_back(edg); } + + std::vector getVecShiftedVrts() const { return m_vecShiftedVrts; } + +// std::vector getVecOrigFracEdges() const { return m_vecOrigEdges; } + +private: + + VRT m_crossVrt; + IndTyp m_numbCrossFracs; + std::vector m_vecShiftedVrts; +// std::vector m_vecOrigEdges; +}; + + +////////////////////////////////////////////////////////////////// + + + +#endif + From a43fb16e4efa0798173d0e0f2478049f539a8a7f Mon Sep 17 00:00:00 2001 From: Arne Naegel Date: Thu, 11 Jul 2024 11:41:01 +0200 Subject: [PATCH 38/58] Refactoring: Moving >3000 LOC to separate file. --- ugbase/lib_grid/CMakeLists.txt | 1 + .../algorithms/extrusion/expand_layers.cpp | 3571 ---------------- .../algorithms/extrusion/expand_layers.h | 8 - .../extrusion/expand_layers_arte.cpp | 3590 +++++++++++++++++ .../algorithms/extrusion/expand_layers_arte.h | 26 + 5 files changed, 3617 insertions(+), 3579 deletions(-) create mode 100644 ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.cpp create mode 100644 ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.h diff --git a/ugbase/lib_grid/CMakeLists.txt b/ugbase/lib_grid/CMakeLists.txt index a846e329d..eadce4b15 100644 --- a/ugbase/lib_grid/CMakeLists.txt +++ b/ugbase/lib_grid/CMakeLists.txt @@ -83,6 +83,7 @@ set(srcAlgorithms algorithms/debug_util.cpp algorithms/extrusion/extrude.cpp algorithms/extrusion/cylinder_extrusion.cpp algorithms/extrusion/expand_layers.cpp + algorithms/extrusion/expand_layers_arte.cpp algorithms/projections/overlying_subset_finder.hpp algorithms/projections/z_ray_tracer.hpp refinement/projectors/projection_handler.cpp diff --git a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp index b47ce9f8b..0db34358a 100644 --- a/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp +++ b/ugbase/lib_grid/algorithms/extrusion/expand_layers.cpp @@ -39,17 +39,6 @@ #include "lib_grid/grid/grid_util.h" //#include "lib_grid/util/simple_algebra/least_squares_solver.h" -#include -#include -#include -#include -#include -#include -#include - -#include "support.h" - - using namespace std; namespace ug{ @@ -716,3566 +705,6 @@ bool ExpandFractures2d(Grid& grid, SubsetHandler& sh, const vector return true; } -using VertFracTrip = VertexFractureTriple; - -//using VecVertFracTrip = std::vector; - -//using VvftIterator = VecVertFracTrip::iterator; - -using AttVrtVec = Attachment >; - -using VertexOfFaceInfo = VertexFractureTriple< std::pair, Face*, std::pair >; - - -using IndexType = unsigned short; - -template -bool expandSingleFractureAtGivenSide( vector3 const & nOne, vector3 const & nTwo, - Edge * edgeOne, Edge * edgeTwo, - Face * facOne, Face * facTwo, - vector const & fracInfosBySubset, - vector3 const & posOldVrt, - Grid::VertexAttachmentAccessor & aaPos, - Grid & grid, SubsetHandler & sh, - ASOF const & assoFaces, - std::vector const & nextFracVrt, - Grid::FaceAttachmentAccessor & aaVrtVecFace, - int & dbg_flachen_passiert, - Vertex * iterV - ) -{ - -#if 1 - // gleiche Seite vermutet oder gegeben - - // average the normals - - vector3 normSum; - - VecAdd( normSum, nOne, nTwo ); - - vector3 normSumNormed; - - VecNormalize(normSumNormed, normSum); - - UG_LOG("averaged normal " << normSumNormed << std::endl); - - std::vector attEdg; - std::vector attFac; - - attEdg.push_back( edgeOne ); - attEdg.push_back( edgeTwo ); - - attFac.push_back( facOne ); - attFac.push_back( facTwo ); - - // jetzt neuen Vertex erzeugen in Richtung der Normalen - // sonst ist das attachment Schwachsinn! - - vector3 posNewVrt; - - vector3 moveVrt; - - auto subsIndEdgOne = sh.get_subset_index(edgeOne); - - auto subsIndEdgTwo = sh.get_subset_index(edgeTwo); - - if( subsIndEdgOne != subsIndEdgTwo ) - { - UG_THROW("subsets passen nicht Vereinheitlichung" << std::endl ); - } - - number width = fracInfosBySubset.at(subsIndEdgOne).width; - - // der Faktor ist Käse und muss noch aus den Eingaben übernommen werden - VecScale(moveVrt, normSumNormed, width/2. ); - - VecAdd(posNewVrt, posOldVrt, moveVrt ); - - UG_LOG("neuer Vertex " << posNewVrt << std::endl ); - - // TODO FIXME hier ist das PROBLEM, SEGFAULT durch create regular vertex - - Vertex * newShiftVrtx = *grid.create(); - aaPos[newShiftVrtx] = posNewVrt; - - sh.assign_subset(newShiftVrtx, subsIndEdgOne ); - - - - // alle anhängenden faces müssen noch zu wissen bekommen - // dass es diesen neuen Vertex gibt, nicht nur die - // an den edges anhängenden - // vielleicht gibt es einen Loop über attached faces des - // Vertex, für die schon bekannten direkt angehängten klar - // wenn auch dort vermerkt werden muss im Attachment von Seb - // bei den anderen, die keine Edge haben von der Kluft - // da muss man die Normale ins Zentrum bestimmen - // um heraus zu finden, ob sie auf dieser seite sind - // am besten dann das Attachment der faces für vertizes - // von Seb recyclen - - // loop über assosciated faces des vertex am besten - // vermutlich auch noch assosciated edges, um - // zu markieren, welche weg fallen sollen, wenn - // nicht von Kluft selber, sondern quasi verschoben - // und neu erzeugt - - int dbg_FaceIterator = 0; - - for( auto const & ifac : assoFaces ) - { - bool isFromFrac = false; - - int dbg_innterFacFracIt = 0; - - for( auto const & facFrac : attFac ) - { - - static_assert( std::is_same< decltype( (facFrac) ), decltype ( ifac ) >::value ); - - if( ifac == facFrac ) - { - isFromFrac = true; - - static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value ); - static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value ); - - } - } - - bool atRightSide = false; - - if( isFromFrac ) - atRightSide = true; - - if( !isFromFrac ) - { - // check if on same side of edge where the normal points to: compute cosinus between vector of face center - // perpendicular to the edge - - vector3 facCenter = CalculateCenter( ifac, aaPos ); - - vector3 perpendicu; - - if( nextFracVrt.size() != 2 ) - { - UG_THROW("komische Groesse" << std::endl); - } - - DropAPerpendicular(perpendicu, facCenter, aaPos[nextFracVrt[0]], aaPos[nextFracVrt[1]]); - - vector3 tmpN; - - VecSubtract(tmpN, facCenter, perpendicu ); - - VecNormalize(tmpN, tmpN); - - UG_LOG("Normale zum Face ist " << tmpN << std::endl); - - number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, normSumNormed ); - - UG_LOG("Cosinus zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); - - if( cosBetwFracEdgAndDirection2Face > 0 ) - { - UG_LOG("assuming face to be on richt side" << std::endl); - - atRightSide = true; - -#if ANSCHAULICH_ERZEUGE_SUDOS_ANHANG - - Vertex * otherFacCent = *grid.create(); - aaPos[otherFacCent] = facCenter; - sh.assign_subset(otherFacCent, 5 ); - - Vertex * pp = *grid.create(); - aaPos[pp] = perpendicu; - sh.assign_subset(pp, 6 ); - - sh.assign_subset(*iterFac,7); -#endif - - } - else - { - UG_LOG("assuming face to be on wrong side" << std::endl); - } - - - dbg_flachen_passiert++; - } - - - if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein - { - - // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! - vector& newVrts4Fac = aaVrtVecFace[ ifac ]; - - IndexType vrtxFnd = 0; - - for(size_t indVrt = 0; indVrt < (ifac)->num_vertices(); indVrt++ ) - { - Vertex* facVrt = (ifac)->vertex(indVrt); - - if( facVrt == iterV ) - { - newVrts4Fac[ indVrt ] = newShiftVrtx; - vrtxFnd++; - } - } - - - if( vrtxFnd <= 0 ) - { - UG_THROW("vertex not found!" << std::endl); - } - else if( vrtxFnd > 1 ) - { - UG_THROW("vertex zu oft gefunden " << vrtxFnd << std::endl ); - } - else if ( vrtxFnd == 1 ) - { - } - else - { - UG_THROW("vertex finden komisch " << std::endl); - } - - - } - - dbg_innterFacFracIt++; - - - - dbg_FaceIterator++; - - } -#endif - - return true; - -} - -#ifndef NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX -#define NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX 1 -#endif - -#ifndef ANSCHAULICH_ERZEUGE_SUDOS_ANHANG -#define ANSCHAULICH_ERZEUGE_SUDOS_ANHANG 0 -#endif - -#ifndef OLD_PROFREITER_STUFF -#define OLD_PROFREITER_STUFF 0 -#endif - -bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector const & fracInfos, - bool expandInnerFracBnds, bool expandOuterFracBnds) -{ - -// static constexpr bool dehneInnereKluftGrenzpunkteAus = false; - -// expandInnerFracBnds = false; - -// expandOuterFracBnds = true; - -// access position attachment - if(!grid.has_vertex_attachment(aPosition)){ - UG_LOG("Error in ExpandFractures 2D Arte: Missing position attachment"); - return false; - } - Grid::VertexAttachmentAccessor aaPos(grid, aPosition); - - if(!grid.option_is_enabled(FACEOPT_AUTOGENERATE_EDGES)){ - UG_LOG("WARNING in Arte 2D CalculateCreaseNormal: grid option FACEOPT_AUTOGENERATE_EDGES autoenabled.\n"); - grid.enable_options(FACEOPT_AUTOGENERATE_EDGES); - } - -// objects for temporary results - FaceDescriptor fd; - vector edges; // used for temporary results. - vector faces; // used for temporary results. - -// vectors that allow to access fracture properties by subset index - vector fracInfosBySubset(sh.num_subsets(), FractureInfo(-1, -1, 0)); - for(size_t i = 0; i < fracInfos.size(); ++i){ - if(fracInfos[i].subsetIndex >= sh.num_subsets()){ - throw(UGError("Bad subsetIndex in given fracInfos.")); - } - - fracInfosBySubset[fracInfos[i].subsetIndex] = fracInfos[i]; - } - -//////////////////////////////// -// Collect surrounding faces of all fractures in a selector -// and select edges and vertices too. - Selector sel(grid); - sel.enable_autoselection(false); - sel.enable_selection_inheritance(false); - -#if OLD_PROFREITER_STUFF - AInt aAdjMarker; // used to mark how many adjacent fractures a vertex has. - // 0: no frac, 1: frac-boundary, >1: inner frac vertex - // TODO FIXME das sieht komisch aus, ist das immer so, wenn z.B. an einer Grenze sich zwei fracs treffen? - grid.attach_to_vertices_dv(aAdjMarker, 0); - Grid::VertexAttachmentAccessor aaMarkVRT(grid, aAdjMarker); - grid.attach_to_edges_dv(aAdjMarker, 0); - Grid::EdgeAttachmentAccessor aaMarkEDGE(grid, aAdjMarker); -#endif - -// using IndexType = unsigned short; - using AttVerFracProp = Attachment >; - // attachment pair boundary is fracture, number fractures crossing - - AttVerFracProp aAdjMarkerVFP; - - VertexFractureProperties vfp0( false, 0 ); - // default value: no boundary fracture, no fractures crossing - - grid.attach_to_vertices_dv(aAdjMarkerVFP, vfp0 ); - Grid::VertexAttachmentAccessor aaMarkVrtVFP(grid, aAdjMarkerVFP); - - ABool aAdjMarkerB; // used to know if an edge is frac edge - grid.attach_to_edges_dv(aAdjMarkerB, false); - Grid::EdgeAttachmentAccessor aaMarkEdgeB(grid, aAdjMarkerB); - - - // die Vertizes, Faces und Edges, die mit einer Kluft zu tun haben - -// using VertFracTrip = VertexFractureTriple; -// - using VecVertFracTrip = std::vector; - - VecVertFracTrip vertexNoInfo; - - using AttVecVertFracTrip = Attachment; - - AttVecVertFracTrip aAdjInfoAVVFT; - - grid.attach_to_vertices_dv( aAdjInfoAVVFT, vertexNoInfo ); - Grid::VertexAttachmentAccessor aaVrtInfoFraTri(grid, aAdjInfoAVVFT ); - - - using VecEdge = std::vector; - using VecFace = std::vector; - - using AttVecEdge = Attachment; - using AttVecFace = Attachment; - - VecEdge noEdge; - VecFace noFace; - AttVecEdge aAdjInfoEdges; - AttVecFace aAdjInfoFaces; - - grid.attach_to_vertices_dv( aAdjInfoEdges, noEdge ); - Grid::VertexAttachmentAccessor aaVrtInfoAssoEdges( grid, aAdjInfoEdges ); - - grid.attach_to_vertices_dv( aAdjInfoFaces, noFace ); - Grid::VertexAttachmentAccessor aaVrtInfoAssoFaces( grid, aAdjInfoFaces ); - - // das ist Käse, ich brauche für jeden Vertex ein Attachment der Form - // class VertexTriple, bzw std vektoren von solchen vertex triplen - // da weiss dann jeder Vertex das triple - // Kante (damit subdom) - Face - normal (von Kante in Face rein) - // dann kann man nämlich anhand des Winkels von zwei Normalen - // von solchen Vertizes bestimmtn, ob sie auf die gleiche Seite der Kante zeigen - // und dann kann man sie mitteln, sofern die Vertizes keine Kreuzungs Vertizes sind - // oder keine äusseren Vertizes - ob sie dsa sind, dafür haben wir schon attachments! - - // TODO FIXME diese komischen accessoren sollen jetzt so zugewiesen - // werden, dass - /* - * jeder Kluftvertex soll wissen, welche Kluftedges ihm anliegen, und welche faces - * jede Kluftedge soll wissen, welche Vertizes ihr anliegen, und welche faces - * jedes Face, das an eine Kluft anliegt, soll wissen, welche Vertizes und Edges - * ihm anliegen - * letzteres muss man vielleicht noch ausdehnen, indem man subdomain indizes - * dazu bringt - * das kann auch notwendig sein fuer alle anderen - wirklich? - * die edges und faces kennen ihre subdomain - * nur beim Vertex kann in Kreuzungspunkten ein Problem sein - * zudem ist die subdomain der faces EGAL, im Zweifel entscheidet die subdomain - * der edges, die anliegen bzw der edge, die anliegt! - * - */ - -// iterate over the given fracture infos and select all fracture edges -// and fracture vertices. - for(size_t i_fi = 0; i_fi < fracInfos.size(); ++i_fi) - { - int fracInd = fracInfos[i_fi].subsetIndex; - - for(EdgeIterator iter = sh.begin(fracInd); iter != sh.end(fracInd); ++iter) - { - // mark edge and vertices - sel.select(*iter); - -#if OLD_PROFREITER_STUFF - aaMarkEDGE[*iter] = 1; -#endif - - aaMarkEdgeB[*iter] = true; - - // select associated vertices - for(size_t i = 0; i < 2; ++i) - { - Vertex* v = (*iter)->vertex(i); - sel.select(v); - - // wird in jedem Fall inkrimiert, da der Vertex auf jeden Fall mit einer Kante einer frac verbunden sein muss, sonst darf der loop gar nicht darüber gehen - aaMarkVrtVFP[v]++; - - if( IsBoundaryVertex2D(grid, v) ) - aaMarkVrtVFP[v].setIsBndFracVertex(); - - -#if OLD_PROFREITER_STUFF - // das ist Sebastians loop, den nicht mehr lassen lassen - // if fracture boundaries are expanded, we'll regard all fracture vertices - // as inner vertices - if(expandInnerFracBnds) - { - if(!expandOuterFracBnds) - { - if(IsBoundaryVertex2D(grid, v)) - aaMarkVRT[v]++; - else - aaMarkVRT[v] = 2; - } - else - aaMarkVRT[v] = 2; - } - else - aaMarkVRT[v]++; -#endif - - } - } - } - - -#if OLD_PROFREITER_STUFF -// Make sure that selected vertices that lie on the boundary of the geometry -// are treated as inner fracture vertices. -// This is only required if frac-boundaries are not expanded anyways. - if(expandOuterFracBnds && !expandInnerFracBnds){ - for(VertexIterator iter = sel.vertices_begin(); - iter != sel.vertices_end(); ++iter) - { - Vertex* v = *iter; - if(aaMarkVRT[v] == 1){ - if(IsBoundaryVertex2D(grid, v)) - aaMarkVRT[v] = 2; - } - } - } - // TODO FIXME was soll das fuer ein Kaese sein? -#endif - - int dbg_flachen_passiert = 0; - - for(VertexIterator iter = sel.begin(); iter != sel.end(); ++iter) - { - - bool wahl = true; - - - // so stimmt es vielleicht, aber ist auch ein komischer Fall, innen expandieren und aussen nicht...... die Frage ist, ob es oonst Sinn macht..... - if( expandInnerFracBnds && !expandOuterFracBnds && aaMarkVrtVFP[*iter].getIsBndFracVertex() ) - wahl = false; - - static_assert( std::is_same< decltype(*iter), Vertex * >::value ); - - bool isBnd = aaMarkVrtVFP[ *iter ].getIsBndFracVertex(); - auto numCrosFrac = aaMarkVrtVFP[ *iter ].getNumberFracEdgesInVertex(); - - if( ! isBnd && numCrosFrac == 1 ) - { - wahl = false; - } - -// if( ! dehneInnereKluftGrenzpunkteAus ) -// { -// if( numCrosFrac == 1 ) // inner frac boundary vertex -// { -// wahl = false; -// } -// } - - - if( wahl ) - { - sel.select(grid.associated_edges_begin(*iter), - grid.associated_edges_end(*iter)); - sel.select(grid.associated_faces_begin(*iter), - grid.associated_faces_end(*iter)); - - // TODO FIXME hier ein attachment der associated faces und vertizes, am besten als Klasse, die std vertizes davon frisst, an jeden Vertex anhängen - // so muss man später nicht nochmal über alle Faces und Edges laufen, sondern hat die angehängten schon zur Hand - // im Fall, dass eine Kreuzung vorliegt, das Ganze irgendwann ordnen, dass nebeneinander liegende Faces und edges in eine verkettete Liste kommen - // vielleicht das aber nur bei den Schnittvertizes später - // und vielleicht sollen die Faces Zeiger auf ihre Edges bekommen, und die edges auf die faces, aber wird irgendwann zu wild verzeigert..... - // vielleicht einfach attachment von faces und edges unabhängig an jeden Fracture Vertex...... - - // testen, ob ein Schnittvertex vor liegt, indem die Anzahl der touches getestet wird, anhand einfacher Geometrien testen, was die Anzahl ist - - // mit UG_LOG ausgeben, was die Koordinaten sind, und die Anzahl der hits - - VecFace assFac; - VecEdge assEdg; - -// UG_LOG("----------" << std::endl); - - for( std::vector::iterator iterFac = grid.associated_faces_begin(*iter); iterFac != grid.associated_faces_end(*iter); iterFac++ ) - { - assFac.push_back(*iterFac); -// vector3 facCenter = CalculateCenter( *iterFac, aaPos ); -// UG_LOG("fac center " << facCenter << std::endl); - -// sh.assign_subset(*iterFac, 10); - } - -// UG_LOG("----------" << std::endl); - - for( std::vector::iterator iterEdg = grid.associated_edges_begin(*iter); iterEdg != grid.associated_edges_end(*iter); iterEdg++ ) - { - assEdg.push_back(*iterEdg); -// sh.assign_subset(*iterEdg,10); - } - - aaVrtInfoAssoFaces[*iter] = assFac; - aaVrtInfoAssoEdges[*iter] = assEdg; - - UG_LOG("marked vertex wahl: " << aaPos[*iter] << " is bnd " << isBnd << " number cross frac " << numCrosFrac << std::endl ); - - // fuer Nicht Boundary Vertizes muessen wir durch 2 teilen, damit wir richtige Anzahl der - // Fracs haben, die durch den spezifischen Vertex durch geht - // FALSCH war mal so, ist schon abgestellt, es wird angezeigt, wieviele Ecken von Kanten rein kommen - - } - else - { - UG_LOG("marked vertex unwahl: " << aaPos[*iter] << " is bnd " << isBnd << " number cross frac " << numCrosFrac << std::endl ); - } - - } - -// return true; - - using pairIndDbl = std::pair; - - std::vector< pairIndDbl > fracSubdom_facePerpendMinVal; - - for( auto const & pf: fracInfos ) - { - fracSubdom_facePerpendMinVal.push_back( pairIndDbl( pf.subsetIndex, std::numeric_limits::max() ) ); - } - - T_min minDistPerpOverall( std::numeric_limits::max() ); - -// for( auto fI : fracInfos ) -// for( size_t fraInfInd = 0; fraInfInd < fracInfos.size(); fraInfInd++ ) - for( auto & fsfpmv : fracSubdom_facePerpendMinVal ) - { -// int fracInd = fracInfos[fraInfInd].subsetIndex; -// int fracInd = fI.subsetIndex; - - auto fracInd = fsfpmv.first; - - T_min minDistPerpThisFrac( fsfpmv.second ); - - for(EdgeIterator iterEdg = sh.begin(fracInd); iterEdg != sh.end(fracInd); iterEdg++ ) - { - - // get subdomain of edge - - auto sudoEdg = sh.get_subset_index(*iterEdg); - - static_assert( std::is_same< decltype(sudoEdg), int >::value ); - - // get vertices of edge, always 2 - - std::vector verticesEdg; - - static_assert( std::is_same< Vertex*, decltype( (*iterEdg)->vertex(0) ) >::value ); - - for( size_t i = 0; i < 2; ++i ) - verticesEdg.push_back( (*iterEdg)->vertex(i) ); - - // get attached faces - -#if 0 - std::vector assFace; - - // TODO FIXME dieser loop kann vielleicht vereinfacht werden, wenn dieser ganze loop umgebaut wird - // denn die Vertizes kennen dann die assosciated faces schon - // der Name AssociatedFaceIterator ist sowieso verwirrend, hat mit assosciated nix zu tun, bezieht sich auf alle std Vektoren von Face * - UG_LOG("XXXXXXXXXXXX" << std::endl); - for(Grid::AssociatedFaceIterator iterAFI = grid.associated_faces_begin( verticesEdg[0] ); - iterAFI != grid.associated_faces_end( verticesEdg[0] ); - iterAFI++ ) - { - - if(FaceContains( *iterAFI, *iterEdg )) - { - assFace.push_back( *iterAFI ); - - - vector3 facCenter = CalculateCenter( *iterAFI, aaPos ); - UG_LOG("fac center " << facCenter << std::endl); - - - -// sh.assign_subset( *iterAFI, sh.get_subset_index(*iterEdg)); - } - - } - UG_LOG("XXXXXXXXX" << std::endl); -#else - - std::vector & assFaceVrt0 = aaVrtInfoAssoFaces[verticesEdg[0]]; - - std::vector assFace; - -// static_assert( std::is_same< decltype( aaVrtInfoAssoFaces[verticesEdg[0]] )[0], std::vector >::value ); - //static_assert( std::is_same< decltype( *(aaVrtInfoAssoFaces[verticesEdg[0]]) ), Face * >::value ); - -// UG_LOG("XXXXXXXXXXXX" << std::endl); - - for( auto const & ifa : assFaceVrt0 ) - { - if(FaceContains( ifa, *iterEdg )) - { - assFace.push_back( ifa ); - -// vector3 facCenter = CalculateCenter( ifa, aaPos ); -// UG_LOG("fac center " << facCenter << std::endl); - } - } - - std::vector & assFaceVrt1 = aaVrtInfoAssoFaces[verticesEdg[1]]; - - for( auto const & ifa : assFaceVrt1 ) - { - if(FaceContains( ifa, *iterEdg )) - { - bool faceContained = false; - - for( auto const & afa : assFace ) - { - if( afa == ifa ) - faceContained = true; - } - - if( !faceContained ) - assFace.push_back( ifa ); - } - } - - -// UG_LOG("XXXXXXXXX" << std::endl); - -#endif - // von hier lernen: - // VecFace & assoFaces = aaVrtInfoAssoFaces[*iterV ist verticesEdg[0] ]; - // for( auto const & ifac : assoFaces ) - // { - // static_assert( std::is_same< decltype( ifac ), Face * const & >::value ); - // } - - - - // compute normal of edge - - std::vector< vector3 > edgeNormals; - - std::vector perpendDistances; - - for( auto const & fac : assFace ) - { - vector3 facCenter = CalculateCenter( fac, aaPos ); - - vector3 perpendicu; - - DropAPerpendicular(perpendicu, facCenter, aaPos[verticesEdg[0]], aaPos[verticesEdg[1]]); - - double perpendDist = VecLength( perpendicu ); // betrag perpendicu - - perpendDistances.push_back( perpendDist ); - - minDistPerpThisFrac( perpendDist ); - - - // vector from projection to center is the unnormalized normal - vector3 tmpN; - - VecSubtract(tmpN, facCenter, perpendicu ); - - VecNormalize(tmpN, tmpN); - - edgeNormals.push_back( tmpN ); - - static_assert( std::is_same< Edge*, decltype(*iterEdg) >::value ); - - static_assert( std::is_same< Face * const &, decltype(fac) >::value ); - static_assert( std::is_same< Face *, decltype( const_cast(fac) ) >::value ); - static_assert( std::is_same< vector3, decltype( tmpN ) >::value ); - - VertFracTrip infoVertizesThisEdge( *iterEdg, fac, tmpN ); - -// UG_LOG("TypE Fac " << typeid(const_cast(fac) ).name() << std::endl); -// UG_LOG("TypE Edg " << typeid( *iterEdg ).name() << std::endl); -// UG_LOG("TypE Vec " << typeid( tmpN ).name() << std::endl); - - - for( auto const & v : verticesEdg ) - { - static_assert( std::is_same< decltype(v), Vertex * const & >::value ); - static_assert( std::is_same< decltype(const_cast(v)), Vertex * >::value ); - aaVrtInfoFraTri[v].push_back( infoVertizesThisEdge ); - -// VecVertFracTrip allInfosVrtxThisEdg = aaVrtInfoFraTri[v]; - -// static_assert( std::is_same< decltype( aaVrtInfoFraTri[v] ), VecVertFracTrip >::value ); - -// UG_LOG("type Fac " << typeid( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getFace() ).name() << std::endl); -// UG_LOG("type Edg " << typeid( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getEdge() ).name() << std::endl); -// UG_LOG("type Vec " << typeid( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getNormal() ).name() << std::endl); - - static_assert( std::is_same< decltype( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getFace() ), Face * >::value ); - static_assert( std::is_same< decltype( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getEdge() ), Edge * >::value ); - static_assert( std::is_same< decltype( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getNormal() ), vector3 const >::value ); - } - - } - - // damit speichern wir die plus und minus Normale, und das ist alles, und auch - // gleich wieder weg - // TODO FIXME besser, wir speichern die gemittelte Normale an den Vertizes - // vielleihct als attachment pair, das die subdom kennt der frac und die Normale dazu? - // ziemlich nutzlos, die Normale wie hier gemacht in einen kurzen Vektor zu speichern, der schnell - // wieder weg ist...... - // wir brauchen alle Normalen zu jeder fracture an jedem fracture Vertex, also die Mittelung vermutlich - // diese Mittelung kann aber erst stattfinden, wenn wir nachher über die vertizes loopen, - // hier kennen wir nur die Vertizes, die an derselben Edge anliegen - - UG_LOG("EDGE NORMALS: " << sh.get_subset_index(*iterEdg) << " -> "); - - int j = 0; - - for( auto const & en: edgeNormals ) - { - - for( size_t i = 0; i < 3; i++ ) - UG_LOG( en[i] << ", " ); - - - UG_LOG(" --- " << perpendDistances[j] << " ///////// " ); - - j++; - } - - UG_LOG(std::endl); - - } - - fsfpmv.second = minDistPerpThisFrac(); - - minDistPerpOverall( fsfpmv.second ); - - UG_LOG("first " << fsfpmv.first << " second " << fsfpmv.second << std::endl); - } - - for( auto const & fsfpmv : fracSubdom_facePerpendMinVal ) - { - UG_LOG("min dist sd " << fsfpmv.first << " -> " << fsfpmv.second << std::endl ); - } - - UG_LOG("overall min dist " << minDistPerpOverall() << std::endl); - - - - // von Sebastian teilweise das Prinzip übernommen, dass die Faces wissen können, was ihre neuen Vertizes sein sollen - // create new vertices - - // we have to associate a vector of vertices with each node in the fracture. - // since an empty vector is quite small, we can associate one with each vertex in - // the whole grid. This could be optimized if required, by using subset attachments. - - // es reicht vielleicht, hier statt einem Vektor einfach nur einen Vertex * zu storen -// using AttVrtVec = Attachment >; - AttVrtVec attVrtVec; - - // we associate a vector of vertices for each face adjacent to the frac. - // it will store a set of vertices. An entry contains the new vertex, if the - // corresponding vertex is an inner fracture vertex, and NULL if not. - grid.attach_to_faces(attVrtVec); - Grid::FaceAttachmentAccessor aaVrtVecFace(grid, attVrtVec); - - - // iterate over all surrounding faces to enable face changes, this loop taken from SR but shortened - for(FaceIterator iter_sf = sel.faces_begin(); iter_sf != sel.faces_end(); ++iter_sf) - { - Face* sf = *iter_sf; - - std::vector& newVrts = aaVrtVecFace[sf]; - newVrts.resize(sf->num_vertices()); - - for(size_t i_vrt = 0; i_vrt < sf->num_vertices(); ++i_vrt) - { - newVrts[i_vrt] = NULL; - } - // erstmal so tun, als ob keine neuen Vertizes erzeugt werden an den alten Vertizes - } - - - // attachment to allow fracture vertizes to know the newly created vertizes - // due to extrusion which are related to them, in connection with - // the normals which are an average of the related edges and the faces - // defining the original normal - - // usage: store edges and associated faces in SAME order in std vectors! - using ExpandVertexMultiplett = VertexFractureTriple< std::vector, std::vector, vector3 >; - // holds the averaged normal of the related edges and their corresponding faces which give direction - - using VecExpandVertexMultiplett = std::vector; - - - VecExpandVertexMultiplett vertexMultiplettEmpty; - - using AttVecExpandVertexMultiplett = Attachment; - - AttVecExpandVertexMultiplett aAdjInfoVVEVM; - - grid.attach_to_vertices_dv( aAdjInfoVVEVM, vertexMultiplettEmpty ); - Grid::VertexAttachmentAccessor aaVrtExpMP(grid, aAdjInfoVVEVM ); - - - - // am Ende dieser Prozedur sollten alle Vertizes wissen, welche Tripel vom Typ Edge - Face - Normal zum Face hin an ihnen angelagert sind - - // damit weiss, wenn es stimmt, jeder Vertex, der an einer Fracture ist, wieviele Schnittpunkte von Fractures er hat, - // ob er ein boundary vertex ist, und was für einen Vektor von Tripeln an ihm angehängt sind - // die subdomain der Fracture muss anhand der subdomain der edge bestimmt werden immer - - UG_LOG("loop over all marked vertizes " << std::endl); - - int dbg_vertizesPassiert = 0; - - // jetzt können wir alle Vertizes ablaufen und an ihnen neue Vertizes erzeugen, die anhand der gemittelten Normalen von den Vertizes weg gehen - // ob zwei anhängende Faces auf der gleichen Seite liegen, wenn es kein Schnittvertex von zwei oder mehr Klüften ist - // das kann man anhand des Winkels zwischen zwei face Normalen unterscheiden vermutlich - // dabei müssen die edges sowieso disjunkt sein, sonst ist man sowieso sicher auf verschiedenen Seiten - // wenn wir es mit einem boundary Vertex zu tun haben, müssen wir weiter überlegen, wie wir die Verschiebung auf die äussere Kante projizieren - // muss auch mit dem Winkel zu tun haben - for(VertexIterator iterV = sel.begin(); iterV != sel.end(); ++iterV) - { - - // POsition dieses Vertex - vector3 posOldVrt = aaPos[*iterV]; - - // vielleicht muss man, wenn die neuen Vertizes da sind, diese auch gleich mit den umliegenden Knoten per neuer Kanten verbinden - // und die neuen faces erzeugen nach Löschen der alten? - // oder alle neuen Vertizes wie bei Prof Reiter in einen std Vektor, der als attachment den bisherigen Face Vertizes angehängt wird - // und Edge Vernichtung und Erzeugung neuer edges und faces wie bei Prof Reiter in Folgeschritten? - - VecVertFracTrip & vecVertFracTrip = aaVrtInfoFraTri[*iterV]; - - std::vector & allAssoEdges = aaVrtInfoAssoEdges[*iterV]; - - static_assert( std::is_same< decltype( vecVertFracTrip[ vecVertFracTrip.size() - 1 ].getFace() ), Face * >::value ); - static_assert( std::is_same< decltype( vecVertFracTrip[ vecVertFracTrip.size() - 1 ].getEdge() ), Edge * >::value ); - static_assert( std::is_same< decltype( vecVertFracTrip[ vecVertFracTrip.size() - 1 ].getNormal() ), vector3 const >::value ); - - for( auto const & vft : vecVertFracTrip ) - { - static_assert( std::is_same< decltype( vft.getFace() ), Face * >::value ); - static_assert( std::is_same< decltype( vft.getEdge() ), Edge * >::value ); - static_assert( std::is_same< decltype( vft.getNormal() ), vector3 const >::value ); - - Face * f = vft.getFace(); - Edge * e = vft.getEdge(); - vector3 n = vft.getNormal(); - - } - - using VvftIterator = VecVertFracTrip::iterator; - - VecFace & assoFaces = aaVrtInfoAssoFaces[*iterV]; - // TODO FIXME hier braucht man das nicht zu ordnen - // aber bei Kreuzpunkten von Klueften muss es so geordnet werden, wie es nebeneinander liegt - // bei den Edges gibt es auch die benachbarten, und die edges haben das attachment, ob sie Kluftedges sind - -// for( auto const & ifac : assoFaces ) -// { -// static_assert( std::is_same< decltype( ifac ), Face * const & >::value ); -// } - - - - // Anzahl der Kreuzungspunkte auslesen und danach unterscheiden, erstmal keine Kreuzung! TODO FIXME - - // irgendwie muessen wir diese Infos jetzt verwerten, um als erstes neue Vertizes zu erzeugen, anfangs für eine Kluft nur - // und danach die alten Edges und faces löschen und an neuer Stelle neu erzeugen, plus die sowieso neuen, - // oder Edges verschieben, wenn es möglich ist, die Vertizes zu verschieben, und die Edges und in Folge faces passen sich an, - // dann müssen nur die neuen edges und faces neu erzeugt werden - // verschieben der Position des Vertex löst Kaskade aus, dass Edge und Face auch verschoben werden, kann also angewendet werden - // allerdings Problem, dass die Vertizes dafür verdoppelt werden müssen und die Kanten, sonst kann man sie nicht nach aussen verschieben - // also doch komplette Neuerzeugung vermutlich..... oder doppeltes Klonen, und das alte bleibt in der Mitte..... - - vector3 posThisVrt = aaPos[*iterV]; - - UG_LOG("vertex at " << posThisVrt << std::endl ); - - bool vrtxIsBndVrt = aaMarkVrtVFP[*iterV].getIsBndFracVertex(); - // alternativ wäre möglich: IsBoundaryVertex2D(grid, *iterV) - - UG_LOG("is bndry " << vrtxIsBndVrt << std::endl); - - IndexType numFracsCrossAtVrt = aaMarkVrtVFP[*iterV].getNumberFracEdgesInVertex(); - - UG_LOG("number crossing fracs " << numFracsCrossAtVrt << std::endl); - - size_t numbAttTripl = vecVertFracTrip.size(); - - UG_LOG("sizes of vft " << numbAttTripl << std::endl ); - - if( ! vrtxIsBndVrt ) - { - - if( numFracsCrossAtVrt < 1 ) - { - UG_THROW("no fracs crossing but marked vertex? << std::endl"); - } - else if( numFracsCrossAtVrt == 1 ) - { - -// if( numbAttTripl != 0 ) -// { -// UG_THROW("Anzahl der angehaengten Triples kann nicht stimmen, Vertex einer Kluft ohne Schnittpunkte, nicht am Rand, Kluftende " << std::endl); -// } - - - - UG_LOG("END THIS VERTEX NORMAL INNER ENDING CLEFT" << std::endl); - - -// if( ! dehneInnereKluftGrenzpunkteAus ) -// { -// break; -// } - // inner vertex where fracture ends - // TODO FIXME - - // in this case, we have two attached edges, and each of these edges has two attached faces - // the faces have a naormal, and based on the normal, we can decide which faces belong to the same side of the edges - -#if 0 - - if( numbAttTripl != 2 ) - { - UG_THROW("Anzahl der angehaengten Triples kann nicht stimmen, Vertex einer Kluft ohne Schnittpunkte, nicht am Rand, Kluftende " << std::endl); - } - - // Zuordnung der Edges und Faces, die auf der gleichen Seite der fracture sind - - // und gleich auch Erzeugung der neuen Knoten, die dann - // in einem Doublett zusammen mit ihren Normalen an die alten Vertizes - // angehängt werden; der Winkel zur Normalen hilft später, die Seite - // heraus zu finden, Seite von den Edges - - int dbg_iteratorAblaufen = 0; - - -#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX - - int dbg_laenge = 0; - - for( auto const & vft : vecVertFracTrip ) - { - dbg_laenge++; - - UG_LOG("VERTEXFRACTRIP" << std::endl); - - vector3 ve = vft.getNormal(); - - UG_LOG("NORMAL " << ve << std::endl); - - UG_LOG("laenge " << dbg_laenge << std::endl ); - } - - int dbg_laenge_eins = 0; - -#endif - - - - for( VvftIterator vvftV = vecVertFracTrip.begin(); - vvftV != vecVertFracTrip.end(); - vvftV++ - ) - { - -#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX - dbg_laenge_eins++; - - if( dbg_laenge_eins > dbg_laenge ) - { - break; - } - -#endif - - vector3 nV = vvftV->getNormal(); - - Edge * edgeV = vvftV->getEdge(); - - - -#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX - - UG_LOG("NORMAL " << vvftV->getNormal() << std::endl); - UG_LOG("LAENGE EINZ " << dbg_laenge_eins << std::endl ); -#endif - - Vertex * nextFracVrt; - - IndexType foundThisVrt = 0; - - for( size_t i = 0; i < 2; ++i ) - { - Vertex * vrtEdgEnd = edgeV->vertex(i); - - if( vrtEdgEnd == *iterV ) - { - foundThisVrt++; - } - else - { - nextFracVrt = vrtEdgEnd ; - } - - } - - if( foundThisVrt != 1 ) - { - UG_THROW("zu viel zu wenig vertizex one " << std::endl); - } - - - - // Klasse schreiben, die als attachment an einen Fracture-Vertex - // die neuen Vertizes samt ihrer gemittelten Normalen speichert - // also std::vector von dieser neuen Klasse als Vertex attachment - - std::vector attEdg; - std::vector attFac; - - attEdg.push_back( edgeV ); - - Face * facV = vvftV->getFace(); - - attFac.push_back( facV ); - - // jetzt neuen Vertex erzeugen in Richtung der Normalen - // sonst ist das attachment Schwachsinn! - - vector3 posNewVrt; - - vector3 moveVrt; - - auto subsIndEdgV = sh.get_subset_index(edgeV); - - number width = fracInfosBySubset.at(subsIndEdgV).width; - -// if( expandInnerFracBnds ) -// { -// // der Faktor ist Käse und muss noch aus den Eingaben übernommen werden -// VecScale(moveVrt, nV, width/2. ); -// } -// else -// { -// // auf Annes Wunsch hin werden die Normalen innendrin an einer endenen Kluft zu Null gesetzt -// -// VecScale(moveVrt, nV, 0. ); -// -// } - - VecScale(moveVrt, nV, width/2. ); - - VecAdd(posNewVrt, posOldVrt, moveVrt ); - - UG_LOG("neuer Vertex " << posNewVrt << std::endl ); - - // TODO FIXME hier ist das PROBLEM, SEGFAULT durch create regular vertex - - - - Vertex * newShiftVrtx = *grid.create(); - aaPos[newShiftVrtx] = posNewVrt; - - sh.assign_subset(newShiftVrtx, subsIndEdgV ); - - - - // fuer was braucheh wir das eigentlich? selber schon vergessen..... - - ExpandVertexMultiplett vrtMtpl( attEdg, attFac, nV ); - - aaVrtExpMP[ *iterV ].push_back( vrtMtpl ); - - - - // alle anhängenden faces müssen noch zu wissen bekommen - // dass es diesen neuen Vertex gibt, nicht nur die - // an den edges anhängenden - // vielleicht gibt es einen Loop über attached faces des - // Vertex, für die schon bekannten direkt angehängten klar - // wenn auch dort vermerkt werden muss im Attachment von Seb - // bei den anderen, die keine Edge haben von der Kluft - // da muss man die Normale ins Zentrum bestimmen - // um heraus zu finden, ob sie auf dieser seite sind - // am besten dann das Attachment der faces für vertizes - // von Seb recyclen - - // loop über assosciated faces des vertex am besten - // vermutlich auch noch assosciated edges, um - // zu markieren, welche weg fallen sollen, wenn - // nicht von Kluft selber, sondern quasi verschoben - // und neu erzeugt - - int dbg_FaceIterator = 0; - - - - for( auto const & ifac : assoFaces ) - { - bool isFromFrac = false; - - for( auto const & facFrac : attFac ) - { - -// static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype ( ifac ) >::value ); - static_assert( std::is_same< decltype( (facFrac) ), decltype ( ifac ) >::value ); - - if( ifac == facFrac ) - { - isFromFrac = true; - -// static_assert( std::is_same< decltype( const_cast(facFrac) ), Face * & >::value ); - static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value ); -// static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype( ifac ) >::value ); - static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value ); - - } - } - - - bool atRightSide = false; - - if( isFromFrac ) - atRightSide = true; - - if( !isFromFrac ) - { - // check if on same side of edge where the normal points to: compute cosinus between vector of face center - // perpendicular to the edge - - - - - vector3 facCenter = CalculateCenter( ifac, aaPos ); - - vector3 perpendicu; - - -// UG_LOG("pos 0 " << aaPos[nextFracVrt[0]] << std::endl); -// UG_LOG("pos 1 " << aaPos[*iterV] << std::endl); -// UG_LOG("fac ce " << facCenter << std::endl); - - DropAPerpendicular(perpendicu, facCenter, aaPos[nextFracVrt], aaPos[*iterV]); - -// if( dbg_FaceIterator == 1 ) -// { -// UG_LOG("huhu a0" << std::endl); -// return true; -// } - - - vector3 tmpN; - - VecSubtract(tmpN, facCenter, perpendicu ); - - VecNormalize(tmpN, tmpN); - - UG_LOG("Normale zum Face ist " << tmpN << std::endl); - - number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, nV ); - - UG_LOG("Cosinus zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); - -// if( dbg_FaceIterator == 1 ) -// { -// UG_LOG("huhu a" << std::endl); -//// return true; -// } - - - if( cosBetwFracEdgAndDirection2Face > 0 ) - { - UG_LOG("assuming face to be on richt side" << std::endl); - - atRightSide = true; - -#if ANSCHAULICH_ERZEUGE_SUDOS_ANHANG - - Vertex * otherFacCent = *grid.create(); - aaPos[otherFacCent] = facCenter; - sh.assign_subset(otherFacCent, 6 ); - - Vertex * pp = *grid.create(); - aaPos[pp] = perpendicu; - sh.assign_subset(pp, 7 ); - - sh.assign_subset(ifac,8); - -#endif - - } - else - { - UG_LOG("assuming face to be on wrong side" << std::endl); - } - - - dbg_flachen_passiert++; - } - - -// if( dbg_FaceIterator == 1 ) -// { -// UG_LOG("huhu b" << std::endl); -//// return true; -// } - - - - if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein - { - - // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! - vector& newVrts4Fac = aaVrtVecFace[ ifac ]; - - IndexType vrtxFnd = 0; - - for(size_t indVrt = 0; indVrt < (ifac)->num_vertices(); indVrt++ ) - { - Vertex* facVrt = (ifac)->vertex(indVrt); - - if( facVrt == *iterV ) - { - newVrts4Fac[ indVrt ] = newShiftVrtx; - vrtxFnd++; - } - } - - - if( vrtxFnd <= 0 ) - { - UG_THROW("vertex not found!" << std::endl); - } - else if( vrtxFnd > 1 ) - { - UG_THROW("vertex zu oft gefunden " << vrtxFnd << std::endl ); - } - else if ( vrtxFnd == 1 ) - { - } - else - { - UG_THROW("vertex finden komisch " << std::endl); - } - - - } - - dbg_FaceIterator++; - - } - - - - - - - - - } - - - - dbg_iteratorAblaufen++; - - - -// // Ziel: die beiden parallelen Normalen mitteln, und in die jeweiligen beiden Richtungen je einen neuen Vertex erzeugen -// // irgendwie muss der Vertex oder die Edge besser sogar wissen, dass sie einen neuen Verschiebevertex bekommen hat -// // denn später müssen neue Edges und neue Faces basierend auf den neuen Vertizes erzeugt werden -// // vielleicht braucht die edge und das face ein Attachment, das ihnen das sagt, ähnlihc wie VertexTrible std Vektoren? -// -// -// - UG_LOG("END THIS VERTEX NORMAL INNER ENDING CLEFT" << std::endl); - -#endif - - -// return true; - - - } - else if( numFracsCrossAtVrt == 2 ) // free line of fracture, no crossing point, not at boundary - { - // in this case, we have two attached edges, and each of these edges has two attached faces - // the faces have a naormal, and based on the normal, we can decide which faces belong to the same side of the edges - - - if( numbAttTripl != 4 ) - { - - UG_LOG("NUMBER OF TRIPLETTS " << numbAttTripl << std::endl); - -// return true; - - UG_THROW("Anzahl der angehaengten Triples kann nicht stimmen, Vertex einer Kluft ohne Schnittpunkte, nicht am Rand " << std::endl); - } - - // Zuordnung der Edges und Faces, die auf der gleichen Seite der fracture sind - - // und gleich auch Erzeugung der neuen Knoten, die dann - // in einem Doublett zusammen mit ihren Normalen an die alten Vertizes - // angehängt werden; der Winkel zur Normalen hilft später, die Seite - // heraus zu finden, Seite von den Edges - - - - int dbg_iteratorAblaufen = 0; - -#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX - - int dbg_laenge = 0; - - for( auto const & vft : vecVertFracTrip ) - { - dbg_laenge++; - - UG_LOG("VERTEXFRACTRIP" << std::endl); - - vector3 ve = vft.getNormal(); - - UG_LOG("NORMAL " << ve << std::endl); - - UG_LOG("laenge " << dbg_laenge << std::endl ); - } - - - UG_LOG("SINGLE" << std::endl); - - - for( VvftIterator vvftOne = vecVertFracTrip.begin(); - vvftOne != vecVertFracTrip.end() - 1; - vvftOne++ - ) - { - - - Edge * edgeOne = vvftOne->getEdge(); - vector3 nOne = vvftOne->getNormal(); - - - for( VvftIterator vvftTwo = vvftOne + 1; - vvftTwo != vecVertFracTrip.end(); - vvftTwo++ - ) - { - Edge * edgeTwo = vvftTwo->getEdge(); - vector3 nTwo = vvftTwo->getNormal(); - - number cosinus = VecDot( nOne, nTwo ); - if( edgeOne != edgeTwo ) - { - UG_LOG("COSI between " << nOne << " and " << nTwo << " -> " << cosinus << std::endl ); - } - - } - } - - UG_LOG("SINGLE END" << std::endl); - - int dbg_laenge_eins = 0; - -#endif - - - for( VvftIterator vvftOne = vecVertFracTrip.begin(); - vvftOne != vecVertFracTrip.end() - 1; - vvftOne++ - ) - { - -#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX - dbg_laenge_eins++; - - if( dbg_laenge_eins > dbg_laenge ) - { - break; - } - - int dbg_laenge_zwei = dbg_laenge_eins; -#endif - int dbg_zweiterIteratorAblaufen = 0; - - vector3 nOne = vvftOne->getNormal(); - - Edge * edgeOne = vvftOne->getEdge(); - - - - for( VvftIterator vvftTwo = vvftOne + 1; - vvftTwo != vecVertFracTrip.end(); - vvftTwo++ - ) - { - -#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX - dbg_laenge_zwei++; - - if( dbg_laenge_zwei > dbg_laenge ) - { - break; - } - - UG_LOG("NORMAL ONE " << vvftOne->getNormal() << std::endl); - UG_LOG("NORMAL TWO " << vvftTwo->getNormal() << std::endl); - UG_LOG("LAENGE EINZ ZWO " << dbg_laenge_eins << " " << dbg_laenge_zwei << std::endl ); -#endif - - // dieselben brauchen wir nicht vergleichen - if( vvftOne == vvftTwo ) - { - // sollte nie vorkommen! - UG_THROW("Unsinn " << std::endl); - } - else - { - - Edge * edgeTwo = vvftTwo->getEdge(); - - // noch testen, ob nicht die Kante dieselbe ist, geht das? - // bei der gleichen Ecke ist es unnötig, da es gegensätzlich sein muss - - - - if( edgeOne != edgeTwo ) - { - - std::vector nextFracVrt; - - IndexType foundThisVrtOne = 0; - - for( size_t i = 0; i < 2; ++i ) - { - Vertex * vrtEdgEnd = edgeOne->vertex(i); - - if( vrtEdgEnd == *iterV ) - { - foundThisVrtOne++; - } - else - { - nextFracVrt.push_back( vrtEdgEnd ); - } - - } - - if( foundThisVrtOne != 1 ) - { - UG_THROW("zu viel zu wenig vertizex one " << std::endl); - } - - - IndexType foundThisVrtTwo = 0; - - for( size_t i = 0; i < 2; ++i ) - { - Vertex * vrtEdgEnd = edgeTwo->vertex(i); - - if( vrtEdgEnd == *iterV ) - { - foundThisVrtTwo++; - } - else - { - nextFracVrt.push_back( vrtEdgEnd ); - } - - } - - if( foundThisVrtTwo != 1 ) - { - UG_THROW("zu viel zu wenig vertizex two " << std::endl); - } - - - - vector3 nTwo = vvftTwo->getNormal(); - - number cosinus = VecDot( nOne, nTwo ); - -// bool vz = ! std::signbit(cosinus); - - UG_LOG("cosinus " << dbg_vertizesPassiert << " between " << nOne << " and " << nTwo << " -> " << cosinus << std::endl ); - //UG_LOG("sign between " << nOne << " and " << nTwo << " -> " << vz << std::endl ); - - - - if( cosinus > 0 ) - { - // gleiche Seite vermutet - - // sind die edges dieselben? pruefen! gleiche unnoetig - wird oben schon abgefragt - - // Klasse schreiben, die als attachment an einen Fracture-Vertex - // die neuen Vertizes samt ihrer gemittelten Normalen speichert - // also std::vector von dieser neuen Klasse als Vertex attachment - -#if 1 - - Face * facOne = vvftOne->getFace(); - Face * facTwo = vvftTwo->getFace(); - - expandSingleFractureAtGivenSide( nOne, nTwo, - edgeOne, edgeTwo, - facOne, facTwo, - fracInfosBySubset, - posOldVrt, - aaPos, - grid, sh, - assoFaces - , - nextFracVrt, - aaVrtVecFace, - dbg_flachen_passiert, - *iterV - ); - -#else - - // average the normals - - vector3 normSum; - - VecAdd( normSum, nOne, nTwo ); - - vector3 normSumNormed; - - VecNormalize(normSumNormed, normSum); - - UG_LOG("averaged normal " << normSumNormed << std::endl); - - std::vector attEdg; - std::vector attFac; - - attEdg.push_back( edgeOne ); - attEdg.push_back( edgeTwo ); - -// Face * facOne = vvftOne->getFace(); -// Face * facTwo = vvftTwo->getFace(); - - attFac.push_back( facOne ); - attFac.push_back( facTwo ); - - // jetzt neuen Vertex erzeugen in Richtung der Normalen - // sonst ist das attachment Schwachsinn! - - vector3 posNewVrt; - - vector3 moveVrt; - - auto subsIndEdgOne = sh.get_subset_index(edgeOne); - - auto subsIndEdgTwo = sh.get_subset_index(edgeTwo); - - - if( subsIndEdgOne != subsIndEdgTwo ) - { - UG_THROW("subsets passen nicht" << std::endl ); - } - - - - - number width = fracInfosBySubset.at(subsIndEdgOne).width; - - // der Faktor ist Käse und muss noch aus den Eingaben übernommen werden - VecScale(moveVrt, normSumNormed, width/2. ); - - VecAdd(posNewVrt, posOldVrt, moveVrt ); - - UG_LOG("neuer Vertex " << posNewVrt << std::endl ); - - // TODO FIXME hier ist das PROBLEM, SEGFAULT durch create regular vertex - - Vertex * newShiftVrtx = *grid.create(); - aaPos[newShiftVrtx] = posNewVrt; - - sh.assign_subset(newShiftVrtx, subsIndEdgOne ); - - - - // fuer was braucheh wir das eigentlich? selber schon vergessen..... - - ExpandVertexMultiplett vrtMtpl( attEdg, attFac, normSumNormed ); - - aaVrtExpMP[ *iterV ].push_back( vrtMtpl ); - - - - // alle anhängenden faces müssen noch zu wissen bekommen - // dass es diesen neuen Vertex gibt, nicht nur die - // an den edges anhängenden - // vielleicht gibt es einen Loop über attached faces des - // Vertex, für die schon bekannten direkt angehängten klar - // wenn auch dort vermerkt werden muss im Attachment von Seb - // bei den anderen, die keine Edge haben von der Kluft - // da muss man die Normale ins Zentrum bestimmen - // um heraus zu finden, ob sie auf dieser seite sind - // am besten dann das Attachment der faces für vertizes - // von Seb recyclen - - // loop über assosciated faces des vertex am besten - // vermutlich auch noch assosciated edges, um - // zu markieren, welche weg fallen sollen, wenn - // nicht von Kluft selber, sondern quasi verschoben - // und neu erzeugt - - int dbg_FaceIterator = 0; - -#if 0 -// for( auto iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ ) - for( std::vector::iterator iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ ) - { - bool isFromFrac = false; - -// for( std::vector::iterator iterF2 = attFac.begin(); iterF2 != attFac.end(); iterF2++ ) -// { -// static_assert( std::is_same< decltype( *iterF2 ), decltype ( *iterFac ) >::value ); -// -// } - - int dbg_innterFacFracIt = 0; - - for( auto const & facFrac : attFac ) - { - - -// UG_LOG("type iter facFrac " << typeid( facFrac ).name() << std::endl); -// -// UG_LOG("type iter Fac " << typeid( *iterFac ).name() << std::endl); - - static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype ( *iterFac ) >::value ); - - - - - if( *iterFac == facFrac ) - { - isFromFrac = true; - - static_assert( std::is_same< decltype( const_cast(facFrac) ), Face * & >::value ); - static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype( * iterFac ) >::value ); - - } - } - - bool atRightSide = false; - - if( isFromFrac ) - atRightSide = true; - - if( !isFromFrac ) - { - // check if on same side of edge where the normal points to: compute cosinus between vector of face center - // perpendicular to the edge - // TODO FIXME - // KAESE!!! - - vector3 facCenter = CalculateCenter( *iterFac, aaPos ); - - vector3 perpendicu; - - if( nextFracVrt.size() != 2 ) - { - UG_THROW("komische Groesse" << std::endl); - } - - DropAPerpendicular(perpendicu, facCenter, aaPos[nextFracVrt[0]], aaPos[nextFracVrt[1]]); - - vector3 tmpN; - - VecSubtract(tmpN, facCenter, perpendicu ); - - VecNormalize(tmpN, tmpN); - - UG_LOG("Normale zum Face ist " << tmpN << std::endl); - - number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, normSumNormed ); - - UG_LOG("Cosinus zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); - - if( cosBetwFracEdgAndDirection2Face > 0 ) - { - UG_LOG("assuming face to be on richt side" << std::endl); - - atRightSide = true; - -#if ANSCHAULICH_ERZEUGE_SUDOS_ANHANG - - Vertex * otherFacCent = *grid.create(); - aaPos[otherFacCent] = facCenter; - sh.assign_subset(otherFacCent, 5 ); - - Vertex * pp = *grid.create(); - aaPos[pp] = perpendicu; - sh.assign_subset(pp, 6 ); - - sh.assign_subset(*iterFac,7); -#endif - - } - else - { - UG_LOG("assuming face to be on wrong side" << std::endl); - } - -// if( dbg_flachen_passiert == 0 ) -// { -// UG_LOG("passiert " << dbg_flachen_passiert << std::endl); -// -// Vertex * otherFacCent = *grid.create(); -// aaPos[otherFacCent] = facCenter; -// sh.assign_subset(otherFacCent, 5 ); -// -// Vertex * pp = *grid.create(); -// aaPos[pp] = perpendicu; -// sh.assign_subset(pp, 6 ); -// -// sh.assign_subset(*iterFac,7); -// -// -// sh.assign_subset(*iterFac,3); -// -// UG_LOG("is from frac " << isFromFrac << std::endl); -// -// return true; -// } - - - dbg_flachen_passiert++; - } - - - if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein - { - - - // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! - vector& newVrts4Fac = aaVrtVecFace[ * iterFac ]; - - IndexType vrtxFnd = 0; - - for(size_t indVrt = 0; indVrt < (*iterFac)->num_vertices(); indVrt++ ) - { - Vertex* facVrt = (*iterFac)->vertex(indVrt); - - if( facVrt == *iterV ) - { - newVrts4Fac[ indVrt ] = newShiftVrtx; - // UG_LOG("vertex found " << indVrt << std::endl ); - vrtxFnd++; - } - } - - - if( vrtxFnd <= 0 ) - { - UG_THROW("vertex not found!" << std::endl); - } - else if( vrtxFnd > 1 ) - { - UG_THROW("vertex zu oft gefunden " << vrtxFnd << std::endl ); - } - else if ( vrtxFnd == 1 ) - { - // UG_LOG("vertex found abgeschlossen" << std::endl); - } - else - { - UG_THROW("vertex finden komisch " << std::endl); - } - - - } - - dbg_innterFacFracIt++; - - - -// -// -// if( ! isFromFrac ) -// { -// // Vektor zum Zentrum von KNoten aus berechnen und Winkel zur Normalen bestimmen zur Unterscheidung der Seite -// // wenn auf richtiger Seite, zuweisen -// } - - dbg_FaceIterator++; - - } -#else -// std::vector & assFaceVrt = aaVrtInfoAssoFaces[*iterV]; - - // VecFace & assoFaces = aaVrtInfoAssoFaces[*iterV]; - // TODO FIXME hier braucht man das nicht zu ordnen - // aber bei Kreuzpunkten von Klueften muss es so geordnet werden, wie es nebeneinander liegt - // bei den Edges gibt es auch die benachbarten, und die edges haben das attachment, ob sie Kluftedges sind - - // for( auto const & ifac : assoFaces ) - // { - // static_assert( std::is_same< decltype( ifac ), Face * const & >::value ); - // - // // TODO FIXME folgenden loop durch diesen ersetzen - // // Achtung: Zeigerproblematik, Referenzen, etc..... - // // *iterFac ersetzen durch ifac vermutlich, aber wer weiss - // } - - - // for( auto iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ ) - //for( std::vector::iterator iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ ) - for( auto const & ifac : assoFaces ) - { - bool isFromFrac = false; - - - int dbg_innterFacFracIt = 0; - - for( auto const & facFrac : attFac ) - { - -// static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype ( ifac ) >::value ); - static_assert( std::is_same< decltype( (facFrac) ), decltype ( ifac ) >::value ); - - if( ifac == facFrac ) - { - isFromFrac = true; - -// static_assert( std::is_same< decltype( const_cast(facFrac) ), Face * & >::value ); - static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value ); -// static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype( ifac ) >::value ); - static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value ); - - } - } - - bool atRightSide = false; - - if( isFromFrac ) - atRightSide = true; - - if( !isFromFrac ) - { - // check if on same side of edge where the normal points to: compute cosinus between vector of face center - // perpendicular to the edge - - vector3 facCenter = CalculateCenter( ifac, aaPos ); - - vector3 perpendicu; - - if( nextFracVrt.size() != 2 ) - { - UG_THROW("komische Groesse" << std::endl); - } - - DropAPerpendicular(perpendicu, facCenter, aaPos[nextFracVrt[0]], aaPos[nextFracVrt[1]]); - - vector3 tmpN; - - VecSubtract(tmpN, facCenter, perpendicu ); - - VecNormalize(tmpN, tmpN); - - UG_LOG("Normale zum Face ist " << tmpN << std::endl); - - number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, normSumNormed ); - - UG_LOG("Cosinus zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); - - if( cosBetwFracEdgAndDirection2Face > 0 ) - { - UG_LOG("assuming face to be on richt side" << std::endl); - - atRightSide = true; - -#if ANSCHAULICH_ERZEUGE_SUDOS_ANHANG - - Vertex * otherFacCent = *grid.create(); - aaPos[otherFacCent] = facCenter; - sh.assign_subset(otherFacCent, 5 ); - - Vertex * pp = *grid.create(); - aaPos[pp] = perpendicu; - sh.assign_subset(pp, 6 ); - - sh.assign_subset(*iterFac,7); -#endif - - } - else - { - UG_LOG("assuming face to be on wrong side" << std::endl); - } - - - dbg_flachen_passiert++; - } - - - if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein - { - - // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! - vector& newVrts4Fac = aaVrtVecFace[ ifac ]; - - IndexType vrtxFnd = 0; - - for(size_t indVrt = 0; indVrt < (ifac)->num_vertices(); indVrt++ ) - { - Vertex* facVrt = (ifac)->vertex(indVrt); - - if( facVrt == *iterV ) - { - newVrts4Fac[ indVrt ] = newShiftVrtx; - vrtxFnd++; - } - } - - - if( vrtxFnd <= 0 ) - { - UG_THROW("vertex not found!" << std::endl); - } - else if( vrtxFnd > 1 ) - { - UG_THROW("vertex zu oft gefunden " << vrtxFnd << std::endl ); - } - else if ( vrtxFnd == 1 ) - { - } - else - { - UG_THROW("vertex finden komisch " << std::endl); - } - - - } - - dbg_innterFacFracIt++; - - - - dbg_FaceIterator++; - - } - -#endif - -#endif - - } - else - { - // andere Seite vermutet, nichts tun! - } - - - - } - - - } - - dbg_zweiterIteratorAblaufen++; - - } - - dbg_iteratorAblaufen++; - - } - - -// // Ziel: die beiden parallelen Normalen mitteln, und in die jeweiligen beiden Richtungen je einen neuen Vertex erzeugen -// // irgendwie muss der Vertex oder die Edge besser sogar wissen, dass sie einen neuen Verschiebevertex bekommen hat -// // denn später müssen neue Edges und neue Faces basierend auf den neuen Vertizes erzeugt werden -// // vielleicht braucht die edge und das face ein Attachment, das ihnen das sagt, ähnlihc wie VertexTrible std Vektoren? -// -// -// - - - UG_LOG("END THIS VERTEX NORMAL COSINE" << std::endl); - - - - } - else // two fractures completely crossing, numFracsCrossAtVrt >= 3, i.e. T crossing and two fractures completely crossing - { - - // TODO FIXME in case of three fractures, we have to use the method for eine durchgehende fracture - // auf der Seite, wo die zweite fracture NICHT rein geht - - IndexType countedCrossingFracEdgs = 0; - - // TODO FIXME kreuzende Fractures im Innenraum -> Arte in Reinform implementieren - - // verkettete Liste der anhängenden fractures in Reihenfolge - // der Anhängung mit INfo, ob eine Kluft vorliegt - - for( auto const & attVFT : vecVertFracTrip ) - { - Edge * edg = attVFT.getEdge(); - Face * fac = attVFT.getFace(); - vector3 nv = attVFT.getNormal(); - } - -// // hier werden ALLE attached Faces benötigt, auch die, die zwischen den direkt an den fractures liegenden Faces sind -// - // copies of all faces and of fractured ones - auto vVFT = vecVertFracTrip; // caution: COPY, not reference! - auto aF = assoFaces; // caution: COPY, not reference! - - UG_LOG("Gesamtanzahl faces um Knoten " << aF.size() << std::endl ); - - // erstmal die ganzen anhaengenden Faces ordnen, dass wir wissen, in welcher Reihenfolge wir durchlaufen muessen - // jede Edge hat ein bool attachment schon, das weiss, ob sie Fracture edge ist oder nicht - // Reihenfolge der faces und die edges auch dazu, vielleicht neues Triple oder dergleiche, dabei zwei edges und zwei normals - // und wie gesagt, die edges wissen, ob sie fractures sind, dazu keine neuen Variablen notwendig - - using VertexOfFaceInfo = VertexFractureTriple< std::pair, Face*, std::pair >; - // all edges of the attached face - must always be two, the face itself, and the normal vectors of the face in direction of the two edges - // the size of the normal vector vector also must be two - // however, if an edge of the face is not a fracture edge, we do not compute the normal, but assign zero as norm - // for those edges and faces which are Kluft edges, we assign the normal known from the info computed before, vertex fracture triple - - using VecVertexOfFaceInfo = std::vector; - - VecVertexOfFaceInfo orderedFaces; - - using SegmentsFractExtrus = std::vector; - - SegmentsFractExtrus segments; - // single components always from one fracture edge to the next one - - VecVertexOfFaceInfo segmentPart; - - // note: we do not attach this info to the vertex, as we only need it local; in principle, in case of further need, it would - // be usful to establish some sort of attachment - - if( vVFT.size() == 0 ) - UG_THROW("vertex frac triple zu klein an Kreuzung " << std::endl); - - // we start with the first fracture face edge stuff, copy it, and delete this immidiately - VertFracTrip startVertFracTrip = vVFT[0]; - - vVFT.erase(vVFT.begin()); - - bool atFirstTriple = true; - - Face* fracFac = startVertFracTrip.getFace(); - Edge* fracEdg = startVertFracTrip.getEdge(); - vector3 fracNorm = startVertFracTrip.getNormal(); - - Edge* originalStartEdge = startVertFracTrip.getEdge(); - - if( fracEdg != 0 ) - { - countedCrossingFracEdgs++; - } - - // do not change this pointer - Edge* startEdg = fracEdg; - Face* startFace = fracFac; - - vector3 startNormal = fracNorm; - - Face* nextFace = NULL; - - UG_LOG("Gesamtanzahl faces um Knoten vor while " << aF.size() << std::endl ); - - - while( aF.size() != 0 ) - { - - UG_LOG("Gesamtanzahl faces um Knoten Anfang while " << aF.size() << std::endl ); - - - Face* face2Append = startFace; - Edge* startEdg2Append = startEdg; - - - IndexType fndCommEdg = 0; - vector3 nuVe(0,0,0); - - Edge* nextEdge = NULL; - - std::pair edge2Append( startEdg2Append, nextEdge ); - std::pair normal2Append( startNormal, nuVe ); - - - // if start face and start edge from a triple, then has to be erased this triple, exept for the entire start, as already erased - if( ! atFirstTriple ) - { - for( VecVertFracTrip::iterator itAttVFT = vVFT.begin(); itAttVFT != vVFT.end(); itAttVFT++ ) - { - auto vft = *itAttVFT; - - Edge * edgIt = vft.getEdge(); - - Face * facIt = vft.getFace(); - - if( edgIt == startEdg && facIt == startFace ) - { - // the first edge if from a fracture and the face is connected to it - - vVFT.erase(itAttVFT); - - normal2Append.first = vft.getNormal(); - - if( ! FaceContains( facIt, startEdg )) - { - UG_THROW("Face does not contain start edge of its edge" << std::endl); - } - - break; - } - } - - } - else // we can save the investigation if we have a triple, and we do not need to erase, as already erased..... - { - atFirstTriple = false; - } - - - for( auto const & iE : allAssoEdges ) // werden nicht gelöscht, deswegen Zugriff auf attachment direkt - { - if( FaceContains(face2Append, iE) ) - { - fndCommEdg++; - - if( iE != startEdg ) - { - nextEdge = iE; - - edge2Append.second = iE; - - } - } - - - } - - if( fndCommEdg != 2 ) - { - UG_THROW("komische Anzahl gemeinsamer Ecke " << fndCommEdg << std::endl); - } - - if( nextEdge == NULL ) - { - UG_THROW("wieso keine zweite Ecke gefunden???? " << std::endl); - } - - if( edge2Append.first == NULL || edge2Append.second == NULL ) - { - UG_THROW("null immer noch?" << std::endl); - } - - // erase the face from the list - - IndexType faceFound = 0; - - for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ ) - { - Face * iFa = *itFac; - - if( iFa == startFace && FaceContains( iFa, nextEdge ) && FaceContains(iFa, startEdg)) - { - faceFound++; - } - } - - int totalSubsNum = sh.num_subsets(); - - int newSubsToAdd = totalSubsNum; - - if( faceFound != 1 ) - { - - - sh.assign_subset(startFace,newSubsToAdd++); - sh.assign_subset(startEdg,newSubsToAdd++); - sh.assign_subset(nextEdge,newSubsToAdd++); - - int faNum = aF.size(); - - UG_LOG("Gesamtzahl faces vor Absturz " << faNum << std::endl); - - UG_LOG("Gesicht in falscher Anztahl gefunden " << faceFound << std::endl); - -// return true; - - - - UG_THROW("Gesicht in falscher Anztahl gefunden " << faceFound << std::endl); - } - else - { -// sh.assign_subset(startFace,newSubsToAdd++); -// sh.assign_subset(startEdg,newSubsToAdd++); -// sh.assign_subset(nextEdge,newSubsToAdd++); - - int faNum = aF.size(); - - UG_LOG("Gesamtzahl faces ohne Absturz " << faNum << std::endl); - - } - - for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ ) - { - Face * iFa = *itFac; - - if( iFa == startFace && FaceContains( iFa, nextEdge ) && FaceContains(iFa, startEdg) ) - { - aF.erase(itFac); - break; - } - } - - - - - bool sndEdgIsFracEdgeAlso = aaMarkEdgeB[nextEdge]; - - bool tripFound = false; - - if( sndEdgIsFracEdgeAlso ) - { - - if( nextEdge != originalStartEdge ) - countedCrossingFracEdgs++; - - // we need to have a look for the next triple - - // check if the next normal is a frac normal which contains the face as well - - for( VecVertFracTrip::iterator itAttVFT = vVFT.begin(); itAttVFT != vVFT.end(); itAttVFT++ ) - { - auto vft = *itAttVFT; - - Edge * edgIt = vft.getEdge(); - - Face * facIt = vft.getFace(); - - if( edgIt == nextEdge && facIt == face2Append ) - { - // the second edge if from a fracture and the face is connected to it - - tripFound = true; - - vVFT.erase(itAttVFT); - - normal2Append.second = vft.getNormal(); - - if( ! FaceContains( facIt, nextEdge )) - { - UG_THROW("Face does not contain edge of its edge" << std::endl); - } - - break; - } - } - - } - - if( ! tripFound && sndEdgIsFracEdgeAlso ) - { - UG_THROW("Triple nicht gefunden trotz markierter Edge" << std::endl); - } - - - // check if aF or vVFT still contain the former or the next face - must not be the case! - - VertexOfFaceInfo vOFI( edge2Append, face2Append, normal2Append ); - - orderedFaces.push_back( vOFI ); - - segmentPart.push_back( vOFI ); - - if( sndEdgIsFracEdgeAlso ) - { - segments.push_back( segmentPart ); - - segmentPart.clear(); - } - - - // what is next face, what is next edge? - // wie kriegen wir es hin, auch das nächste Triple zu erasen, wenn es jetzt kommt als nächstes? - - - startNormal = nuVe; - startEdg = nextEdge; - - if( aF.size() == 0 ) - { - if( nextEdge != originalStartEdge ) - { - UG_THROW("Gesichter leer, aber keine Anfangsecke gefunden" << std::endl); - } - else - { - break; // while loop zu Ende, raus aus dem while loop, den Rest nicht mehr machen, würde schief gehen zwingendermassen - } - - } - - - // bleibt noch das nächste Gesicht heraus zu finden, dafür kommt eigentlich nur noch eines in Frage, da das zweite Gesicht vom edge - // geloescht sein muss in aF, es muss das einzig übrige face sein, das die jetzt start edge enthält, davon darf es nur eines geben, wir löschen aber noch nicht - - IndexType nextFaceFound = 0; - - for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ ) - { - Face * iFa = *itFac; - - if( FaceContains(iFa, startEdg ) ) - { - nextFaceFound++; - } - } - - if( nextFaceFound != 1 ) - { - UG_THROW("folgendes Gesicht in falscher Anztahl gefunden " << nextFaceFound << std::endl); - } - - for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ ) - { - Face * iFa = *itFac; - - if( FaceContains(iFa, startEdg ) ) - { - startFace = iFa; - break; - } - } - - - } - - if( vVFT.size() != 0 ) - { - UG_THROW("not all triples found! " << std::endl); - } - - if( aF.size() != 0 ) - UG_THROW("not all faces found " << std::endl); - - if( startEdg != originalStartEdge ) - { - UG_THROW("wir sind nicht am Anfang wieder angekommen" << std::endl); - } - - - if( segmentPart.size() != 0 ) - { - UG_THROW("die Segmentteile muessen alle verarbeitet sein" << std::endl); - } - - UG_LOG("Kreislauf geschlossen" << std::endl); - - - // test if the segments and their partition produce sumething useful, for debug purposes - - // als nächstes muss man die Klassen von durch Klüften abgetrennten ordered Faces durchgehen, und die Verschiebevertizes erzeugen - // als nächstes die verschiedenen Sektionen durch gehen, eventuell nochmal extra Objekte dafür erzeugen - // oder gleich beim Durchgehen die neuen Vertizes erzeugen, Startsignal durch ein Face mit erster Edge KLuft, und dann die nächste - // Kluftedge finden, egal ob vom gleihen face oder von einem späteren face im kreis - - // now figure out to which face this next edge belongs, and if this is a fracture edge, then we have the triple and the normal info - // else we let the normal zero - - // figure out if second edge is also frac edge, i.e. if it belongs to an edge of the remaining vVFT elements - // first easily asking if it is marked as frac edge, simplifies research - - // in principle from here on need to loop through all triples and through all faces, find out some way to construct next edge and to - // build one element after the other of the ordered faces vector, still even the first element is not completed - - // TODO FIXME kreuzende Fractures im Innenraum -> Arte in Reinform implementieren - // later assign somehow next edge to start edge, or use new variable, when we have figured out next face - // at end, chech if we have arrived again at original first edge - - - int totalSubsNum = sh.num_subsets(); - -// int newSubsToAdd = totalSubsNum; - -// for( VertexOfFaceInfo const & vertFracInfo : orderedFaces ) -// { -//// Face * fa = vertFracInfo.getFace(); -//// -//// sh.assign_subset(fa,newSubsToAdd++); -// } - - number totAnglsEdg = 0; - number totAnglsNrm = 0; - - for( VecVertexOfFaceInfo const & segPart : segments ) - { -// newSubsToAdd++; - - IndexType numbTriangs = segPart.size(); - - if( numbAttTripl == 0 ) - { - UG_THROW("zu wenig Dreiecke " << std::endl); - } - - VertexOfFaceInfo const & vFISBegin = segPart[0]; - VertexOfFaceInfo const & vFISEnd = segPart[numbTriangs-1]; - - std::pair edgesBegin = vFISBegin.getEdge(); - std::pair edgesEnd = vFISEnd.getEdge(); - - std::pair normalBegin = vFISBegin.getNormal(); - std::pair normalEnd = vFISEnd.getNormal(); - - Edge* edgeFracOne = edgesBegin.first; - Edge* edgeFracTwo = edgesEnd.second; - - auto subsIndFracOne = sh.get_subset_index(edgeFracOne); - auto subsIndFracTwo = sh.get_subset_index(edgeFracTwo); - - vector3 normalFracOne = normalBegin.first; - vector3 normalFracTwo = normalEnd.second; - -// sh.assign_subset(edgeFracOne, newSubsToAdd); -// -// if( edgeFracTwo != originalStartEdge ) -// sh.assign_subset(edgeFracTwo, newSubsToAdd); - - // neue Punkte erzeugen - - number cosBetweenNormals = VecDot( normalFracOne, normalFracTwo ); - - if( subsIndFracOne == subsIndFracTwo ) - { - if( numFracsCrossAtVrt != 3 ) - { - UG_THROW("Fracture Segment an beiden Seiten gleiche sudo, aber keine T Kreuzung?" << std::endl); - } - - // dieselben Methoden wie im Fall von einer durchgehenden Kluft an einem Vertex, dort kopieren - // bzw Funktion schreiben, die beides macht - - // hier wird der Fall abgezweigt, dass wir auf der durchgehenden Seite einer Kluft sind - // wenn wir eine T-Kreuzung haben - - std::vector nextFracVrt; - - IndexType foundThisVrtOne = 0; - - for( size_t i = 0; i < 2; ++i ) - { - Vertex * vrtEdgEnd = edgeFracOne->vertex(i); - - if( vrtEdgEnd == *iterV ) - { - foundThisVrtOne++; - } - else - { - nextFracVrt.push_back( vrtEdgEnd ); - } - - } - - if( foundThisVrtOne != 1 ) - { - UG_THROW("zu viel zu wenig vertizex one " << std::endl); - } - - - IndexType foundThisVrtTwo = 0; - - for( size_t i = 0; i < 2; ++i ) - { - Vertex * vrtEdgEnd = edgeFracTwo->vertex(i); - - if( vrtEdgEnd == *iterV ) - { - foundThisVrtTwo++; - } - else - { - nextFracVrt.push_back( vrtEdgEnd ); - } - - } - - if( foundThisVrtTwo != 1 ) - { - UG_THROW("zu viel zu wenig vertizex two " << std::endl); - } - - Face * faceBegin = vFISBegin.getFace(); - Face * faceEnd = vFISEnd.getFace(); - - - - expandSingleFractureAtGivenSide( normalFracTwo, normalFracTwo, - edgeFracOne, edgeFracTwo, - faceBegin, faceEnd, - fracInfosBySubset, - posOldVrt, - aaPos, - grid, sh, - assoFaces - , - nextFracVrt, - aaVrtVecFace, - dbg_flachen_passiert, - *iterV - ); - - - - } - else - { - - // create normal vectors into direction of relevant edges - - vector3 alongEdgeOne; - vector3 alongEdgeTwo; - - Vertex * vrtEdgeOneBegin = NULL; - Vertex * vrtEdgeTwoBegin = NULL; - Vertex * vrtEdgeOneEnd = NULL; - Vertex * vrtEdgeTwoEnd = NULL; - - - for( size_t i = 0; i < 2; ++i ) - { - Vertex * vrtFromEdgeOne = edgeFracOne->vertex(i); - Vertex * vrtFromEdgeTwo = edgeFracTwo->vertex(i); - - if( vrtFromEdgeOne == *iterV ) - { - vrtEdgeOneBegin = vrtFromEdgeOne; - } - else - { - vrtEdgeOneEnd = vrtFromEdgeOne; - } - - if( vrtFromEdgeTwo == *iterV ) - { - vrtEdgeTwoBegin = vrtFromEdgeTwo; - } - else - { - vrtEdgeTwoEnd = vrtFromEdgeTwo; - } - - } - - if( vrtEdgeOneBegin == NULL || vrtEdgeTwoBegin == NULL || vrtEdgeOneEnd == NULL || vrtEdgeTwoEnd == NULL ) - { - UG_THROW("lauter Nullen vertizes" << std::endl); - } - - vector3 fracVrtPos = aaPos[*iterV]; - - vector3 fracEdgOneEndPos = aaPos[ vrtEdgeOneEnd ]; - vector3 fracEdgTwoEndPos = aaPos[ vrtEdgeTwoEnd ]; - - vector3 directionEdgOne; - VecSubtract(directionEdgOne, fracEdgOneEndPos, fracVrtPos); - - vector3 directionEdgTwo; - VecSubtract(directionEdgTwo, fracEdgTwoEndPos, fracVrtPos); - - vector3 nrmdVecEdgOne; - VecNormalize(nrmdVecEdgOne, directionEdgOne); - - vector3 nrmdVecEdgTwo; - VecNormalize(nrmdVecEdgTwo, directionEdgTwo); - - number cosBetweenEdges = VecDot(nrmdVecEdgOne,nrmdVecEdgTwo); - - number angleEdges = std::acos( cosBetweenEdges ); - number angleNormls = std::acos( cosBetweenNormals ); - - totAnglsEdg += angleEdges; - totAnglsNrm += angleNormls; - - UG_LOG("cosinus Edges Normals " << cosBetweenEdges << " " << cosBetweenNormals << std::endl); - UG_LOG("angles edges normals " << angleEdges << " " << angleNormls << std::endl); - - // prject normal 1 onto edge 2 and normal 2 on edge 1, scale with width one half resp with width two half - - - number cosBetweenNrmFraOneEdgTwo = VecDot(normalFracOne,nrmdVecEdgTwo); - number cosBetweenNrmFraTwoEdgOne = VecDot(normalFracTwo,nrmdVecEdgOne); - - vector3 projectNrmFraOneToEdgTwoDirection; - VecScale(projectNrmFraOneToEdgTwoDirection, nrmdVecEdgTwo, 1./cosBetweenNrmFraOneEdgTwo); - - vector3 projectNrmFraTwoToEdgOneDirection; - VecScale(projectNrmFraTwoToEdgOneDirection, nrmdVecEdgOne, 1./cosBetweenNrmFraTwoEdgOne); - - // auto subsIndFracOne = sh.get_subset_index(edgeFracOne); - // auto subsIndFracTwo = sh.get_subset_index(edgeFracTwo); - - number shiftOne = fracInfosBySubset.at( subsIndFracOne ).width / 2. ; - number shiftTwo = fracInfosBySubset.at( subsIndFracTwo ).width / 2. ; - - vector3 shiftAlongEdgeTwo; - VecScale(shiftAlongEdgeTwo, projectNrmFraOneToEdgTwoDirection, shiftOne); - - vector3 shiftAlongEdgeOne; - VecScale(shiftAlongEdgeOne, projectNrmFraTwoToEdgOneDirection, shiftTwo); - - vector3 shiftPart; - VecAdd(shiftPart, fracVrtPos, shiftAlongEdgeTwo); - - vector3 posNewVrt; - VecAdd( posNewVrt, shiftPart, shiftAlongEdgeOne); - - UG_LOG("neuer Vertex Kreuzung " << posNewVrt << std::endl ); - - Vertex * newShiftVrtx = *grid.create(); - aaPos[newShiftVrtx] = posNewVrt; - - // sh.assign_subset(newShiftVrtx, newSubsToAdd ); - - - for( VertexOfFaceInfo const & vertFracInfoSeg : segPart ) - { - Face * fac = vertFracInfoSeg.getFace(); - - // sh.assign_subset(fa,newSubsToAdd); - - - // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! - vector& newVrts4Fac = aaVrtVecFace[ fac ]; - - IndexType vrtxFnd = 0; - - for(size_t indVrt = 0; indVrt < (fac)->num_vertices(); indVrt++ ) - { - Vertex* facVrt = (fac)->vertex(indVrt); - - if( facVrt == *iterV ) - { - newVrts4Fac[ indVrt ] = newShiftVrtx; - vrtxFnd++; - } - } - - - if( vrtxFnd <= 0 ) - { - UG_THROW("vertex not found kreuzung!" << std::endl); - } - else if( vrtxFnd > 1 ) - { - UG_THROW("vertex zu oft gefunden kreuzung " << vrtxFnd << std::endl ); - } - else if ( vrtxFnd == 1 ) - { - } - else - { - UG_THROW("vertex finden komisch kreuzung " << std::endl); - } - - } - } - } - - UG_LOG("sum angles edges normals " << totAnglsEdg << " " << totAnglsNrm << std::endl); - -// return true; - -#if 0 - // das folgende ist vermutlich Unsinn TODO FIXME, waren wohl Versuche am Anfang..... nochmal prüfen!!!! - - // get starting point of the "rotation" around the vertex where fractures are crossing -// for( auto & attVFT : vVFT ) // not const, as we need to erase found elements! - for( VecVertFracTrip::iterator itAttVFT = vVFT.begin(); itAttVFT != vVFT.end(); ) - { - Face * facAtVrtWithFrac = itAttVFT->getFace(); - - bool facFound = false; - -// for( auto const & ifac : assoFaces ) // not const, as we need to erase found elements! - for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); ) - { - if( *itFac == facAtVrtWithFrac ) - { - // found a starting face - // copy first the found info, then delete the original one - auto attVFTCop = *itAttVFT; // copy, not reference! - - vVFT.erase(itAttVFT); - aF.erase(itFac); - - // TODO FIXME erase ifac and attVFT, how to do? - - Face * startFace = facAtVrtWithFrac; - - // now determine the common edge(s), the first edge of the vector must be a frac edge, the second one might be one - - Edge * startEdg = attVFTCop.getEdge(); - - // unnecessary check, but for test purposes at beginning, later should be removed - if( !FaceContains(facAtVrtWithFrac, startEdg )) - { - UG_THROW("face hat ecke nicht, die es haben soll" << std::endl); - } - - // loop around the edges of the ifac face attached to the vertex - - // determin second edge of the startFace, not stored in the vecVertFracTrip information - // check number of common edges containing the same vertex - - IndexType fndCommEdg = 0; - std::vector assoEdg2Fac; - - assoEdg2Fac.push_back( startEdg ); - - std::vector assoNorm; - - vector3 norm2Frac = attVFTCop.getNormal(); - - Edge * secondEdge; - secondEdge = NULL; - - for( auto const & iE : allAssoEdges ) // werden nicht gelöscht, deswegen Zugriff auf attachment direkt - { - if( FaceContains(facAtVrtWithFrac, iE) ) - { - fndCommEdg++; - if( iE != startEdg ) - { - secondEdge = iE; - } - } - - if( fndCommEdg != 2 ) - { - UG_THROW("komische Anzahl gemeinsamer Ecke " << fndCommEdg << std::endl); - } - - if( secondEdge == NULL ) - { - UG_THROW("wieso keine zweite Ecke gefunden???? " << std::endl); - } - - assoEdg2Fac.push_back(secondEdge); - - // check, if second edge belongs to anothter fracture fac, i.e. if it is also a fracture edge - - // check if second edge is edge of a fracture face, i.e. either this edge, or another one is from a fracture - - bool scndEdgIsFracEdg = aaMarkEdgeB[secondEdge]; - - if( scndEdgIsFracEdg ) - { - // TODO FIXME figure out second vertex fracture info, in this case, we have found the next part of the chain! - - for( VecVertFracTrip::iterator itAttVFTTwo = vVFT.begin(); itAttVFTTwo != vVFT.end(); ) - { - // need to erase also this element soon, also in the list of all attached elements - - Face* vFTTwoFac = itAttVFTTwo->getFace(); - - if( FaceContains( vFTTwoFac, secondEdge)) - { - auto vVFT2 = *itAttVFTTwo; - vVFT.erase( itAttVFTTwo ); - - Face * nextFace = vFTTwoFac; - - if( secondEdge != vVFT2.getEdge() ) - { - UG_THROW("Ecke nicht Ecke " << std::endl); - } - - - } - } - } - else // find the next attached face, either from the - { - - } - } - - break; - } - - if( ! facFound ) - { - UG_THROW("Gesicht unauffindbar" << std::endl); - } - - break; - } - } - - while( vVFT.size() != 0 ) - { - while( aF.size() != 0 ) - { - - } - } - -#endif - - - } - - } -// // // different treatment for boundary vertizes - else - { - - // TODO FIXME es muss wohl noch ein Problem mit den Verschiebungen bei boundary Vertizes geben..... - // TODO FIXME XXXXXXXXXXXXXX hier sind wir - - - if( numFracsCrossAtVrt < 1 ) - { - UG_THROW("no fracs crossing but marked vertex at boundary? << std::endl"); - } - else if( numFracsCrossAtVrt == 1 ) // no crossing point at boundary - { - // in this case, we have ONE attached edges, the edges has two attached faces - // the faces have a normal, and based on the normal, we can decide which faces belong to the same side of the edges - - if( numbAttTripl != 2 ) - { - UG_THROW("Anzahl der angehaengten Triples kann nicht stimmen, Vertex einer Kluft ohne Schnittpunkte am Rand " << std::endl); - } - - // Zuordnung der Edges und Faces, die auf der gleichen Seite der fracture sind - - // und gleich auch Erzeugung der neuen Knoten, die dann - // in einem Doublett zusammen mit ihren Normalen an die alten Vertizes - // angehängt werden; der Winkel zur Normalen hilft später, die Seite - // heraus zu finden, Seite von den Edges - - // get edges adjacent to this vertex which lie on the boundary of the domain - - std::vector adjBndEdgs; - -// std::vector & allAssoEdges = aaVrtInfoAssoEdges[*iterV]; - -// for( std::vector::iterator iterBVEdg = grid.associated_edges_begin(*iterV); iterBVEdg != grid.associated_edges_end(*iterV); iterBVEdg++ ) -// { -// if( IsBoundaryEdge2D(grid,*iterBVEdg) ) -// { -// adjBndEdgs.push_back( *iterBVEdg ); -// } -// } - for( auto const & iBVE : allAssoEdges ) - { - if( IsBoundaryEdge2D(grid, iBVE ) ) - { - adjBndEdgs.push_back( iBVE ); - } - } - - // to compute the normals, compute the vector of the edge and normalize it - std::vector bndEdgeDirection; - - for( auto const & bE : adjBndEdgs ) - { - - // get vertices, i.e. get seocnd vertex, first one must be known - -// std::vector verticesEdg; - - static_assert( std::is_same< Edge* const &, decltype( bE ) >::value ); - - static_assert( std::is_same< Vertex*, decltype( bE->vertex(0) ) >::value ); - - IndexType fndIV = 0; - - Vertex * vrtOtherEdg; - vrtOtherEdg = NULL; - - for( size_t i = 0; i < 2; ++i ) - { -// verticesEdg.push_back( adjBndEdgs.vertex(i) ); - - Vertex * vrtOfEdg = bE->vertex(i); - - if( vrtOfEdg == *iterV ) - { - fndIV++; - } - else - { - vrtOtherEdg = vrtOfEdg; - } - } - - vector3 posOtherVrt = aaPos[vrtOtherEdg]; - - UG_LOG("BOUNDARY EDGE VERTIZES " << posOldVrt << ", " << posOtherVrt << std::endl); - - vector3 fromIterV2Other; - - VecSubtract(fromIterV2Other, posOtherVrt, posOldVrt); - - vector3 nV; - - VecNormalize(nV, fromIterV2Other); - - bndEdgeDirection.push_back(nV); - } - - - -#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX - - IndexType dbg_lim = vecVertFracTrip.size(); - - int dbg_cnt = 0; -#endif - - for( VvftIterator vvftAtBnd = vecVertFracTrip.begin(); - vvftAtBnd != vecVertFracTrip.end(); - vvftAtBnd++ - ) - { -#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX - - if( dbg_lim == dbg_cnt ) - { - UG_LOG("DARF NICHT SEIN" << std::endl); - break; - } - - dbg_cnt++; -#endif - - // Ziel: den parallelen Anteil der Normalen auf die jeweilige Randkante projizieren - - vector3 nrmEdg = vvftAtBnd->getNormal(); - - Edge * edgeOfFrac = vvftAtBnd->getEdge(); - - // figure out the adjoint boundary edge into the same direction - - // the normal in both directions have to be compared with the vectors in direction of boundary edges - for( auto bED : bndEdgeDirection ) - { - // check orientation of boundary edges wrt the normals - - number cosinus = VecDot( nrmEdg, bED ); - - UG_LOG("BOUNDARY COSINUS between " << nrmEdg << " and " << bED << " -> " << cosinus << std::endl); - - if( cosinus > 0 ) - { - // gleiche Seite vermutet - - // muessen wissen, wie lange das gestreckt werden soll - - vector3 alongEdgV; - - auto subsIndEdgOF = sh.get_subset_index(edgeOfFrac); - - number width = fracInfosBySubset.at(subsIndEdgOF).width; - - number scal = width / 2. / cosinus; - - VecScale( alongEdgV, bED, scal ); - - vector3 posNewVrtOnBnd; - - VecAdd(posNewVrtOnBnd, posOldVrt, alongEdgV ); - - UG_LOG("neuer Vertex Edge " << posNewVrtOnBnd << std::endl ); - - Vertex * newShiftEdgVrtx = *grid.create(); - aaPos[newShiftEdgVrtx] = posNewVrtOnBnd; - - sh.assign_subset(newShiftEdgVrtx, subsIndEdgOF ); - - std::vector attEdg; - std::vector attFac; - - attEdg.push_back(edgeOfFrac); - - Face * facFrac = vvftAtBnd->getFace(); - - attFac.push_back( facFrac ); - - // we store the boundary edge direction for boundary verzizes rather than the normal, in contrast to inner vertizes, where we store the averaged normal - ExpandVertexMultiplett vrtMtpl( attEdg, attFac, bED ); - - aaVrtExpMP[ *iterV ].push_back( vrtMtpl ); - -#if 0 - // the attached faces need to know that they need a new vertex to be shifted - for( std::vector::iterator iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ ) - { - bool isFromFrac = false; - - for( auto const & facFrac : attFac ) - { - if( *iterFac == facFrac ) - { - isFromFrac = true; - } - } - - bool atRightSide = false; - - if( isFromFrac ) - atRightSide = true; - - if( !isFromFrac ) - { - - // check if on same side of edge where the normal points to: compute cosinus between vector of face center - // perpendicular to the edge - // TODO FIXME - - vector3 facCenter = CalculateCenter( *iterFac, aaPos ); - - vector3 perpendicu; - - DropAPerpendicular(perpendicu, facCenter, aaPos[edgeOfFrac->vertex(0)], aaPos[edgeOfFrac->vertex(1)]); - - vector3 tmpN; - - VecSubtract(tmpN, facCenter, perpendicu ); - - VecNormalize(tmpN, tmpN); - - UG_LOG("Normale Boundary zum Face ist " << tmpN << std::endl); - - number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, nrmEdg ); - - UG_LOG("Cosinus Boundary zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); - - if( cosBetwFracEdgAndDirection2Face > 0 ) - { - UG_LOG("assuming boundary face to be on richt side" << std::endl); - - atRightSide = true; - -#if ANSCHAULICH_ERZEUGE_SUDOS_ANHANG - Vertex * otherFacCent = *grid.create(); - aaPos[otherFacCent] = facCenter; - sh.assign_subset(otherFacCent, 5 ); - - Vertex * pp = *grid.create(); - aaPos[pp] = perpendicu; - sh.assign_subset(pp, 6 ); - - sh.assign_subset(*iterFac,7); -#endif - - - } - else - { - UG_LOG("assuming boundary face to be on wrong side" << std::endl); - } - - } - - if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein - { - - - vector& newVrts4Fac = aaVrtVecFace[ * iterFac ]; - - IndexType vrtxFnd = 0; - - for(size_t indVrt = 0; indVrt < (*iterFac)->num_vertices(); indVrt++ ) - { - Vertex* facVrt = (*iterFac)->vertex(indVrt); - - if( facVrt == *iterV ) - { - newVrts4Fac[ indVrt ] = newShiftEdgVrtx; - vrtxFnd++; - } - } - - - - if( vrtxFnd <= 0 ) - { - UG_THROW("vertex not found bnd!" << std::endl); - } - else if( vrtxFnd > 1 ) - { - UG_THROW("vertex zu oft gefunden bnd " << vrtxFnd << std::endl ); - } - else if ( vrtxFnd == 1 ) - { -// UG_LOG("vertex found abgeschlossen" << std::endl); - } - else - { - UG_THROW("vertex finden bnd komisch " << std::endl); - } - } - - } -#else - for( auto const & ifac : assoFaces ) - { - bool isFromFrac = false; - - for( auto const & facFrac : attFac ) - { - if( ifac == facFrac ) - { - isFromFrac = true; - } - } - - bool atRightSide = false; - - if( isFromFrac ) - atRightSide = true; - - if( !isFromFrac ) - { - - // check if on same side of edge where the normal points to: compute cosinus between vector of face center - // perpendicular to the edge - // TODO FIXME - - vector3 facCenter = CalculateCenter( ifac, aaPos ); - - vector3 perpendicu; - - DropAPerpendicular(perpendicu, facCenter, aaPos[edgeOfFrac->vertex(0)], aaPos[edgeOfFrac->vertex(1)]); - - vector3 tmpN; - - VecSubtract(tmpN, facCenter, perpendicu ); - - VecNormalize(tmpN, tmpN); - - UG_LOG("Normale Boundary zum Face ist " << tmpN << std::endl); - - number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, nrmEdg ); - - UG_LOG("Cosinus Boundary zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); - - if( cosBetwFracEdgAndDirection2Face > 0 ) - { - UG_LOG("assuming boundary face to be on richt side" << std::endl); - - atRightSide = true; - -#if ANSCHAULICH_ERZEUGE_SUDOS_ANHANG - Vertex * otherFacCent = *grid.create(); - aaPos[otherFacCent] = facCenter; - sh.assign_subset(otherFacCent, 5 ); - - Vertex * pp = *grid.create(); - aaPos[pp] = perpendicu; - sh.assign_subset(pp, 6 ); - - sh.assign_subset(*iterFac,7); -#endif - - - } - else - { - UG_LOG("assuming boundary face to be on wrong side" << std::endl); - } - - } - - if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein - { - - - vector& newVrts4Fac = aaVrtVecFace[ ifac ]; - - IndexType vrtxFnd = 0; - - for(size_t indVrt = 0; indVrt < (ifac)->num_vertices(); indVrt++ ) - { - Vertex* facVrt = (ifac)->vertex(indVrt); - - if( facVrt == *iterV ) - { - newVrts4Fac[ indVrt ] = newShiftEdgVrtx; - vrtxFnd++; - } - } - - - - if( vrtxFnd <= 0 ) - { - UG_THROW("vertex not found bnd!" << std::endl); - } - else if( vrtxFnd > 1 ) - { - UG_THROW("vertex zu oft gefunden bnd " << vrtxFnd << std::endl ); - } - else if ( vrtxFnd == 1 ) - { -// UG_LOG("vertex found abgeschlossen" << std::endl); - } - else - { - UG_THROW("vertex finden bnd komisch " << std::endl); - } - } - } - -#endif - - - - } - } - } - - } - else // fractures are crossing at boundary even - { - - } - - - UG_LOG("END THIS BOUNDARY VERTEX" << std::endl); - } - - dbg_vertizesPassiert++; - - } - - -// // neue Vertizes in der Entfernung der Klüfte von den Klüften weg erzeugen, -// // basierend auf den Normalen multipliziert mit der halben Kluftdicke -// //für eine Kluft erstmal nur -// // die neuen Kanten und Faces erzeugen, die alten falschen Kanten löschen und ebenso die alten Faces -// // später auf mehr Klüfte ausdehnen, mit Problemstelle Kreuzung, aber erst, wenn eine Kluft funktioniert -// - -// return true; - - // jetzt Seb Sachen beinahe unverändert - - //////////////////////////////// - // create new elements - - // first we create new edges from selected ones which are connected to - // inner vertices. This allows to preserve old subsets. - // Since we have to make sure that we use the right vertices, - // we have to iterate over the selected faces and perform all actions on the edges - // of those faces. - for(FaceIterator iter_sf = sel.faces_begin(); iter_sf != sel.faces_end(); ++iter_sf) - { - Face* sf = *iter_sf; - // check for each edge whether it has to be copied. - for(size_t i_edge = 0; i_edge < sf->num_edges(); ++i_edge) - { - Edge* e = grid.get_edge(sf, i_edge); - - if(sel.is_selected(e)) - { - // check the associated vertices through the volumes aaVrtVecVol attachment. - // If at least one has an associated new vertex and if no edge between the - // new vertices already exists, we'll create the new edge. - size_t ind0 = i_edge; - size_t ind1 = (i_edge + 1) % sf->num_edges(); - - Vertex* nv0 = (aaVrtVecFace[sf])[ind0]; - Vertex* nv1 = (aaVrtVecFace[sf])[ind1]; - - if(nv0 || nv1) - { - // if one vertex has no associated new one, then we use the vertex itself - if(!nv0) - nv0 = sf->vertex(ind0); - if(!nv1) - nv1 = sf->vertex(ind1); - - // create the new edge if it not already exists. - if(!grid.get_edge(nv0, nv1)) - grid.create_by_cloning(e, EdgeDescriptor(nv0, nv1), e); - } - } - } - } - - - std::vector newFaces; - std::vector subsOfNewFaces; - - // iterate over all surrounding faces and create new vertices. - // Since faces are replaced on the fly, we have to take care with the iterator. - for(FaceIterator iter_sf = sel.faces_begin(); iter_sf != sel.faces_end();) - { - Face* sf = *iter_sf; - ++iter_sf; - - vector newVrts = aaVrtVecFace[sf]; - - // all new vertices have been assigned to newVrts. - // Note that if newVrts[i] == NULL, then we have to take the - // old vertex sf->vertex(i). - // now expand the fracture edges of sf to faces. - for(size_t i_vrt = 0; i_vrt < sf->num_vertices(); ++i_vrt) - { - size_t iv1 = i_vrt; - size_t iv2 = (i_vrt + 1) % sf->num_vertices(); - - Edge* tEdge = grid.get_edge(sf->vertex(iv1), sf->vertex(iv2)); - - if(tEdge) - { - if( aaMarkEdgeB[tEdge] ) - { - Face* expFace = NULL; - if(newVrts[iv1] && newVrts[iv2]) - { - // create a new quadrilateral - expFace = *grid.create( - QuadrilateralDescriptor(sf->vertex(iv1), sf->vertex(iv2), - newVrts[iv2], newVrts[iv1])); - } - else if(newVrts[iv1]) - { - // create a new triangle - expFace = *grid.create( - TriangleDescriptor(sf->vertex(iv1), sf->vertex(iv2), newVrts[iv1])); - } - else if(newVrts[iv2]) - { - // create a new triangle - expFace = *grid.create( - TriangleDescriptor(sf->vertex(iv1), sf->vertex(iv2), newVrts[iv2])); - } - else - { - -//// sh.assign_subset(*iter_sf,10); -//// sh.assign_subset(tEdge,11); -// -// return true; -// // this code-block should never be entered. If it is entered then -// // we selected the wrong faces. This is would be a BUG!!! -// // remove the temporary attachments and throw an error -// -// // remove the temporary attachments -//#if OLD_PROFREITER_STUFF -// grid.detach_from_vertices(aAdjMarker); -// grid.detach_from_edges(aAdjMarker); -//#endif -// grid.detach_from_vertices(aAdjMarkerVFP); -// grid.detach_from_edges(aAdjMarkerB); -// -// grid.detach_from_vertices( aAdjInfoAVVFT ); -// grid.detach_from_faces(attVrtVec); -// -// grid.detach_from_vertices( aAdjInfoEdges ); -// grid.detach_from_vertices( aAdjInfoFaces ); -// -// -// // TODO FIXME auch die weiteren Marker und INfos, alle Attachments, detachen!!!! -// -// throw(UGError("Implementation error in ExpandFractures2d Arte.")); - } - - // TODO FIXME selektion closen irgendwie, damit auch alle Randkanten zum subset gehoeren!!! - - if( expFace ) - { - sh.assign_subset(expFace, fracInfosBySubset.at(sh.get_subset_index(tEdge)).newSubsetIndex); - - int subs = fracInfosBySubset.at(sh.get_subset_index(tEdge)).newSubsetIndex; - - subsOfNewFaces.push_back( subs ); - - newFaces.push_back( expFace ); - } - } - } - } - - - - - // now set up a new face descriptor and replace the face. - if(fd.num_vertices() != sf->num_vertices()) - fd.set_num_vertices(sf->num_vertices()); - - for(size_t i_vrt = 0; i_vrt < sf->num_vertices(); ++i_vrt) - { - if(newVrts[i_vrt]) - fd.set_vertex(i_vrt, newVrts[i_vrt]); - else - fd.set_vertex(i_vrt, sf->vertex(i_vrt)); - } - - grid.create_by_cloning(sf, fd, sf); - grid.erase(sf); - } - - // we have to clean up unused edges. - // All selected edges with mark 0 have to be deleted. - for(EdgeIterator iter = sel.edges_begin(); iter != sel.edges_end();) - { - // be careful with the iterator - Edge* e = *iter; - ++iter; - - if(!aaMarkEdgeB[e]) - grid.erase(e); - } - - if( subsOfNewFaces.size() != newFaces.size() ) - { - UG_THROW("andere zahl neue faces als subdoms " << std::endl); - } - - IndexType nfn = 0; - - for( auto const & nf : newFaces ) - { - for(size_t i_edge = 0; i_edge < nf->num_edges(); ++i_edge) - { - Edge* edg = grid.get_edge(nf, i_edge); - - sh.assign_subset( edg, subsOfNewFaces[nfn] ); - } - - nfn++; - } - - // sollen die Boundary Edges zur boundary gehören, oder zur Kluft? - // wie ist es mit den Knoten, sind die alle richtig zugewiesen bezüglich subset? - - // TODO FIXME HHHHHHHHHHHHHHHHHH - // jetzt muss noch der Diamant erzeugt werden - // Ziel: KluftInnen erzeugen - - // remove the temporary attachments - -#if OLD_PROFREITER_STUFF - grid.detach_from_vertices(aAdjMarker); - grid.detach_from_edges(aAdjMarker); -#endif - grid.detach_from_vertices(aAdjMarkerVFP); - grid.detach_from_edges(aAdjMarkerB); - - grid.detach_from_vertices( aAdjInfoAVVFT ); - grid.detach_from_faces(attVrtVec); - - grid.detach_from_vertices( aAdjInfoEdges ); - grid.detach_from_vertices(aAdjInfoFaces ); - - - // TODO FIXME alles detachen, was noch attached ist, da ist einiges hinzu gekommen! - - - return true; - - // ENDE NEUES ZEUG SELEKTION - - - - - - - -#if OLD_PROFREITER_STUFF - // TODO FIXME von diesem Loop kann man noch für oben die calculate crease normal lernen, vielleicht minimal abgewandelt, vielleicht exakt gleich - - // a callback that returns true if the edge is a fracture edge, neues System - AttachmentUnequal > isFracEdgeB(aaMarkEdgeB, false); - - // iterate over all surrounding faces and create new vertices. - for(FaceIterator iter_sf = sel.faces_begin(); iter_sf != sel.faces_end(); ++iter_sf) - { - Face* sf = *iter_sf; - - // check for each vertex whether it lies in the fracture - // (aaMarkVRT > 1 in this case) - // if so, we have to copy or create a vertex from/in aaVrtVec[vrt] which is - // associated with the crease normal on the side of sf. - for(size_t i_vrt = 0; i_vrt < sf->num_vertices(); ++i_vrt) - { - Vertex* vrt = sf->vertex(i_vrt); - if(aaMarkVRT[vrt] > 1) - { - // calculate the normal on this side of the frac - // TODO FIXME so eine Funktion brauchen wir vielleicht oben auch zur Vereinfachung des Codes!!! - vector3 n_v2 = CalculateCreaseNormal(grid, sf, vrt, isFracEdgeB, aaPos); - // das calculate crease normal scheint mir ein Schwachsinn zu sein - // aber vielleicht doch nicht? - - UG_LOG("calculated crease normal v2: " << n_v2 << endl); - - } - } -#endif - - - - - - - -} - - - /** Selects all involved geometic objects and assigns marks to them. * If required, som edges may be split, so that we always operate * on a fully expandable fracture. diff --git a/ugbase/lib_grid/algorithms/extrusion/expand_layers.h b/ugbase/lib_grid/algorithms/extrusion/expand_layers.h index 6819d60c7..667d6e359 100644 --- a/ugbase/lib_grid/algorithms/extrusion/expand_layers.h +++ b/ugbase/lib_grid/algorithms/extrusion/expand_layers.h @@ -75,14 +75,6 @@ bool ExpandFractures2d(Grid& grid, SubsetHandler& sh, const std::vector& fracInfos, bool expandInnerFracBnds, bool expandOuterFracBnds); -/** - * 2 dimensional fracture expansion for finite extensions, using the Arte algorithm - * - */ -bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, - const std::vector& fracInfos, - bool expandInnerFracBnds, bool expandOuterFracBnds); - /** * This algorithm indirectly uses Grid::mark. diff --git a/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.cpp b/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.cpp new file mode 100644 index 000000000..8f734be8d --- /dev/null +++ b/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.cpp @@ -0,0 +1,3590 @@ +/* + * expand_layers_arte.cpp + * + * Created on: 11.07.2024 + * Author: mknodel + */ + +#include + +#include "expand_layers.h" +#include "lib_grid/algorithms/geom_obj_util/geom_obj_util.h" +#include "lib_grid/callbacks/callbacks.h" +#include "lib_grid/grid/grid_util.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "support.h" + +namespace ug{ +using VertFracTrip = VertexFractureTriple; + +//using VecVertFracTrip = std::vector; + +//using VvftIterator = VecVertFracTrip::iterator; + +using std::vector; + +typedef Attachment > AttVrtVec; + +using VertexOfFaceInfo = VertexFractureTriple< std::pair, Face*, std::pair >; + + +using IndexType = unsigned short; + +template +bool expandSingleFractureAtGivenSide( vector3 const & nOne, vector3 const & nTwo, + Edge * edgeOne, Edge * edgeTwo, + Face * facOne, Face * facTwo, + vector const & fracInfosBySubset, + vector3 const & posOldVrt, + Grid::VertexAttachmentAccessor & aaPos, + Grid & grid, SubsetHandler & sh, + ASOF const & assoFaces, + std::vector const & nextFracVrt, + Grid::FaceAttachmentAccessor & aaVrtVecFace, + int & dbg_flachen_passiert, + Vertex * iterV + ) +{ + +#if 1 + // gleiche Seite vermutet oder gegeben + + // average the normals + + vector3 normSum; + + VecAdd( normSum, nOne, nTwo ); + + vector3 normSumNormed; + + VecNormalize(normSumNormed, normSum); + + UG_LOG("averaged normal " << normSumNormed << std::endl); + + std::vector attEdg; + std::vector attFac; + + attEdg.push_back( edgeOne ); + attEdg.push_back( edgeTwo ); + + attFac.push_back( facOne ); + attFac.push_back( facTwo ); + + // jetzt neuen Vertex erzeugen in Richtung der Normalen + // sonst ist das attachment Schwachsinn! + + vector3 posNewVrt; + + vector3 moveVrt; + + auto subsIndEdgOne = sh.get_subset_index(edgeOne); + + auto subsIndEdgTwo = sh.get_subset_index(edgeTwo); + + if( subsIndEdgOne != subsIndEdgTwo ) + { + UG_THROW("subsets passen nicht Vereinheitlichung" << std::endl ); + } + + number width = fracInfosBySubset.at(subsIndEdgOne).width; + + // der Faktor ist Käse und muss noch aus den Eingaben übernommen werden + VecScale(moveVrt, normSumNormed, width/2. ); + + VecAdd(posNewVrt, posOldVrt, moveVrt ); + + UG_LOG("neuer Vertex " << posNewVrt << std::endl ); + + // TODO FIXME hier ist das PROBLEM, SEGFAULT durch create regular vertex + + Vertex * newShiftVrtx = *grid.create(); + aaPos[newShiftVrtx] = posNewVrt; + + sh.assign_subset(newShiftVrtx, subsIndEdgOne ); + + + + // alle anhängenden faces müssen noch zu wissen bekommen + // dass es diesen neuen Vertex gibt, nicht nur die + // an den edges anhängenden + // vielleicht gibt es einen Loop über attached faces des + // Vertex, für die schon bekannten direkt angehängten klar + // wenn auch dort vermerkt werden muss im Attachment von Seb + // bei den anderen, die keine Edge haben von der Kluft + // da muss man die Normale ins Zentrum bestimmen + // um heraus zu finden, ob sie auf dieser seite sind + // am besten dann das Attachment der faces für vertizes + // von Seb recyclen + + // loop über assosciated faces des vertex am besten + // vermutlich auch noch assosciated edges, um + // zu markieren, welche weg fallen sollen, wenn + // nicht von Kluft selber, sondern quasi verschoben + // und neu erzeugt + + int dbg_FaceIterator = 0; + + for( auto const & ifac : assoFaces ) + { + bool isFromFrac = false; + + int dbg_innterFacFracIt = 0; + + for( auto const & facFrac : attFac ) + { + + static_assert( std::is_same< decltype( (facFrac) ), decltype ( ifac ) >::value ); + + if( ifac == facFrac ) + { + isFromFrac = true; + + static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value ); + static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value ); + + } + } + + bool atRightSide = false; + + if( isFromFrac ) + atRightSide = true; + + if( !isFromFrac ) + { + // check if on same side of edge where the normal points to: compute cosinus between vector of face center + // perpendicular to the edge + + vector3 facCenter = CalculateCenter( ifac, aaPos ); + + vector3 perpendicu; + + if( nextFracVrt.size() != 2 ) + { + UG_THROW("komische Groesse" << std::endl); + } + + DropAPerpendicular(perpendicu, facCenter, aaPos[nextFracVrt[0]], aaPos[nextFracVrt[1]]); + + vector3 tmpN; + + VecSubtract(tmpN, facCenter, perpendicu ); + + VecNormalize(tmpN, tmpN); + + UG_LOG("Normale zum Face ist " << tmpN << std::endl); + + number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, normSumNormed ); + + UG_LOG("Cosinus zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); + + if( cosBetwFracEdgAndDirection2Face > 0 ) + { + UG_LOG("assuming face to be on richt side" << std::endl); + + atRightSide = true; + +#if ANSCHAULICH_ERZEUGE_SUDOS_ANHANG + + Vertex * otherFacCent = *grid.create(); + aaPos[otherFacCent] = facCenter; + sh.assign_subset(otherFacCent, 5 ); + + Vertex * pp = *grid.create(); + aaPos[pp] = perpendicu; + sh.assign_subset(pp, 6 ); + + sh.assign_subset(*iterFac,7); +#endif + + } + else + { + UG_LOG("assuming face to be on wrong side" << std::endl); + } + + + dbg_flachen_passiert++; + } + + + if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein + { + + // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! + vector& newVrts4Fac = aaVrtVecFace[ ifac ]; + + IndexType vrtxFnd = 0; + + for(size_t indVrt = 0; indVrt < (ifac)->num_vertices(); indVrt++ ) + { + Vertex* facVrt = (ifac)->vertex(indVrt); + + if( facVrt == iterV ) + { + newVrts4Fac[ indVrt ] = newShiftVrtx; + vrtxFnd++; + } + } + + + if( vrtxFnd <= 0 ) + { + UG_THROW("vertex not found!" << std::endl); + } + else if( vrtxFnd > 1 ) + { + UG_THROW("vertex zu oft gefunden " << vrtxFnd << std::endl ); + } + else if ( vrtxFnd == 1 ) + { + } + else + { + UG_THROW("vertex finden komisch " << std::endl); + } + + + } + + dbg_innterFacFracIt++; + + + + dbg_FaceIterator++; + + } +#endif + + return true; + +} + +#ifndef NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX +#define NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX 1 +#endif + +#ifndef ANSCHAULICH_ERZEUGE_SUDOS_ANHANG +#define ANSCHAULICH_ERZEUGE_SUDOS_ANHANG 0 +#endif + +#ifndef OLD_PROFREITER_STUFF +#define OLD_PROFREITER_STUFF 0 +#endif + +bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector const & fracInfos, + bool expandInnerFracBnds, bool expandOuterFracBnds) +{ + +// static constexpr bool dehneInnereKluftGrenzpunkteAus = false; + +// expandInnerFracBnds = false; + +// expandOuterFracBnds = true; + +// access position attachment + if(!grid.has_vertex_attachment(aPosition)){ + UG_LOG("Error in ExpandFractures 2D Arte: Missing position attachment"); + return false; + } + Grid::VertexAttachmentAccessor aaPos(grid, aPosition); + + if(!grid.option_is_enabled(FACEOPT_AUTOGENERATE_EDGES)){ + UG_LOG("WARNING in Arte 2D CalculateCreaseNormal: grid option FACEOPT_AUTOGENERATE_EDGES autoenabled.\n"); + grid.enable_options(FACEOPT_AUTOGENERATE_EDGES); + } + +// objects for temporary results + FaceDescriptor fd; + vector edges; // used for temporary results. + vector faces; // used for temporary results. + +// vectors that allow to access fracture properties by subset index + vector fracInfosBySubset(sh.num_subsets(), FractureInfo(-1, -1, 0)); + for(size_t i = 0; i < fracInfos.size(); ++i){ + if(fracInfos[i].subsetIndex >= sh.num_subsets()){ + throw(UGError("Bad subsetIndex in given fracInfos.")); + } + + fracInfosBySubset[fracInfos[i].subsetIndex] = fracInfos[i]; + } + +//////////////////////////////// +// Collect surrounding faces of all fractures in a selector +// and select edges and vertices too. + Selector sel(grid); + sel.enable_autoselection(false); + sel.enable_selection_inheritance(false); + +#if OLD_PROFREITER_STUFF + AInt aAdjMarker; // used to mark how many adjacent fractures a vertex has. + // 0: no frac, 1: frac-boundary, >1: inner frac vertex + // TODO FIXME das sieht komisch aus, ist das immer so, wenn z.B. an einer Grenze sich zwei fracs treffen? + grid.attach_to_vertices_dv(aAdjMarker, 0); + Grid::VertexAttachmentAccessor aaMarkVRT(grid, aAdjMarker); + grid.attach_to_edges_dv(aAdjMarker, 0); + Grid::EdgeAttachmentAccessor aaMarkEDGE(grid, aAdjMarker); +#endif + +// using IndexType = unsigned short; + using AttVerFracProp = Attachment >; + // attachment pair boundary is fracture, number fractures crossing + + AttVerFracProp aAdjMarkerVFP; + + VertexFractureProperties vfp0( false, 0 ); + // default value: no boundary fracture, no fractures crossing + + grid.attach_to_vertices_dv(aAdjMarkerVFP, vfp0 ); + Grid::VertexAttachmentAccessor aaMarkVrtVFP(grid, aAdjMarkerVFP); + + ABool aAdjMarkerB; // used to know if an edge is frac edge + grid.attach_to_edges_dv(aAdjMarkerB, false); + Grid::EdgeAttachmentAccessor aaMarkEdgeB(grid, aAdjMarkerB); + + + // die Vertizes, Faces und Edges, die mit einer Kluft zu tun haben + +// using VertFracTrip = VertexFractureTriple; +// + using VecVertFracTrip = std::vector; + + VecVertFracTrip vertexNoInfo; + + using AttVecVertFracTrip = Attachment; + + AttVecVertFracTrip aAdjInfoAVVFT; + + grid.attach_to_vertices_dv( aAdjInfoAVVFT, vertexNoInfo ); + Grid::VertexAttachmentAccessor aaVrtInfoFraTri(grid, aAdjInfoAVVFT ); + + + using VecEdge = std::vector; + using VecFace = std::vector; + + using AttVecEdge = Attachment; + using AttVecFace = Attachment; + + VecEdge noEdge; + VecFace noFace; + AttVecEdge aAdjInfoEdges; + AttVecFace aAdjInfoFaces; + + grid.attach_to_vertices_dv( aAdjInfoEdges, noEdge ); + Grid::VertexAttachmentAccessor aaVrtInfoAssoEdges( grid, aAdjInfoEdges ); + + grid.attach_to_vertices_dv( aAdjInfoFaces, noFace ); + Grid::VertexAttachmentAccessor aaVrtInfoAssoFaces( grid, aAdjInfoFaces ); + + // das ist Käse, ich brauche für jeden Vertex ein Attachment der Form + // class VertexTriple, bzw std vektoren von solchen vertex triplen + // da weiss dann jeder Vertex das triple + // Kante (damit subdom) - Face - normal (von Kante in Face rein) + // dann kann man nämlich anhand des Winkels von zwei Normalen + // von solchen Vertizes bestimmtn, ob sie auf die gleiche Seite der Kante zeigen + // und dann kann man sie mitteln, sofern die Vertizes keine Kreuzungs Vertizes sind + // oder keine äusseren Vertizes - ob sie dsa sind, dafür haben wir schon attachments! + + // TODO FIXME diese komischen accessoren sollen jetzt so zugewiesen + // werden, dass + /* + * jeder Kluftvertex soll wissen, welche Kluftedges ihm anliegen, und welche faces + * jede Kluftedge soll wissen, welche Vertizes ihr anliegen, und welche faces + * jedes Face, das an eine Kluft anliegt, soll wissen, welche Vertizes und Edges + * ihm anliegen + * letzteres muss man vielleicht noch ausdehnen, indem man subdomain indizes + * dazu bringt + * das kann auch notwendig sein fuer alle anderen - wirklich? + * die edges und faces kennen ihre subdomain + * nur beim Vertex kann in Kreuzungspunkten ein Problem sein + * zudem ist die subdomain der faces EGAL, im Zweifel entscheidet die subdomain + * der edges, die anliegen bzw der edge, die anliegt! + * + */ + +// iterate over the given fracture infos and select all fracture edges +// and fracture vertices. + for(size_t i_fi = 0; i_fi < fracInfos.size(); ++i_fi) + { + int fracInd = fracInfos[i_fi].subsetIndex; + + for(EdgeIterator iter = sh.begin(fracInd); iter != sh.end(fracInd); ++iter) + { + // mark edge and vertices + sel.select(*iter); + +#if OLD_PROFREITER_STUFF + aaMarkEDGE[*iter] = 1; +#endif + + aaMarkEdgeB[*iter] = true; + + // select associated vertices + for(size_t i = 0; i < 2; ++i) + { + Vertex* v = (*iter)->vertex(i); + sel.select(v); + + // wird in jedem Fall inkrimiert, da der Vertex auf jeden Fall mit einer Kante einer frac verbunden sein muss, sonst darf der loop gar nicht darüber gehen + aaMarkVrtVFP[v]++; + + if( IsBoundaryVertex2D(grid, v) ) + aaMarkVrtVFP[v].setIsBndFracVertex(); + + +#if OLD_PROFREITER_STUFF + // das ist Sebastians loop, den nicht mehr lassen lassen + // if fracture boundaries are expanded, we'll regard all fracture vertices + // as inner vertices + if(expandInnerFracBnds) + { + if(!expandOuterFracBnds) + { + if(IsBoundaryVertex2D(grid, v)) + aaMarkVRT[v]++; + else + aaMarkVRT[v] = 2; + } + else + aaMarkVRT[v] = 2; + } + else + aaMarkVRT[v]++; +#endif + + } + } + } + + +#if OLD_PROFREITER_STUFF +// Make sure that selected vertices that lie on the boundary of the geometry +// are treated as inner fracture vertices. +// This is only required if frac-boundaries are not expanded anyways. + if(expandOuterFracBnds && !expandInnerFracBnds){ + for(VertexIterator iter = sel.vertices_begin(); + iter != sel.vertices_end(); ++iter) + { + Vertex* v = *iter; + if(aaMarkVRT[v] == 1){ + if(IsBoundaryVertex2D(grid, v)) + aaMarkVRT[v] = 2; + } + } + } + // TODO FIXME was soll das fuer ein Kaese sein? +#endif + + int dbg_flachen_passiert = 0; + + for(VertexIterator iter = sel.begin(); iter != sel.end(); ++iter) + { + + bool wahl = true; + + + // so stimmt es vielleicht, aber ist auch ein komischer Fall, innen expandieren und aussen nicht...... die Frage ist, ob es oonst Sinn macht..... + if( expandInnerFracBnds && !expandOuterFracBnds && aaMarkVrtVFP[*iter].getIsBndFracVertex() ) + wahl = false; + + static_assert( std::is_same< decltype(*iter), Vertex * >::value ); + + bool isBnd = aaMarkVrtVFP[ *iter ].getIsBndFracVertex(); + auto numCrosFrac = aaMarkVrtVFP[ *iter ].getNumberFracEdgesInVertex(); + + if( ! isBnd && numCrosFrac == 1 ) + { + wahl = false; + } + +// if( ! dehneInnereKluftGrenzpunkteAus ) +// { +// if( numCrosFrac == 1 ) // inner frac boundary vertex +// { +// wahl = false; +// } +// } + + + if( wahl ) + { + sel.select(grid.associated_edges_begin(*iter), + grid.associated_edges_end(*iter)); + sel.select(grid.associated_faces_begin(*iter), + grid.associated_faces_end(*iter)); + + // TODO FIXME hier ein attachment der associated faces und vertizes, am besten als Klasse, die std vertizes davon frisst, an jeden Vertex anhängen + // so muss man später nicht nochmal über alle Faces und Edges laufen, sondern hat die angehängten schon zur Hand + // im Fall, dass eine Kreuzung vorliegt, das Ganze irgendwann ordnen, dass nebeneinander liegende Faces und edges in eine verkettete Liste kommen + // vielleicht das aber nur bei den Schnittvertizes später + // und vielleicht sollen die Faces Zeiger auf ihre Edges bekommen, und die edges auf die faces, aber wird irgendwann zu wild verzeigert..... + // vielleicht einfach attachment von faces und edges unabhängig an jeden Fracture Vertex...... + + // testen, ob ein Schnittvertex vor liegt, indem die Anzahl der touches getestet wird, anhand einfacher Geometrien testen, was die Anzahl ist + + // mit UG_LOG ausgeben, was die Koordinaten sind, und die Anzahl der hits + + VecFace assFac; + VecEdge assEdg; + +// UG_LOG("----------" << std::endl); + + for( std::vector::iterator iterFac = grid.associated_faces_begin(*iter); iterFac != grid.associated_faces_end(*iter); iterFac++ ) + { + assFac.push_back(*iterFac); +// vector3 facCenter = CalculateCenter( *iterFac, aaPos ); +// UG_LOG("fac center " << facCenter << std::endl); + +// sh.assign_subset(*iterFac, 10); + } + +// UG_LOG("----------" << std::endl); + + for( std::vector::iterator iterEdg = grid.associated_edges_begin(*iter); iterEdg != grid.associated_edges_end(*iter); iterEdg++ ) + { + assEdg.push_back(*iterEdg); +// sh.assign_subset(*iterEdg,10); + } + + aaVrtInfoAssoFaces[*iter] = assFac; + aaVrtInfoAssoEdges[*iter] = assEdg; + + UG_LOG("marked vertex wahl: " << aaPos[*iter] << " is bnd " << isBnd << " number cross frac " << numCrosFrac << std::endl ); + + // fuer Nicht Boundary Vertizes muessen wir durch 2 teilen, damit wir richtige Anzahl der + // Fracs haben, die durch den spezifischen Vertex durch geht + // FALSCH war mal so, ist schon abgestellt, es wird angezeigt, wieviele Ecken von Kanten rein kommen + + } + else + { + UG_LOG("marked vertex unwahl: " << aaPos[*iter] << " is bnd " << isBnd << " number cross frac " << numCrosFrac << std::endl ); + } + + } + +// return true; + + using pairIndDbl = std::pair; + + std::vector< pairIndDbl > fracSubdom_facePerpendMinVal; + + for( auto const & pf: fracInfos ) + { + fracSubdom_facePerpendMinVal.push_back( pairIndDbl( pf.subsetIndex, std::numeric_limits::max() ) ); + } + + T_min minDistPerpOverall( std::numeric_limits::max() ); + +// for( auto fI : fracInfos ) +// for( size_t fraInfInd = 0; fraInfInd < fracInfos.size(); fraInfInd++ ) + for( auto & fsfpmv : fracSubdom_facePerpendMinVal ) + { +// int fracInd = fracInfos[fraInfInd].subsetIndex; +// int fracInd = fI.subsetIndex; + + auto fracInd = fsfpmv.first; + + T_min minDistPerpThisFrac( fsfpmv.second ); + + for(EdgeIterator iterEdg = sh.begin(fracInd); iterEdg != sh.end(fracInd); iterEdg++ ) + { + + // get subdomain of edge + + auto sudoEdg = sh.get_subset_index(*iterEdg); + + static_assert( std::is_same< decltype(sudoEdg), int >::value ); + + // get vertices of edge, always 2 + + std::vector verticesEdg; + + static_assert( std::is_same< Vertex*, decltype( (*iterEdg)->vertex(0) ) >::value ); + + for( size_t i = 0; i < 2; ++i ) + verticesEdg.push_back( (*iterEdg)->vertex(i) ); + + // get attached faces + +#if 0 + std::vector assFace; + + // TODO FIXME dieser loop kann vielleicht vereinfacht werden, wenn dieser ganze loop umgebaut wird + // denn die Vertizes kennen dann die assosciated faces schon + // der Name AssociatedFaceIterator ist sowieso verwirrend, hat mit assosciated nix zu tun, bezieht sich auf alle std Vektoren von Face * + UG_LOG("XXXXXXXXXXXX" << std::endl); + for(Grid::AssociatedFaceIterator iterAFI = grid.associated_faces_begin( verticesEdg[0] ); + iterAFI != grid.associated_faces_end( verticesEdg[0] ); + iterAFI++ ) + { + + if(FaceContains( *iterAFI, *iterEdg )) + { + assFace.push_back( *iterAFI ); + + + vector3 facCenter = CalculateCenter( *iterAFI, aaPos ); + UG_LOG("fac center " << facCenter << std::endl); + + + +// sh.assign_subset( *iterAFI, sh.get_subset_index(*iterEdg)); + } + + } + UG_LOG("XXXXXXXXX" << std::endl); +#else + + std::vector & assFaceVrt0 = aaVrtInfoAssoFaces[verticesEdg[0]]; + + std::vector assFace; + +// static_assert( std::is_same< decltype( aaVrtInfoAssoFaces[verticesEdg[0]] )[0], std::vector >::value ); + //static_assert( std::is_same< decltype( *(aaVrtInfoAssoFaces[verticesEdg[0]]) ), Face * >::value ); + +// UG_LOG("XXXXXXXXXXXX" << std::endl); + + for( auto const & ifa : assFaceVrt0 ) + { + if(FaceContains( ifa, *iterEdg )) + { + assFace.push_back( ifa ); + +// vector3 facCenter = CalculateCenter( ifa, aaPos ); +// UG_LOG("fac center " << facCenter << std::endl); + } + } + + std::vector & assFaceVrt1 = aaVrtInfoAssoFaces[verticesEdg[1]]; + + for( auto const & ifa : assFaceVrt1 ) + { + if(FaceContains( ifa, *iterEdg )) + { + bool faceContained = false; + + for( auto const & afa : assFace ) + { + if( afa == ifa ) + faceContained = true; + } + + if( !faceContained ) + assFace.push_back( ifa ); + } + } + + +// UG_LOG("XXXXXXXXX" << std::endl); + +#endif + // von hier lernen: + // VecFace & assoFaces = aaVrtInfoAssoFaces[*iterV ist verticesEdg[0] ]; + // for( auto const & ifac : assoFaces ) + // { + // static_assert( std::is_same< decltype( ifac ), Face * const & >::value ); + // } + + + + // compute normal of edge + + std::vector< vector3 > edgeNormals; + + std::vector perpendDistances; + + for( auto const & fac : assFace ) + { + vector3 facCenter = CalculateCenter( fac, aaPos ); + + vector3 perpendicu; + + DropAPerpendicular(perpendicu, facCenter, aaPos[verticesEdg[0]], aaPos[verticesEdg[1]]); + + double perpendDist = VecLength( perpendicu ); // betrag perpendicu + + perpendDistances.push_back( perpendDist ); + + minDistPerpThisFrac( perpendDist ); + + + // vector from projection to center is the unnormalized normal + vector3 tmpN; + + VecSubtract(tmpN, facCenter, perpendicu ); + + VecNormalize(tmpN, tmpN); + + edgeNormals.push_back( tmpN ); + + static_assert( std::is_same< Edge*, decltype(*iterEdg) >::value ); + + static_assert( std::is_same< Face * const &, decltype(fac) >::value ); + static_assert( std::is_same< Face *, decltype( const_cast(fac) ) >::value ); + static_assert( std::is_same< vector3, decltype( tmpN ) >::value ); + + VertFracTrip infoVertizesThisEdge( *iterEdg, fac, tmpN ); + +// UG_LOG("TypE Fac " << typeid(const_cast(fac) ).name() << std::endl); +// UG_LOG("TypE Edg " << typeid( *iterEdg ).name() << std::endl); +// UG_LOG("TypE Vec " << typeid( tmpN ).name() << std::endl); + + + for( auto const & v : verticesEdg ) + { + static_assert( std::is_same< decltype(v), Vertex * const & >::value ); + static_assert( std::is_same< decltype(const_cast(v)), Vertex * >::value ); + aaVrtInfoFraTri[v].push_back( infoVertizesThisEdge ); + +// VecVertFracTrip allInfosVrtxThisEdg = aaVrtInfoFraTri[v]; + +// static_assert( std::is_same< decltype( aaVrtInfoFraTri[v] ), VecVertFracTrip >::value ); + +// UG_LOG("type Fac " << typeid( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getFace() ).name() << std::endl); +// UG_LOG("type Edg " << typeid( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getEdge() ).name() << std::endl); +// UG_LOG("type Vec " << typeid( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getNormal() ).name() << std::endl); + + static_assert( std::is_same< decltype( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getFace() ), Face * >::value ); + static_assert( std::is_same< decltype( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getEdge() ), Edge * >::value ); + static_assert( std::is_same< decltype( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getNormal() ), vector3 const >::value ); + } + + } + + // damit speichern wir die plus und minus Normale, und das ist alles, und auch + // gleich wieder weg + // TODO FIXME besser, wir speichern die gemittelte Normale an den Vertizes + // vielleihct als attachment pair, das die subdom kennt der frac und die Normale dazu? + // ziemlich nutzlos, die Normale wie hier gemacht in einen kurzen Vektor zu speichern, der schnell + // wieder weg ist...... + // wir brauchen alle Normalen zu jeder fracture an jedem fracture Vertex, also die Mittelung vermutlich + // diese Mittelung kann aber erst stattfinden, wenn wir nachher über die vertizes loopen, + // hier kennen wir nur die Vertizes, die an derselben Edge anliegen + + UG_LOG("EDGE NORMALS: " << sh.get_subset_index(*iterEdg) << " -> "); + + int j = 0; + + for( auto const & en: edgeNormals ) + { + + for( size_t i = 0; i < 3; i++ ) + UG_LOG( en[i] << ", " ); + + + UG_LOG(" --- " << perpendDistances[j] << " ///////// " ); + + j++; + } + + UG_LOG(std::endl); + + } + + fsfpmv.second = minDistPerpThisFrac(); + + minDistPerpOverall( fsfpmv.second ); + + UG_LOG("first " << fsfpmv.first << " second " << fsfpmv.second << std::endl); + } + + for( auto const & fsfpmv : fracSubdom_facePerpendMinVal ) + { + UG_LOG("min dist sd " << fsfpmv.first << " -> " << fsfpmv.second << std::endl ); + } + + UG_LOG("overall min dist " << minDistPerpOverall() << std::endl); + + + + // von Sebastian teilweise das Prinzip übernommen, dass die Faces wissen können, was ihre neuen Vertizes sein sollen + // create new vertices + + // we have to associate a vector of vertices with each node in the fracture. + // since an empty vector is quite small, we can associate one with each vertex in + // the whole grid. This could be optimized if required, by using subset attachments. + + // es reicht vielleicht, hier statt einem Vektor einfach nur einen Vertex * zu storen +// using AttVrtVec = Attachment >; + AttVrtVec attVrtVec; + + // we associate a vector of vertices for each face adjacent to the frac. + // it will store a set of vertices. An entry contains the new vertex, if the + // corresponding vertex is an inner fracture vertex, and NULL if not. + grid.attach_to_faces(attVrtVec); + Grid::FaceAttachmentAccessor aaVrtVecFace(grid, attVrtVec); + + + // iterate over all surrounding faces to enable face changes, this loop taken from SR but shortened + for(FaceIterator iter_sf = sel.faces_begin(); iter_sf != sel.faces_end(); ++iter_sf) + { + Face* sf = *iter_sf; + + std::vector& newVrts = aaVrtVecFace[sf]; + newVrts.resize(sf->num_vertices()); + + for(size_t i_vrt = 0; i_vrt < sf->num_vertices(); ++i_vrt) + { + newVrts[i_vrt] = NULL; + } + // erstmal so tun, als ob keine neuen Vertizes erzeugt werden an den alten Vertizes + } + + + // attachment to allow fracture vertizes to know the newly created vertizes + // due to extrusion which are related to them, in connection with + // the normals which are an average of the related edges and the faces + // defining the original normal + + // usage: store edges and associated faces in SAME order in std vectors! + using ExpandVertexMultiplett = VertexFractureTriple< std::vector, std::vector, vector3 >; + // holds the averaged normal of the related edges and their corresponding faces which give direction + + using VecExpandVertexMultiplett = std::vector; + + + VecExpandVertexMultiplett vertexMultiplettEmpty; + + using AttVecExpandVertexMultiplett = Attachment; + + AttVecExpandVertexMultiplett aAdjInfoVVEVM; + + grid.attach_to_vertices_dv( aAdjInfoVVEVM, vertexMultiplettEmpty ); + Grid::VertexAttachmentAccessor aaVrtExpMP(grid, aAdjInfoVVEVM ); + + + + // am Ende dieser Prozedur sollten alle Vertizes wissen, welche Tripel vom Typ Edge - Face - Normal zum Face hin an ihnen angelagert sind + + // damit weiss, wenn es stimmt, jeder Vertex, der an einer Fracture ist, wieviele Schnittpunkte von Fractures er hat, + // ob er ein boundary vertex ist, und was für einen Vektor von Tripeln an ihm angehängt sind + // die subdomain der Fracture muss anhand der subdomain der edge bestimmt werden immer + + UG_LOG("loop over all marked vertizes " << std::endl); + + int dbg_vertizesPassiert = 0; + + // jetzt können wir alle Vertizes ablaufen und an ihnen neue Vertizes erzeugen, die anhand der gemittelten Normalen von den Vertizes weg gehen + // ob zwei anhängende Faces auf der gleichen Seite liegen, wenn es kein Schnittvertex von zwei oder mehr Klüften ist + // das kann man anhand des Winkels zwischen zwei face Normalen unterscheiden vermutlich + // dabei müssen die edges sowieso disjunkt sein, sonst ist man sowieso sicher auf verschiedenen Seiten + // wenn wir es mit einem boundary Vertex zu tun haben, müssen wir weiter überlegen, wie wir die Verschiebung auf die äussere Kante projizieren + // muss auch mit dem Winkel zu tun haben + for(VertexIterator iterV = sel.begin(); iterV != sel.end(); ++iterV) + { + + // POsition dieses Vertex + vector3 posOldVrt = aaPos[*iterV]; + + // vielleicht muss man, wenn die neuen Vertizes da sind, diese auch gleich mit den umliegenden Knoten per neuer Kanten verbinden + // und die neuen faces erzeugen nach Löschen der alten? + // oder alle neuen Vertizes wie bei Prof Reiter in einen std Vektor, der als attachment den bisherigen Face Vertizes angehängt wird + // und Edge Vernichtung und Erzeugung neuer edges und faces wie bei Prof Reiter in Folgeschritten? + + VecVertFracTrip & vecVertFracTrip = aaVrtInfoFraTri[*iterV]; + + std::vector & allAssoEdges = aaVrtInfoAssoEdges[*iterV]; + + static_assert( std::is_same< decltype( vecVertFracTrip[ vecVertFracTrip.size() - 1 ].getFace() ), Face * >::value ); + static_assert( std::is_same< decltype( vecVertFracTrip[ vecVertFracTrip.size() - 1 ].getEdge() ), Edge * >::value ); + static_assert( std::is_same< decltype( vecVertFracTrip[ vecVertFracTrip.size() - 1 ].getNormal() ), vector3 const >::value ); + + for( auto const & vft : vecVertFracTrip ) + { + static_assert( std::is_same< decltype( vft.getFace() ), Face * >::value ); + static_assert( std::is_same< decltype( vft.getEdge() ), Edge * >::value ); + static_assert( std::is_same< decltype( vft.getNormal() ), vector3 const >::value ); + + Face * f = vft.getFace(); + Edge * e = vft.getEdge(); + vector3 n = vft.getNormal(); + + } + + using VvftIterator = VecVertFracTrip::iterator; + + VecFace & assoFaces = aaVrtInfoAssoFaces[*iterV]; + // TODO FIXME hier braucht man das nicht zu ordnen + // aber bei Kreuzpunkten von Klueften muss es so geordnet werden, wie es nebeneinander liegt + // bei den Edges gibt es auch die benachbarten, und die edges haben das attachment, ob sie Kluftedges sind + +// for( auto const & ifac : assoFaces ) +// { +// static_assert( std::is_same< decltype( ifac ), Face * const & >::value ); +// } + + + + // Anzahl der Kreuzungspunkte auslesen und danach unterscheiden, erstmal keine Kreuzung! TODO FIXME + + // irgendwie muessen wir diese Infos jetzt verwerten, um als erstes neue Vertizes zu erzeugen, anfangs für eine Kluft nur + // und danach die alten Edges und faces löschen und an neuer Stelle neu erzeugen, plus die sowieso neuen, + // oder Edges verschieben, wenn es möglich ist, die Vertizes zu verschieben, und die Edges und in Folge faces passen sich an, + // dann müssen nur die neuen edges und faces neu erzeugt werden + // verschieben der Position des Vertex löst Kaskade aus, dass Edge und Face auch verschoben werden, kann also angewendet werden + // allerdings Problem, dass die Vertizes dafür verdoppelt werden müssen und die Kanten, sonst kann man sie nicht nach aussen verschieben + // also doch komplette Neuerzeugung vermutlich..... oder doppeltes Klonen, und das alte bleibt in der Mitte..... + + vector3 posThisVrt = aaPos[*iterV]; + + UG_LOG("vertex at " << posThisVrt << std::endl ); + + bool vrtxIsBndVrt = aaMarkVrtVFP[*iterV].getIsBndFracVertex(); + // alternativ wäre möglich: IsBoundaryVertex2D(grid, *iterV) + + UG_LOG("is bndry " << vrtxIsBndVrt << std::endl); + + IndexType numFracsCrossAtVrt = aaMarkVrtVFP[*iterV].getNumberFracEdgesInVertex(); + + UG_LOG("number crossing fracs " << numFracsCrossAtVrt << std::endl); + + size_t numbAttTripl = vecVertFracTrip.size(); + + UG_LOG("sizes of vft " << numbAttTripl << std::endl ); + + if( ! vrtxIsBndVrt ) + { + + if( numFracsCrossAtVrt < 1 ) + { + UG_THROW("no fracs crossing but marked vertex? << std::endl"); + } + else if( numFracsCrossAtVrt == 1 ) + { + +// if( numbAttTripl != 0 ) +// { +// UG_THROW("Anzahl der angehaengten Triples kann nicht stimmen, Vertex einer Kluft ohne Schnittpunkte, nicht am Rand, Kluftende " << std::endl); +// } + + + + UG_LOG("END THIS VERTEX NORMAL INNER ENDING CLEFT" << std::endl); + + +// if( ! dehneInnereKluftGrenzpunkteAus ) +// { +// break; +// } + // inner vertex where fracture ends + // TODO FIXME + + // in this case, we have two attached edges, and each of these edges has two attached faces + // the faces have a naormal, and based on the normal, we can decide which faces belong to the same side of the edges + +#if 0 + + if( numbAttTripl != 2 ) + { + UG_THROW("Anzahl der angehaengten Triples kann nicht stimmen, Vertex einer Kluft ohne Schnittpunkte, nicht am Rand, Kluftende " << std::endl); + } + + // Zuordnung der Edges und Faces, die auf der gleichen Seite der fracture sind + + // und gleich auch Erzeugung der neuen Knoten, die dann + // in einem Doublett zusammen mit ihren Normalen an die alten Vertizes + // angehängt werden; der Winkel zur Normalen hilft später, die Seite + // heraus zu finden, Seite von den Edges + + int dbg_iteratorAblaufen = 0; + + +#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX + + int dbg_laenge = 0; + + for( auto const & vft : vecVertFracTrip ) + { + dbg_laenge++; + + UG_LOG("VERTEXFRACTRIP" << std::endl); + + vector3 ve = vft.getNormal(); + + UG_LOG("NORMAL " << ve << std::endl); + + UG_LOG("laenge " << dbg_laenge << std::endl ); + } + + int dbg_laenge_eins = 0; + +#endif + + + + for( VvftIterator vvftV = vecVertFracTrip.begin(); + vvftV != vecVertFracTrip.end(); + vvftV++ + ) + { + +#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX + dbg_laenge_eins++; + + if( dbg_laenge_eins > dbg_laenge ) + { + break; + } + +#endif + + vector3 nV = vvftV->getNormal(); + + Edge * edgeV = vvftV->getEdge(); + + + +#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX + + UG_LOG("NORMAL " << vvftV->getNormal() << std::endl); + UG_LOG("LAENGE EINZ " << dbg_laenge_eins << std::endl ); +#endif + + Vertex * nextFracVrt; + + IndexType foundThisVrt = 0; + + for( size_t i = 0; i < 2; ++i ) + { + Vertex * vrtEdgEnd = edgeV->vertex(i); + + if( vrtEdgEnd == *iterV ) + { + foundThisVrt++; + } + else + { + nextFracVrt = vrtEdgEnd ; + } + + } + + if( foundThisVrt != 1 ) + { + UG_THROW("zu viel zu wenig vertizex one " << std::endl); + } + + + + // Klasse schreiben, die als attachment an einen Fracture-Vertex + // die neuen Vertizes samt ihrer gemittelten Normalen speichert + // also std::vector von dieser neuen Klasse als Vertex attachment + + std::vector attEdg; + std::vector attFac; + + attEdg.push_back( edgeV ); + + Face * facV = vvftV->getFace(); + + attFac.push_back( facV ); + + // jetzt neuen Vertex erzeugen in Richtung der Normalen + // sonst ist das attachment Schwachsinn! + + vector3 posNewVrt; + + vector3 moveVrt; + + auto subsIndEdgV = sh.get_subset_index(edgeV); + + number width = fracInfosBySubset.at(subsIndEdgV).width; + +// if( expandInnerFracBnds ) +// { +// // der Faktor ist Käse und muss noch aus den Eingaben übernommen werden +// VecScale(moveVrt, nV, width/2. ); +// } +// else +// { +// // auf Annes Wunsch hin werden die Normalen innendrin an einer endenen Kluft zu Null gesetzt +// +// VecScale(moveVrt, nV, 0. ); +// +// } + + VecScale(moveVrt, nV, width/2. ); + + VecAdd(posNewVrt, posOldVrt, moveVrt ); + + UG_LOG("neuer Vertex " << posNewVrt << std::endl ); + + // TODO FIXME hier ist das PROBLEM, SEGFAULT durch create regular vertex + + + + Vertex * newShiftVrtx = *grid.create(); + aaPos[newShiftVrtx] = posNewVrt; + + sh.assign_subset(newShiftVrtx, subsIndEdgV ); + + + + // fuer was braucheh wir das eigentlich? selber schon vergessen..... + + ExpandVertexMultiplett vrtMtpl( attEdg, attFac, nV ); + + aaVrtExpMP[ *iterV ].push_back( vrtMtpl ); + + + + // alle anhängenden faces müssen noch zu wissen bekommen + // dass es diesen neuen Vertex gibt, nicht nur die + // an den edges anhängenden + // vielleicht gibt es einen Loop über attached faces des + // Vertex, für die schon bekannten direkt angehängten klar + // wenn auch dort vermerkt werden muss im Attachment von Seb + // bei den anderen, die keine Edge haben von der Kluft + // da muss man die Normale ins Zentrum bestimmen + // um heraus zu finden, ob sie auf dieser seite sind + // am besten dann das Attachment der faces für vertizes + // von Seb recyclen + + // loop über assosciated faces des vertex am besten + // vermutlich auch noch assosciated edges, um + // zu markieren, welche weg fallen sollen, wenn + // nicht von Kluft selber, sondern quasi verschoben + // und neu erzeugt + + int dbg_FaceIterator = 0; + + + + for( auto const & ifac : assoFaces ) + { + bool isFromFrac = false; + + for( auto const & facFrac : attFac ) + { + +// static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype ( ifac ) >::value ); + static_assert( std::is_same< decltype( (facFrac) ), decltype ( ifac ) >::value ); + + if( ifac == facFrac ) + { + isFromFrac = true; + +// static_assert( std::is_same< decltype( const_cast(facFrac) ), Face * & >::value ); + static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value ); +// static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype( ifac ) >::value ); + static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value ); + + } + } + + + bool atRightSide = false; + + if( isFromFrac ) + atRightSide = true; + + if( !isFromFrac ) + { + // check if on same side of edge where the normal points to: compute cosinus between vector of face center + // perpendicular to the edge + + + + + vector3 facCenter = CalculateCenter( ifac, aaPos ); + + vector3 perpendicu; + + +// UG_LOG("pos 0 " << aaPos[nextFracVrt[0]] << std::endl); +// UG_LOG("pos 1 " << aaPos[*iterV] << std::endl); +// UG_LOG("fac ce " << facCenter << std::endl); + + DropAPerpendicular(perpendicu, facCenter, aaPos[nextFracVrt], aaPos[*iterV]); + +// if( dbg_FaceIterator == 1 ) +// { +// UG_LOG("huhu a0" << std::endl); +// return true; +// } + + + vector3 tmpN; + + VecSubtract(tmpN, facCenter, perpendicu ); + + VecNormalize(tmpN, tmpN); + + UG_LOG("Normale zum Face ist " << tmpN << std::endl); + + number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, nV ); + + UG_LOG("Cosinus zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); + +// if( dbg_FaceIterator == 1 ) +// { +// UG_LOG("huhu a" << std::endl); +//// return true; +// } + + + if( cosBetwFracEdgAndDirection2Face > 0 ) + { + UG_LOG("assuming face to be on richt side" << std::endl); + + atRightSide = true; + +#if ANSCHAULICH_ERZEUGE_SUDOS_ANHANG + + Vertex * otherFacCent = *grid.create(); + aaPos[otherFacCent] = facCenter; + sh.assign_subset(otherFacCent, 6 ); + + Vertex * pp = *grid.create(); + aaPos[pp] = perpendicu; + sh.assign_subset(pp, 7 ); + + sh.assign_subset(ifac,8); + +#endif + + } + else + { + UG_LOG("assuming face to be on wrong side" << std::endl); + } + + + dbg_flachen_passiert++; + } + + +// if( dbg_FaceIterator == 1 ) +// { +// UG_LOG("huhu b" << std::endl); +//// return true; +// } + + + + if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein + { + + // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! + vector& newVrts4Fac = aaVrtVecFace[ ifac ]; + + IndexType vrtxFnd = 0; + + for(size_t indVrt = 0; indVrt < (ifac)->num_vertices(); indVrt++ ) + { + Vertex* facVrt = (ifac)->vertex(indVrt); + + if( facVrt == *iterV ) + { + newVrts4Fac[ indVrt ] = newShiftVrtx; + vrtxFnd++; + } + } + + + if( vrtxFnd <= 0 ) + { + UG_THROW("vertex not found!" << std::endl); + } + else if( vrtxFnd > 1 ) + { + UG_THROW("vertex zu oft gefunden " << vrtxFnd << std::endl ); + } + else if ( vrtxFnd == 1 ) + { + } + else + { + UG_THROW("vertex finden komisch " << std::endl); + } + + + } + + dbg_FaceIterator++; + + } + + + + + + + + + } + + + + dbg_iteratorAblaufen++; + + + +// // Ziel: die beiden parallelen Normalen mitteln, und in die jeweiligen beiden Richtungen je einen neuen Vertex erzeugen +// // irgendwie muss der Vertex oder die Edge besser sogar wissen, dass sie einen neuen Verschiebevertex bekommen hat +// // denn später müssen neue Edges und neue Faces basierend auf den neuen Vertizes erzeugt werden +// // vielleicht braucht die edge und das face ein Attachment, das ihnen das sagt, ähnlihc wie VertexTrible std Vektoren? +// +// +// + UG_LOG("END THIS VERTEX NORMAL INNER ENDING CLEFT" << std::endl); + +#endif + + +// return true; + + + } + else if( numFracsCrossAtVrt == 2 ) // free line of fracture, no crossing point, not at boundary + { + // in this case, we have two attached edges, and each of these edges has two attached faces + // the faces have a naormal, and based on the normal, we can decide which faces belong to the same side of the edges + + + if( numbAttTripl != 4 ) + { + + UG_LOG("NUMBER OF TRIPLETTS " << numbAttTripl << std::endl); + +// return true; + + UG_THROW("Anzahl der angehaengten Triples kann nicht stimmen, Vertex einer Kluft ohne Schnittpunkte, nicht am Rand " << std::endl); + } + + // Zuordnung der Edges und Faces, die auf der gleichen Seite der fracture sind + + // und gleich auch Erzeugung der neuen Knoten, die dann + // in einem Doublett zusammen mit ihren Normalen an die alten Vertizes + // angehängt werden; der Winkel zur Normalen hilft später, die Seite + // heraus zu finden, Seite von den Edges + + + + int dbg_iteratorAblaufen = 0; + +#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX + + int dbg_laenge = 0; + + for( auto const & vft : vecVertFracTrip ) + { + dbg_laenge++; + + UG_LOG("VERTEXFRACTRIP" << std::endl); + + vector3 ve = vft.getNormal(); + + UG_LOG("NORMAL " << ve << std::endl); + + UG_LOG("laenge " << dbg_laenge << std::endl ); + } + + + UG_LOG("SINGLE" << std::endl); + + + for( VvftIterator vvftOne = vecVertFracTrip.begin(); + vvftOne != vecVertFracTrip.end() - 1; + vvftOne++ + ) + { + + + Edge * edgeOne = vvftOne->getEdge(); + vector3 nOne = vvftOne->getNormal(); + + + for( VvftIterator vvftTwo = vvftOne + 1; + vvftTwo != vecVertFracTrip.end(); + vvftTwo++ + ) + { + Edge * edgeTwo = vvftTwo->getEdge(); + vector3 nTwo = vvftTwo->getNormal(); + + number cosinus = VecDot( nOne, nTwo ); + if( edgeOne != edgeTwo ) + { + UG_LOG("COSI between " << nOne << " and " << nTwo << " -> " << cosinus << std::endl ); + } + + } + } + + UG_LOG("SINGLE END" << std::endl); + + int dbg_laenge_eins = 0; + +#endif + + + for( VvftIterator vvftOne = vecVertFracTrip.begin(); + vvftOne != vecVertFracTrip.end() - 1; + vvftOne++ + ) + { + +#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX + dbg_laenge_eins++; + + if( dbg_laenge_eins > dbg_laenge ) + { + break; + } + + int dbg_laenge_zwei = dbg_laenge_eins; +#endif + int dbg_zweiterIteratorAblaufen = 0; + + vector3 nOne = vvftOne->getNormal(); + + Edge * edgeOne = vvftOne->getEdge(); + + + + for( VvftIterator vvftTwo = vvftOne + 1; + vvftTwo != vecVertFracTrip.end(); + vvftTwo++ + ) + { + +#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX + dbg_laenge_zwei++; + + if( dbg_laenge_zwei > dbg_laenge ) + { + break; + } + + UG_LOG("NORMAL ONE " << vvftOne->getNormal() << std::endl); + UG_LOG("NORMAL TWO " << vvftTwo->getNormal() << std::endl); + UG_LOG("LAENGE EINZ ZWO " << dbg_laenge_eins << " " << dbg_laenge_zwei << std::endl ); +#endif + + // dieselben brauchen wir nicht vergleichen + if( vvftOne == vvftTwo ) + { + // sollte nie vorkommen! + UG_THROW("Unsinn " << std::endl); + } + else + { + + Edge * edgeTwo = vvftTwo->getEdge(); + + // noch testen, ob nicht die Kante dieselbe ist, geht das? + // bei der gleichen Ecke ist es unnötig, da es gegensätzlich sein muss + + + + if( edgeOne != edgeTwo ) + { + + std::vector nextFracVrt; + + IndexType foundThisVrtOne = 0; + + for( size_t i = 0; i < 2; ++i ) + { + Vertex * vrtEdgEnd = edgeOne->vertex(i); + + if( vrtEdgEnd == *iterV ) + { + foundThisVrtOne++; + } + else + { + nextFracVrt.push_back( vrtEdgEnd ); + } + + } + + if( foundThisVrtOne != 1 ) + { + UG_THROW("zu viel zu wenig vertizex one " << std::endl); + } + + + IndexType foundThisVrtTwo = 0; + + for( size_t i = 0; i < 2; ++i ) + { + Vertex * vrtEdgEnd = edgeTwo->vertex(i); + + if( vrtEdgEnd == *iterV ) + { + foundThisVrtTwo++; + } + else + { + nextFracVrt.push_back( vrtEdgEnd ); + } + + } + + if( foundThisVrtTwo != 1 ) + { + UG_THROW("zu viel zu wenig vertizex two " << std::endl); + } + + + + vector3 nTwo = vvftTwo->getNormal(); + + number cosinus = VecDot( nOne, nTwo ); + +// bool vz = ! std::signbit(cosinus); + + UG_LOG("cosinus " << dbg_vertizesPassiert << " between " << nOne << " and " << nTwo << " -> " << cosinus << std::endl ); + //UG_LOG("sign between " << nOne << " and " << nTwo << " -> " << vz << std::endl ); + + + + if( cosinus > 0 ) + { + // gleiche Seite vermutet + + // sind die edges dieselben? pruefen! gleiche unnoetig - wird oben schon abgefragt + + // Klasse schreiben, die als attachment an einen Fracture-Vertex + // die neuen Vertizes samt ihrer gemittelten Normalen speichert + // also std::vector von dieser neuen Klasse als Vertex attachment + +#if 1 + + Face * facOne = vvftOne->getFace(); + Face * facTwo = vvftTwo->getFace(); + + expandSingleFractureAtGivenSide( nOne, nTwo, + edgeOne, edgeTwo, + facOne, facTwo, + fracInfosBySubset, + posOldVrt, + aaPos, + grid, sh, + assoFaces + , + nextFracVrt, + aaVrtVecFace, + dbg_flachen_passiert, + *iterV + ); + +#else + + // average the normals + + vector3 normSum; + + VecAdd( normSum, nOne, nTwo ); + + vector3 normSumNormed; + + VecNormalize(normSumNormed, normSum); + + UG_LOG("averaged normal " << normSumNormed << std::endl); + + std::vector attEdg; + std::vector attFac; + + attEdg.push_back( edgeOne ); + attEdg.push_back( edgeTwo ); + +// Face * facOne = vvftOne->getFace(); +// Face * facTwo = vvftTwo->getFace(); + + attFac.push_back( facOne ); + attFac.push_back( facTwo ); + + // jetzt neuen Vertex erzeugen in Richtung der Normalen + // sonst ist das attachment Schwachsinn! + + vector3 posNewVrt; + + vector3 moveVrt; + + auto subsIndEdgOne = sh.get_subset_index(edgeOne); + + auto subsIndEdgTwo = sh.get_subset_index(edgeTwo); + + + if( subsIndEdgOne != subsIndEdgTwo ) + { + UG_THROW("subsets passen nicht" << std::endl ); + } + + + + + number width = fracInfosBySubset.at(subsIndEdgOne).width; + + // der Faktor ist Käse und muss noch aus den Eingaben übernommen werden + VecScale(moveVrt, normSumNormed, width/2. ); + + VecAdd(posNewVrt, posOldVrt, moveVrt ); + + UG_LOG("neuer Vertex " << posNewVrt << std::endl ); + + // TODO FIXME hier ist das PROBLEM, SEGFAULT durch create regular vertex + + Vertex * newShiftVrtx = *grid.create(); + aaPos[newShiftVrtx] = posNewVrt; + + sh.assign_subset(newShiftVrtx, subsIndEdgOne ); + + + + // fuer was braucheh wir das eigentlich? selber schon vergessen..... + + ExpandVertexMultiplett vrtMtpl( attEdg, attFac, normSumNormed ); + + aaVrtExpMP[ *iterV ].push_back( vrtMtpl ); + + + + // alle anhängenden faces müssen noch zu wissen bekommen + // dass es diesen neuen Vertex gibt, nicht nur die + // an den edges anhängenden + // vielleicht gibt es einen Loop über attached faces des + // Vertex, für die schon bekannten direkt angehängten klar + // wenn auch dort vermerkt werden muss im Attachment von Seb + // bei den anderen, die keine Edge haben von der Kluft + // da muss man die Normale ins Zentrum bestimmen + // um heraus zu finden, ob sie auf dieser seite sind + // am besten dann das Attachment der faces für vertizes + // von Seb recyclen + + // loop über assosciated faces des vertex am besten + // vermutlich auch noch assosciated edges, um + // zu markieren, welche weg fallen sollen, wenn + // nicht von Kluft selber, sondern quasi verschoben + // und neu erzeugt + + int dbg_FaceIterator = 0; + +#if 0 +// for( auto iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ ) + for( std::vector::iterator iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ ) + { + bool isFromFrac = false; + +// for( std::vector::iterator iterF2 = attFac.begin(); iterF2 != attFac.end(); iterF2++ ) +// { +// static_assert( std::is_same< decltype( *iterF2 ), decltype ( *iterFac ) >::value ); +// +// } + + int dbg_innterFacFracIt = 0; + + for( auto const & facFrac : attFac ) + { + + +// UG_LOG("type iter facFrac " << typeid( facFrac ).name() << std::endl); +// +// UG_LOG("type iter Fac " << typeid( *iterFac ).name() << std::endl); + + static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype ( *iterFac ) >::value ); + + + + + if( *iterFac == facFrac ) + { + isFromFrac = true; + + static_assert( std::is_same< decltype( const_cast(facFrac) ), Face * & >::value ); + static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype( * iterFac ) >::value ); + + } + } + + bool atRightSide = false; + + if( isFromFrac ) + atRightSide = true; + + if( !isFromFrac ) + { + // check if on same side of edge where the normal points to: compute cosinus between vector of face center + // perpendicular to the edge + // TODO FIXME + // KAESE!!! + + vector3 facCenter = CalculateCenter( *iterFac, aaPos ); + + vector3 perpendicu; + + if( nextFracVrt.size() != 2 ) + { + UG_THROW("komische Groesse" << std::endl); + } + + DropAPerpendicular(perpendicu, facCenter, aaPos[nextFracVrt[0]], aaPos[nextFracVrt[1]]); + + vector3 tmpN; + + VecSubtract(tmpN, facCenter, perpendicu ); + + VecNormalize(tmpN, tmpN); + + UG_LOG("Normale zum Face ist " << tmpN << std::endl); + + number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, normSumNormed ); + + UG_LOG("Cosinus zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); + + if( cosBetwFracEdgAndDirection2Face > 0 ) + { + UG_LOG("assuming face to be on richt side" << std::endl); + + atRightSide = true; + +#if ANSCHAULICH_ERZEUGE_SUDOS_ANHANG + + Vertex * otherFacCent = *grid.create(); + aaPos[otherFacCent] = facCenter; + sh.assign_subset(otherFacCent, 5 ); + + Vertex * pp = *grid.create(); + aaPos[pp] = perpendicu; + sh.assign_subset(pp, 6 ); + + sh.assign_subset(*iterFac,7); +#endif + + } + else + { + UG_LOG("assuming face to be on wrong side" << std::endl); + } + +// if( dbg_flachen_passiert == 0 ) +// { +// UG_LOG("passiert " << dbg_flachen_passiert << std::endl); +// +// Vertex * otherFacCent = *grid.create(); +// aaPos[otherFacCent] = facCenter; +// sh.assign_subset(otherFacCent, 5 ); +// +// Vertex * pp = *grid.create(); +// aaPos[pp] = perpendicu; +// sh.assign_subset(pp, 6 ); +// +// sh.assign_subset(*iterFac,7); +// +// +// sh.assign_subset(*iterFac,3); +// +// UG_LOG("is from frac " << isFromFrac << std::endl); +// +// return true; +// } + + + dbg_flachen_passiert++; + } + + + if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein + { + + + // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! + vector& newVrts4Fac = aaVrtVecFace[ * iterFac ]; + + IndexType vrtxFnd = 0; + + for(size_t indVrt = 0; indVrt < (*iterFac)->num_vertices(); indVrt++ ) + { + Vertex* facVrt = (*iterFac)->vertex(indVrt); + + if( facVrt == *iterV ) + { + newVrts4Fac[ indVrt ] = newShiftVrtx; + // UG_LOG("vertex found " << indVrt << std::endl ); + vrtxFnd++; + } + } + + + if( vrtxFnd <= 0 ) + { + UG_THROW("vertex not found!" << std::endl); + } + else if( vrtxFnd > 1 ) + { + UG_THROW("vertex zu oft gefunden " << vrtxFnd << std::endl ); + } + else if ( vrtxFnd == 1 ) + { + // UG_LOG("vertex found abgeschlossen" << std::endl); + } + else + { + UG_THROW("vertex finden komisch " << std::endl); + } + + + } + + dbg_innterFacFracIt++; + + + +// +// +// if( ! isFromFrac ) +// { +// // Vektor zum Zentrum von KNoten aus berechnen und Winkel zur Normalen bestimmen zur Unterscheidung der Seite +// // wenn auf richtiger Seite, zuweisen +// } + + dbg_FaceIterator++; + + } +#else +// std::vector & assFaceVrt = aaVrtInfoAssoFaces[*iterV]; + + // VecFace & assoFaces = aaVrtInfoAssoFaces[*iterV]; + // TODO FIXME hier braucht man das nicht zu ordnen + // aber bei Kreuzpunkten von Klueften muss es so geordnet werden, wie es nebeneinander liegt + // bei den Edges gibt es auch die benachbarten, und die edges haben das attachment, ob sie Kluftedges sind + + // for( auto const & ifac : assoFaces ) + // { + // static_assert( std::is_same< decltype( ifac ), Face * const & >::value ); + // + // // TODO FIXME folgenden loop durch diesen ersetzen + // // Achtung: Zeigerproblematik, Referenzen, etc..... + // // *iterFac ersetzen durch ifac vermutlich, aber wer weiss + // } + + + // for( auto iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ ) + //for( std::vector::iterator iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ ) + for( auto const & ifac : assoFaces ) + { + bool isFromFrac = false; + + + int dbg_innterFacFracIt = 0; + + for( auto const & facFrac : attFac ) + { + +// static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype ( ifac ) >::value ); + static_assert( std::is_same< decltype( (facFrac) ), decltype ( ifac ) >::value ); + + if( ifac == facFrac ) + { + isFromFrac = true; + +// static_assert( std::is_same< decltype( const_cast(facFrac) ), Face * & >::value ); + static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value ); +// static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype( ifac ) >::value ); + static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value ); + + } + } + + bool atRightSide = false; + + if( isFromFrac ) + atRightSide = true; + + if( !isFromFrac ) + { + // check if on same side of edge where the normal points to: compute cosinus between vector of face center + // perpendicular to the edge + + vector3 facCenter = CalculateCenter( ifac, aaPos ); + + vector3 perpendicu; + + if( nextFracVrt.size() != 2 ) + { + UG_THROW("komische Groesse" << std::endl); + } + + DropAPerpendicular(perpendicu, facCenter, aaPos[nextFracVrt[0]], aaPos[nextFracVrt[1]]); + + vector3 tmpN; + + VecSubtract(tmpN, facCenter, perpendicu ); + + VecNormalize(tmpN, tmpN); + + UG_LOG("Normale zum Face ist " << tmpN << std::endl); + + number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, normSumNormed ); + + UG_LOG("Cosinus zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); + + if( cosBetwFracEdgAndDirection2Face > 0 ) + { + UG_LOG("assuming face to be on richt side" << std::endl); + + atRightSide = true; + +#if ANSCHAULICH_ERZEUGE_SUDOS_ANHANG + + Vertex * otherFacCent = *grid.create(); + aaPos[otherFacCent] = facCenter; + sh.assign_subset(otherFacCent, 5 ); + + Vertex * pp = *grid.create(); + aaPos[pp] = perpendicu; + sh.assign_subset(pp, 6 ); + + sh.assign_subset(*iterFac,7); +#endif + + } + else + { + UG_LOG("assuming face to be on wrong side" << std::endl); + } + + + dbg_flachen_passiert++; + } + + + if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein + { + + // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! + vector& newVrts4Fac = aaVrtVecFace[ ifac ]; + + IndexType vrtxFnd = 0; + + for(size_t indVrt = 0; indVrt < (ifac)->num_vertices(); indVrt++ ) + { + Vertex* facVrt = (ifac)->vertex(indVrt); + + if( facVrt == *iterV ) + { + newVrts4Fac[ indVrt ] = newShiftVrtx; + vrtxFnd++; + } + } + + + if( vrtxFnd <= 0 ) + { + UG_THROW("vertex not found!" << std::endl); + } + else if( vrtxFnd > 1 ) + { + UG_THROW("vertex zu oft gefunden " << vrtxFnd << std::endl ); + } + else if ( vrtxFnd == 1 ) + { + } + else + { + UG_THROW("vertex finden komisch " << std::endl); + } + + + } + + dbg_innterFacFracIt++; + + + + dbg_FaceIterator++; + + } + +#endif + +#endif + + } + else + { + // andere Seite vermutet, nichts tun! + } + + + + } + + + } + + dbg_zweiterIteratorAblaufen++; + + } + + dbg_iteratorAblaufen++; + + } + + +// // Ziel: die beiden parallelen Normalen mitteln, und in die jeweiligen beiden Richtungen je einen neuen Vertex erzeugen +// // irgendwie muss der Vertex oder die Edge besser sogar wissen, dass sie einen neuen Verschiebevertex bekommen hat +// // denn später müssen neue Edges und neue Faces basierend auf den neuen Vertizes erzeugt werden +// // vielleicht braucht die edge und das face ein Attachment, das ihnen das sagt, ähnlihc wie VertexTrible std Vektoren? +// +// +// + + + UG_LOG("END THIS VERTEX NORMAL COSINE" << std::endl); + + + + } + else // two fractures completely crossing, numFracsCrossAtVrt >= 3, i.e. T crossing and two fractures completely crossing + { + + // TODO FIXME in case of three fractures, we have to use the method for eine durchgehende fracture + // auf der Seite, wo die zweite fracture NICHT rein geht + + IndexType countedCrossingFracEdgs = 0; + + // TODO FIXME kreuzende Fractures im Innenraum -> Arte in Reinform implementieren + + // verkettete Liste der anhängenden fractures in Reihenfolge + // der Anhängung mit INfo, ob eine Kluft vorliegt + + for( auto const & attVFT : vecVertFracTrip ) + { + Edge * edg = attVFT.getEdge(); + Face * fac = attVFT.getFace(); + vector3 nv = attVFT.getNormal(); + } + +// // hier werden ALLE attached Faces benötigt, auch die, die zwischen den direkt an den fractures liegenden Faces sind +// + // copies of all faces and of fractured ones + auto vVFT = vecVertFracTrip; // caution: COPY, not reference! + auto aF = assoFaces; // caution: COPY, not reference! + + UG_LOG("Gesamtanzahl faces um Knoten " << aF.size() << std::endl ); + + // erstmal die ganzen anhaengenden Faces ordnen, dass wir wissen, in welcher Reihenfolge wir durchlaufen muessen + // jede Edge hat ein bool attachment schon, das weiss, ob sie Fracture edge ist oder nicht + // Reihenfolge der faces und die edges auch dazu, vielleicht neues Triple oder dergleiche, dabei zwei edges und zwei normals + // und wie gesagt, die edges wissen, ob sie fractures sind, dazu keine neuen Variablen notwendig + + using VertexOfFaceInfo = VertexFractureTriple< std::pair, Face*, std::pair >; + // all edges of the attached face - must always be two, the face itself, and the normal vectors of the face in direction of the two edges + // the size of the normal vector vector also must be two + // however, if an edge of the face is not a fracture edge, we do not compute the normal, but assign zero as norm + // for those edges and faces which are Kluft edges, we assign the normal known from the info computed before, vertex fracture triple + + using VecVertexOfFaceInfo = std::vector; + + VecVertexOfFaceInfo orderedFaces; + + using SegmentsFractExtrus = std::vector; + + SegmentsFractExtrus segments; + // single components always from one fracture edge to the next one + + VecVertexOfFaceInfo segmentPart; + + // note: we do not attach this info to the vertex, as we only need it local; in principle, in case of further need, it would + // be usful to establish some sort of attachment + + if( vVFT.size() == 0 ) + UG_THROW("vertex frac triple zu klein an Kreuzung " << std::endl); + + // we start with the first fracture face edge stuff, copy it, and delete this immidiately + VertFracTrip startVertFracTrip = vVFT[0]; + + vVFT.erase(vVFT.begin()); + + bool atFirstTriple = true; + + Face* fracFac = startVertFracTrip.getFace(); + Edge* fracEdg = startVertFracTrip.getEdge(); + vector3 fracNorm = startVertFracTrip.getNormal(); + + Edge* originalStartEdge = startVertFracTrip.getEdge(); + + if( fracEdg != 0 ) + { + countedCrossingFracEdgs++; + } + + // do not change this pointer + Edge* startEdg = fracEdg; + Face* startFace = fracFac; + + vector3 startNormal = fracNorm; + + Face* nextFace = NULL; + + UG_LOG("Gesamtanzahl faces um Knoten vor while " << aF.size() << std::endl ); + + + while( aF.size() != 0 ) + { + + UG_LOG("Gesamtanzahl faces um Knoten Anfang while " << aF.size() << std::endl ); + + + Face* face2Append = startFace; + Edge* startEdg2Append = startEdg; + + + IndexType fndCommEdg = 0; + vector3 nuVe(0,0,0); + + Edge* nextEdge = NULL; + + std::pair edge2Append( startEdg2Append, nextEdge ); + std::pair normal2Append( startNormal, nuVe ); + + + // if start face and start edge from a triple, then has to be erased this triple, exept for the entire start, as already erased + if( ! atFirstTriple ) + { + for( VecVertFracTrip::iterator itAttVFT = vVFT.begin(); itAttVFT != vVFT.end(); itAttVFT++ ) + { + auto vft = *itAttVFT; + + Edge * edgIt = vft.getEdge(); + + Face * facIt = vft.getFace(); + + if( edgIt == startEdg && facIt == startFace ) + { + // the first edge if from a fracture and the face is connected to it + + vVFT.erase(itAttVFT); + + normal2Append.first = vft.getNormal(); + + if( ! FaceContains( facIt, startEdg )) + { + UG_THROW("Face does not contain start edge of its edge" << std::endl); + } + + break; + } + } + + } + else // we can save the investigation if we have a triple, and we do not need to erase, as already erased..... + { + atFirstTriple = false; + } + + + for( auto const & iE : allAssoEdges ) // werden nicht gelöscht, deswegen Zugriff auf attachment direkt + { + if( FaceContains(face2Append, iE) ) + { + fndCommEdg++; + + if( iE != startEdg ) + { + nextEdge = iE; + + edge2Append.second = iE; + + } + } + + + } + + if( fndCommEdg != 2 ) + { + UG_THROW("komische Anzahl gemeinsamer Ecke " << fndCommEdg << std::endl); + } + + if( nextEdge == NULL ) + { + UG_THROW("wieso keine zweite Ecke gefunden???? " << std::endl); + } + + if( edge2Append.first == NULL || edge2Append.second == NULL ) + { + UG_THROW("null immer noch?" << std::endl); + } + + // erase the face from the list + + IndexType faceFound = 0; + + for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ ) + { + Face * iFa = *itFac; + + if( iFa == startFace && FaceContains( iFa, nextEdge ) && FaceContains(iFa, startEdg)) + { + faceFound++; + } + } + + int totalSubsNum = sh.num_subsets(); + + int newSubsToAdd = totalSubsNum; + + if( faceFound != 1 ) + { + + + sh.assign_subset(startFace,newSubsToAdd++); + sh.assign_subset(startEdg,newSubsToAdd++); + sh.assign_subset(nextEdge,newSubsToAdd++); + + int faNum = aF.size(); + + UG_LOG("Gesamtzahl faces vor Absturz " << faNum << std::endl); + + UG_LOG("Gesicht in falscher Anztahl gefunden " << faceFound << std::endl); + +// return true; + + + + UG_THROW("Gesicht in falscher Anztahl gefunden " << faceFound << std::endl); + } + else + { +// sh.assign_subset(startFace,newSubsToAdd++); +// sh.assign_subset(startEdg,newSubsToAdd++); +// sh.assign_subset(nextEdge,newSubsToAdd++); + + int faNum = aF.size(); + + UG_LOG("Gesamtzahl faces ohne Absturz " << faNum << std::endl); + + } + + for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ ) + { + Face * iFa = *itFac; + + if( iFa == startFace && FaceContains( iFa, nextEdge ) && FaceContains(iFa, startEdg) ) + { + aF.erase(itFac); + break; + } + } + + + + + bool sndEdgIsFracEdgeAlso = aaMarkEdgeB[nextEdge]; + + bool tripFound = false; + + if( sndEdgIsFracEdgeAlso ) + { + + if( nextEdge != originalStartEdge ) + countedCrossingFracEdgs++; + + // we need to have a look for the next triple + + // check if the next normal is a frac normal which contains the face as well + + for( VecVertFracTrip::iterator itAttVFT = vVFT.begin(); itAttVFT != vVFT.end(); itAttVFT++ ) + { + auto vft = *itAttVFT; + + Edge * edgIt = vft.getEdge(); + + Face * facIt = vft.getFace(); + + if( edgIt == nextEdge && facIt == face2Append ) + { + // the second edge if from a fracture and the face is connected to it + + tripFound = true; + + vVFT.erase(itAttVFT); + + normal2Append.second = vft.getNormal(); + + if( ! FaceContains( facIt, nextEdge )) + { + UG_THROW("Face does not contain edge of its edge" << std::endl); + } + + break; + } + } + + } + + if( ! tripFound && sndEdgIsFracEdgeAlso ) + { + UG_THROW("Triple nicht gefunden trotz markierter Edge" << std::endl); + } + + + // check if aF or vVFT still contain the former or the next face - must not be the case! + + VertexOfFaceInfo vOFI( edge2Append, face2Append, normal2Append ); + + orderedFaces.push_back( vOFI ); + + segmentPart.push_back( vOFI ); + + if( sndEdgIsFracEdgeAlso ) + { + segments.push_back( segmentPart ); + + segmentPart.clear(); + } + + + // what is next face, what is next edge? + // wie kriegen wir es hin, auch das nächste Triple zu erasen, wenn es jetzt kommt als nächstes? + + + startNormal = nuVe; + startEdg = nextEdge; + + if( aF.size() == 0 ) + { + if( nextEdge != originalStartEdge ) + { + UG_THROW("Gesichter leer, aber keine Anfangsecke gefunden" << std::endl); + } + else + { + break; // while loop zu Ende, raus aus dem while loop, den Rest nicht mehr machen, würde schief gehen zwingendermassen + } + + } + + + // bleibt noch das nächste Gesicht heraus zu finden, dafür kommt eigentlich nur noch eines in Frage, da das zweite Gesicht vom edge + // geloescht sein muss in aF, es muss das einzig übrige face sein, das die jetzt start edge enthält, davon darf es nur eines geben, wir löschen aber noch nicht + + IndexType nextFaceFound = 0; + + for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ ) + { + Face * iFa = *itFac; + + if( FaceContains(iFa, startEdg ) ) + { + nextFaceFound++; + } + } + + if( nextFaceFound != 1 ) + { + UG_THROW("folgendes Gesicht in falscher Anztahl gefunden " << nextFaceFound << std::endl); + } + + for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ ) + { + Face * iFa = *itFac; + + if( FaceContains(iFa, startEdg ) ) + { + startFace = iFa; + break; + } + } + + + } + + if( vVFT.size() != 0 ) + { + UG_THROW("not all triples found! " << std::endl); + } + + if( aF.size() != 0 ) + UG_THROW("not all faces found " << std::endl); + + if( startEdg != originalStartEdge ) + { + UG_THROW("wir sind nicht am Anfang wieder angekommen" << std::endl); + } + + + if( segmentPart.size() != 0 ) + { + UG_THROW("die Segmentteile muessen alle verarbeitet sein" << std::endl); + } + + UG_LOG("Kreislauf geschlossen" << std::endl); + + + // test if the segments and their partition produce sumething useful, for debug purposes + + // als nächstes muss man die Klassen von durch Klüften abgetrennten ordered Faces durchgehen, und die Verschiebevertizes erzeugen + // als nächstes die verschiedenen Sektionen durch gehen, eventuell nochmal extra Objekte dafür erzeugen + // oder gleich beim Durchgehen die neuen Vertizes erzeugen, Startsignal durch ein Face mit erster Edge KLuft, und dann die nächste + // Kluftedge finden, egal ob vom gleihen face oder von einem späteren face im kreis + + // now figure out to which face this next edge belongs, and if this is a fracture edge, then we have the triple and the normal info + // else we let the normal zero + + // figure out if second edge is also frac edge, i.e. if it belongs to an edge of the remaining vVFT elements + // first easily asking if it is marked as frac edge, simplifies research + + // in principle from here on need to loop through all triples and through all faces, find out some way to construct next edge and to + // build one element after the other of the ordered faces vector, still even the first element is not completed + + // TODO FIXME kreuzende Fractures im Innenraum -> Arte in Reinform implementieren + // later assign somehow next edge to start edge, or use new variable, when we have figured out next face + // at end, chech if we have arrived again at original first edge + + + int totalSubsNum = sh.num_subsets(); + +// int newSubsToAdd = totalSubsNum; + +// for( VertexOfFaceInfo const & vertFracInfo : orderedFaces ) +// { +//// Face * fa = vertFracInfo.getFace(); +//// +//// sh.assign_subset(fa,newSubsToAdd++); +// } + + number totAnglsEdg = 0; + number totAnglsNrm = 0; + + for( VecVertexOfFaceInfo const & segPart : segments ) + { +// newSubsToAdd++; + + IndexType numbTriangs = segPart.size(); + + if( numbAttTripl == 0 ) + { + UG_THROW("zu wenig Dreiecke " << std::endl); + } + + VertexOfFaceInfo const & vFISBegin = segPart[0]; + VertexOfFaceInfo const & vFISEnd = segPart[numbTriangs-1]; + + std::pair edgesBegin = vFISBegin.getEdge(); + std::pair edgesEnd = vFISEnd.getEdge(); + + std::pair normalBegin = vFISBegin.getNormal(); + std::pair normalEnd = vFISEnd.getNormal(); + + Edge* edgeFracOne = edgesBegin.first; + Edge* edgeFracTwo = edgesEnd.second; + + auto subsIndFracOne = sh.get_subset_index(edgeFracOne); + auto subsIndFracTwo = sh.get_subset_index(edgeFracTwo); + + vector3 normalFracOne = normalBegin.first; + vector3 normalFracTwo = normalEnd.second; + +// sh.assign_subset(edgeFracOne, newSubsToAdd); +// +// if( edgeFracTwo != originalStartEdge ) +// sh.assign_subset(edgeFracTwo, newSubsToAdd); + + // neue Punkte erzeugen + + number cosBetweenNormals = VecDot( normalFracOne, normalFracTwo ); + + if( subsIndFracOne == subsIndFracTwo ) + { + if( numFracsCrossAtVrt != 3 ) + { + UG_THROW("Fracture Segment an beiden Seiten gleiche sudo, aber keine T Kreuzung?" << std::endl); + } + + // dieselben Methoden wie im Fall von einer durchgehenden Kluft an einem Vertex, dort kopieren + // bzw Funktion schreiben, die beides macht + + // hier wird der Fall abgezweigt, dass wir auf der durchgehenden Seite einer Kluft sind + // wenn wir eine T-Kreuzung haben + + std::vector nextFracVrt; + + IndexType foundThisVrtOne = 0; + + for( size_t i = 0; i < 2; ++i ) + { + Vertex * vrtEdgEnd = edgeFracOne->vertex(i); + + if( vrtEdgEnd == *iterV ) + { + foundThisVrtOne++; + } + else + { + nextFracVrt.push_back( vrtEdgEnd ); + } + + } + + if( foundThisVrtOne != 1 ) + { + UG_THROW("zu viel zu wenig vertizex one " << std::endl); + } + + + IndexType foundThisVrtTwo = 0; + + for( size_t i = 0; i < 2; ++i ) + { + Vertex * vrtEdgEnd = edgeFracTwo->vertex(i); + + if( vrtEdgEnd == *iterV ) + { + foundThisVrtTwo++; + } + else + { + nextFracVrt.push_back( vrtEdgEnd ); + } + + } + + if( foundThisVrtTwo != 1 ) + { + UG_THROW("zu viel zu wenig vertizex two " << std::endl); + } + + Face * faceBegin = vFISBegin.getFace(); + Face * faceEnd = vFISEnd.getFace(); + + + + expandSingleFractureAtGivenSide( normalFracTwo, normalFracTwo, + edgeFracOne, edgeFracTwo, + faceBegin, faceEnd, + fracInfosBySubset, + posOldVrt, + aaPos, + grid, sh, + assoFaces + , + nextFracVrt, + aaVrtVecFace, + dbg_flachen_passiert, + *iterV + ); + + + + } + else + { + + // create normal vectors into direction of relevant edges + + vector3 alongEdgeOne; + vector3 alongEdgeTwo; + + Vertex * vrtEdgeOneBegin = NULL; + Vertex * vrtEdgeTwoBegin = NULL; + Vertex * vrtEdgeOneEnd = NULL; + Vertex * vrtEdgeTwoEnd = NULL; + + + for( size_t i = 0; i < 2; ++i ) + { + Vertex * vrtFromEdgeOne = edgeFracOne->vertex(i); + Vertex * vrtFromEdgeTwo = edgeFracTwo->vertex(i); + + if( vrtFromEdgeOne == *iterV ) + { + vrtEdgeOneBegin = vrtFromEdgeOne; + } + else + { + vrtEdgeOneEnd = vrtFromEdgeOne; + } + + if( vrtFromEdgeTwo == *iterV ) + { + vrtEdgeTwoBegin = vrtFromEdgeTwo; + } + else + { + vrtEdgeTwoEnd = vrtFromEdgeTwo; + } + + } + + if( vrtEdgeOneBegin == NULL || vrtEdgeTwoBegin == NULL || vrtEdgeOneEnd == NULL || vrtEdgeTwoEnd == NULL ) + { + UG_THROW("lauter Nullen vertizes" << std::endl); + } + + vector3 fracVrtPos = aaPos[*iterV]; + + vector3 fracEdgOneEndPos = aaPos[ vrtEdgeOneEnd ]; + vector3 fracEdgTwoEndPos = aaPos[ vrtEdgeTwoEnd ]; + + vector3 directionEdgOne; + VecSubtract(directionEdgOne, fracEdgOneEndPos, fracVrtPos); + + vector3 directionEdgTwo; + VecSubtract(directionEdgTwo, fracEdgTwoEndPos, fracVrtPos); + + vector3 nrmdVecEdgOne; + VecNormalize(nrmdVecEdgOne, directionEdgOne); + + vector3 nrmdVecEdgTwo; + VecNormalize(nrmdVecEdgTwo, directionEdgTwo); + + number cosBetweenEdges = VecDot(nrmdVecEdgOne,nrmdVecEdgTwo); + + number angleEdges = std::acos( cosBetweenEdges ); + number angleNormls = std::acos( cosBetweenNormals ); + + totAnglsEdg += angleEdges; + totAnglsNrm += angleNormls; + + UG_LOG("cosinus Edges Normals " << cosBetweenEdges << " " << cosBetweenNormals << std::endl); + UG_LOG("angles edges normals " << angleEdges << " " << angleNormls << std::endl); + + // prject normal 1 onto edge 2 and normal 2 on edge 1, scale with width one half resp with width two half + + + number cosBetweenNrmFraOneEdgTwo = VecDot(normalFracOne,nrmdVecEdgTwo); + number cosBetweenNrmFraTwoEdgOne = VecDot(normalFracTwo,nrmdVecEdgOne); + + vector3 projectNrmFraOneToEdgTwoDirection; + VecScale(projectNrmFraOneToEdgTwoDirection, nrmdVecEdgTwo, 1./cosBetweenNrmFraOneEdgTwo); + + vector3 projectNrmFraTwoToEdgOneDirection; + VecScale(projectNrmFraTwoToEdgOneDirection, nrmdVecEdgOne, 1./cosBetweenNrmFraTwoEdgOne); + + // auto subsIndFracOne = sh.get_subset_index(edgeFracOne); + // auto subsIndFracTwo = sh.get_subset_index(edgeFracTwo); + + number shiftOne = fracInfosBySubset.at( subsIndFracOne ).width / 2. ; + number shiftTwo = fracInfosBySubset.at( subsIndFracTwo ).width / 2. ; + + vector3 shiftAlongEdgeTwo; + VecScale(shiftAlongEdgeTwo, projectNrmFraOneToEdgTwoDirection, shiftOne); + + vector3 shiftAlongEdgeOne; + VecScale(shiftAlongEdgeOne, projectNrmFraTwoToEdgOneDirection, shiftTwo); + + vector3 shiftPart; + VecAdd(shiftPart, fracVrtPos, shiftAlongEdgeTwo); + + vector3 posNewVrt; + VecAdd( posNewVrt, shiftPart, shiftAlongEdgeOne); + + UG_LOG("neuer Vertex Kreuzung " << posNewVrt << std::endl ); + + Vertex * newShiftVrtx = *grid.create(); + aaPos[newShiftVrtx] = posNewVrt; + + // sh.assign_subset(newShiftVrtx, newSubsToAdd ); + + + for( VertexOfFaceInfo const & vertFracInfoSeg : segPart ) + { + Face * fac = vertFracInfoSeg.getFace(); + + // sh.assign_subset(fa,newSubsToAdd); + + + // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! + vector& newVrts4Fac = aaVrtVecFace[ fac ]; + + IndexType vrtxFnd = 0; + + for(size_t indVrt = 0; indVrt < (fac)->num_vertices(); indVrt++ ) + { + Vertex* facVrt = (fac)->vertex(indVrt); + + if( facVrt == *iterV ) + { + newVrts4Fac[ indVrt ] = newShiftVrtx; + vrtxFnd++; + } + } + + + if( vrtxFnd <= 0 ) + { + UG_THROW("vertex not found kreuzung!" << std::endl); + } + else if( vrtxFnd > 1 ) + { + UG_THROW("vertex zu oft gefunden kreuzung " << vrtxFnd << std::endl ); + } + else if ( vrtxFnd == 1 ) + { + } + else + { + UG_THROW("vertex finden komisch kreuzung " << std::endl); + } + + } + } + } + + UG_LOG("sum angles edges normals " << totAnglsEdg << " " << totAnglsNrm << std::endl); + +// return true; + +#if 0 + // das folgende ist vermutlich Unsinn TODO FIXME, waren wohl Versuche am Anfang..... nochmal prüfen!!!! + + // get starting point of the "rotation" around the vertex where fractures are crossing +// for( auto & attVFT : vVFT ) // not const, as we need to erase found elements! + for( VecVertFracTrip::iterator itAttVFT = vVFT.begin(); itAttVFT != vVFT.end(); ) + { + Face * facAtVrtWithFrac = itAttVFT->getFace(); + + bool facFound = false; + +// for( auto const & ifac : assoFaces ) // not const, as we need to erase found elements! + for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); ) + { + if( *itFac == facAtVrtWithFrac ) + { + // found a starting face + // copy first the found info, then delete the original one + auto attVFTCop = *itAttVFT; // copy, not reference! + + vVFT.erase(itAttVFT); + aF.erase(itFac); + + // TODO FIXME erase ifac and attVFT, how to do? + + Face * startFace = facAtVrtWithFrac; + + // now determine the common edge(s), the first edge of the vector must be a frac edge, the second one might be one + + Edge * startEdg = attVFTCop.getEdge(); + + // unnecessary check, but for test purposes at beginning, later should be removed + if( !FaceContains(facAtVrtWithFrac, startEdg )) + { + UG_THROW("face hat ecke nicht, die es haben soll" << std::endl); + } + + // loop around the edges of the ifac face attached to the vertex + + // determin second edge of the startFace, not stored in the vecVertFracTrip information + // check number of common edges containing the same vertex + + IndexType fndCommEdg = 0; + std::vector assoEdg2Fac; + + assoEdg2Fac.push_back( startEdg ); + + std::vector assoNorm; + + vector3 norm2Frac = attVFTCop.getNormal(); + + Edge * secondEdge; + secondEdge = NULL; + + for( auto const & iE : allAssoEdges ) // werden nicht gelöscht, deswegen Zugriff auf attachment direkt + { + if( FaceContains(facAtVrtWithFrac, iE) ) + { + fndCommEdg++; + if( iE != startEdg ) + { + secondEdge = iE; + } + } + + if( fndCommEdg != 2 ) + { + UG_THROW("komische Anzahl gemeinsamer Ecke " << fndCommEdg << std::endl); + } + + if( secondEdge == NULL ) + { + UG_THROW("wieso keine zweite Ecke gefunden???? " << std::endl); + } + + assoEdg2Fac.push_back(secondEdge); + + // check, if second edge belongs to anothter fracture fac, i.e. if it is also a fracture edge + + // check if second edge is edge of a fracture face, i.e. either this edge, or another one is from a fracture + + bool scndEdgIsFracEdg = aaMarkEdgeB[secondEdge]; + + if( scndEdgIsFracEdg ) + { + // TODO FIXME figure out second vertex fracture info, in this case, we have found the next part of the chain! + + for( VecVertFracTrip::iterator itAttVFTTwo = vVFT.begin(); itAttVFTTwo != vVFT.end(); ) + { + // need to erase also this element soon, also in the list of all attached elements + + Face* vFTTwoFac = itAttVFTTwo->getFace(); + + if( FaceContains( vFTTwoFac, secondEdge)) + { + auto vVFT2 = *itAttVFTTwo; + vVFT.erase( itAttVFTTwo ); + + Face * nextFace = vFTTwoFac; + + if( secondEdge != vVFT2.getEdge() ) + { + UG_THROW("Ecke nicht Ecke " << std::endl); + } + + + } + } + } + else // find the next attached face, either from the + { + + } + } + + break; + } + + if( ! facFound ) + { + UG_THROW("Gesicht unauffindbar" << std::endl); + } + + break; + } + } + + while( vVFT.size() != 0 ) + { + while( aF.size() != 0 ) + { + + } + } + +#endif + + + } + + } +// // // different treatment for boundary vertizes + else + { + + // TODO FIXME es muss wohl noch ein Problem mit den Verschiebungen bei boundary Vertizes geben..... + // TODO FIXME XXXXXXXXXXXXXX hier sind wir + + + if( numFracsCrossAtVrt < 1 ) + { + UG_THROW("no fracs crossing but marked vertex at boundary? << std::endl"); + } + else if( numFracsCrossAtVrt == 1 ) // no crossing point at boundary + { + // in this case, we have ONE attached edges, the edges has two attached faces + // the faces have a normal, and based on the normal, we can decide which faces belong to the same side of the edges + + if( numbAttTripl != 2 ) + { + UG_THROW("Anzahl der angehaengten Triples kann nicht stimmen, Vertex einer Kluft ohne Schnittpunkte am Rand " << std::endl); + } + + // Zuordnung der Edges und Faces, die auf der gleichen Seite der fracture sind + + // und gleich auch Erzeugung der neuen Knoten, die dann + // in einem Doublett zusammen mit ihren Normalen an die alten Vertizes + // angehängt werden; der Winkel zur Normalen hilft später, die Seite + // heraus zu finden, Seite von den Edges + + // get edges adjacent to this vertex which lie on the boundary of the domain + + std::vector adjBndEdgs; + +// std::vector & allAssoEdges = aaVrtInfoAssoEdges[*iterV]; + +// for( std::vector::iterator iterBVEdg = grid.associated_edges_begin(*iterV); iterBVEdg != grid.associated_edges_end(*iterV); iterBVEdg++ ) +// { +// if( IsBoundaryEdge2D(grid,*iterBVEdg) ) +// { +// adjBndEdgs.push_back( *iterBVEdg ); +// } +// } + for( auto const & iBVE : allAssoEdges ) + { + if( IsBoundaryEdge2D(grid, iBVE ) ) + { + adjBndEdgs.push_back( iBVE ); + } + } + + // to compute the normals, compute the vector of the edge and normalize it + std::vector bndEdgeDirection; + + for( auto const & bE : adjBndEdgs ) + { + + // get vertices, i.e. get seocnd vertex, first one must be known + +// std::vector verticesEdg; + + static_assert( std::is_same< Edge* const &, decltype( bE ) >::value ); + + static_assert( std::is_same< Vertex*, decltype( bE->vertex(0) ) >::value ); + + IndexType fndIV = 0; + + Vertex * vrtOtherEdg; + vrtOtherEdg = NULL; + + for( size_t i = 0; i < 2; ++i ) + { +// verticesEdg.push_back( adjBndEdgs.vertex(i) ); + + Vertex * vrtOfEdg = bE->vertex(i); + + if( vrtOfEdg == *iterV ) + { + fndIV++; + } + else + { + vrtOtherEdg = vrtOfEdg; + } + } + + vector3 posOtherVrt = aaPos[vrtOtherEdg]; + + UG_LOG("BOUNDARY EDGE VERTIZES " << posOldVrt << ", " << posOtherVrt << std::endl); + + vector3 fromIterV2Other; + + VecSubtract(fromIterV2Other, posOtherVrt, posOldVrt); + + vector3 nV; + + VecNormalize(nV, fromIterV2Other); + + bndEdgeDirection.push_back(nV); + } + + + +#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX + + IndexType dbg_lim = vecVertFracTrip.size(); + + int dbg_cnt = 0; +#endif + + for( VvftIterator vvftAtBnd = vecVertFracTrip.begin(); + vvftAtBnd != vecVertFracTrip.end(); + vvftAtBnd++ + ) + { +#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX + + if( dbg_lim == dbg_cnt ) + { + UG_LOG("DARF NICHT SEIN" << std::endl); + break; + } + + dbg_cnt++; +#endif + + // Ziel: den parallelen Anteil der Normalen auf die jeweilige Randkante projizieren + + vector3 nrmEdg = vvftAtBnd->getNormal(); + + Edge * edgeOfFrac = vvftAtBnd->getEdge(); + + // figure out the adjoint boundary edge into the same direction + + // the normal in both directions have to be compared with the vectors in direction of boundary edges + for( auto bED : bndEdgeDirection ) + { + // check orientation of boundary edges wrt the normals + + number cosinus = VecDot( nrmEdg, bED ); + + UG_LOG("BOUNDARY COSINUS between " << nrmEdg << " and " << bED << " -> " << cosinus << std::endl); + + if( cosinus > 0 ) + { + // gleiche Seite vermutet + + // muessen wissen, wie lange das gestreckt werden soll + + vector3 alongEdgV; + + auto subsIndEdgOF = sh.get_subset_index(edgeOfFrac); + + number width = fracInfosBySubset.at(subsIndEdgOF).width; + + number scal = width / 2. / cosinus; + + VecScale( alongEdgV, bED, scal ); + + vector3 posNewVrtOnBnd; + + VecAdd(posNewVrtOnBnd, posOldVrt, alongEdgV ); + + UG_LOG("neuer Vertex Edge " << posNewVrtOnBnd << std::endl ); + + Vertex * newShiftEdgVrtx = *grid.create(); + aaPos[newShiftEdgVrtx] = posNewVrtOnBnd; + + sh.assign_subset(newShiftEdgVrtx, subsIndEdgOF ); + + std::vector attEdg; + std::vector attFac; + + attEdg.push_back(edgeOfFrac); + + Face * facFrac = vvftAtBnd->getFace(); + + attFac.push_back( facFrac ); + + // we store the boundary edge direction for boundary verzizes rather than the normal, in contrast to inner vertizes, where we store the averaged normal + ExpandVertexMultiplett vrtMtpl( attEdg, attFac, bED ); + + aaVrtExpMP[ *iterV ].push_back( vrtMtpl ); + +#if 0 + // the attached faces need to know that they need a new vertex to be shifted + for( std::vector::iterator iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ ) + { + bool isFromFrac = false; + + for( auto const & facFrac : attFac ) + { + if( *iterFac == facFrac ) + { + isFromFrac = true; + } + } + + bool atRightSide = false; + + if( isFromFrac ) + atRightSide = true; + + if( !isFromFrac ) + { + + // check if on same side of edge where the normal points to: compute cosinus between vector of face center + // perpendicular to the edge + // TODO FIXME + + vector3 facCenter = CalculateCenter( *iterFac, aaPos ); + + vector3 perpendicu; + + DropAPerpendicular(perpendicu, facCenter, aaPos[edgeOfFrac->vertex(0)], aaPos[edgeOfFrac->vertex(1)]); + + vector3 tmpN; + + VecSubtract(tmpN, facCenter, perpendicu ); + + VecNormalize(tmpN, tmpN); + + UG_LOG("Normale Boundary zum Face ist " << tmpN << std::endl); + + number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, nrmEdg ); + + UG_LOG("Cosinus Boundary zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); + + if( cosBetwFracEdgAndDirection2Face > 0 ) + { + UG_LOG("assuming boundary face to be on richt side" << std::endl); + + atRightSide = true; + +#if ANSCHAULICH_ERZEUGE_SUDOS_ANHANG + Vertex * otherFacCent = *grid.create(); + aaPos[otherFacCent] = facCenter; + sh.assign_subset(otherFacCent, 5 ); + + Vertex * pp = *grid.create(); + aaPos[pp] = perpendicu; + sh.assign_subset(pp, 6 ); + + sh.assign_subset(*iterFac,7); +#endif + + + } + else + { + UG_LOG("assuming boundary face to be on wrong side" << std::endl); + } + + } + + if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein + { + + + vector& newVrts4Fac = aaVrtVecFace[ * iterFac ]; + + IndexType vrtxFnd = 0; + + for(size_t indVrt = 0; indVrt < (*iterFac)->num_vertices(); indVrt++ ) + { + Vertex* facVrt = (*iterFac)->vertex(indVrt); + + if( facVrt == *iterV ) + { + newVrts4Fac[ indVrt ] = newShiftEdgVrtx; + vrtxFnd++; + } + } + + + + if( vrtxFnd <= 0 ) + { + UG_THROW("vertex not found bnd!" << std::endl); + } + else if( vrtxFnd > 1 ) + { + UG_THROW("vertex zu oft gefunden bnd " << vrtxFnd << std::endl ); + } + else if ( vrtxFnd == 1 ) + { +// UG_LOG("vertex found abgeschlossen" << std::endl); + } + else + { + UG_THROW("vertex finden bnd komisch " << std::endl); + } + } + + } +#else + for( auto const & ifac : assoFaces ) + { + bool isFromFrac = false; + + for( auto const & facFrac : attFac ) + { + if( ifac == facFrac ) + { + isFromFrac = true; + } + } + + bool atRightSide = false; + + if( isFromFrac ) + atRightSide = true; + + if( !isFromFrac ) + { + + // check if on same side of edge where the normal points to: compute cosinus between vector of face center + // perpendicular to the edge + // TODO FIXME + + vector3 facCenter = CalculateCenter( ifac, aaPos ); + + vector3 perpendicu; + + DropAPerpendicular(perpendicu, facCenter, aaPos[edgeOfFrac->vertex(0)], aaPos[edgeOfFrac->vertex(1)]); + + vector3 tmpN; + + VecSubtract(tmpN, facCenter, perpendicu ); + + VecNormalize(tmpN, tmpN); + + UG_LOG("Normale Boundary zum Face ist " << tmpN << std::endl); + + number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, nrmEdg ); + + UG_LOG("Cosinus Boundary zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); + + if( cosBetwFracEdgAndDirection2Face > 0 ) + { + UG_LOG("assuming boundary face to be on richt side" << std::endl); + + atRightSide = true; + +#if ANSCHAULICH_ERZEUGE_SUDOS_ANHANG + Vertex * otherFacCent = *grid.create(); + aaPos[otherFacCent] = facCenter; + sh.assign_subset(otherFacCent, 5 ); + + Vertex * pp = *grid.create(); + aaPos[pp] = perpendicu; + sh.assign_subset(pp, 6 ); + + sh.assign_subset(*iterFac,7); +#endif + + + } + else + { + UG_LOG("assuming boundary face to be on wrong side" << std::endl); + } + + } + + if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein + { + + + vector& newVrts4Fac = aaVrtVecFace[ ifac ]; + + IndexType vrtxFnd = 0; + + for(size_t indVrt = 0; indVrt < (ifac)->num_vertices(); indVrt++ ) + { + Vertex* facVrt = (ifac)->vertex(indVrt); + + if( facVrt == *iterV ) + { + newVrts4Fac[ indVrt ] = newShiftEdgVrtx; + vrtxFnd++; + } + } + + + + if( vrtxFnd <= 0 ) + { + UG_THROW("vertex not found bnd!" << std::endl); + } + else if( vrtxFnd > 1 ) + { + UG_THROW("vertex zu oft gefunden bnd " << vrtxFnd << std::endl ); + } + else if ( vrtxFnd == 1 ) + { +// UG_LOG("vertex found abgeschlossen" << std::endl); + } + else + { + UG_THROW("vertex finden bnd komisch " << std::endl); + } + } + } + +#endif + + + + } + } + } + + } + else // fractures are crossing at boundary even + { + + } + + + UG_LOG("END THIS BOUNDARY VERTEX" << std::endl); + } + + dbg_vertizesPassiert++; + + } + + +// // neue Vertizes in der Entfernung der Klüfte von den Klüften weg erzeugen, +// // basierend auf den Normalen multipliziert mit der halben Kluftdicke +// //für eine Kluft erstmal nur +// // die neuen Kanten und Faces erzeugen, die alten falschen Kanten löschen und ebenso die alten Faces +// // später auf mehr Klüfte ausdehnen, mit Problemstelle Kreuzung, aber erst, wenn eine Kluft funktioniert +// + +// return true; + + // jetzt Seb Sachen beinahe unverändert + + //////////////////////////////// + // create new elements + + // first we create new edges from selected ones which are connected to + // inner vertices. This allows to preserve old subsets. + // Since we have to make sure that we use the right vertices, + // we have to iterate over the selected faces and perform all actions on the edges + // of those faces. + for(FaceIterator iter_sf = sel.faces_begin(); iter_sf != sel.faces_end(); ++iter_sf) + { + Face* sf = *iter_sf; + // check for each edge whether it has to be copied. + for(size_t i_edge = 0; i_edge < sf->num_edges(); ++i_edge) + { + Edge* e = grid.get_edge(sf, i_edge); + + if(sel.is_selected(e)) + { + // check the associated vertices through the volumes aaVrtVecVol attachment. + // If at least one has an associated new vertex and if no edge between the + // new vertices already exists, we'll create the new edge. + size_t ind0 = i_edge; + size_t ind1 = (i_edge + 1) % sf->num_edges(); + + Vertex* nv0 = (aaVrtVecFace[sf])[ind0]; + Vertex* nv1 = (aaVrtVecFace[sf])[ind1]; + + if(nv0 || nv1) + { + // if one vertex has no associated new one, then we use the vertex itself + if(!nv0) + nv0 = sf->vertex(ind0); + if(!nv1) + nv1 = sf->vertex(ind1); + + // create the new edge if it not already exists. + if(!grid.get_edge(nv0, nv1)) + grid.create_by_cloning(e, EdgeDescriptor(nv0, nv1), e); + } + } + } + } + + + std::vector newFaces; + std::vector subsOfNewFaces; + + // iterate over all surrounding faces and create new vertices. + // Since faces are replaced on the fly, we have to take care with the iterator. + for(FaceIterator iter_sf = sel.faces_begin(); iter_sf != sel.faces_end();) + { + Face* sf = *iter_sf; + ++iter_sf; + + vector newVrts = aaVrtVecFace[sf]; + + // all new vertices have been assigned to newVrts. + // Note that if newVrts[i] == NULL, then we have to take the + // old vertex sf->vertex(i). + // now expand the fracture edges of sf to faces. + for(size_t i_vrt = 0; i_vrt < sf->num_vertices(); ++i_vrt) + { + size_t iv1 = i_vrt; + size_t iv2 = (i_vrt + 1) % sf->num_vertices(); + + Edge* tEdge = grid.get_edge(sf->vertex(iv1), sf->vertex(iv2)); + + if(tEdge) + { + if( aaMarkEdgeB[tEdge] ) + { + Face* expFace = NULL; + if(newVrts[iv1] && newVrts[iv2]) + { + // create a new quadrilateral + expFace = *grid.create( + QuadrilateralDescriptor(sf->vertex(iv1), sf->vertex(iv2), + newVrts[iv2], newVrts[iv1])); + } + else if(newVrts[iv1]) + { + // create a new triangle + expFace = *grid.create( + TriangleDescriptor(sf->vertex(iv1), sf->vertex(iv2), newVrts[iv1])); + } + else if(newVrts[iv2]) + { + // create a new triangle + expFace = *grid.create( + TriangleDescriptor(sf->vertex(iv1), sf->vertex(iv2), newVrts[iv2])); + } + else + { + +//// sh.assign_subset(*iter_sf,10); +//// sh.assign_subset(tEdge,11); +// +// return true; +// // this code-block should never be entered. If it is entered then +// // we selected the wrong faces. This is would be a BUG!!! +// // remove the temporary attachments and throw an error +// +// // remove the temporary attachments +//#if OLD_PROFREITER_STUFF +// grid.detach_from_vertices(aAdjMarker); +// grid.detach_from_edges(aAdjMarker); +//#endif +// grid.detach_from_vertices(aAdjMarkerVFP); +// grid.detach_from_edges(aAdjMarkerB); +// +// grid.detach_from_vertices( aAdjInfoAVVFT ); +// grid.detach_from_faces(attVrtVec); +// +// grid.detach_from_vertices( aAdjInfoEdges ); +// grid.detach_from_vertices( aAdjInfoFaces ); +// +// +// // TODO FIXME auch die weiteren Marker und INfos, alle Attachments, detachen!!!! +// +// throw(UGError("Implementation error in ExpandFractures2d Arte.")); + } + + // TODO FIXME selektion closen irgendwie, damit auch alle Randkanten zum subset gehoeren!!! + + if( expFace ) + { + sh.assign_subset(expFace, fracInfosBySubset.at(sh.get_subset_index(tEdge)).newSubsetIndex); + + int subs = fracInfosBySubset.at(sh.get_subset_index(tEdge)).newSubsetIndex; + + subsOfNewFaces.push_back( subs ); + + newFaces.push_back( expFace ); + } + } + } + } + + + + + // now set up a new face descriptor and replace the face. + if(fd.num_vertices() != sf->num_vertices()) + fd.set_num_vertices(sf->num_vertices()); + + for(size_t i_vrt = 0; i_vrt < sf->num_vertices(); ++i_vrt) + { + if(newVrts[i_vrt]) + fd.set_vertex(i_vrt, newVrts[i_vrt]); + else + fd.set_vertex(i_vrt, sf->vertex(i_vrt)); + } + + grid.create_by_cloning(sf, fd, sf); + grid.erase(sf); + } + + // we have to clean up unused edges. + // All selected edges with mark 0 have to be deleted. + for(EdgeIterator iter = sel.edges_begin(); iter != sel.edges_end();) + { + // be careful with the iterator + Edge* e = *iter; + ++iter; + + if(!aaMarkEdgeB[e]) + grid.erase(e); + } + + if( subsOfNewFaces.size() != newFaces.size() ) + { + UG_THROW("andere zahl neue faces als subdoms " << std::endl); + } + + IndexType nfn = 0; + + for( auto const & nf : newFaces ) + { + for(size_t i_edge = 0; i_edge < nf->num_edges(); ++i_edge) + { + Edge* edg = grid.get_edge(nf, i_edge); + + sh.assign_subset( edg, subsOfNewFaces[nfn] ); + } + + nfn++; + } + + // sollen die Boundary Edges zur boundary gehören, oder zur Kluft? + // wie ist es mit den Knoten, sind die alle richtig zugewiesen bezüglich subset? + + // TODO FIXME HHHHHHHHHHHHHHHHHH + // jetzt muss noch der Diamant erzeugt werden + // Ziel: KluftInnen erzeugen + + // remove the temporary attachments + +#if OLD_PROFREITER_STUFF + grid.detach_from_vertices(aAdjMarker); + grid.detach_from_edges(aAdjMarker); +#endif + grid.detach_from_vertices(aAdjMarkerVFP); + grid.detach_from_edges(aAdjMarkerB); + + grid.detach_from_vertices( aAdjInfoAVVFT ); + grid.detach_from_faces(attVrtVec); + + grid.detach_from_vertices( aAdjInfoEdges ); + grid.detach_from_vertices(aAdjInfoFaces ); + + + // TODO FIXME alles detachen, was noch attached ist, da ist einiges hinzu gekommen! + + + return true; + + // ENDE NEUES ZEUG SELEKTION + + + + + + + +#if OLD_PROFREITER_STUFF + // TODO FIXME von diesem Loop kann man noch für oben die calculate crease normal lernen, vielleicht minimal abgewandelt, vielleicht exakt gleich + + // a callback that returns true if the edge is a fracture edge, neues System + AttachmentUnequal > isFracEdgeB(aaMarkEdgeB, false); + + // iterate over all surrounding faces and create new vertices. + for(FaceIterator iter_sf = sel.faces_begin(); iter_sf != sel.faces_end(); ++iter_sf) + { + Face* sf = *iter_sf; + + // check for each vertex whether it lies in the fracture + // (aaMarkVRT > 1 in this case) + // if so, we have to copy or create a vertex from/in aaVrtVec[vrt] which is + // associated with the crease normal on the side of sf. + for(size_t i_vrt = 0; i_vrt < sf->num_vertices(); ++i_vrt) + { + Vertex* vrt = sf->vertex(i_vrt); + if(aaMarkVRT[vrt] > 1) + { + // calculate the normal on this side of the frac + // TODO FIXME so eine Funktion brauchen wir vielleicht oben auch zur Vereinfachung des Codes!!! + vector3 n_v2 = CalculateCreaseNormal(grid, sf, vrt, isFracEdgeB, aaPos); + // das calculate crease normal scheint mir ein Schwachsinn zu sein + // aber vielleicht doch nicht? + + UG_LOG("calculated crease normal v2: " << n_v2 << endl); + + } + } +#endif + + + + + + + +} + + + + +} diff --git a/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.h b/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.h new file mode 100644 index 000000000..8f7056291 --- /dev/null +++ b/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.h @@ -0,0 +1,26 @@ +/* + * expand_layers_arte.h + * + * Created on: 11.07.2024 + * Author: mknodel + */ + +#ifndef UGBASE_LIB_GRID_ALGORITHMS_EXTRUSION_EXPAND_LAYERS_ARTE_H_ +#define UGBASE_LIB_GRID_ALGORITHMS_EXTRUSION_EXPAND_LAYERS_ARTE_H_ + +namespace ug +{ + +/** + * 2 dimensional fracture expansion for finite extensions, using the Arte algorithm + * + */ +bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, + const std::vector& fracInfos, + bool expandInnerFracBnds, bool expandOuterFracBnds); + + + +} + +#endif /* UGBASE_LIB_GRID_ALGORITHMS_EXTRUSION_EXPAND_LAYERS_ARTE_H_ */ From 7fa440455a79b9f2c403f446ad1345f39953d6c2 Mon Sep 17 00:00:00 2001 From: Markus Date: Wed, 26 Jun 2024 12:45:53 +0200 Subject: [PATCH 39/58] Fixing Out-of-line definition --- ugbase/lib_grid/file_io/file_io_vtu.cpp | 2 ++ ugbase/lib_grid/file_io/file_io_vtu.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ugbase/lib_grid/file_io/file_io_vtu.cpp b/ugbase/lib_grid/file_io/file_io_vtu.cpp index ac8ee9d5b..367253fbd 100644 --- a/ugbase/lib_grid/file_io/file_io_vtu.cpp +++ b/ugbase/lib_grid/file_io/file_io_vtu.cpp @@ -889,4 +889,6 @@ find_child_node_by_argument_value(rapidxml::xml_node<>* parent, return NULL; } +std::string GridReaderVTU::m_regionOfInterest = "regions"; + }// end of namespace diff --git a/ugbase/lib_grid/file_io/file_io_vtu.h b/ugbase/lib_grid/file_io/file_io_vtu.h index a02aaaa84..4692ddae7 100644 --- a/ugbase/lib_grid/file_io/file_io_vtu.h +++ b/ugbase/lib_grid/file_io/file_io_vtu.h @@ -297,7 +297,7 @@ class GridReaderVTU - inline static std::string m_regionOfInterest = "regions"; // ProMesh standard, in Braunschweig case often "Material Id", but not always + static std::string m_regionOfInterest; // ProMesh standard = "regions", in Braunschweig case often "Material Id", but not always }; From d4984331a07641b8a3adddfac4d8688fbb4fc1a4 Mon Sep 17 00:00:00 2001 From: Arne Naegel Date: Thu, 11 Jul 2024 13:32:55 +0200 Subject: [PATCH 40/58] Revert "Merge branch 'master' into arte-merge" This reverts commit 317720d0bae23d07013c0bcd22c880a2148a0146, reversing changes made to 7fa440455a79b9f2c403f446ad1345f39953d6c2. --- .github/workflows/jenkins-trigger.yml | 25 ++--- scripts/shell/schedulers/pbs-generic | 4 +- ugbase/bridge/grid_bridges/file_io_bridge.cpp | 11 +- ugbase/lib_grid/file_io/file_io_vtu.cpp | 100 +++++++++++++++++- ugbase/lib_grid/file_io/file_io_vtu.h | 10 ++ ugbase/lib_grid/tools/creator_grid_util.h | 10 +- 6 files changed, 138 insertions(+), 22 deletions(-) diff --git a/.github/workflows/jenkins-trigger.yml b/.github/workflows/jenkins-trigger.yml index 239b3bbaa..eabbb5328 100644 --- a/.github/workflows/jenkins-trigger.yml +++ b/.github/workflows/jenkins-trigger.yml @@ -1,5 +1,4 @@ name: Trigger Jenkins CI - # Controls when the workflow will run on: # Triggers the workflow on push or pull request events but only for the main branch @@ -7,18 +6,20 @@ on: branches: [ master ] pull_request: branches: [ master ] - + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: - trigger-jenkins-job: + # This workflow contains a single job called "build" + build: + name: Build runs-on: ubuntu-latest steps: - - id: triggerjenkinsjob - uses: mickeygoussetorg/trigger-jenkins-job@v1 + - name: Trigger jenkins job + uses: anaegel/jenkins-githubaction@master with: - jenkins-server: ${{ secrets.JENKINS_URL }} # URL of the jenkins server. ex: http://myjenkins.acme.com:8080 - jenkins-job: "ug-build-pipeline" # The name of the jenkins job to run - jenkins-username: ${{ secrets.JENKINS_USER }} # user name for accessing jenkins - jenkins-pat: ${{ secrets.JENKINS_TOKEN }} # personal Access token for accessing Jenkins - poll-time: 90 # how often (seconds) to poll the jenkins server for results - timeout-value: 3600 # How long (seconds) to poll before timing out the action - verbose: true # true/false - turns on extra logging + url: ${{ secrets.JENKINS_URL }} + job_name: ug-build-pipeline + username: ${{ secrets.JENKINS_USER }} + api_token: ${{ secrets.JENKINS_TOKEN }} + timeout: "3600" + interval: "300" diff --git a/scripts/shell/schedulers/pbs-generic b/scripts/shell/schedulers/pbs-generic index 74170d6b2..6e0299eb7 100755 --- a/scripts/shell/schedulers/pbs-generic +++ b/scripts/shell/schedulers/pbs-generic @@ -34,7 +34,7 @@ function UJS_Submit # PBSnodes="-l select=$nnodes:node_type=rome:mpiprocs=$nppn" - PBSnodes="-l select=$nnodes:ncpus=$nppn:mpiprocs=$nppn" + PBSnodes="" if [ -z "$queue" ]; then @@ -82,7 +82,7 @@ function UJS_Submit exit fi jobid=`echo $jobid | sed 's/\([0-9]*\).*/\1/'` - fi + fi } diff --git a/ugbase/bridge/grid_bridges/file_io_bridge.cpp b/ugbase/bridge/grid_bridges/file_io_bridge.cpp index f22de584d..0f832ab5c 100644 --- a/ugbase/bridge/grid_bridges/file_io_bridge.cpp +++ b/ugbase/bridge/grid_bridges/file_io_bridge.cpp @@ -35,6 +35,7 @@ #include "lib_grid/multi_grid.h" #include "lib_grid/file_io/file_io.h" #include "lib_grid/file_io/file_io_ugx.h" +#include "lib_grid/file_io/file_io_vtu.h" using namespace std; @@ -77,6 +78,13 @@ bool SaveGridHierarchy(MultiGrid& mg, const char* filename) return SaveGridToFile(mg, mg.get_hierarchy_handler(), filename); } +void SetVTURegionOfInterestIdentifier( char const * regOfInt ) +{ + PROFILE_FUNC_GROUP("grid"); + GridReaderVTU::setRegionOfInterestIdentifier( std::string( regOfInt ) ); + return; +} + void RegisterGridBridge_FileIO(Registry& reg, string parentGroup) { @@ -129,7 +137,8 @@ void RegisterGridBridge_FileIO(Registry& reg, string parentGroup) .add_function("SaveParallelGridLayout", &SaveParallelGridLayout, grp, "", "mg#filename#offset") .add_function("SaveSurfaceViewTransformed", &SaveSurfaceViewTransformed) - .add_function("SaveGridLevelToFile", &SaveGridLevelToFile); + .add_function("SaveGridLevelToFile", &SaveGridLevelToFile) + .add_function("SetVTURegionOfInterestIdentifier", static_cast(&SetVTURegionOfInterestIdentifier) ); } }// end of namespace diff --git a/ugbase/lib_grid/file_io/file_io_vtu.cpp b/ugbase/lib_grid/file_io/file_io_vtu.cpp index 41ab32cd1..367253fbd 100644 --- a/ugbase/lib_grid/file_io/file_io_vtu.cpp +++ b/ugbase/lib_grid/file_io/file_io_vtu.cpp @@ -31,6 +31,8 @@ */ #include "file_io_vtu.h" +#include +#include using namespace std; using namespace rapidxml; @@ -411,7 +413,8 @@ GridReaderVTU::~GridReaderVTU() { } - +#if 0 +// original function bool GridReaderVTU:: parse_file(const char* filename) { @@ -442,6 +445,81 @@ parse_file(const char* filename) // notify derived classes that a new document has been parsed. return new_document_parsed(); } +#else + +bool GridReaderVTU:: +parse_file(const char* filename) +{ + ifstream in(filename, ios::binary); + if(!in) + return false; + + m_filename = filename; + +// get the length of the file + streampos posStart = in.tellg(); + in.seekg(0, ios_base::end); + streampos posEnd = in.tellg(); + streamsize size = posEnd - posStart; + +// go back to the start of the file + in.seekg(posStart); + + char * fileContentOriginal = new char[size + 1]; + + in.read(fileContentOriginal,size); + fileContentOriginal[size] = 0; + in.close(); + + std::string fiCo2Str(fileContentOriginal); + + delete [] fileContentOriginal; + fileContentOriginal = NULL; + + std::string regInf("RegionInfo"); + + if ( fiCo2Str.find(regInf) == std::string::npos && fiCo2Str.find(m_regionOfInterest) != std::string::npos ) + { + // we need to insert the additional string + + std::string regInfLines; + + regInfLines.append( "\n\n"); + + regInfLines.append( "" ); + + std::string insAft( "" ); + + size_t cedava = fiCo2Str.find( insAft ); + + if( cedava == std::string::npos ) + return false; + + size_t insVal = cedava + insAft.size(); + + fiCo2Str.insert( insVal, regInfLines ); + + } + + char* fileContent = m_doc.allocate_string(0, fiCo2Str.size() ); + + strcpy(fileContent, fiCo2Str.c_str()); + + +// parse the xml-data + m_doc.parse<0>(fileContent); + +// notify derived classes that a new document has been parsed. + return new_document_parsed(); +} + +#endif + + bool GridReaderVTU:: new_document_parsed() @@ -461,6 +539,7 @@ new_document_parsed() m_entries.push_back(GridEntry(curNode)); GridEntry& gridEntry = m_entries.back(); + // collect associated subset handlers xml_node<>* curSHNode = curNode->first_node("RegionInfo"); while(curSHNode){ @@ -569,6 +648,14 @@ subset_handler(ISubsetHandler& shOut, vector subsetIndices; read_scalar_data(subsetIndices, regionDataNode, true); + if( subsetIndices.size() != cells.size() ) + { + vector subsetIndicesDbl; + read_scalar_data(subsetIndicesDbl, regionDataNode, true); + + trafoDblVec2Int( subsetIndicesDbl, subsetIndices ); + } + UG_COND_THROW(subsetIndices.size() != cells.size(), "Mismatch regarding number of cells and number of region-indices!"); @@ -772,6 +859,17 @@ create_cells(std::vector& cellsOut, return true; } +void GridReaderVTU:: +trafoDblVec2Int( std::vector const & dblVec, std::vector & intVec ) +{ + intVec = std::vector(); + + for( auto d : dblVec ) + { + intVec.push_back( static_cast( d ) ); + } +} + xml_node<>* GridReaderVTU:: find_child_node_by_argument_value(rapidxml::xml_node<>* parent, diff --git a/ugbase/lib_grid/file_io/file_io_vtu.h b/ugbase/lib_grid/file_io/file_io_vtu.h index 3ea0c2dd6..4692ddae7 100644 --- a/ugbase/lib_grid/file_io/file_io_vtu.h +++ b/ugbase/lib_grid/file_io/file_io_vtu.h @@ -220,6 +220,12 @@ class GridReaderVTU size_t refGridIndex, size_t subsetHandlerIndex); + static std::string const getRegionOfInterestIdentifyer() + { return m_regionOfInterest; } + + static void setRegionOfInterestIdentifier( std::string const & regOfInt ) + { m_regionOfInterest = regOfInt; } + protected: struct SubsetHandlerEntry { @@ -269,6 +275,8 @@ class GridReaderVTU rapidxml::xml_node<>* dataNode, bool clearData = true); + void trafoDblVec2Int( std::vector const & dblVec, std::vector & intVec ); + template void check_indices(std::vector& inds, size_t first, size_t num, size_t max); @@ -287,6 +295,8 @@ class GridReaderVTU /// holds grids which already have been created std::vector m_entries; + + static std::string m_regionOfInterest; // ProMesh standard = "regions", in Braunschweig case often "Material Id", but not always }; diff --git a/ugbase/lib_grid/tools/creator_grid_util.h b/ugbase/lib_grid/tools/creator_grid_util.h index f3676644d..11df9e6ac 100644 --- a/ugbase/lib_grid/tools/creator_grid_util.h +++ b/ugbase/lib_grid/tools/creator_grid_util.h @@ -40,9 +40,7 @@ namespace ug{ //////////////////////////////////////////////////////////////////////// /** * To Create GridObject directly under UG4-C++ - * instead of ProMesh: - * - * Functions are copied from plugins/ProMesh/tools/grid_generation_tools.cpp + * instead of ProMesh */ template Vertex* CreateVertex(Grid& grid,const TPosition& pos,Grid::VertexAttachmentAccessor >& aaPos ) @@ -58,7 +56,7 @@ Vertex* CreateVertex(Grid& grid,const TPosition& pos,Grid::VertexAttachmentAcces -Edge* CreateEdge(Grid& grid, Vertex* vrts[], const size_t numVrts){ +Edge* CreateEdge(Grid& grid, Vertex* vrts[], const size_t, numVrts){ //uniquify vrts by hash_value: no //The vrts can't be simply uniquified by hash_values since it will change the orientation of vrts. // Hence,it should be generated by aaPos before using this function. @@ -146,7 +144,7 @@ Face* CreateFace(Grid& grid, Vertex* vrts[], const size_t numVrts){ //return CreateFace(grid, avrts, numVrts); }*/ -Volume* CreateVolume(Grid& grid, Vertex* vrts[], const size_t numVrts){ +Volume* CreateVolume(Grid& grid, Vertex* vrts, const size_t numVrts){ //if(numVrts < 4 || numVrts > 8){ UG_ASSERT(numVrts>3 || numVrts<9,"Bad number of vertices! Can't create a volume element from " << numVrts << " vertices."); @@ -211,7 +209,7 @@ void CreatePlane(Grid& grid, const TPosition& upRight, const TPosition& lowLeft, const TPosition& lowRight, - Grid::VertexAttachmentAccessor >& aaPos, + Grid::VertexAttachmentAccessor >& aaPos bool fill) { Vertex* vrts[4]; From 069afe1cbd8e61fe6076abe048e1a6dbe78eb0ed Mon Sep 17 00:00:00 2001 From: Arne Naegel Date: Thu, 11 Jul 2024 13:41:33 +0200 Subject: [PATCH 41/58] Restoring master version --- .github/workflows/jenkins-trigger.yml | 25 ++++++++++++------------- scripts/shell/schedulers/pbs-generic | 2 +- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/.github/workflows/jenkins-trigger.yml b/.github/workflows/jenkins-trigger.yml index eabbb5328..239b3bbaa 100644 --- a/.github/workflows/jenkins-trigger.yml +++ b/.github/workflows/jenkins-trigger.yml @@ -1,4 +1,5 @@ name: Trigger Jenkins CI + # Controls when the workflow will run on: # Triggers the workflow on push or pull request events but only for the main branch @@ -6,20 +7,18 @@ on: branches: [ master ] pull_request: branches: [ master ] - -# A workflow run is made up of one or more jobs that can run sequentially or in parallel + jobs: - # This workflow contains a single job called "build" - build: - name: Build + trigger-jenkins-job: runs-on: ubuntu-latest steps: - - name: Trigger jenkins job - uses: anaegel/jenkins-githubaction@master + - id: triggerjenkinsjob + uses: mickeygoussetorg/trigger-jenkins-job@v1 with: - url: ${{ secrets.JENKINS_URL }} - job_name: ug-build-pipeline - username: ${{ secrets.JENKINS_USER }} - api_token: ${{ secrets.JENKINS_TOKEN }} - timeout: "3600" - interval: "300" + jenkins-server: ${{ secrets.JENKINS_URL }} # URL of the jenkins server. ex: http://myjenkins.acme.com:8080 + jenkins-job: "ug-build-pipeline" # The name of the jenkins job to run + jenkins-username: ${{ secrets.JENKINS_USER }} # user name for accessing jenkins + jenkins-pat: ${{ secrets.JENKINS_TOKEN }} # personal Access token for accessing Jenkins + poll-time: 90 # how often (seconds) to poll the jenkins server for results + timeout-value: 3600 # How long (seconds) to poll before timing out the action + verbose: true # true/false - turns on extra logging diff --git a/scripts/shell/schedulers/pbs-generic b/scripts/shell/schedulers/pbs-generic index 6e0299eb7..921d21f72 100755 --- a/scripts/shell/schedulers/pbs-generic +++ b/scripts/shell/schedulers/pbs-generic @@ -34,7 +34,7 @@ function UJS_Submit # PBSnodes="-l select=$nnodes:node_type=rome:mpiprocs=$nppn" - PBSnodes="" + PBSnodes="-l select=$nnodes:ncpus=$nppn:mpiprocs=$nppn" if [ -z "$queue" ]; then From 875133b413bbebb8446401438180d882328d12c3 Mon Sep 17 00:00:00 2001 From: Dmitriy Logashenko Date: Tue, 30 Jul 2024 17:35:57 +0300 Subject: [PATCH 42/58] Introducing the object names for the userdata class. This is a debugging facility. --- .../bridge/disc_bridges/user_data_bridge.cpp | 4 ++- .../spatial_disc/user_data/user_data.h | 26 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/ugbase/bridge/disc_bridges/user_data_bridge.cpp b/ugbase/bridge/disc_bridges/user_data_bridge.cpp index ae275c4e3..7cb66b1c9 100644 --- a/ugbase/bridge/disc_bridges/user_data_bridge.cpp +++ b/ugbase/bridge/disc_bridges/user_data_bridge.cpp @@ -597,7 +597,9 @@ static void Common(Registry& reg, string grp) // UserDataInfo { - reg.add_class_("UserDataInfo", grp); + reg.add_class_("UserDataInfo", grp) + .add_method("set_obj_name", &UserDataInfo::set_obj_name) + .add_method("obj_name", &UserDataInfo::obj_name); } #ifdef UG_DIM_2 diff --git a/ugbase/lib_disc/spatial_disc/user_data/user_data.h b/ugbase/lib_disc/spatial_disc/user_data/user_data.h index 0376dabad..43ecc612b 100644 --- a/ugbase/lib_disc/spatial_disc/user_data/user_data.h +++ b/ugbase/lib_disc/spatial_disc/user_data/user_data.h @@ -34,6 +34,8 @@ #define __H__UG__LIB_DISC__SPATIAL_DISC__USER_DATA__USER_DATA__ #include +#include + #include "common/types.h" #include "lib_disc/common/local_algebra.h" #include "lib_disc/time_disc/solution_time_series.h" @@ -77,6 +79,27 @@ class UserDataInfo { /// number of functions this export depends on size_t num_fct() const {return m_map.num_fct();} + + /// sets the name of the object (s. the field m_objName) + /** + * Note that the object name is not unique in general. Several objects may have the same name. + */ + void set_obj_name(const char * name) + { + if (name == NULL) {m_objName = SPNULL; return;} + if (m_objName.valid ()) // we assume that the name is assigned once; otherwise we warn + UG_LOG ("Warning: Replacing existing UserData object name '" << m_objName.get() << "' with '" << name << "'.\n"); + const size_t name_len = strnlen (name, 128); + SmartPtr new_name (new char [name_len+1]); + memcpy (new_name.get(), name, name_len); (new_name.get()) [name_len] = '\0'; + m_objName = new_name; + } + + /// gets the name of the object (s. the field m_objName) + /** + * Note that the object name is not unique in general. Several objects may have the same name. + */ + const char * obj_name () {return m_objName.get ();} protected: /// functions the data depends on @@ -84,6 +107,9 @@ class UserDataInfo { /// Mapping for import fct FunctionIndexMapping m_map; + + /// This field is used mainly for debugging: One can assign a name to the object to identify it when running + SmartPtr m_objName; ///< this strange type underlines the debugging nature of this field: it is seldom used but should be easily accessed in a debugger }; //////////////////////////////////////////////////////////////////////////////// From 40e5f1d401e7c76871d082e2355af8929cb3724f Mon Sep 17 00:00:00 2001 From: Dmitriy Logashenko Date: Tue, 30 Jul 2024 17:36:55 +0300 Subject: [PATCH 43/58] Bug fix: Releasing set but not cleared ip's in the local discretizations. ToDo: Should this be also done for the error estimators? --- .../spatial_disc/user_data/data_evaluator.cpp | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/ugbase/lib_disc/spatial_disc/user_data/data_evaluator.cpp b/ugbase/lib_disc/spatial_disc/user_data/data_evaluator.cpp index 9dbeef97e..5418b4425 100644 --- a/ugbase/lib_disc/spatial_disc/user_data/data_evaluator.cpp +++ b/ugbase/lib_disc/spatial_disc/user_data/data_evaluator.cpp @@ -92,12 +92,37 @@ void DataEvaluator::finish_elem_loop() { // finish each elem disc try{ - for(size_t i = 0; i < m_vElemDisc[PT_ALL].size(); ++i) - m_vElemDisc[PT_ALL][i]->do_fsh_elem_loop(); + for(size_t d = 0; d < m_vElemDisc[PT_ALL].size(); ++d) + { + IElemDisc* disc = m_vElemDisc[PT_ALL][d]; + + disc->do_fsh_elem_loop(); + + /* TODO: + * In prepare_elem_loop, the elemdiscs initialize the local ip's independently + * on if they are used. For ex., the ip's used only for the mass matrix are + * initialized, too, even if only the stiffness part is assembled. These ip's + * are not cleared below as they do not get into the lists, and this creates + * issues with the linkers that share subordinated userdata objects. For that, + * we clear here all the assigned ip's. + * + * Should it be done here on in do_fsh_elem_loop? + */ + for (size_t i = 0; i < disc->num_imports(); ++i) + { + IDataImport& imp = disc->get_import(i); + if(imp.data_given()) + imp.data()->clear(); + } + } } UG_CATCH_THROW("DataEvaluatorBase::fsh_elem_loop: Cannot finish element loop"); // clear positions at user data + /* TODO: + * Could it be done in a more elegant way? For ex., why clearing here all the ip + * series and not only the ones assigned to the particular userdata objects? + */ clear_positions_in_user_data(); } From f0ec9b57ab6bd5372670c8603dd026faef0cd8e2 Mon Sep 17 00:00:00 2001 From: Markus Date: Thu, 1 Aug 2024 00:48:36 +0200 Subject: [PATCH 44/58] removed static_asserts and other compiler warning reasons --- .../extrusion/expand_layers_arte.cpp | 184 +++++++++--------- .../algorithms/extrusion/expand_layers_arte.h | 5 +- 2 files changed, 94 insertions(+), 95 deletions(-) diff --git a/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.cpp b/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.cpp index 8f734be8d..1f53b9f5a 100644 --- a/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.cpp +++ b/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.cpp @@ -142,14 +142,14 @@ bool expandSingleFractureAtGivenSide( vector3 const & nOne, vector3 const & nTwo for( auto const & facFrac : attFac ) { - static_assert( std::is_same< decltype( (facFrac) ), decltype ( ifac ) >::value ); + //static_assert( std::is_same< decltype( (facFrac) ), decltype ( ifac ) >::value ); if( ifac == facFrac ) { isFromFrac = true; - static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value ); - static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value ); + //static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value ); + //static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value ); } } @@ -193,7 +193,7 @@ bool expandSingleFractureAtGivenSide( vector3 const & nOne, vector3 const & nTwo atRightSide = true; -#if ANSCHAULICH_ERZEUGE_SUDOS_ANHANG +#if GRAPHICAL_SUDO_CREATION_DBG Vertex * otherFacCent = *grid.create(); aaPos[otherFacCent] = facCenter; @@ -269,20 +269,20 @@ bool expandSingleFractureAtGivenSide( vector3 const & nOne, vector3 const & nTwo } -#ifndef NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX -#define NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX 1 +#ifndef WORKAROUND_SEGFAULT_CREATE_VERTEX +#define WORKAROUND_SEGFAULT_CREATE_VERTEX 1 #endif -#ifndef ANSCHAULICH_ERZEUGE_SUDOS_ANHANG -#define ANSCHAULICH_ERZEUGE_SUDOS_ANHANG 0 +#ifndef GRAPHICAL_SUDO_CREATION_DBG +#define GRAPHICAL_SUDO_CREATION_DBG 0 #endif -#ifndef OLD_PROFREITER_STUFF -#define OLD_PROFREITER_STUFF 0 +#ifndef FORMER_EXPANSION_TECHNIQUES +#define FORMER_EXPANSION_TECHNIQUES 0 #endif -bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector const & fracInfos, - bool expandInnerFracBnds, bool expandOuterFracBnds) +bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, vector const & fracInfos, + bool expandInnerFracBnds, bool expandOuterFracBnds ) { // static constexpr bool dehneInnereKluftGrenzpunkteAus = false; @@ -325,7 +325,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c sel.enable_autoselection(false); sel.enable_selection_inheritance(false); -#if OLD_PROFREITER_STUFF +#if FORMER_EXPANSION_TECHNIQUES AInt aAdjMarker; // used to mark how many adjacent fractures a vertex has. // 0: no frac, 1: frac-boundary, >1: inner frac vertex // TODO FIXME das sieht komisch aus, ist das immer so, wenn z.B. an einer Grenze sich zwei fracs treffen? @@ -422,7 +422,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c // mark edge and vertices sel.select(*iter); -#if OLD_PROFREITER_STUFF +#if FORMER_EXPANSION_TECHNIQUES aaMarkEDGE[*iter] = 1; #endif @@ -441,7 +441,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c aaMarkVrtVFP[v].setIsBndFracVertex(); -#if OLD_PROFREITER_STUFF +#if FORMER_EXPANSION_TECHNIQUES // das ist Sebastians loop, den nicht mehr lassen lassen // if fracture boundaries are expanded, we'll regard all fracture vertices // as inner vertices @@ -466,7 +466,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c } -#if OLD_PROFREITER_STUFF +#if FORMER_EXPANSION_TECHNIQUES // Make sure that selected vertices that lie on the boundary of the geometry // are treated as inner fracture vertices. // This is only required if frac-boundaries are not expanded anyways. @@ -496,7 +496,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c if( expandInnerFracBnds && !expandOuterFracBnds && aaMarkVrtVFP[*iter].getIsBndFracVertex() ) wahl = false; - static_assert( std::is_same< decltype(*iter), Vertex * >::value ); + //static_assert( std::is_same< decltype(*iter), Vertex * >::value ); bool isBnd = aaMarkVrtVFP[ *iter ].getIsBndFracVertex(); auto numCrosFrac = aaMarkVrtVFP[ *iter ].getNumberFracEdgesInVertex(); @@ -601,15 +601,15 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c // get subdomain of edge - auto sudoEdg = sh.get_subset_index(*iterEdg); +// auto sudoEdg = sh.get_subset_index(*iterEdg); - static_assert( std::is_same< decltype(sudoEdg), int >::value ); + //static_assert( std::is_same< decltype(sudoEdg), int >::value ); // get vertices of edge, always 2 std::vector verticesEdg; - static_assert( std::is_same< Vertex*, decltype( (*iterEdg)->vertex(0) ) >::value ); + //static_assert( std::is_same< Vertex*, decltype( (*iterEdg)->vertex(0) ) >::value ); for( size_t i = 0; i < 2; ++i ) verticesEdg.push_back( (*iterEdg)->vertex(i) ); @@ -649,8 +649,8 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c std::vector assFace; -// static_assert( std::is_same< decltype( aaVrtInfoAssoFaces[verticesEdg[0]] )[0], std::vector >::value ); - //static_assert( std::is_same< decltype( *(aaVrtInfoAssoFaces[verticesEdg[0]]) ), Face * >::value ); +// //static_assert( std::is_same< decltype( aaVrtInfoAssoFaces[verticesEdg[0]] )[0], std::vector >::value ); + ////static_assert( std::is_same< decltype( *(aaVrtInfoAssoFaces[verticesEdg[0]]) ), Face * >::value ); // UG_LOG("XXXXXXXXXXXX" << std::endl); @@ -692,7 +692,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c // VecFace & assoFaces = aaVrtInfoAssoFaces[*iterV ist verticesEdg[0] ]; // for( auto const & ifac : assoFaces ) // { - // static_assert( std::is_same< decltype( ifac ), Face * const & >::value ); + // //static_assert( std::is_same< decltype( ifac ), Face * const & >::value ); // } @@ -727,11 +727,11 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c edgeNormals.push_back( tmpN ); - static_assert( std::is_same< Edge*, decltype(*iterEdg) >::value ); + //static_assert( std::is_same< Edge*, decltype(*iterEdg) >::value ); - static_assert( std::is_same< Face * const &, decltype(fac) >::value ); - static_assert( std::is_same< Face *, decltype( const_cast(fac) ) >::value ); - static_assert( std::is_same< vector3, decltype( tmpN ) >::value ); + //static_assert( std::is_same< Face * const &, decltype(fac) >::value ); + //static_assert( std::is_same< Face *, decltype( const_cast(fac) ) >::value ); + //static_assert( std::is_same< vector3, decltype( tmpN ) >::value ); VertFracTrip infoVertizesThisEdge( *iterEdg, fac, tmpN ); @@ -742,21 +742,21 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c for( auto const & v : verticesEdg ) { - static_assert( std::is_same< decltype(v), Vertex * const & >::value ); - static_assert( std::is_same< decltype(const_cast(v)), Vertex * >::value ); + //static_assert( std::is_same< decltype(v), Vertex * const & >::value ); + //static_assert( std::is_same< decltype(const_cast(v)), Vertex * >::value ); aaVrtInfoFraTri[v].push_back( infoVertizesThisEdge ); // VecVertFracTrip allInfosVrtxThisEdg = aaVrtInfoFraTri[v]; -// static_assert( std::is_same< decltype( aaVrtInfoFraTri[v] ), VecVertFracTrip >::value ); +// //static_assert( std::is_same< decltype( aaVrtInfoFraTri[v] ), VecVertFracTrip >::value ); // UG_LOG("type Fac " << typeid( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getFace() ).name() << std::endl); // UG_LOG("type Edg " << typeid( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getEdge() ).name() << std::endl); // UG_LOG("type Vec " << typeid( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getNormal() ).name() << std::endl); - static_assert( std::is_same< decltype( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getFace() ), Face * >::value ); - static_assert( std::is_same< decltype( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getEdge() ), Edge * >::value ); - static_assert( std::is_same< decltype( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getNormal() ), vector3 const >::value ); + //static_assert( std::is_same< decltype( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getFace() ), Face * >::value ); + //static_assert( std::is_same< decltype( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getEdge() ), Edge * >::value ); + //static_assert( std::is_same< decltype( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getNormal() ), vector3 const >::value ); } } @@ -895,21 +895,21 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c std::vector & allAssoEdges = aaVrtInfoAssoEdges[*iterV]; - static_assert( std::is_same< decltype( vecVertFracTrip[ vecVertFracTrip.size() - 1 ].getFace() ), Face * >::value ); - static_assert( std::is_same< decltype( vecVertFracTrip[ vecVertFracTrip.size() - 1 ].getEdge() ), Edge * >::value ); - static_assert( std::is_same< decltype( vecVertFracTrip[ vecVertFracTrip.size() - 1 ].getNormal() ), vector3 const >::value ); + //static_assert( std::is_same< decltype( vecVertFracTrip[ vecVertFracTrip.size() - 1 ].getFace() ), Face * >::value ); + //static_assert( std::is_same< decltype( vecVertFracTrip[ vecVertFracTrip.size() - 1 ].getEdge() ), Edge * >::value ); + //static_assert( std::is_same< decltype( vecVertFracTrip[ vecVertFracTrip.size() - 1 ].getNormal() ), vector3 const >::value ); - for( auto const & vft : vecVertFracTrip ) - { - static_assert( std::is_same< decltype( vft.getFace() ), Face * >::value ); - static_assert( std::is_same< decltype( vft.getEdge() ), Edge * >::value ); - static_assert( std::is_same< decltype( vft.getNormal() ), vector3 const >::value ); - - Face * f = vft.getFace(); - Edge * e = vft.getEdge(); - vector3 n = vft.getNormal(); - - } +// for( auto const & vft : vecVertFracTrip ) +// { +// //static_assert( std::is_same< decltype( vft.getFace() ), Face * >::value ); +// //static_assert( std::is_same< decltype( vft.getEdge() ), Edge * >::value ); +// //static_assert( std::is_same< decltype( vft.getNormal() ), vector3 const >::value ); +// +// Face * f = vft.getFace(); +// Edge * e = vft.getEdge(); +// vector3 n = vft.getNormal(); +// +// } using VvftIterator = VecVertFracTrip::iterator; @@ -920,7 +920,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c // for( auto const & ifac : assoFaces ) // { -// static_assert( std::is_same< decltype( ifac ), Face * const & >::value ); +// //static_assert( std::is_same< decltype( ifac ), Face * const & >::value ); // } @@ -999,7 +999,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c int dbg_iteratorAblaufen = 0; -#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX +#if WORKAROUND_SEGFAULT_CREATE_VERTEX int dbg_laenge = 0; @@ -1028,7 +1028,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c ) { -#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX +#if WORKAROUND_SEGFAULT_CREATE_VERTEX dbg_laenge_eins++; if( dbg_laenge_eins > dbg_laenge ) @@ -1044,7 +1044,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c -#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX +#if WORKAROUND_SEGFAULT_CREATE_VERTEX UG_LOG("NORMAL " << vvftV->getNormal() << std::endl); UG_LOG("LAENGE EINZ " << dbg_laenge_eins << std::endl ); @@ -1167,17 +1167,17 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c for( auto const & facFrac : attFac ) { -// static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype ( ifac ) >::value ); - static_assert( std::is_same< decltype( (facFrac) ), decltype ( ifac ) >::value ); +// //static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype ( ifac ) >::value ); + //static_assert( std::is_same< decltype( (facFrac) ), decltype ( ifac ) >::value ); if( ifac == facFrac ) { isFromFrac = true; -// static_assert( std::is_same< decltype( const_cast(facFrac) ), Face * & >::value ); - static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value ); -// static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype( ifac ) >::value ); - static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value ); +// //static_assert( std::is_same< decltype( const_cast(facFrac) ), Face * & >::value ); + //static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value ); +// //static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype( ifac ) >::value ); + //static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value ); } } @@ -1239,7 +1239,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c atRightSide = true; -#if ANSCHAULICH_ERZEUGE_SUDOS_ANHANG +#if GRAPHICAL_SUDO_CREATION_DBG Vertex * otherFacCent = *grid.create(); aaPos[otherFacCent] = facCenter; @@ -1373,7 +1373,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c int dbg_iteratorAblaufen = 0; -#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX +#if WORKAROUND_SEGFAULT_CREATE_VERTEX int dbg_laenge = 0; @@ -1435,7 +1435,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c ) { -#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX +#if WORKAROUND_SEGFAULT_CREATE_VERTEX dbg_laenge_eins++; if( dbg_laenge_eins > dbg_laenge ) @@ -1459,7 +1459,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c ) { -#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX +#if WORKAROUND_SEGFAULT_CREATE_VERTEX dbg_laenge_zwei++; if( dbg_laenge_zwei > dbg_laenge ) @@ -1681,7 +1681,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c // for( std::vector::iterator iterF2 = attFac.begin(); iterF2 != attFac.end(); iterF2++ ) // { -// static_assert( std::is_same< decltype( *iterF2 ), decltype ( *iterFac ) >::value ); +// //static_assert( std::is_same< decltype( *iterF2 ), decltype ( *iterFac ) >::value ); // // } @@ -1695,7 +1695,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c // // UG_LOG("type iter Fac " << typeid( *iterFac ).name() << std::endl); - static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype ( *iterFac ) >::value ); + //static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype ( *iterFac ) >::value ); @@ -1704,8 +1704,8 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c { isFromFrac = true; - static_assert( std::is_same< decltype( const_cast(facFrac) ), Face * & >::value ); - static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype( * iterFac ) >::value ); + //static_assert( std::is_same< decltype( const_cast(facFrac) ), Face * & >::value ); + //static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype( * iterFac ) >::value ); } } @@ -1751,7 +1751,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c atRightSide = true; -#if ANSCHAULICH_ERZEUGE_SUDOS_ANHANG +#if GRAPHICAL_SUDO_CREATION_DBG Vertex * otherFacCent = *grid.create(); aaPos[otherFacCent] = facCenter; @@ -1864,7 +1864,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c // for( auto const & ifac : assoFaces ) // { - // static_assert( std::is_same< decltype( ifac ), Face * const & >::value ); + // //static_assert( std::is_same< decltype( ifac ), Face * const & >::value ); // // // TODO FIXME folgenden loop durch diesen ersetzen // // Achtung: Zeigerproblematik, Referenzen, etc..... @@ -1884,17 +1884,17 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c for( auto const & facFrac : attFac ) { -// static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype ( ifac ) >::value ); - static_assert( std::is_same< decltype( (facFrac) ), decltype ( ifac ) >::value ); +// //static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype ( ifac ) >::value ); + //static_assert( std::is_same< decltype( (facFrac) ), decltype ( ifac ) >::value ); if( ifac == facFrac ) { isFromFrac = true; -// static_assert( std::is_same< decltype( const_cast(facFrac) ), Face * & >::value ); - static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value ); -// static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype( ifac ) >::value ); - static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value ); +// //static_assert( std::is_same< decltype( const_cast(facFrac) ), Face * & >::value ); + //static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value ); +// //static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype( ifac ) >::value ); + //static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value ); } } @@ -1938,7 +1938,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c atRightSide = true; -#if ANSCHAULICH_ERZEUGE_SUDOS_ANHANG +#if GRAPHICAL_SUDO_CREATION_DBG Vertex * otherFacCent = *grid.create(); aaPos[otherFacCent] = facCenter; @@ -2062,13 +2062,13 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c // verkettete Liste der anhängenden fractures in Reihenfolge // der Anhängung mit INfo, ob eine Kluft vorliegt - for( auto const & attVFT : vecVertFracTrip ) - { - Edge * edg = attVFT.getEdge(); - Face * fac = attVFT.getFace(); - vector3 nv = attVFT.getNormal(); - } - +// for( auto const & attVFT : vecVertFracTrip ) +// { +// Edge * edg = attVFT.getEdge(); +// Face * fac = attVFT.getFace(); +// vector3 nv = attVFT.getNormal(); +// } +// // // hier werden ALLE attached Faces benötigt, auch die, die zwischen den direkt an den fractures liegenden Faces sind // // copies of all faces and of fractured ones @@ -2129,7 +2129,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c vector3 startNormal = fracNorm; - Face* nextFace = NULL; +// Face* nextFace = NULL; UG_LOG("Gesamtanzahl faces um Knoten vor while " << aF.size() << std::endl ); @@ -2448,7 +2448,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c // at end, chech if we have arrived again at original first edge - int totalSubsNum = sh.num_subsets(); +// int totalSubsNum = sh.num_subsets(); // int newSubsToAdd = totalSubsNum; @@ -2942,9 +2942,9 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c // std::vector verticesEdg; - static_assert( std::is_same< Edge* const &, decltype( bE ) >::value ); + //static_assert( std::is_same< Edge* const &, decltype( bE ) >::value ); - static_assert( std::is_same< Vertex*, decltype( bE->vertex(0) ) >::value ); + //static_assert( std::is_same< Vertex*, decltype( bE->vertex(0) ) >::value ); IndexType fndIV = 0; @@ -2984,7 +2984,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c -#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX +#if WORKAROUND_SEGFAULT_CREATE_VERTEX IndexType dbg_lim = vecVertFracTrip.size(); @@ -2996,7 +2996,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c vvftAtBnd++ ) { -#if NOTLOESUNG_EINSCHALTEN_SEGFAULT_CREATE_VERTEX +#if WORKAROUND_SEGFAULT_CREATE_VERTEX if( dbg_lim == dbg_cnt ) { @@ -3115,7 +3115,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c atRightSide = true; -#if ANSCHAULICH_ERZEUGE_SUDOS_ANHANG +#if GRAPHICAL_SUDO_CREATION_DBG Vertex * otherFacCent = *grid.create(); aaPos[otherFacCent] = facCenter; sh.assign_subset(otherFacCent, 5 ); @@ -3225,7 +3225,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c atRightSide = true; -#if ANSCHAULICH_ERZEUGE_SUDOS_ANHANG +#if GRAPHICAL_SUDO_CREATION_DBG Vertex * otherFacCent = *grid.create(); aaPos[otherFacCent] = facCenter; sh.assign_subset(otherFacCent, 5 ); @@ -3423,7 +3423,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c // // remove the temporary attachments and throw an error // // // remove the temporary attachments -//#if OLD_PROFREITER_STUFF +//#if FORMER_EXPANSION_TECHNIQUES // grid.detach_from_vertices(aAdjMarker); // grid.detach_from_edges(aAdjMarker); //#endif @@ -3517,7 +3517,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c // remove the temporary attachments -#if OLD_PROFREITER_STUFF +#if FORMER_EXPANSION_TECHNIQUES grid.detach_from_vertices(aAdjMarker); grid.detach_from_edges(aAdjMarker); #endif @@ -3544,7 +3544,7 @@ bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, vector c -#if OLD_PROFREITER_STUFF +#if FORMER_EXPANSION_TECHNIQUES // TODO FIXME von diesem Loop kann man noch für oben die calculate crease normal lernen, vielleicht minimal abgewandelt, vielleicht exakt gleich // a callback that returns true if the edge is a fracture edge, neues System diff --git a/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.h b/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.h index 8f7056291..d38c7fb52 100644 --- a/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.h +++ b/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.h @@ -15,9 +15,8 @@ namespace ug * 2 dimensional fracture expansion for finite extensions, using the Arte algorithm * */ -bool ExpandFractures2dArte(Grid& grid, SubsetHandler& sh, - const std::vector& fracInfos, - bool expandInnerFracBnds, bool expandOuterFracBnds); +bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, std::vector const & fracInfos, + bool expandInnerFracBnds, bool expandOuterFracBnds ); From 68bacc5703ead81da8bc5587e8abe84f42d0dbfa Mon Sep 17 00:00:00 2001 From: Markus Date: Thu, 1 Aug 2024 03:27:12 +0200 Subject: [PATCH 45/58] empty function to allow Jenkins to be successful --- .../extrusion/expand_layers_arte.cpp | 3560 +---------------- 1 file changed, 2 insertions(+), 3558 deletions(-) diff --git a/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.cpp b/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.cpp index 1f53b9f5a..6a3134911 100644 --- a/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.cpp +++ b/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.cpp @@ -24,3567 +24,11 @@ #include "support.h" namespace ug{ -using VertFracTrip = VertexFractureTriple; -//using VecVertFracTrip = std::vector; - -//using VvftIterator = VecVertFracTrip::iterator; - -using std::vector; - -typedef Attachment > AttVrtVec; - -using VertexOfFaceInfo = VertexFractureTriple< std::pair, Face*, std::pair >; - - -using IndexType = unsigned short; - -template -bool expandSingleFractureAtGivenSide( vector3 const & nOne, vector3 const & nTwo, - Edge * edgeOne, Edge * edgeTwo, - Face * facOne, Face * facTwo, - vector const & fracInfosBySubset, - vector3 const & posOldVrt, - Grid::VertexAttachmentAccessor & aaPos, - Grid & grid, SubsetHandler & sh, - ASOF const & assoFaces, - std::vector const & nextFracVrt, - Grid::FaceAttachmentAccessor & aaVrtVecFace, - int & dbg_flachen_passiert, - Vertex * iterV - ) +bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, std::vector const & fracInfos, + bool expandInnerFracBnds, bool expandOuterFracBnds ) { -#if 1 - // gleiche Seite vermutet oder gegeben - - // average the normals - - vector3 normSum; - - VecAdd( normSum, nOne, nTwo ); - - vector3 normSumNormed; - - VecNormalize(normSumNormed, normSum); - - UG_LOG("averaged normal " << normSumNormed << std::endl); - - std::vector attEdg; - std::vector attFac; - - attEdg.push_back( edgeOne ); - attEdg.push_back( edgeTwo ); - - attFac.push_back( facOne ); - attFac.push_back( facTwo ); - - // jetzt neuen Vertex erzeugen in Richtung der Normalen - // sonst ist das attachment Schwachsinn! - - vector3 posNewVrt; - - vector3 moveVrt; - - auto subsIndEdgOne = sh.get_subset_index(edgeOne); - - auto subsIndEdgTwo = sh.get_subset_index(edgeTwo); - - if( subsIndEdgOne != subsIndEdgTwo ) - { - UG_THROW("subsets passen nicht Vereinheitlichung" << std::endl ); - } - - number width = fracInfosBySubset.at(subsIndEdgOne).width; - - // der Faktor ist Käse und muss noch aus den Eingaben übernommen werden - VecScale(moveVrt, normSumNormed, width/2. ); - - VecAdd(posNewVrt, posOldVrt, moveVrt ); - - UG_LOG("neuer Vertex " << posNewVrt << std::endl ); - - // TODO FIXME hier ist das PROBLEM, SEGFAULT durch create regular vertex - - Vertex * newShiftVrtx = *grid.create(); - aaPos[newShiftVrtx] = posNewVrt; - - sh.assign_subset(newShiftVrtx, subsIndEdgOne ); - - - - // alle anhängenden faces müssen noch zu wissen bekommen - // dass es diesen neuen Vertex gibt, nicht nur die - // an den edges anhängenden - // vielleicht gibt es einen Loop über attached faces des - // Vertex, für die schon bekannten direkt angehängten klar - // wenn auch dort vermerkt werden muss im Attachment von Seb - // bei den anderen, die keine Edge haben von der Kluft - // da muss man die Normale ins Zentrum bestimmen - // um heraus zu finden, ob sie auf dieser seite sind - // am besten dann das Attachment der faces für vertizes - // von Seb recyclen - - // loop über assosciated faces des vertex am besten - // vermutlich auch noch assosciated edges, um - // zu markieren, welche weg fallen sollen, wenn - // nicht von Kluft selber, sondern quasi verschoben - // und neu erzeugt - - int dbg_FaceIterator = 0; - - for( auto const & ifac : assoFaces ) - { - bool isFromFrac = false; - - int dbg_innterFacFracIt = 0; - - for( auto const & facFrac : attFac ) - { - - //static_assert( std::is_same< decltype( (facFrac) ), decltype ( ifac ) >::value ); - - if( ifac == facFrac ) - { - isFromFrac = true; - - //static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value ); - //static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value ); - - } - } - - bool atRightSide = false; - - if( isFromFrac ) - atRightSide = true; - - if( !isFromFrac ) - { - // check if on same side of edge where the normal points to: compute cosinus between vector of face center - // perpendicular to the edge - - vector3 facCenter = CalculateCenter( ifac, aaPos ); - - vector3 perpendicu; - - if( nextFracVrt.size() != 2 ) - { - UG_THROW("komische Groesse" << std::endl); - } - - DropAPerpendicular(perpendicu, facCenter, aaPos[nextFracVrt[0]], aaPos[nextFracVrt[1]]); - - vector3 tmpN; - - VecSubtract(tmpN, facCenter, perpendicu ); - - VecNormalize(tmpN, tmpN); - - UG_LOG("Normale zum Face ist " << tmpN << std::endl); - - number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, normSumNormed ); - - UG_LOG("Cosinus zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); - - if( cosBetwFracEdgAndDirection2Face > 0 ) - { - UG_LOG("assuming face to be on richt side" << std::endl); - - atRightSide = true; - -#if GRAPHICAL_SUDO_CREATION_DBG - - Vertex * otherFacCent = *grid.create(); - aaPos[otherFacCent] = facCenter; - sh.assign_subset(otherFacCent, 5 ); - - Vertex * pp = *grid.create(); - aaPos[pp] = perpendicu; - sh.assign_subset(pp, 6 ); - - sh.assign_subset(*iterFac,7); -#endif - - } - else - { - UG_LOG("assuming face to be on wrong side" << std::endl); - } - - - dbg_flachen_passiert++; - } - - - if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein - { - - // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! - vector& newVrts4Fac = aaVrtVecFace[ ifac ]; - - IndexType vrtxFnd = 0; - - for(size_t indVrt = 0; indVrt < (ifac)->num_vertices(); indVrt++ ) - { - Vertex* facVrt = (ifac)->vertex(indVrt); - - if( facVrt == iterV ) - { - newVrts4Fac[ indVrt ] = newShiftVrtx; - vrtxFnd++; - } - } - - - if( vrtxFnd <= 0 ) - { - UG_THROW("vertex not found!" << std::endl); - } - else if( vrtxFnd > 1 ) - { - UG_THROW("vertex zu oft gefunden " << vrtxFnd << std::endl ); - } - else if ( vrtxFnd == 1 ) - { - } - else - { - UG_THROW("vertex finden komisch " << std::endl); - } - - - } - - dbg_innterFacFracIt++; - - - - dbg_FaceIterator++; - - } -#endif - return true; - } - -#ifndef WORKAROUND_SEGFAULT_CREATE_VERTEX -#define WORKAROUND_SEGFAULT_CREATE_VERTEX 1 -#endif - -#ifndef GRAPHICAL_SUDO_CREATION_DBG -#define GRAPHICAL_SUDO_CREATION_DBG 0 -#endif - -#ifndef FORMER_EXPANSION_TECHNIQUES -#define FORMER_EXPANSION_TECHNIQUES 0 -#endif - -bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, vector const & fracInfos, - bool expandInnerFracBnds, bool expandOuterFracBnds ) -{ - -// static constexpr bool dehneInnereKluftGrenzpunkteAus = false; - -// expandInnerFracBnds = false; - -// expandOuterFracBnds = true; - -// access position attachment - if(!grid.has_vertex_attachment(aPosition)){ - UG_LOG("Error in ExpandFractures 2D Arte: Missing position attachment"); - return false; - } - Grid::VertexAttachmentAccessor aaPos(grid, aPosition); - - if(!grid.option_is_enabled(FACEOPT_AUTOGENERATE_EDGES)){ - UG_LOG("WARNING in Arte 2D CalculateCreaseNormal: grid option FACEOPT_AUTOGENERATE_EDGES autoenabled.\n"); - grid.enable_options(FACEOPT_AUTOGENERATE_EDGES); - } - -// objects for temporary results - FaceDescriptor fd; - vector edges; // used for temporary results. - vector faces; // used for temporary results. - -// vectors that allow to access fracture properties by subset index - vector fracInfosBySubset(sh.num_subsets(), FractureInfo(-1, -1, 0)); - for(size_t i = 0; i < fracInfos.size(); ++i){ - if(fracInfos[i].subsetIndex >= sh.num_subsets()){ - throw(UGError("Bad subsetIndex in given fracInfos.")); - } - - fracInfosBySubset[fracInfos[i].subsetIndex] = fracInfos[i]; - } - -//////////////////////////////// -// Collect surrounding faces of all fractures in a selector -// and select edges and vertices too. - Selector sel(grid); - sel.enable_autoselection(false); - sel.enable_selection_inheritance(false); - -#if FORMER_EXPANSION_TECHNIQUES - AInt aAdjMarker; // used to mark how many adjacent fractures a vertex has. - // 0: no frac, 1: frac-boundary, >1: inner frac vertex - // TODO FIXME das sieht komisch aus, ist das immer so, wenn z.B. an einer Grenze sich zwei fracs treffen? - grid.attach_to_vertices_dv(aAdjMarker, 0); - Grid::VertexAttachmentAccessor aaMarkVRT(grid, aAdjMarker); - grid.attach_to_edges_dv(aAdjMarker, 0); - Grid::EdgeAttachmentAccessor aaMarkEDGE(grid, aAdjMarker); -#endif - -// using IndexType = unsigned short; - using AttVerFracProp = Attachment >; - // attachment pair boundary is fracture, number fractures crossing - - AttVerFracProp aAdjMarkerVFP; - - VertexFractureProperties vfp0( false, 0 ); - // default value: no boundary fracture, no fractures crossing - - grid.attach_to_vertices_dv(aAdjMarkerVFP, vfp0 ); - Grid::VertexAttachmentAccessor aaMarkVrtVFP(grid, aAdjMarkerVFP); - - ABool aAdjMarkerB; // used to know if an edge is frac edge - grid.attach_to_edges_dv(aAdjMarkerB, false); - Grid::EdgeAttachmentAccessor aaMarkEdgeB(grid, aAdjMarkerB); - - - // die Vertizes, Faces und Edges, die mit einer Kluft zu tun haben - -// using VertFracTrip = VertexFractureTriple; -// - using VecVertFracTrip = std::vector; - - VecVertFracTrip vertexNoInfo; - - using AttVecVertFracTrip = Attachment; - - AttVecVertFracTrip aAdjInfoAVVFT; - - grid.attach_to_vertices_dv( aAdjInfoAVVFT, vertexNoInfo ); - Grid::VertexAttachmentAccessor aaVrtInfoFraTri(grid, aAdjInfoAVVFT ); - - - using VecEdge = std::vector; - using VecFace = std::vector; - - using AttVecEdge = Attachment; - using AttVecFace = Attachment; - - VecEdge noEdge; - VecFace noFace; - AttVecEdge aAdjInfoEdges; - AttVecFace aAdjInfoFaces; - - grid.attach_to_vertices_dv( aAdjInfoEdges, noEdge ); - Grid::VertexAttachmentAccessor aaVrtInfoAssoEdges( grid, aAdjInfoEdges ); - - grid.attach_to_vertices_dv( aAdjInfoFaces, noFace ); - Grid::VertexAttachmentAccessor aaVrtInfoAssoFaces( grid, aAdjInfoFaces ); - - // das ist Käse, ich brauche für jeden Vertex ein Attachment der Form - // class VertexTriple, bzw std vektoren von solchen vertex triplen - // da weiss dann jeder Vertex das triple - // Kante (damit subdom) - Face - normal (von Kante in Face rein) - // dann kann man nämlich anhand des Winkels von zwei Normalen - // von solchen Vertizes bestimmtn, ob sie auf die gleiche Seite der Kante zeigen - // und dann kann man sie mitteln, sofern die Vertizes keine Kreuzungs Vertizes sind - // oder keine äusseren Vertizes - ob sie dsa sind, dafür haben wir schon attachments! - - // TODO FIXME diese komischen accessoren sollen jetzt so zugewiesen - // werden, dass - /* - * jeder Kluftvertex soll wissen, welche Kluftedges ihm anliegen, und welche faces - * jede Kluftedge soll wissen, welche Vertizes ihr anliegen, und welche faces - * jedes Face, das an eine Kluft anliegt, soll wissen, welche Vertizes und Edges - * ihm anliegen - * letzteres muss man vielleicht noch ausdehnen, indem man subdomain indizes - * dazu bringt - * das kann auch notwendig sein fuer alle anderen - wirklich? - * die edges und faces kennen ihre subdomain - * nur beim Vertex kann in Kreuzungspunkten ein Problem sein - * zudem ist die subdomain der faces EGAL, im Zweifel entscheidet die subdomain - * der edges, die anliegen bzw der edge, die anliegt! - * - */ - -// iterate over the given fracture infos and select all fracture edges -// and fracture vertices. - for(size_t i_fi = 0; i_fi < fracInfos.size(); ++i_fi) - { - int fracInd = fracInfos[i_fi].subsetIndex; - - for(EdgeIterator iter = sh.begin(fracInd); iter != sh.end(fracInd); ++iter) - { - // mark edge and vertices - sel.select(*iter); - -#if FORMER_EXPANSION_TECHNIQUES - aaMarkEDGE[*iter] = 1; -#endif - - aaMarkEdgeB[*iter] = true; - - // select associated vertices - for(size_t i = 0; i < 2; ++i) - { - Vertex* v = (*iter)->vertex(i); - sel.select(v); - - // wird in jedem Fall inkrimiert, da der Vertex auf jeden Fall mit einer Kante einer frac verbunden sein muss, sonst darf der loop gar nicht darüber gehen - aaMarkVrtVFP[v]++; - - if( IsBoundaryVertex2D(grid, v) ) - aaMarkVrtVFP[v].setIsBndFracVertex(); - - -#if FORMER_EXPANSION_TECHNIQUES - // das ist Sebastians loop, den nicht mehr lassen lassen - // if fracture boundaries are expanded, we'll regard all fracture vertices - // as inner vertices - if(expandInnerFracBnds) - { - if(!expandOuterFracBnds) - { - if(IsBoundaryVertex2D(grid, v)) - aaMarkVRT[v]++; - else - aaMarkVRT[v] = 2; - } - else - aaMarkVRT[v] = 2; - } - else - aaMarkVRT[v]++; -#endif - - } - } - } - - -#if FORMER_EXPANSION_TECHNIQUES -// Make sure that selected vertices that lie on the boundary of the geometry -// are treated as inner fracture vertices. -// This is only required if frac-boundaries are not expanded anyways. - if(expandOuterFracBnds && !expandInnerFracBnds){ - for(VertexIterator iter = sel.vertices_begin(); - iter != sel.vertices_end(); ++iter) - { - Vertex* v = *iter; - if(aaMarkVRT[v] == 1){ - if(IsBoundaryVertex2D(grid, v)) - aaMarkVRT[v] = 2; - } - } - } - // TODO FIXME was soll das fuer ein Kaese sein? -#endif - - int dbg_flachen_passiert = 0; - - for(VertexIterator iter = sel.begin(); iter != sel.end(); ++iter) - { - - bool wahl = true; - - - // so stimmt es vielleicht, aber ist auch ein komischer Fall, innen expandieren und aussen nicht...... die Frage ist, ob es oonst Sinn macht..... - if( expandInnerFracBnds && !expandOuterFracBnds && aaMarkVrtVFP[*iter].getIsBndFracVertex() ) - wahl = false; - - //static_assert( std::is_same< decltype(*iter), Vertex * >::value ); - - bool isBnd = aaMarkVrtVFP[ *iter ].getIsBndFracVertex(); - auto numCrosFrac = aaMarkVrtVFP[ *iter ].getNumberFracEdgesInVertex(); - - if( ! isBnd && numCrosFrac == 1 ) - { - wahl = false; - } - -// if( ! dehneInnereKluftGrenzpunkteAus ) -// { -// if( numCrosFrac == 1 ) // inner frac boundary vertex -// { -// wahl = false; -// } -// } - - - if( wahl ) - { - sel.select(grid.associated_edges_begin(*iter), - grid.associated_edges_end(*iter)); - sel.select(grid.associated_faces_begin(*iter), - grid.associated_faces_end(*iter)); - - // TODO FIXME hier ein attachment der associated faces und vertizes, am besten als Klasse, die std vertizes davon frisst, an jeden Vertex anhängen - // so muss man später nicht nochmal über alle Faces und Edges laufen, sondern hat die angehängten schon zur Hand - // im Fall, dass eine Kreuzung vorliegt, das Ganze irgendwann ordnen, dass nebeneinander liegende Faces und edges in eine verkettete Liste kommen - // vielleicht das aber nur bei den Schnittvertizes später - // und vielleicht sollen die Faces Zeiger auf ihre Edges bekommen, und die edges auf die faces, aber wird irgendwann zu wild verzeigert..... - // vielleicht einfach attachment von faces und edges unabhängig an jeden Fracture Vertex...... - - // testen, ob ein Schnittvertex vor liegt, indem die Anzahl der touches getestet wird, anhand einfacher Geometrien testen, was die Anzahl ist - - // mit UG_LOG ausgeben, was die Koordinaten sind, und die Anzahl der hits - - VecFace assFac; - VecEdge assEdg; - -// UG_LOG("----------" << std::endl); - - for( std::vector::iterator iterFac = grid.associated_faces_begin(*iter); iterFac != grid.associated_faces_end(*iter); iterFac++ ) - { - assFac.push_back(*iterFac); -// vector3 facCenter = CalculateCenter( *iterFac, aaPos ); -// UG_LOG("fac center " << facCenter << std::endl); - -// sh.assign_subset(*iterFac, 10); - } - -// UG_LOG("----------" << std::endl); - - for( std::vector::iterator iterEdg = grid.associated_edges_begin(*iter); iterEdg != grid.associated_edges_end(*iter); iterEdg++ ) - { - assEdg.push_back(*iterEdg); -// sh.assign_subset(*iterEdg,10); - } - - aaVrtInfoAssoFaces[*iter] = assFac; - aaVrtInfoAssoEdges[*iter] = assEdg; - - UG_LOG("marked vertex wahl: " << aaPos[*iter] << " is bnd " << isBnd << " number cross frac " << numCrosFrac << std::endl ); - - // fuer Nicht Boundary Vertizes muessen wir durch 2 teilen, damit wir richtige Anzahl der - // Fracs haben, die durch den spezifischen Vertex durch geht - // FALSCH war mal so, ist schon abgestellt, es wird angezeigt, wieviele Ecken von Kanten rein kommen - - } - else - { - UG_LOG("marked vertex unwahl: " << aaPos[*iter] << " is bnd " << isBnd << " number cross frac " << numCrosFrac << std::endl ); - } - - } - -// return true; - - using pairIndDbl = std::pair; - - std::vector< pairIndDbl > fracSubdom_facePerpendMinVal; - - for( auto const & pf: fracInfos ) - { - fracSubdom_facePerpendMinVal.push_back( pairIndDbl( pf.subsetIndex, std::numeric_limits::max() ) ); - } - - T_min minDistPerpOverall( std::numeric_limits::max() ); - -// for( auto fI : fracInfos ) -// for( size_t fraInfInd = 0; fraInfInd < fracInfos.size(); fraInfInd++ ) - for( auto & fsfpmv : fracSubdom_facePerpendMinVal ) - { -// int fracInd = fracInfos[fraInfInd].subsetIndex; -// int fracInd = fI.subsetIndex; - - auto fracInd = fsfpmv.first; - - T_min minDistPerpThisFrac( fsfpmv.second ); - - for(EdgeIterator iterEdg = sh.begin(fracInd); iterEdg != sh.end(fracInd); iterEdg++ ) - { - - // get subdomain of edge - -// auto sudoEdg = sh.get_subset_index(*iterEdg); - - //static_assert( std::is_same< decltype(sudoEdg), int >::value ); - - // get vertices of edge, always 2 - - std::vector verticesEdg; - - //static_assert( std::is_same< Vertex*, decltype( (*iterEdg)->vertex(0) ) >::value ); - - for( size_t i = 0; i < 2; ++i ) - verticesEdg.push_back( (*iterEdg)->vertex(i) ); - - // get attached faces - -#if 0 - std::vector assFace; - - // TODO FIXME dieser loop kann vielleicht vereinfacht werden, wenn dieser ganze loop umgebaut wird - // denn die Vertizes kennen dann die assosciated faces schon - // der Name AssociatedFaceIterator ist sowieso verwirrend, hat mit assosciated nix zu tun, bezieht sich auf alle std Vektoren von Face * - UG_LOG("XXXXXXXXXXXX" << std::endl); - for(Grid::AssociatedFaceIterator iterAFI = grid.associated_faces_begin( verticesEdg[0] ); - iterAFI != grid.associated_faces_end( verticesEdg[0] ); - iterAFI++ ) - { - - if(FaceContains( *iterAFI, *iterEdg )) - { - assFace.push_back( *iterAFI ); - - - vector3 facCenter = CalculateCenter( *iterAFI, aaPos ); - UG_LOG("fac center " << facCenter << std::endl); - - - -// sh.assign_subset( *iterAFI, sh.get_subset_index(*iterEdg)); - } - - } - UG_LOG("XXXXXXXXX" << std::endl); -#else - - std::vector & assFaceVrt0 = aaVrtInfoAssoFaces[verticesEdg[0]]; - - std::vector assFace; - -// //static_assert( std::is_same< decltype( aaVrtInfoAssoFaces[verticesEdg[0]] )[0], std::vector >::value ); - ////static_assert( std::is_same< decltype( *(aaVrtInfoAssoFaces[verticesEdg[0]]) ), Face * >::value ); - -// UG_LOG("XXXXXXXXXXXX" << std::endl); - - for( auto const & ifa : assFaceVrt0 ) - { - if(FaceContains( ifa, *iterEdg )) - { - assFace.push_back( ifa ); - -// vector3 facCenter = CalculateCenter( ifa, aaPos ); -// UG_LOG("fac center " << facCenter << std::endl); - } - } - - std::vector & assFaceVrt1 = aaVrtInfoAssoFaces[verticesEdg[1]]; - - for( auto const & ifa : assFaceVrt1 ) - { - if(FaceContains( ifa, *iterEdg )) - { - bool faceContained = false; - - for( auto const & afa : assFace ) - { - if( afa == ifa ) - faceContained = true; - } - - if( !faceContained ) - assFace.push_back( ifa ); - } - } - - -// UG_LOG("XXXXXXXXX" << std::endl); - -#endif - // von hier lernen: - // VecFace & assoFaces = aaVrtInfoAssoFaces[*iterV ist verticesEdg[0] ]; - // for( auto const & ifac : assoFaces ) - // { - // //static_assert( std::is_same< decltype( ifac ), Face * const & >::value ); - // } - - - - // compute normal of edge - - std::vector< vector3 > edgeNormals; - - std::vector perpendDistances; - - for( auto const & fac : assFace ) - { - vector3 facCenter = CalculateCenter( fac, aaPos ); - - vector3 perpendicu; - - DropAPerpendicular(perpendicu, facCenter, aaPos[verticesEdg[0]], aaPos[verticesEdg[1]]); - - double perpendDist = VecLength( perpendicu ); // betrag perpendicu - - perpendDistances.push_back( perpendDist ); - - minDistPerpThisFrac( perpendDist ); - - - // vector from projection to center is the unnormalized normal - vector3 tmpN; - - VecSubtract(tmpN, facCenter, perpendicu ); - - VecNormalize(tmpN, tmpN); - - edgeNormals.push_back( tmpN ); - - //static_assert( std::is_same< Edge*, decltype(*iterEdg) >::value ); - - //static_assert( std::is_same< Face * const &, decltype(fac) >::value ); - //static_assert( std::is_same< Face *, decltype( const_cast(fac) ) >::value ); - //static_assert( std::is_same< vector3, decltype( tmpN ) >::value ); - - VertFracTrip infoVertizesThisEdge( *iterEdg, fac, tmpN ); - -// UG_LOG("TypE Fac " << typeid(const_cast(fac) ).name() << std::endl); -// UG_LOG("TypE Edg " << typeid( *iterEdg ).name() << std::endl); -// UG_LOG("TypE Vec " << typeid( tmpN ).name() << std::endl); - - - for( auto const & v : verticesEdg ) - { - //static_assert( std::is_same< decltype(v), Vertex * const & >::value ); - //static_assert( std::is_same< decltype(const_cast(v)), Vertex * >::value ); - aaVrtInfoFraTri[v].push_back( infoVertizesThisEdge ); - -// VecVertFracTrip allInfosVrtxThisEdg = aaVrtInfoFraTri[v]; - -// //static_assert( std::is_same< decltype( aaVrtInfoFraTri[v] ), VecVertFracTrip >::value ); - -// UG_LOG("type Fac " << typeid( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getFace() ).name() << std::endl); -// UG_LOG("type Edg " << typeid( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getEdge() ).name() << std::endl); -// UG_LOG("type Vec " << typeid( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getNormal() ).name() << std::endl); - - //static_assert( std::is_same< decltype( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getFace() ), Face * >::value ); - //static_assert( std::is_same< decltype( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getEdge() ), Edge * >::value ); - //static_assert( std::is_same< decltype( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getNormal() ), vector3 const >::value ); - } - - } - - // damit speichern wir die plus und minus Normale, und das ist alles, und auch - // gleich wieder weg - // TODO FIXME besser, wir speichern die gemittelte Normale an den Vertizes - // vielleihct als attachment pair, das die subdom kennt der frac und die Normale dazu? - // ziemlich nutzlos, die Normale wie hier gemacht in einen kurzen Vektor zu speichern, der schnell - // wieder weg ist...... - // wir brauchen alle Normalen zu jeder fracture an jedem fracture Vertex, also die Mittelung vermutlich - // diese Mittelung kann aber erst stattfinden, wenn wir nachher über die vertizes loopen, - // hier kennen wir nur die Vertizes, die an derselben Edge anliegen - - UG_LOG("EDGE NORMALS: " << sh.get_subset_index(*iterEdg) << " -> "); - - int j = 0; - - for( auto const & en: edgeNormals ) - { - - for( size_t i = 0; i < 3; i++ ) - UG_LOG( en[i] << ", " ); - - - UG_LOG(" --- " << perpendDistances[j] << " ///////// " ); - - j++; - } - - UG_LOG(std::endl); - - } - - fsfpmv.second = minDistPerpThisFrac(); - - minDistPerpOverall( fsfpmv.second ); - - UG_LOG("first " << fsfpmv.first << " second " << fsfpmv.second << std::endl); - } - - for( auto const & fsfpmv : fracSubdom_facePerpendMinVal ) - { - UG_LOG("min dist sd " << fsfpmv.first << " -> " << fsfpmv.second << std::endl ); - } - - UG_LOG("overall min dist " << minDistPerpOverall() << std::endl); - - - - // von Sebastian teilweise das Prinzip übernommen, dass die Faces wissen können, was ihre neuen Vertizes sein sollen - // create new vertices - - // we have to associate a vector of vertices with each node in the fracture. - // since an empty vector is quite small, we can associate one with each vertex in - // the whole grid. This could be optimized if required, by using subset attachments. - - // es reicht vielleicht, hier statt einem Vektor einfach nur einen Vertex * zu storen -// using AttVrtVec = Attachment >; - AttVrtVec attVrtVec; - - // we associate a vector of vertices for each face adjacent to the frac. - // it will store a set of vertices. An entry contains the new vertex, if the - // corresponding vertex is an inner fracture vertex, and NULL if not. - grid.attach_to_faces(attVrtVec); - Grid::FaceAttachmentAccessor aaVrtVecFace(grid, attVrtVec); - - - // iterate over all surrounding faces to enable face changes, this loop taken from SR but shortened - for(FaceIterator iter_sf = sel.faces_begin(); iter_sf != sel.faces_end(); ++iter_sf) - { - Face* sf = *iter_sf; - - std::vector& newVrts = aaVrtVecFace[sf]; - newVrts.resize(sf->num_vertices()); - - for(size_t i_vrt = 0; i_vrt < sf->num_vertices(); ++i_vrt) - { - newVrts[i_vrt] = NULL; - } - // erstmal so tun, als ob keine neuen Vertizes erzeugt werden an den alten Vertizes - } - - - // attachment to allow fracture vertizes to know the newly created vertizes - // due to extrusion which are related to them, in connection with - // the normals which are an average of the related edges and the faces - // defining the original normal - - // usage: store edges and associated faces in SAME order in std vectors! - using ExpandVertexMultiplett = VertexFractureTriple< std::vector, std::vector, vector3 >; - // holds the averaged normal of the related edges and their corresponding faces which give direction - - using VecExpandVertexMultiplett = std::vector; - - - VecExpandVertexMultiplett vertexMultiplettEmpty; - - using AttVecExpandVertexMultiplett = Attachment; - - AttVecExpandVertexMultiplett aAdjInfoVVEVM; - - grid.attach_to_vertices_dv( aAdjInfoVVEVM, vertexMultiplettEmpty ); - Grid::VertexAttachmentAccessor aaVrtExpMP(grid, aAdjInfoVVEVM ); - - - - // am Ende dieser Prozedur sollten alle Vertizes wissen, welche Tripel vom Typ Edge - Face - Normal zum Face hin an ihnen angelagert sind - - // damit weiss, wenn es stimmt, jeder Vertex, der an einer Fracture ist, wieviele Schnittpunkte von Fractures er hat, - // ob er ein boundary vertex ist, und was für einen Vektor von Tripeln an ihm angehängt sind - // die subdomain der Fracture muss anhand der subdomain der edge bestimmt werden immer - - UG_LOG("loop over all marked vertizes " << std::endl); - - int dbg_vertizesPassiert = 0; - - // jetzt können wir alle Vertizes ablaufen und an ihnen neue Vertizes erzeugen, die anhand der gemittelten Normalen von den Vertizes weg gehen - // ob zwei anhängende Faces auf der gleichen Seite liegen, wenn es kein Schnittvertex von zwei oder mehr Klüften ist - // das kann man anhand des Winkels zwischen zwei face Normalen unterscheiden vermutlich - // dabei müssen die edges sowieso disjunkt sein, sonst ist man sowieso sicher auf verschiedenen Seiten - // wenn wir es mit einem boundary Vertex zu tun haben, müssen wir weiter überlegen, wie wir die Verschiebung auf die äussere Kante projizieren - // muss auch mit dem Winkel zu tun haben - for(VertexIterator iterV = sel.begin(); iterV != sel.end(); ++iterV) - { - - // POsition dieses Vertex - vector3 posOldVrt = aaPos[*iterV]; - - // vielleicht muss man, wenn die neuen Vertizes da sind, diese auch gleich mit den umliegenden Knoten per neuer Kanten verbinden - // und die neuen faces erzeugen nach Löschen der alten? - // oder alle neuen Vertizes wie bei Prof Reiter in einen std Vektor, der als attachment den bisherigen Face Vertizes angehängt wird - // und Edge Vernichtung und Erzeugung neuer edges und faces wie bei Prof Reiter in Folgeschritten? - - VecVertFracTrip & vecVertFracTrip = aaVrtInfoFraTri[*iterV]; - - std::vector & allAssoEdges = aaVrtInfoAssoEdges[*iterV]; - - //static_assert( std::is_same< decltype( vecVertFracTrip[ vecVertFracTrip.size() - 1 ].getFace() ), Face * >::value ); - //static_assert( std::is_same< decltype( vecVertFracTrip[ vecVertFracTrip.size() - 1 ].getEdge() ), Edge * >::value ); - //static_assert( std::is_same< decltype( vecVertFracTrip[ vecVertFracTrip.size() - 1 ].getNormal() ), vector3 const >::value ); - -// for( auto const & vft : vecVertFracTrip ) -// { -// //static_assert( std::is_same< decltype( vft.getFace() ), Face * >::value ); -// //static_assert( std::is_same< decltype( vft.getEdge() ), Edge * >::value ); -// //static_assert( std::is_same< decltype( vft.getNormal() ), vector3 const >::value ); -// -// Face * f = vft.getFace(); -// Edge * e = vft.getEdge(); -// vector3 n = vft.getNormal(); -// -// } - - using VvftIterator = VecVertFracTrip::iterator; - - VecFace & assoFaces = aaVrtInfoAssoFaces[*iterV]; - // TODO FIXME hier braucht man das nicht zu ordnen - // aber bei Kreuzpunkten von Klueften muss es so geordnet werden, wie es nebeneinander liegt - // bei den Edges gibt es auch die benachbarten, und die edges haben das attachment, ob sie Kluftedges sind - -// for( auto const & ifac : assoFaces ) -// { -// //static_assert( std::is_same< decltype( ifac ), Face * const & >::value ); -// } - - - - // Anzahl der Kreuzungspunkte auslesen und danach unterscheiden, erstmal keine Kreuzung! TODO FIXME - - // irgendwie muessen wir diese Infos jetzt verwerten, um als erstes neue Vertizes zu erzeugen, anfangs für eine Kluft nur - // und danach die alten Edges und faces löschen und an neuer Stelle neu erzeugen, plus die sowieso neuen, - // oder Edges verschieben, wenn es möglich ist, die Vertizes zu verschieben, und die Edges und in Folge faces passen sich an, - // dann müssen nur die neuen edges und faces neu erzeugt werden - // verschieben der Position des Vertex löst Kaskade aus, dass Edge und Face auch verschoben werden, kann also angewendet werden - // allerdings Problem, dass die Vertizes dafür verdoppelt werden müssen und die Kanten, sonst kann man sie nicht nach aussen verschieben - // also doch komplette Neuerzeugung vermutlich..... oder doppeltes Klonen, und das alte bleibt in der Mitte..... - - vector3 posThisVrt = aaPos[*iterV]; - - UG_LOG("vertex at " << posThisVrt << std::endl ); - - bool vrtxIsBndVrt = aaMarkVrtVFP[*iterV].getIsBndFracVertex(); - // alternativ wäre möglich: IsBoundaryVertex2D(grid, *iterV) - - UG_LOG("is bndry " << vrtxIsBndVrt << std::endl); - - IndexType numFracsCrossAtVrt = aaMarkVrtVFP[*iterV].getNumberFracEdgesInVertex(); - - UG_LOG("number crossing fracs " << numFracsCrossAtVrt << std::endl); - - size_t numbAttTripl = vecVertFracTrip.size(); - - UG_LOG("sizes of vft " << numbAttTripl << std::endl ); - - if( ! vrtxIsBndVrt ) - { - - if( numFracsCrossAtVrt < 1 ) - { - UG_THROW("no fracs crossing but marked vertex? << std::endl"); - } - else if( numFracsCrossAtVrt == 1 ) - { - -// if( numbAttTripl != 0 ) -// { -// UG_THROW("Anzahl der angehaengten Triples kann nicht stimmen, Vertex einer Kluft ohne Schnittpunkte, nicht am Rand, Kluftende " << std::endl); -// } - - - - UG_LOG("END THIS VERTEX NORMAL INNER ENDING CLEFT" << std::endl); - - -// if( ! dehneInnereKluftGrenzpunkteAus ) -// { -// break; -// } - // inner vertex where fracture ends - // TODO FIXME - - // in this case, we have two attached edges, and each of these edges has two attached faces - // the faces have a naormal, and based on the normal, we can decide which faces belong to the same side of the edges - -#if 0 - - if( numbAttTripl != 2 ) - { - UG_THROW("Anzahl der angehaengten Triples kann nicht stimmen, Vertex einer Kluft ohne Schnittpunkte, nicht am Rand, Kluftende " << std::endl); - } - - // Zuordnung der Edges und Faces, die auf der gleichen Seite der fracture sind - - // und gleich auch Erzeugung der neuen Knoten, die dann - // in einem Doublett zusammen mit ihren Normalen an die alten Vertizes - // angehängt werden; der Winkel zur Normalen hilft später, die Seite - // heraus zu finden, Seite von den Edges - - int dbg_iteratorAblaufen = 0; - - -#if WORKAROUND_SEGFAULT_CREATE_VERTEX - - int dbg_laenge = 0; - - for( auto const & vft : vecVertFracTrip ) - { - dbg_laenge++; - - UG_LOG("VERTEXFRACTRIP" << std::endl); - - vector3 ve = vft.getNormal(); - - UG_LOG("NORMAL " << ve << std::endl); - - UG_LOG("laenge " << dbg_laenge << std::endl ); - } - - int dbg_laenge_eins = 0; - -#endif - - - - for( VvftIterator vvftV = vecVertFracTrip.begin(); - vvftV != vecVertFracTrip.end(); - vvftV++ - ) - { - -#if WORKAROUND_SEGFAULT_CREATE_VERTEX - dbg_laenge_eins++; - - if( dbg_laenge_eins > dbg_laenge ) - { - break; - } - -#endif - - vector3 nV = vvftV->getNormal(); - - Edge * edgeV = vvftV->getEdge(); - - - -#if WORKAROUND_SEGFAULT_CREATE_VERTEX - - UG_LOG("NORMAL " << vvftV->getNormal() << std::endl); - UG_LOG("LAENGE EINZ " << dbg_laenge_eins << std::endl ); -#endif - - Vertex * nextFracVrt; - - IndexType foundThisVrt = 0; - - for( size_t i = 0; i < 2; ++i ) - { - Vertex * vrtEdgEnd = edgeV->vertex(i); - - if( vrtEdgEnd == *iterV ) - { - foundThisVrt++; - } - else - { - nextFracVrt = vrtEdgEnd ; - } - - } - - if( foundThisVrt != 1 ) - { - UG_THROW("zu viel zu wenig vertizex one " << std::endl); - } - - - - // Klasse schreiben, die als attachment an einen Fracture-Vertex - // die neuen Vertizes samt ihrer gemittelten Normalen speichert - // also std::vector von dieser neuen Klasse als Vertex attachment - - std::vector attEdg; - std::vector attFac; - - attEdg.push_back( edgeV ); - - Face * facV = vvftV->getFace(); - - attFac.push_back( facV ); - - // jetzt neuen Vertex erzeugen in Richtung der Normalen - // sonst ist das attachment Schwachsinn! - - vector3 posNewVrt; - - vector3 moveVrt; - - auto subsIndEdgV = sh.get_subset_index(edgeV); - - number width = fracInfosBySubset.at(subsIndEdgV).width; - -// if( expandInnerFracBnds ) -// { -// // der Faktor ist Käse und muss noch aus den Eingaben übernommen werden -// VecScale(moveVrt, nV, width/2. ); -// } -// else -// { -// // auf Annes Wunsch hin werden die Normalen innendrin an einer endenen Kluft zu Null gesetzt -// -// VecScale(moveVrt, nV, 0. ); -// -// } - - VecScale(moveVrt, nV, width/2. ); - - VecAdd(posNewVrt, posOldVrt, moveVrt ); - - UG_LOG("neuer Vertex " << posNewVrt << std::endl ); - - // TODO FIXME hier ist das PROBLEM, SEGFAULT durch create regular vertex - - - - Vertex * newShiftVrtx = *grid.create(); - aaPos[newShiftVrtx] = posNewVrt; - - sh.assign_subset(newShiftVrtx, subsIndEdgV ); - - - - // fuer was braucheh wir das eigentlich? selber schon vergessen..... - - ExpandVertexMultiplett vrtMtpl( attEdg, attFac, nV ); - - aaVrtExpMP[ *iterV ].push_back( vrtMtpl ); - - - - // alle anhängenden faces müssen noch zu wissen bekommen - // dass es diesen neuen Vertex gibt, nicht nur die - // an den edges anhängenden - // vielleicht gibt es einen Loop über attached faces des - // Vertex, für die schon bekannten direkt angehängten klar - // wenn auch dort vermerkt werden muss im Attachment von Seb - // bei den anderen, die keine Edge haben von der Kluft - // da muss man die Normale ins Zentrum bestimmen - // um heraus zu finden, ob sie auf dieser seite sind - // am besten dann das Attachment der faces für vertizes - // von Seb recyclen - - // loop über assosciated faces des vertex am besten - // vermutlich auch noch assosciated edges, um - // zu markieren, welche weg fallen sollen, wenn - // nicht von Kluft selber, sondern quasi verschoben - // und neu erzeugt - - int dbg_FaceIterator = 0; - - - - for( auto const & ifac : assoFaces ) - { - bool isFromFrac = false; - - for( auto const & facFrac : attFac ) - { - -// //static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype ( ifac ) >::value ); - //static_assert( std::is_same< decltype( (facFrac) ), decltype ( ifac ) >::value ); - - if( ifac == facFrac ) - { - isFromFrac = true; - -// //static_assert( std::is_same< decltype( const_cast(facFrac) ), Face * & >::value ); - //static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value ); -// //static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype( ifac ) >::value ); - //static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value ); - - } - } - - - bool atRightSide = false; - - if( isFromFrac ) - atRightSide = true; - - if( !isFromFrac ) - { - // check if on same side of edge where the normal points to: compute cosinus between vector of face center - // perpendicular to the edge - - - - - vector3 facCenter = CalculateCenter( ifac, aaPos ); - - vector3 perpendicu; - - -// UG_LOG("pos 0 " << aaPos[nextFracVrt[0]] << std::endl); -// UG_LOG("pos 1 " << aaPos[*iterV] << std::endl); -// UG_LOG("fac ce " << facCenter << std::endl); - - DropAPerpendicular(perpendicu, facCenter, aaPos[nextFracVrt], aaPos[*iterV]); - -// if( dbg_FaceIterator == 1 ) -// { -// UG_LOG("huhu a0" << std::endl); -// return true; -// } - - - vector3 tmpN; - - VecSubtract(tmpN, facCenter, perpendicu ); - - VecNormalize(tmpN, tmpN); - - UG_LOG("Normale zum Face ist " << tmpN << std::endl); - - number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, nV ); - - UG_LOG("Cosinus zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); - -// if( dbg_FaceIterator == 1 ) -// { -// UG_LOG("huhu a" << std::endl); -//// return true; -// } - - - if( cosBetwFracEdgAndDirection2Face > 0 ) - { - UG_LOG("assuming face to be on richt side" << std::endl); - - atRightSide = true; - -#if GRAPHICAL_SUDO_CREATION_DBG - - Vertex * otherFacCent = *grid.create(); - aaPos[otherFacCent] = facCenter; - sh.assign_subset(otherFacCent, 6 ); - - Vertex * pp = *grid.create(); - aaPos[pp] = perpendicu; - sh.assign_subset(pp, 7 ); - - sh.assign_subset(ifac,8); - -#endif - - } - else - { - UG_LOG("assuming face to be on wrong side" << std::endl); - } - - - dbg_flachen_passiert++; - } - - -// if( dbg_FaceIterator == 1 ) -// { -// UG_LOG("huhu b" << std::endl); -//// return true; -// } - - - - if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein - { - - // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! - vector& newVrts4Fac = aaVrtVecFace[ ifac ]; - - IndexType vrtxFnd = 0; - - for(size_t indVrt = 0; indVrt < (ifac)->num_vertices(); indVrt++ ) - { - Vertex* facVrt = (ifac)->vertex(indVrt); - - if( facVrt == *iterV ) - { - newVrts4Fac[ indVrt ] = newShiftVrtx; - vrtxFnd++; - } - } - - - if( vrtxFnd <= 0 ) - { - UG_THROW("vertex not found!" << std::endl); - } - else if( vrtxFnd > 1 ) - { - UG_THROW("vertex zu oft gefunden " << vrtxFnd << std::endl ); - } - else if ( vrtxFnd == 1 ) - { - } - else - { - UG_THROW("vertex finden komisch " << std::endl); - } - - - } - - dbg_FaceIterator++; - - } - - - - - - - - - } - - - - dbg_iteratorAblaufen++; - - - -// // Ziel: die beiden parallelen Normalen mitteln, und in die jeweiligen beiden Richtungen je einen neuen Vertex erzeugen -// // irgendwie muss der Vertex oder die Edge besser sogar wissen, dass sie einen neuen Verschiebevertex bekommen hat -// // denn später müssen neue Edges und neue Faces basierend auf den neuen Vertizes erzeugt werden -// // vielleicht braucht die edge und das face ein Attachment, das ihnen das sagt, ähnlihc wie VertexTrible std Vektoren? -// -// -// - UG_LOG("END THIS VERTEX NORMAL INNER ENDING CLEFT" << std::endl); - -#endif - - -// return true; - - - } - else if( numFracsCrossAtVrt == 2 ) // free line of fracture, no crossing point, not at boundary - { - // in this case, we have two attached edges, and each of these edges has two attached faces - // the faces have a naormal, and based on the normal, we can decide which faces belong to the same side of the edges - - - if( numbAttTripl != 4 ) - { - - UG_LOG("NUMBER OF TRIPLETTS " << numbAttTripl << std::endl); - -// return true; - - UG_THROW("Anzahl der angehaengten Triples kann nicht stimmen, Vertex einer Kluft ohne Schnittpunkte, nicht am Rand " << std::endl); - } - - // Zuordnung der Edges und Faces, die auf der gleichen Seite der fracture sind - - // und gleich auch Erzeugung der neuen Knoten, die dann - // in einem Doublett zusammen mit ihren Normalen an die alten Vertizes - // angehängt werden; der Winkel zur Normalen hilft später, die Seite - // heraus zu finden, Seite von den Edges - - - - int dbg_iteratorAblaufen = 0; - -#if WORKAROUND_SEGFAULT_CREATE_VERTEX - - int dbg_laenge = 0; - - for( auto const & vft : vecVertFracTrip ) - { - dbg_laenge++; - - UG_LOG("VERTEXFRACTRIP" << std::endl); - - vector3 ve = vft.getNormal(); - - UG_LOG("NORMAL " << ve << std::endl); - - UG_LOG("laenge " << dbg_laenge << std::endl ); - } - - - UG_LOG("SINGLE" << std::endl); - - - for( VvftIterator vvftOne = vecVertFracTrip.begin(); - vvftOne != vecVertFracTrip.end() - 1; - vvftOne++ - ) - { - - - Edge * edgeOne = vvftOne->getEdge(); - vector3 nOne = vvftOne->getNormal(); - - - for( VvftIterator vvftTwo = vvftOne + 1; - vvftTwo != vecVertFracTrip.end(); - vvftTwo++ - ) - { - Edge * edgeTwo = vvftTwo->getEdge(); - vector3 nTwo = vvftTwo->getNormal(); - - number cosinus = VecDot( nOne, nTwo ); - if( edgeOne != edgeTwo ) - { - UG_LOG("COSI between " << nOne << " and " << nTwo << " -> " << cosinus << std::endl ); - } - - } - } - - UG_LOG("SINGLE END" << std::endl); - - int dbg_laenge_eins = 0; - -#endif - - - for( VvftIterator vvftOne = vecVertFracTrip.begin(); - vvftOne != vecVertFracTrip.end() - 1; - vvftOne++ - ) - { - -#if WORKAROUND_SEGFAULT_CREATE_VERTEX - dbg_laenge_eins++; - - if( dbg_laenge_eins > dbg_laenge ) - { - break; - } - - int dbg_laenge_zwei = dbg_laenge_eins; -#endif - int dbg_zweiterIteratorAblaufen = 0; - - vector3 nOne = vvftOne->getNormal(); - - Edge * edgeOne = vvftOne->getEdge(); - - - - for( VvftIterator vvftTwo = vvftOne + 1; - vvftTwo != vecVertFracTrip.end(); - vvftTwo++ - ) - { - -#if WORKAROUND_SEGFAULT_CREATE_VERTEX - dbg_laenge_zwei++; - - if( dbg_laenge_zwei > dbg_laenge ) - { - break; - } - - UG_LOG("NORMAL ONE " << vvftOne->getNormal() << std::endl); - UG_LOG("NORMAL TWO " << vvftTwo->getNormal() << std::endl); - UG_LOG("LAENGE EINZ ZWO " << dbg_laenge_eins << " " << dbg_laenge_zwei << std::endl ); -#endif - - // dieselben brauchen wir nicht vergleichen - if( vvftOne == vvftTwo ) - { - // sollte nie vorkommen! - UG_THROW("Unsinn " << std::endl); - } - else - { - - Edge * edgeTwo = vvftTwo->getEdge(); - - // noch testen, ob nicht die Kante dieselbe ist, geht das? - // bei der gleichen Ecke ist es unnötig, da es gegensätzlich sein muss - - - - if( edgeOne != edgeTwo ) - { - - std::vector nextFracVrt; - - IndexType foundThisVrtOne = 0; - - for( size_t i = 0; i < 2; ++i ) - { - Vertex * vrtEdgEnd = edgeOne->vertex(i); - - if( vrtEdgEnd == *iterV ) - { - foundThisVrtOne++; - } - else - { - nextFracVrt.push_back( vrtEdgEnd ); - } - - } - - if( foundThisVrtOne != 1 ) - { - UG_THROW("zu viel zu wenig vertizex one " << std::endl); - } - - - IndexType foundThisVrtTwo = 0; - - for( size_t i = 0; i < 2; ++i ) - { - Vertex * vrtEdgEnd = edgeTwo->vertex(i); - - if( vrtEdgEnd == *iterV ) - { - foundThisVrtTwo++; - } - else - { - nextFracVrt.push_back( vrtEdgEnd ); - } - - } - - if( foundThisVrtTwo != 1 ) - { - UG_THROW("zu viel zu wenig vertizex two " << std::endl); - } - - - - vector3 nTwo = vvftTwo->getNormal(); - - number cosinus = VecDot( nOne, nTwo ); - -// bool vz = ! std::signbit(cosinus); - - UG_LOG("cosinus " << dbg_vertizesPassiert << " between " << nOne << " and " << nTwo << " -> " << cosinus << std::endl ); - //UG_LOG("sign between " << nOne << " and " << nTwo << " -> " << vz << std::endl ); - - - - if( cosinus > 0 ) - { - // gleiche Seite vermutet - - // sind die edges dieselben? pruefen! gleiche unnoetig - wird oben schon abgefragt - - // Klasse schreiben, die als attachment an einen Fracture-Vertex - // die neuen Vertizes samt ihrer gemittelten Normalen speichert - // also std::vector von dieser neuen Klasse als Vertex attachment - -#if 1 - - Face * facOne = vvftOne->getFace(); - Face * facTwo = vvftTwo->getFace(); - - expandSingleFractureAtGivenSide( nOne, nTwo, - edgeOne, edgeTwo, - facOne, facTwo, - fracInfosBySubset, - posOldVrt, - aaPos, - grid, sh, - assoFaces - , - nextFracVrt, - aaVrtVecFace, - dbg_flachen_passiert, - *iterV - ); - -#else - - // average the normals - - vector3 normSum; - - VecAdd( normSum, nOne, nTwo ); - - vector3 normSumNormed; - - VecNormalize(normSumNormed, normSum); - - UG_LOG("averaged normal " << normSumNormed << std::endl); - - std::vector attEdg; - std::vector attFac; - - attEdg.push_back( edgeOne ); - attEdg.push_back( edgeTwo ); - -// Face * facOne = vvftOne->getFace(); -// Face * facTwo = vvftTwo->getFace(); - - attFac.push_back( facOne ); - attFac.push_back( facTwo ); - - // jetzt neuen Vertex erzeugen in Richtung der Normalen - // sonst ist das attachment Schwachsinn! - - vector3 posNewVrt; - - vector3 moveVrt; - - auto subsIndEdgOne = sh.get_subset_index(edgeOne); - - auto subsIndEdgTwo = sh.get_subset_index(edgeTwo); - - - if( subsIndEdgOne != subsIndEdgTwo ) - { - UG_THROW("subsets passen nicht" << std::endl ); - } - - - - - number width = fracInfosBySubset.at(subsIndEdgOne).width; - - // der Faktor ist Käse und muss noch aus den Eingaben übernommen werden - VecScale(moveVrt, normSumNormed, width/2. ); - - VecAdd(posNewVrt, posOldVrt, moveVrt ); - - UG_LOG("neuer Vertex " << posNewVrt << std::endl ); - - // TODO FIXME hier ist das PROBLEM, SEGFAULT durch create regular vertex - - Vertex * newShiftVrtx = *grid.create(); - aaPos[newShiftVrtx] = posNewVrt; - - sh.assign_subset(newShiftVrtx, subsIndEdgOne ); - - - - // fuer was braucheh wir das eigentlich? selber schon vergessen..... - - ExpandVertexMultiplett vrtMtpl( attEdg, attFac, normSumNormed ); - - aaVrtExpMP[ *iterV ].push_back( vrtMtpl ); - - - - // alle anhängenden faces müssen noch zu wissen bekommen - // dass es diesen neuen Vertex gibt, nicht nur die - // an den edges anhängenden - // vielleicht gibt es einen Loop über attached faces des - // Vertex, für die schon bekannten direkt angehängten klar - // wenn auch dort vermerkt werden muss im Attachment von Seb - // bei den anderen, die keine Edge haben von der Kluft - // da muss man die Normale ins Zentrum bestimmen - // um heraus zu finden, ob sie auf dieser seite sind - // am besten dann das Attachment der faces für vertizes - // von Seb recyclen - - // loop über assosciated faces des vertex am besten - // vermutlich auch noch assosciated edges, um - // zu markieren, welche weg fallen sollen, wenn - // nicht von Kluft selber, sondern quasi verschoben - // und neu erzeugt - - int dbg_FaceIterator = 0; - -#if 0 -// for( auto iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ ) - for( std::vector::iterator iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ ) - { - bool isFromFrac = false; - -// for( std::vector::iterator iterF2 = attFac.begin(); iterF2 != attFac.end(); iterF2++ ) -// { -// //static_assert( std::is_same< decltype( *iterF2 ), decltype ( *iterFac ) >::value ); -// -// } - - int dbg_innterFacFracIt = 0; - - for( auto const & facFrac : attFac ) - { - - -// UG_LOG("type iter facFrac " << typeid( facFrac ).name() << std::endl); -// -// UG_LOG("type iter Fac " << typeid( *iterFac ).name() << std::endl); - - //static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype ( *iterFac ) >::value ); - - - - - if( *iterFac == facFrac ) - { - isFromFrac = true; - - //static_assert( std::is_same< decltype( const_cast(facFrac) ), Face * & >::value ); - //static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype( * iterFac ) >::value ); - - } - } - - bool atRightSide = false; - - if( isFromFrac ) - atRightSide = true; - - if( !isFromFrac ) - { - // check if on same side of edge where the normal points to: compute cosinus between vector of face center - // perpendicular to the edge - // TODO FIXME - // KAESE!!! - - vector3 facCenter = CalculateCenter( *iterFac, aaPos ); - - vector3 perpendicu; - - if( nextFracVrt.size() != 2 ) - { - UG_THROW("komische Groesse" << std::endl); - } - - DropAPerpendicular(perpendicu, facCenter, aaPos[nextFracVrt[0]], aaPos[nextFracVrt[1]]); - - vector3 tmpN; - - VecSubtract(tmpN, facCenter, perpendicu ); - - VecNormalize(tmpN, tmpN); - - UG_LOG("Normale zum Face ist " << tmpN << std::endl); - - number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, normSumNormed ); - - UG_LOG("Cosinus zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); - - if( cosBetwFracEdgAndDirection2Face > 0 ) - { - UG_LOG("assuming face to be on richt side" << std::endl); - - atRightSide = true; - -#if GRAPHICAL_SUDO_CREATION_DBG - - Vertex * otherFacCent = *grid.create(); - aaPos[otherFacCent] = facCenter; - sh.assign_subset(otherFacCent, 5 ); - - Vertex * pp = *grid.create(); - aaPos[pp] = perpendicu; - sh.assign_subset(pp, 6 ); - - sh.assign_subset(*iterFac,7); -#endif - - } - else - { - UG_LOG("assuming face to be on wrong side" << std::endl); - } - -// if( dbg_flachen_passiert == 0 ) -// { -// UG_LOG("passiert " << dbg_flachen_passiert << std::endl); -// -// Vertex * otherFacCent = *grid.create(); -// aaPos[otherFacCent] = facCenter; -// sh.assign_subset(otherFacCent, 5 ); -// -// Vertex * pp = *grid.create(); -// aaPos[pp] = perpendicu; -// sh.assign_subset(pp, 6 ); -// -// sh.assign_subset(*iterFac,7); -// -// -// sh.assign_subset(*iterFac,3); -// -// UG_LOG("is from frac " << isFromFrac << std::endl); -// -// return true; -// } - - - dbg_flachen_passiert++; - } - - - if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein - { - - - // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! - vector& newVrts4Fac = aaVrtVecFace[ * iterFac ]; - - IndexType vrtxFnd = 0; - - for(size_t indVrt = 0; indVrt < (*iterFac)->num_vertices(); indVrt++ ) - { - Vertex* facVrt = (*iterFac)->vertex(indVrt); - - if( facVrt == *iterV ) - { - newVrts4Fac[ indVrt ] = newShiftVrtx; - // UG_LOG("vertex found " << indVrt << std::endl ); - vrtxFnd++; - } - } - - - if( vrtxFnd <= 0 ) - { - UG_THROW("vertex not found!" << std::endl); - } - else if( vrtxFnd > 1 ) - { - UG_THROW("vertex zu oft gefunden " << vrtxFnd << std::endl ); - } - else if ( vrtxFnd == 1 ) - { - // UG_LOG("vertex found abgeschlossen" << std::endl); - } - else - { - UG_THROW("vertex finden komisch " << std::endl); - } - - - } - - dbg_innterFacFracIt++; - - - -// -// -// if( ! isFromFrac ) -// { -// // Vektor zum Zentrum von KNoten aus berechnen und Winkel zur Normalen bestimmen zur Unterscheidung der Seite -// // wenn auf richtiger Seite, zuweisen -// } - - dbg_FaceIterator++; - - } -#else -// std::vector & assFaceVrt = aaVrtInfoAssoFaces[*iterV]; - - // VecFace & assoFaces = aaVrtInfoAssoFaces[*iterV]; - // TODO FIXME hier braucht man das nicht zu ordnen - // aber bei Kreuzpunkten von Klueften muss es so geordnet werden, wie es nebeneinander liegt - // bei den Edges gibt es auch die benachbarten, und die edges haben das attachment, ob sie Kluftedges sind - - // for( auto const & ifac : assoFaces ) - // { - // //static_assert( std::is_same< decltype( ifac ), Face * const & >::value ); - // - // // TODO FIXME folgenden loop durch diesen ersetzen - // // Achtung: Zeigerproblematik, Referenzen, etc..... - // // *iterFac ersetzen durch ifac vermutlich, aber wer weiss - // } - - - // for( auto iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ ) - //for( std::vector::iterator iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ ) - for( auto const & ifac : assoFaces ) - { - bool isFromFrac = false; - - - int dbg_innterFacFracIt = 0; - - for( auto const & facFrac : attFac ) - { - -// //static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype ( ifac ) >::value ); - //static_assert( std::is_same< decltype( (facFrac) ), decltype ( ifac ) >::value ); - - if( ifac == facFrac ) - { - isFromFrac = true; - -// //static_assert( std::is_same< decltype( const_cast(facFrac) ), Face * & >::value ); - //static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value ); -// //static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype( ifac ) >::value ); - //static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value ); - - } - } - - bool atRightSide = false; - - if( isFromFrac ) - atRightSide = true; - - if( !isFromFrac ) - { - // check if on same side of edge where the normal points to: compute cosinus between vector of face center - // perpendicular to the edge - - vector3 facCenter = CalculateCenter( ifac, aaPos ); - - vector3 perpendicu; - - if( nextFracVrt.size() != 2 ) - { - UG_THROW("komische Groesse" << std::endl); - } - - DropAPerpendicular(perpendicu, facCenter, aaPos[nextFracVrt[0]], aaPos[nextFracVrt[1]]); - - vector3 tmpN; - - VecSubtract(tmpN, facCenter, perpendicu ); - - VecNormalize(tmpN, tmpN); - - UG_LOG("Normale zum Face ist " << tmpN << std::endl); - - number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, normSumNormed ); - - UG_LOG("Cosinus zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); - - if( cosBetwFracEdgAndDirection2Face > 0 ) - { - UG_LOG("assuming face to be on richt side" << std::endl); - - atRightSide = true; - -#if GRAPHICAL_SUDO_CREATION_DBG - - Vertex * otherFacCent = *grid.create(); - aaPos[otherFacCent] = facCenter; - sh.assign_subset(otherFacCent, 5 ); - - Vertex * pp = *grid.create(); - aaPos[pp] = perpendicu; - sh.assign_subset(pp, 6 ); - - sh.assign_subset(*iterFac,7); -#endif - - } - else - { - UG_LOG("assuming face to be on wrong side" << std::endl); - } - - - dbg_flachen_passiert++; - } - - - if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein - { - - // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! - vector& newVrts4Fac = aaVrtVecFace[ ifac ]; - - IndexType vrtxFnd = 0; - - for(size_t indVrt = 0; indVrt < (ifac)->num_vertices(); indVrt++ ) - { - Vertex* facVrt = (ifac)->vertex(indVrt); - - if( facVrt == *iterV ) - { - newVrts4Fac[ indVrt ] = newShiftVrtx; - vrtxFnd++; - } - } - - - if( vrtxFnd <= 0 ) - { - UG_THROW("vertex not found!" << std::endl); - } - else if( vrtxFnd > 1 ) - { - UG_THROW("vertex zu oft gefunden " << vrtxFnd << std::endl ); - } - else if ( vrtxFnd == 1 ) - { - } - else - { - UG_THROW("vertex finden komisch " << std::endl); - } - - - } - - dbg_innterFacFracIt++; - - - - dbg_FaceIterator++; - - } - -#endif - -#endif - - } - else - { - // andere Seite vermutet, nichts tun! - } - - - - } - - - } - - dbg_zweiterIteratorAblaufen++; - - } - - dbg_iteratorAblaufen++; - - } - - -// // Ziel: die beiden parallelen Normalen mitteln, und in die jeweiligen beiden Richtungen je einen neuen Vertex erzeugen -// // irgendwie muss der Vertex oder die Edge besser sogar wissen, dass sie einen neuen Verschiebevertex bekommen hat -// // denn später müssen neue Edges und neue Faces basierend auf den neuen Vertizes erzeugt werden -// // vielleicht braucht die edge und das face ein Attachment, das ihnen das sagt, ähnlihc wie VertexTrible std Vektoren? -// -// -// - - - UG_LOG("END THIS VERTEX NORMAL COSINE" << std::endl); - - - - } - else // two fractures completely crossing, numFracsCrossAtVrt >= 3, i.e. T crossing and two fractures completely crossing - { - - // TODO FIXME in case of three fractures, we have to use the method for eine durchgehende fracture - // auf der Seite, wo die zweite fracture NICHT rein geht - - IndexType countedCrossingFracEdgs = 0; - - // TODO FIXME kreuzende Fractures im Innenraum -> Arte in Reinform implementieren - - // verkettete Liste der anhängenden fractures in Reihenfolge - // der Anhängung mit INfo, ob eine Kluft vorliegt - -// for( auto const & attVFT : vecVertFracTrip ) -// { -// Edge * edg = attVFT.getEdge(); -// Face * fac = attVFT.getFace(); -// vector3 nv = attVFT.getNormal(); -// } -// -// // hier werden ALLE attached Faces benötigt, auch die, die zwischen den direkt an den fractures liegenden Faces sind -// - // copies of all faces and of fractured ones - auto vVFT = vecVertFracTrip; // caution: COPY, not reference! - auto aF = assoFaces; // caution: COPY, not reference! - - UG_LOG("Gesamtanzahl faces um Knoten " << aF.size() << std::endl ); - - // erstmal die ganzen anhaengenden Faces ordnen, dass wir wissen, in welcher Reihenfolge wir durchlaufen muessen - // jede Edge hat ein bool attachment schon, das weiss, ob sie Fracture edge ist oder nicht - // Reihenfolge der faces und die edges auch dazu, vielleicht neues Triple oder dergleiche, dabei zwei edges und zwei normals - // und wie gesagt, die edges wissen, ob sie fractures sind, dazu keine neuen Variablen notwendig - - using VertexOfFaceInfo = VertexFractureTriple< std::pair, Face*, std::pair >; - // all edges of the attached face - must always be two, the face itself, and the normal vectors of the face in direction of the two edges - // the size of the normal vector vector also must be two - // however, if an edge of the face is not a fracture edge, we do not compute the normal, but assign zero as norm - // for those edges and faces which are Kluft edges, we assign the normal known from the info computed before, vertex fracture triple - - using VecVertexOfFaceInfo = std::vector; - - VecVertexOfFaceInfo orderedFaces; - - using SegmentsFractExtrus = std::vector; - - SegmentsFractExtrus segments; - // single components always from one fracture edge to the next one - - VecVertexOfFaceInfo segmentPart; - - // note: we do not attach this info to the vertex, as we only need it local; in principle, in case of further need, it would - // be usful to establish some sort of attachment - - if( vVFT.size() == 0 ) - UG_THROW("vertex frac triple zu klein an Kreuzung " << std::endl); - - // we start with the first fracture face edge stuff, copy it, and delete this immidiately - VertFracTrip startVertFracTrip = vVFT[0]; - - vVFT.erase(vVFT.begin()); - - bool atFirstTriple = true; - - Face* fracFac = startVertFracTrip.getFace(); - Edge* fracEdg = startVertFracTrip.getEdge(); - vector3 fracNorm = startVertFracTrip.getNormal(); - - Edge* originalStartEdge = startVertFracTrip.getEdge(); - - if( fracEdg != 0 ) - { - countedCrossingFracEdgs++; - } - - // do not change this pointer - Edge* startEdg = fracEdg; - Face* startFace = fracFac; - - vector3 startNormal = fracNorm; - -// Face* nextFace = NULL; - - UG_LOG("Gesamtanzahl faces um Knoten vor while " << aF.size() << std::endl ); - - - while( aF.size() != 0 ) - { - - UG_LOG("Gesamtanzahl faces um Knoten Anfang while " << aF.size() << std::endl ); - - - Face* face2Append = startFace; - Edge* startEdg2Append = startEdg; - - - IndexType fndCommEdg = 0; - vector3 nuVe(0,0,0); - - Edge* nextEdge = NULL; - - std::pair edge2Append( startEdg2Append, nextEdge ); - std::pair normal2Append( startNormal, nuVe ); - - - // if start face and start edge from a triple, then has to be erased this triple, exept for the entire start, as already erased - if( ! atFirstTriple ) - { - for( VecVertFracTrip::iterator itAttVFT = vVFT.begin(); itAttVFT != vVFT.end(); itAttVFT++ ) - { - auto vft = *itAttVFT; - - Edge * edgIt = vft.getEdge(); - - Face * facIt = vft.getFace(); - - if( edgIt == startEdg && facIt == startFace ) - { - // the first edge if from a fracture and the face is connected to it - - vVFT.erase(itAttVFT); - - normal2Append.first = vft.getNormal(); - - if( ! FaceContains( facIt, startEdg )) - { - UG_THROW("Face does not contain start edge of its edge" << std::endl); - } - - break; - } - } - - } - else // we can save the investigation if we have a triple, and we do not need to erase, as already erased..... - { - atFirstTriple = false; - } - - - for( auto const & iE : allAssoEdges ) // werden nicht gelöscht, deswegen Zugriff auf attachment direkt - { - if( FaceContains(face2Append, iE) ) - { - fndCommEdg++; - - if( iE != startEdg ) - { - nextEdge = iE; - - edge2Append.second = iE; - - } - } - - - } - - if( fndCommEdg != 2 ) - { - UG_THROW("komische Anzahl gemeinsamer Ecke " << fndCommEdg << std::endl); - } - - if( nextEdge == NULL ) - { - UG_THROW("wieso keine zweite Ecke gefunden???? " << std::endl); - } - - if( edge2Append.first == NULL || edge2Append.second == NULL ) - { - UG_THROW("null immer noch?" << std::endl); - } - - // erase the face from the list - - IndexType faceFound = 0; - - for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ ) - { - Face * iFa = *itFac; - - if( iFa == startFace && FaceContains( iFa, nextEdge ) && FaceContains(iFa, startEdg)) - { - faceFound++; - } - } - - int totalSubsNum = sh.num_subsets(); - - int newSubsToAdd = totalSubsNum; - - if( faceFound != 1 ) - { - - - sh.assign_subset(startFace,newSubsToAdd++); - sh.assign_subset(startEdg,newSubsToAdd++); - sh.assign_subset(nextEdge,newSubsToAdd++); - - int faNum = aF.size(); - - UG_LOG("Gesamtzahl faces vor Absturz " << faNum << std::endl); - - UG_LOG("Gesicht in falscher Anztahl gefunden " << faceFound << std::endl); - -// return true; - - - - UG_THROW("Gesicht in falscher Anztahl gefunden " << faceFound << std::endl); - } - else - { -// sh.assign_subset(startFace,newSubsToAdd++); -// sh.assign_subset(startEdg,newSubsToAdd++); -// sh.assign_subset(nextEdge,newSubsToAdd++); - - int faNum = aF.size(); - - UG_LOG("Gesamtzahl faces ohne Absturz " << faNum << std::endl); - - } - - for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ ) - { - Face * iFa = *itFac; - - if( iFa == startFace && FaceContains( iFa, nextEdge ) && FaceContains(iFa, startEdg) ) - { - aF.erase(itFac); - break; - } - } - - - - - bool sndEdgIsFracEdgeAlso = aaMarkEdgeB[nextEdge]; - - bool tripFound = false; - - if( sndEdgIsFracEdgeAlso ) - { - - if( nextEdge != originalStartEdge ) - countedCrossingFracEdgs++; - - // we need to have a look for the next triple - - // check if the next normal is a frac normal which contains the face as well - - for( VecVertFracTrip::iterator itAttVFT = vVFT.begin(); itAttVFT != vVFT.end(); itAttVFT++ ) - { - auto vft = *itAttVFT; - - Edge * edgIt = vft.getEdge(); - - Face * facIt = vft.getFace(); - - if( edgIt == nextEdge && facIt == face2Append ) - { - // the second edge if from a fracture and the face is connected to it - - tripFound = true; - - vVFT.erase(itAttVFT); - - normal2Append.second = vft.getNormal(); - - if( ! FaceContains( facIt, nextEdge )) - { - UG_THROW("Face does not contain edge of its edge" << std::endl); - } - - break; - } - } - - } - - if( ! tripFound && sndEdgIsFracEdgeAlso ) - { - UG_THROW("Triple nicht gefunden trotz markierter Edge" << std::endl); - } - - - // check if aF or vVFT still contain the former or the next face - must not be the case! - - VertexOfFaceInfo vOFI( edge2Append, face2Append, normal2Append ); - - orderedFaces.push_back( vOFI ); - - segmentPart.push_back( vOFI ); - - if( sndEdgIsFracEdgeAlso ) - { - segments.push_back( segmentPart ); - - segmentPart.clear(); - } - - - // what is next face, what is next edge? - // wie kriegen wir es hin, auch das nächste Triple zu erasen, wenn es jetzt kommt als nächstes? - - - startNormal = nuVe; - startEdg = nextEdge; - - if( aF.size() == 0 ) - { - if( nextEdge != originalStartEdge ) - { - UG_THROW("Gesichter leer, aber keine Anfangsecke gefunden" << std::endl); - } - else - { - break; // while loop zu Ende, raus aus dem while loop, den Rest nicht mehr machen, würde schief gehen zwingendermassen - } - - } - - - // bleibt noch das nächste Gesicht heraus zu finden, dafür kommt eigentlich nur noch eines in Frage, da das zweite Gesicht vom edge - // geloescht sein muss in aF, es muss das einzig übrige face sein, das die jetzt start edge enthält, davon darf es nur eines geben, wir löschen aber noch nicht - - IndexType nextFaceFound = 0; - - for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ ) - { - Face * iFa = *itFac; - - if( FaceContains(iFa, startEdg ) ) - { - nextFaceFound++; - } - } - - if( nextFaceFound != 1 ) - { - UG_THROW("folgendes Gesicht in falscher Anztahl gefunden " << nextFaceFound << std::endl); - } - - for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ ) - { - Face * iFa = *itFac; - - if( FaceContains(iFa, startEdg ) ) - { - startFace = iFa; - break; - } - } - - - } - - if( vVFT.size() != 0 ) - { - UG_THROW("not all triples found! " << std::endl); - } - - if( aF.size() != 0 ) - UG_THROW("not all faces found " << std::endl); - - if( startEdg != originalStartEdge ) - { - UG_THROW("wir sind nicht am Anfang wieder angekommen" << std::endl); - } - - - if( segmentPart.size() != 0 ) - { - UG_THROW("die Segmentteile muessen alle verarbeitet sein" << std::endl); - } - - UG_LOG("Kreislauf geschlossen" << std::endl); - - - // test if the segments and their partition produce sumething useful, for debug purposes - - // als nächstes muss man die Klassen von durch Klüften abgetrennten ordered Faces durchgehen, und die Verschiebevertizes erzeugen - // als nächstes die verschiedenen Sektionen durch gehen, eventuell nochmal extra Objekte dafür erzeugen - // oder gleich beim Durchgehen die neuen Vertizes erzeugen, Startsignal durch ein Face mit erster Edge KLuft, und dann die nächste - // Kluftedge finden, egal ob vom gleihen face oder von einem späteren face im kreis - - // now figure out to which face this next edge belongs, and if this is a fracture edge, then we have the triple and the normal info - // else we let the normal zero - - // figure out if second edge is also frac edge, i.e. if it belongs to an edge of the remaining vVFT elements - // first easily asking if it is marked as frac edge, simplifies research - - // in principle from here on need to loop through all triples and through all faces, find out some way to construct next edge and to - // build one element after the other of the ordered faces vector, still even the first element is not completed - - // TODO FIXME kreuzende Fractures im Innenraum -> Arte in Reinform implementieren - // later assign somehow next edge to start edge, or use new variable, when we have figured out next face - // at end, chech if we have arrived again at original first edge - - -// int totalSubsNum = sh.num_subsets(); - -// int newSubsToAdd = totalSubsNum; - -// for( VertexOfFaceInfo const & vertFracInfo : orderedFaces ) -// { -//// Face * fa = vertFracInfo.getFace(); -//// -//// sh.assign_subset(fa,newSubsToAdd++); -// } - - number totAnglsEdg = 0; - number totAnglsNrm = 0; - - for( VecVertexOfFaceInfo const & segPart : segments ) - { -// newSubsToAdd++; - - IndexType numbTriangs = segPart.size(); - - if( numbAttTripl == 0 ) - { - UG_THROW("zu wenig Dreiecke " << std::endl); - } - - VertexOfFaceInfo const & vFISBegin = segPart[0]; - VertexOfFaceInfo const & vFISEnd = segPart[numbTriangs-1]; - - std::pair edgesBegin = vFISBegin.getEdge(); - std::pair edgesEnd = vFISEnd.getEdge(); - - std::pair normalBegin = vFISBegin.getNormal(); - std::pair normalEnd = vFISEnd.getNormal(); - - Edge* edgeFracOne = edgesBegin.first; - Edge* edgeFracTwo = edgesEnd.second; - - auto subsIndFracOne = sh.get_subset_index(edgeFracOne); - auto subsIndFracTwo = sh.get_subset_index(edgeFracTwo); - - vector3 normalFracOne = normalBegin.first; - vector3 normalFracTwo = normalEnd.second; - -// sh.assign_subset(edgeFracOne, newSubsToAdd); -// -// if( edgeFracTwo != originalStartEdge ) -// sh.assign_subset(edgeFracTwo, newSubsToAdd); - - // neue Punkte erzeugen - - number cosBetweenNormals = VecDot( normalFracOne, normalFracTwo ); - - if( subsIndFracOne == subsIndFracTwo ) - { - if( numFracsCrossAtVrt != 3 ) - { - UG_THROW("Fracture Segment an beiden Seiten gleiche sudo, aber keine T Kreuzung?" << std::endl); - } - - // dieselben Methoden wie im Fall von einer durchgehenden Kluft an einem Vertex, dort kopieren - // bzw Funktion schreiben, die beides macht - - // hier wird der Fall abgezweigt, dass wir auf der durchgehenden Seite einer Kluft sind - // wenn wir eine T-Kreuzung haben - - std::vector nextFracVrt; - - IndexType foundThisVrtOne = 0; - - for( size_t i = 0; i < 2; ++i ) - { - Vertex * vrtEdgEnd = edgeFracOne->vertex(i); - - if( vrtEdgEnd == *iterV ) - { - foundThisVrtOne++; - } - else - { - nextFracVrt.push_back( vrtEdgEnd ); - } - - } - - if( foundThisVrtOne != 1 ) - { - UG_THROW("zu viel zu wenig vertizex one " << std::endl); - } - - - IndexType foundThisVrtTwo = 0; - - for( size_t i = 0; i < 2; ++i ) - { - Vertex * vrtEdgEnd = edgeFracTwo->vertex(i); - - if( vrtEdgEnd == *iterV ) - { - foundThisVrtTwo++; - } - else - { - nextFracVrt.push_back( vrtEdgEnd ); - } - - } - - if( foundThisVrtTwo != 1 ) - { - UG_THROW("zu viel zu wenig vertizex two " << std::endl); - } - - Face * faceBegin = vFISBegin.getFace(); - Face * faceEnd = vFISEnd.getFace(); - - - - expandSingleFractureAtGivenSide( normalFracTwo, normalFracTwo, - edgeFracOne, edgeFracTwo, - faceBegin, faceEnd, - fracInfosBySubset, - posOldVrt, - aaPos, - grid, sh, - assoFaces - , - nextFracVrt, - aaVrtVecFace, - dbg_flachen_passiert, - *iterV - ); - - - - } - else - { - - // create normal vectors into direction of relevant edges - - vector3 alongEdgeOne; - vector3 alongEdgeTwo; - - Vertex * vrtEdgeOneBegin = NULL; - Vertex * vrtEdgeTwoBegin = NULL; - Vertex * vrtEdgeOneEnd = NULL; - Vertex * vrtEdgeTwoEnd = NULL; - - - for( size_t i = 0; i < 2; ++i ) - { - Vertex * vrtFromEdgeOne = edgeFracOne->vertex(i); - Vertex * vrtFromEdgeTwo = edgeFracTwo->vertex(i); - - if( vrtFromEdgeOne == *iterV ) - { - vrtEdgeOneBegin = vrtFromEdgeOne; - } - else - { - vrtEdgeOneEnd = vrtFromEdgeOne; - } - - if( vrtFromEdgeTwo == *iterV ) - { - vrtEdgeTwoBegin = vrtFromEdgeTwo; - } - else - { - vrtEdgeTwoEnd = vrtFromEdgeTwo; - } - - } - - if( vrtEdgeOneBegin == NULL || vrtEdgeTwoBegin == NULL || vrtEdgeOneEnd == NULL || vrtEdgeTwoEnd == NULL ) - { - UG_THROW("lauter Nullen vertizes" << std::endl); - } - - vector3 fracVrtPos = aaPos[*iterV]; - - vector3 fracEdgOneEndPos = aaPos[ vrtEdgeOneEnd ]; - vector3 fracEdgTwoEndPos = aaPos[ vrtEdgeTwoEnd ]; - - vector3 directionEdgOne; - VecSubtract(directionEdgOne, fracEdgOneEndPos, fracVrtPos); - - vector3 directionEdgTwo; - VecSubtract(directionEdgTwo, fracEdgTwoEndPos, fracVrtPos); - - vector3 nrmdVecEdgOne; - VecNormalize(nrmdVecEdgOne, directionEdgOne); - - vector3 nrmdVecEdgTwo; - VecNormalize(nrmdVecEdgTwo, directionEdgTwo); - - number cosBetweenEdges = VecDot(nrmdVecEdgOne,nrmdVecEdgTwo); - - number angleEdges = std::acos( cosBetweenEdges ); - number angleNormls = std::acos( cosBetweenNormals ); - - totAnglsEdg += angleEdges; - totAnglsNrm += angleNormls; - - UG_LOG("cosinus Edges Normals " << cosBetweenEdges << " " << cosBetweenNormals << std::endl); - UG_LOG("angles edges normals " << angleEdges << " " << angleNormls << std::endl); - - // prject normal 1 onto edge 2 and normal 2 on edge 1, scale with width one half resp with width two half - - - number cosBetweenNrmFraOneEdgTwo = VecDot(normalFracOne,nrmdVecEdgTwo); - number cosBetweenNrmFraTwoEdgOne = VecDot(normalFracTwo,nrmdVecEdgOne); - - vector3 projectNrmFraOneToEdgTwoDirection; - VecScale(projectNrmFraOneToEdgTwoDirection, nrmdVecEdgTwo, 1./cosBetweenNrmFraOneEdgTwo); - - vector3 projectNrmFraTwoToEdgOneDirection; - VecScale(projectNrmFraTwoToEdgOneDirection, nrmdVecEdgOne, 1./cosBetweenNrmFraTwoEdgOne); - - // auto subsIndFracOne = sh.get_subset_index(edgeFracOne); - // auto subsIndFracTwo = sh.get_subset_index(edgeFracTwo); - - number shiftOne = fracInfosBySubset.at( subsIndFracOne ).width / 2. ; - number shiftTwo = fracInfosBySubset.at( subsIndFracTwo ).width / 2. ; - - vector3 shiftAlongEdgeTwo; - VecScale(shiftAlongEdgeTwo, projectNrmFraOneToEdgTwoDirection, shiftOne); - - vector3 shiftAlongEdgeOne; - VecScale(shiftAlongEdgeOne, projectNrmFraTwoToEdgOneDirection, shiftTwo); - - vector3 shiftPart; - VecAdd(shiftPart, fracVrtPos, shiftAlongEdgeTwo); - - vector3 posNewVrt; - VecAdd( posNewVrt, shiftPart, shiftAlongEdgeOne); - - UG_LOG("neuer Vertex Kreuzung " << posNewVrt << std::endl ); - - Vertex * newShiftVrtx = *grid.create(); - aaPos[newShiftVrtx] = posNewVrt; - - // sh.assign_subset(newShiftVrtx, newSubsToAdd ); - - - for( VertexOfFaceInfo const & vertFracInfoSeg : segPart ) - { - Face * fac = vertFracInfoSeg.getFace(); - - // sh.assign_subset(fa,newSubsToAdd); - - - // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! - vector& newVrts4Fac = aaVrtVecFace[ fac ]; - - IndexType vrtxFnd = 0; - - for(size_t indVrt = 0; indVrt < (fac)->num_vertices(); indVrt++ ) - { - Vertex* facVrt = (fac)->vertex(indVrt); - - if( facVrt == *iterV ) - { - newVrts4Fac[ indVrt ] = newShiftVrtx; - vrtxFnd++; - } - } - - - if( vrtxFnd <= 0 ) - { - UG_THROW("vertex not found kreuzung!" << std::endl); - } - else if( vrtxFnd > 1 ) - { - UG_THROW("vertex zu oft gefunden kreuzung " << vrtxFnd << std::endl ); - } - else if ( vrtxFnd == 1 ) - { - } - else - { - UG_THROW("vertex finden komisch kreuzung " << std::endl); - } - - } - } - } - - UG_LOG("sum angles edges normals " << totAnglsEdg << " " << totAnglsNrm << std::endl); - -// return true; - -#if 0 - // das folgende ist vermutlich Unsinn TODO FIXME, waren wohl Versuche am Anfang..... nochmal prüfen!!!! - - // get starting point of the "rotation" around the vertex where fractures are crossing -// for( auto & attVFT : vVFT ) // not const, as we need to erase found elements! - for( VecVertFracTrip::iterator itAttVFT = vVFT.begin(); itAttVFT != vVFT.end(); ) - { - Face * facAtVrtWithFrac = itAttVFT->getFace(); - - bool facFound = false; - -// for( auto const & ifac : assoFaces ) // not const, as we need to erase found elements! - for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); ) - { - if( *itFac == facAtVrtWithFrac ) - { - // found a starting face - // copy first the found info, then delete the original one - auto attVFTCop = *itAttVFT; // copy, not reference! - - vVFT.erase(itAttVFT); - aF.erase(itFac); - - // TODO FIXME erase ifac and attVFT, how to do? - - Face * startFace = facAtVrtWithFrac; - - // now determine the common edge(s), the first edge of the vector must be a frac edge, the second one might be one - - Edge * startEdg = attVFTCop.getEdge(); - - // unnecessary check, but for test purposes at beginning, later should be removed - if( !FaceContains(facAtVrtWithFrac, startEdg )) - { - UG_THROW("face hat ecke nicht, die es haben soll" << std::endl); - } - - // loop around the edges of the ifac face attached to the vertex - - // determin second edge of the startFace, not stored in the vecVertFracTrip information - // check number of common edges containing the same vertex - - IndexType fndCommEdg = 0; - std::vector assoEdg2Fac; - - assoEdg2Fac.push_back( startEdg ); - - std::vector assoNorm; - - vector3 norm2Frac = attVFTCop.getNormal(); - - Edge * secondEdge; - secondEdge = NULL; - - for( auto const & iE : allAssoEdges ) // werden nicht gelöscht, deswegen Zugriff auf attachment direkt - { - if( FaceContains(facAtVrtWithFrac, iE) ) - { - fndCommEdg++; - if( iE != startEdg ) - { - secondEdge = iE; - } - } - - if( fndCommEdg != 2 ) - { - UG_THROW("komische Anzahl gemeinsamer Ecke " << fndCommEdg << std::endl); - } - - if( secondEdge == NULL ) - { - UG_THROW("wieso keine zweite Ecke gefunden???? " << std::endl); - } - - assoEdg2Fac.push_back(secondEdge); - - // check, if second edge belongs to anothter fracture fac, i.e. if it is also a fracture edge - - // check if second edge is edge of a fracture face, i.e. either this edge, or another one is from a fracture - - bool scndEdgIsFracEdg = aaMarkEdgeB[secondEdge]; - - if( scndEdgIsFracEdg ) - { - // TODO FIXME figure out second vertex fracture info, in this case, we have found the next part of the chain! - - for( VecVertFracTrip::iterator itAttVFTTwo = vVFT.begin(); itAttVFTTwo != vVFT.end(); ) - { - // need to erase also this element soon, also in the list of all attached elements - - Face* vFTTwoFac = itAttVFTTwo->getFace(); - - if( FaceContains( vFTTwoFac, secondEdge)) - { - auto vVFT2 = *itAttVFTTwo; - vVFT.erase( itAttVFTTwo ); - - Face * nextFace = vFTTwoFac; - - if( secondEdge != vVFT2.getEdge() ) - { - UG_THROW("Ecke nicht Ecke " << std::endl); - } - - - } - } - } - else // find the next attached face, either from the - { - - } - } - - break; - } - - if( ! facFound ) - { - UG_THROW("Gesicht unauffindbar" << std::endl); - } - - break; - } - } - - while( vVFT.size() != 0 ) - { - while( aF.size() != 0 ) - { - - } - } - -#endif - - - } - - } -// // // different treatment for boundary vertizes - else - { - - // TODO FIXME es muss wohl noch ein Problem mit den Verschiebungen bei boundary Vertizes geben..... - // TODO FIXME XXXXXXXXXXXXXX hier sind wir - - - if( numFracsCrossAtVrt < 1 ) - { - UG_THROW("no fracs crossing but marked vertex at boundary? << std::endl"); - } - else if( numFracsCrossAtVrt == 1 ) // no crossing point at boundary - { - // in this case, we have ONE attached edges, the edges has two attached faces - // the faces have a normal, and based on the normal, we can decide which faces belong to the same side of the edges - - if( numbAttTripl != 2 ) - { - UG_THROW("Anzahl der angehaengten Triples kann nicht stimmen, Vertex einer Kluft ohne Schnittpunkte am Rand " << std::endl); - } - - // Zuordnung der Edges und Faces, die auf der gleichen Seite der fracture sind - - // und gleich auch Erzeugung der neuen Knoten, die dann - // in einem Doublett zusammen mit ihren Normalen an die alten Vertizes - // angehängt werden; der Winkel zur Normalen hilft später, die Seite - // heraus zu finden, Seite von den Edges - - // get edges adjacent to this vertex which lie on the boundary of the domain - - std::vector adjBndEdgs; - -// std::vector & allAssoEdges = aaVrtInfoAssoEdges[*iterV]; - -// for( std::vector::iterator iterBVEdg = grid.associated_edges_begin(*iterV); iterBVEdg != grid.associated_edges_end(*iterV); iterBVEdg++ ) -// { -// if( IsBoundaryEdge2D(grid,*iterBVEdg) ) -// { -// adjBndEdgs.push_back( *iterBVEdg ); -// } -// } - for( auto const & iBVE : allAssoEdges ) - { - if( IsBoundaryEdge2D(grid, iBVE ) ) - { - adjBndEdgs.push_back( iBVE ); - } - } - - // to compute the normals, compute the vector of the edge and normalize it - std::vector bndEdgeDirection; - - for( auto const & bE : adjBndEdgs ) - { - - // get vertices, i.e. get seocnd vertex, first one must be known - -// std::vector verticesEdg; - - //static_assert( std::is_same< Edge* const &, decltype( bE ) >::value ); - - //static_assert( std::is_same< Vertex*, decltype( bE->vertex(0) ) >::value ); - - IndexType fndIV = 0; - - Vertex * vrtOtherEdg; - vrtOtherEdg = NULL; - - for( size_t i = 0; i < 2; ++i ) - { -// verticesEdg.push_back( adjBndEdgs.vertex(i) ); - - Vertex * vrtOfEdg = bE->vertex(i); - - if( vrtOfEdg == *iterV ) - { - fndIV++; - } - else - { - vrtOtherEdg = vrtOfEdg; - } - } - - vector3 posOtherVrt = aaPos[vrtOtherEdg]; - - UG_LOG("BOUNDARY EDGE VERTIZES " << posOldVrt << ", " << posOtherVrt << std::endl); - - vector3 fromIterV2Other; - - VecSubtract(fromIterV2Other, posOtherVrt, posOldVrt); - - vector3 nV; - - VecNormalize(nV, fromIterV2Other); - - bndEdgeDirection.push_back(nV); - } - - - -#if WORKAROUND_SEGFAULT_CREATE_VERTEX - - IndexType dbg_lim = vecVertFracTrip.size(); - - int dbg_cnt = 0; -#endif - - for( VvftIterator vvftAtBnd = vecVertFracTrip.begin(); - vvftAtBnd != vecVertFracTrip.end(); - vvftAtBnd++ - ) - { -#if WORKAROUND_SEGFAULT_CREATE_VERTEX - - if( dbg_lim == dbg_cnt ) - { - UG_LOG("DARF NICHT SEIN" << std::endl); - break; - } - - dbg_cnt++; -#endif - - // Ziel: den parallelen Anteil der Normalen auf die jeweilige Randkante projizieren - - vector3 nrmEdg = vvftAtBnd->getNormal(); - - Edge * edgeOfFrac = vvftAtBnd->getEdge(); - - // figure out the adjoint boundary edge into the same direction - - // the normal in both directions have to be compared with the vectors in direction of boundary edges - for( auto bED : bndEdgeDirection ) - { - // check orientation of boundary edges wrt the normals - - number cosinus = VecDot( nrmEdg, bED ); - - UG_LOG("BOUNDARY COSINUS between " << nrmEdg << " and " << bED << " -> " << cosinus << std::endl); - - if( cosinus > 0 ) - { - // gleiche Seite vermutet - - // muessen wissen, wie lange das gestreckt werden soll - - vector3 alongEdgV; - - auto subsIndEdgOF = sh.get_subset_index(edgeOfFrac); - - number width = fracInfosBySubset.at(subsIndEdgOF).width; - - number scal = width / 2. / cosinus; - - VecScale( alongEdgV, bED, scal ); - - vector3 posNewVrtOnBnd; - - VecAdd(posNewVrtOnBnd, posOldVrt, alongEdgV ); - - UG_LOG("neuer Vertex Edge " << posNewVrtOnBnd << std::endl ); - - Vertex * newShiftEdgVrtx = *grid.create(); - aaPos[newShiftEdgVrtx] = posNewVrtOnBnd; - - sh.assign_subset(newShiftEdgVrtx, subsIndEdgOF ); - - std::vector attEdg; - std::vector attFac; - - attEdg.push_back(edgeOfFrac); - - Face * facFrac = vvftAtBnd->getFace(); - - attFac.push_back( facFrac ); - - // we store the boundary edge direction for boundary verzizes rather than the normal, in contrast to inner vertizes, where we store the averaged normal - ExpandVertexMultiplett vrtMtpl( attEdg, attFac, bED ); - - aaVrtExpMP[ *iterV ].push_back( vrtMtpl ); - -#if 0 - // the attached faces need to know that they need a new vertex to be shifted - for( std::vector::iterator iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ ) - { - bool isFromFrac = false; - - for( auto const & facFrac : attFac ) - { - if( *iterFac == facFrac ) - { - isFromFrac = true; - } - } - - bool atRightSide = false; - - if( isFromFrac ) - atRightSide = true; - - if( !isFromFrac ) - { - - // check if on same side of edge where the normal points to: compute cosinus between vector of face center - // perpendicular to the edge - // TODO FIXME - - vector3 facCenter = CalculateCenter( *iterFac, aaPos ); - - vector3 perpendicu; - - DropAPerpendicular(perpendicu, facCenter, aaPos[edgeOfFrac->vertex(0)], aaPos[edgeOfFrac->vertex(1)]); - - vector3 tmpN; - - VecSubtract(tmpN, facCenter, perpendicu ); - - VecNormalize(tmpN, tmpN); - - UG_LOG("Normale Boundary zum Face ist " << tmpN << std::endl); - - number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, nrmEdg ); - - UG_LOG("Cosinus Boundary zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); - - if( cosBetwFracEdgAndDirection2Face > 0 ) - { - UG_LOG("assuming boundary face to be on richt side" << std::endl); - - atRightSide = true; - -#if GRAPHICAL_SUDO_CREATION_DBG - Vertex * otherFacCent = *grid.create(); - aaPos[otherFacCent] = facCenter; - sh.assign_subset(otherFacCent, 5 ); - - Vertex * pp = *grid.create(); - aaPos[pp] = perpendicu; - sh.assign_subset(pp, 6 ); - - sh.assign_subset(*iterFac,7); -#endif - - - } - else - { - UG_LOG("assuming boundary face to be on wrong side" << std::endl); - } - - } - - if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein - { - - - vector& newVrts4Fac = aaVrtVecFace[ * iterFac ]; - - IndexType vrtxFnd = 0; - - for(size_t indVrt = 0; indVrt < (*iterFac)->num_vertices(); indVrt++ ) - { - Vertex* facVrt = (*iterFac)->vertex(indVrt); - - if( facVrt == *iterV ) - { - newVrts4Fac[ indVrt ] = newShiftEdgVrtx; - vrtxFnd++; - } - } - - - - if( vrtxFnd <= 0 ) - { - UG_THROW("vertex not found bnd!" << std::endl); - } - else if( vrtxFnd > 1 ) - { - UG_THROW("vertex zu oft gefunden bnd " << vrtxFnd << std::endl ); - } - else if ( vrtxFnd == 1 ) - { -// UG_LOG("vertex found abgeschlossen" << std::endl); - } - else - { - UG_THROW("vertex finden bnd komisch " << std::endl); - } - } - - } -#else - for( auto const & ifac : assoFaces ) - { - bool isFromFrac = false; - - for( auto const & facFrac : attFac ) - { - if( ifac == facFrac ) - { - isFromFrac = true; - } - } - - bool atRightSide = false; - - if( isFromFrac ) - atRightSide = true; - - if( !isFromFrac ) - { - - // check if on same side of edge where the normal points to: compute cosinus between vector of face center - // perpendicular to the edge - // TODO FIXME - - vector3 facCenter = CalculateCenter( ifac, aaPos ); - - vector3 perpendicu; - - DropAPerpendicular(perpendicu, facCenter, aaPos[edgeOfFrac->vertex(0)], aaPos[edgeOfFrac->vertex(1)]); - - vector3 tmpN; - - VecSubtract(tmpN, facCenter, perpendicu ); - - VecNormalize(tmpN, tmpN); - - UG_LOG("Normale Boundary zum Face ist " << tmpN << std::endl); - - number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, nrmEdg ); - - UG_LOG("Cosinus Boundary zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); - - if( cosBetwFracEdgAndDirection2Face > 0 ) - { - UG_LOG("assuming boundary face to be on richt side" << std::endl); - - atRightSide = true; - -#if GRAPHICAL_SUDO_CREATION_DBG - Vertex * otherFacCent = *grid.create(); - aaPos[otherFacCent] = facCenter; - sh.assign_subset(otherFacCent, 5 ); - - Vertex * pp = *grid.create(); - aaPos[pp] = perpendicu; - sh.assign_subset(pp, 6 ); - - sh.assign_subset(*iterFac,7); -#endif - - - } - else - { - UG_LOG("assuming boundary face to be on wrong side" << std::endl); - } - - } - - if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein - { - - - vector& newVrts4Fac = aaVrtVecFace[ ifac ]; - - IndexType vrtxFnd = 0; - - for(size_t indVrt = 0; indVrt < (ifac)->num_vertices(); indVrt++ ) - { - Vertex* facVrt = (ifac)->vertex(indVrt); - - if( facVrt == *iterV ) - { - newVrts4Fac[ indVrt ] = newShiftEdgVrtx; - vrtxFnd++; - } - } - - - - if( vrtxFnd <= 0 ) - { - UG_THROW("vertex not found bnd!" << std::endl); - } - else if( vrtxFnd > 1 ) - { - UG_THROW("vertex zu oft gefunden bnd " << vrtxFnd << std::endl ); - } - else if ( vrtxFnd == 1 ) - { -// UG_LOG("vertex found abgeschlossen" << std::endl); - } - else - { - UG_THROW("vertex finden bnd komisch " << std::endl); - } - } - } - -#endif - - - - } - } - } - - } - else // fractures are crossing at boundary even - { - - } - - - UG_LOG("END THIS BOUNDARY VERTEX" << std::endl); - } - - dbg_vertizesPassiert++; - - } - - -// // neue Vertizes in der Entfernung der Klüfte von den Klüften weg erzeugen, -// // basierend auf den Normalen multipliziert mit der halben Kluftdicke -// //für eine Kluft erstmal nur -// // die neuen Kanten und Faces erzeugen, die alten falschen Kanten löschen und ebenso die alten Faces -// // später auf mehr Klüfte ausdehnen, mit Problemstelle Kreuzung, aber erst, wenn eine Kluft funktioniert -// - -// return true; - - // jetzt Seb Sachen beinahe unverändert - - //////////////////////////////// - // create new elements - - // first we create new edges from selected ones which are connected to - // inner vertices. This allows to preserve old subsets. - // Since we have to make sure that we use the right vertices, - // we have to iterate over the selected faces and perform all actions on the edges - // of those faces. - for(FaceIterator iter_sf = sel.faces_begin(); iter_sf != sel.faces_end(); ++iter_sf) - { - Face* sf = *iter_sf; - // check for each edge whether it has to be copied. - for(size_t i_edge = 0; i_edge < sf->num_edges(); ++i_edge) - { - Edge* e = grid.get_edge(sf, i_edge); - - if(sel.is_selected(e)) - { - // check the associated vertices through the volumes aaVrtVecVol attachment. - // If at least one has an associated new vertex and if no edge between the - // new vertices already exists, we'll create the new edge. - size_t ind0 = i_edge; - size_t ind1 = (i_edge + 1) % sf->num_edges(); - - Vertex* nv0 = (aaVrtVecFace[sf])[ind0]; - Vertex* nv1 = (aaVrtVecFace[sf])[ind1]; - - if(nv0 || nv1) - { - // if one vertex has no associated new one, then we use the vertex itself - if(!nv0) - nv0 = sf->vertex(ind0); - if(!nv1) - nv1 = sf->vertex(ind1); - - // create the new edge if it not already exists. - if(!grid.get_edge(nv0, nv1)) - grid.create_by_cloning(e, EdgeDescriptor(nv0, nv1), e); - } - } - } - } - - - std::vector newFaces; - std::vector subsOfNewFaces; - - // iterate over all surrounding faces and create new vertices. - // Since faces are replaced on the fly, we have to take care with the iterator. - for(FaceIterator iter_sf = sel.faces_begin(); iter_sf != sel.faces_end();) - { - Face* sf = *iter_sf; - ++iter_sf; - - vector newVrts = aaVrtVecFace[sf]; - - // all new vertices have been assigned to newVrts. - // Note that if newVrts[i] == NULL, then we have to take the - // old vertex sf->vertex(i). - // now expand the fracture edges of sf to faces. - for(size_t i_vrt = 0; i_vrt < sf->num_vertices(); ++i_vrt) - { - size_t iv1 = i_vrt; - size_t iv2 = (i_vrt + 1) % sf->num_vertices(); - - Edge* tEdge = grid.get_edge(sf->vertex(iv1), sf->vertex(iv2)); - - if(tEdge) - { - if( aaMarkEdgeB[tEdge] ) - { - Face* expFace = NULL; - if(newVrts[iv1] && newVrts[iv2]) - { - // create a new quadrilateral - expFace = *grid.create( - QuadrilateralDescriptor(sf->vertex(iv1), sf->vertex(iv2), - newVrts[iv2], newVrts[iv1])); - } - else if(newVrts[iv1]) - { - // create a new triangle - expFace = *grid.create( - TriangleDescriptor(sf->vertex(iv1), sf->vertex(iv2), newVrts[iv1])); - } - else if(newVrts[iv2]) - { - // create a new triangle - expFace = *grid.create( - TriangleDescriptor(sf->vertex(iv1), sf->vertex(iv2), newVrts[iv2])); - } - else - { - -//// sh.assign_subset(*iter_sf,10); -//// sh.assign_subset(tEdge,11); -// -// return true; -// // this code-block should never be entered. If it is entered then -// // we selected the wrong faces. This is would be a BUG!!! -// // remove the temporary attachments and throw an error -// -// // remove the temporary attachments -//#if FORMER_EXPANSION_TECHNIQUES -// grid.detach_from_vertices(aAdjMarker); -// grid.detach_from_edges(aAdjMarker); -//#endif -// grid.detach_from_vertices(aAdjMarkerVFP); -// grid.detach_from_edges(aAdjMarkerB); -// -// grid.detach_from_vertices( aAdjInfoAVVFT ); -// grid.detach_from_faces(attVrtVec); -// -// grid.detach_from_vertices( aAdjInfoEdges ); -// grid.detach_from_vertices( aAdjInfoFaces ); -// -// -// // TODO FIXME auch die weiteren Marker und INfos, alle Attachments, detachen!!!! -// -// throw(UGError("Implementation error in ExpandFractures2d Arte.")); - } - - // TODO FIXME selektion closen irgendwie, damit auch alle Randkanten zum subset gehoeren!!! - - if( expFace ) - { - sh.assign_subset(expFace, fracInfosBySubset.at(sh.get_subset_index(tEdge)).newSubsetIndex); - - int subs = fracInfosBySubset.at(sh.get_subset_index(tEdge)).newSubsetIndex; - - subsOfNewFaces.push_back( subs ); - - newFaces.push_back( expFace ); - } - } - } - } - - - - - // now set up a new face descriptor and replace the face. - if(fd.num_vertices() != sf->num_vertices()) - fd.set_num_vertices(sf->num_vertices()); - - for(size_t i_vrt = 0; i_vrt < sf->num_vertices(); ++i_vrt) - { - if(newVrts[i_vrt]) - fd.set_vertex(i_vrt, newVrts[i_vrt]); - else - fd.set_vertex(i_vrt, sf->vertex(i_vrt)); - } - - grid.create_by_cloning(sf, fd, sf); - grid.erase(sf); - } - - // we have to clean up unused edges. - // All selected edges with mark 0 have to be deleted. - for(EdgeIterator iter = sel.edges_begin(); iter != sel.edges_end();) - { - // be careful with the iterator - Edge* e = *iter; - ++iter; - - if(!aaMarkEdgeB[e]) - grid.erase(e); - } - - if( subsOfNewFaces.size() != newFaces.size() ) - { - UG_THROW("andere zahl neue faces als subdoms " << std::endl); - } - - IndexType nfn = 0; - - for( auto const & nf : newFaces ) - { - for(size_t i_edge = 0; i_edge < nf->num_edges(); ++i_edge) - { - Edge* edg = grid.get_edge(nf, i_edge); - - sh.assign_subset( edg, subsOfNewFaces[nfn] ); - } - - nfn++; - } - - // sollen die Boundary Edges zur boundary gehören, oder zur Kluft? - // wie ist es mit den Knoten, sind die alle richtig zugewiesen bezüglich subset? - - // TODO FIXME HHHHHHHHHHHHHHHHHH - // jetzt muss noch der Diamant erzeugt werden - // Ziel: KluftInnen erzeugen - - // remove the temporary attachments - -#if FORMER_EXPANSION_TECHNIQUES - grid.detach_from_vertices(aAdjMarker); - grid.detach_from_edges(aAdjMarker); -#endif - grid.detach_from_vertices(aAdjMarkerVFP); - grid.detach_from_edges(aAdjMarkerB); - - grid.detach_from_vertices( aAdjInfoAVVFT ); - grid.detach_from_faces(attVrtVec); - - grid.detach_from_vertices( aAdjInfoEdges ); - grid.detach_from_vertices(aAdjInfoFaces ); - - - // TODO FIXME alles detachen, was noch attached ist, da ist einiges hinzu gekommen! - - - return true; - - // ENDE NEUES ZEUG SELEKTION - - - - - - - -#if FORMER_EXPANSION_TECHNIQUES - // TODO FIXME von diesem Loop kann man noch für oben die calculate crease normal lernen, vielleicht minimal abgewandelt, vielleicht exakt gleich - - // a callback that returns true if the edge is a fracture edge, neues System - AttachmentUnequal > isFracEdgeB(aaMarkEdgeB, false); - - // iterate over all surrounding faces and create new vertices. - for(FaceIterator iter_sf = sel.faces_begin(); iter_sf != sel.faces_end(); ++iter_sf) - { - Face* sf = *iter_sf; - - // check for each vertex whether it lies in the fracture - // (aaMarkVRT > 1 in this case) - // if so, we have to copy or create a vertex from/in aaVrtVec[vrt] which is - // associated with the crease normal on the side of sf. - for(size_t i_vrt = 0; i_vrt < sf->num_vertices(); ++i_vrt) - { - Vertex* vrt = sf->vertex(i_vrt); - if(aaMarkVRT[vrt] > 1) - { - // calculate the normal on this side of the frac - // TODO FIXME so eine Funktion brauchen wir vielleicht oben auch zur Vereinfachung des Codes!!! - vector3 n_v2 = CalculateCreaseNormal(grid, sf, vrt, isFracEdgeB, aaPos); - // das calculate crease normal scheint mir ein Schwachsinn zu sein - // aber vielleicht doch nicht? - - UG_LOG("calculated crease normal v2: " << n_v2 << endl); - - } - } -#endif - - - - - - - -} - - - - } From 2c43dd58667b62b9273c5a69bb38585cf41670c9 Mon Sep 17 00:00:00 2001 From: Markus Date: Mon, 5 Aug 2024 01:58:39 +0200 Subject: [PATCH 46/58] =?UTF-8?q?=C3=9Cbertragen=20von=20arte24=20auf=20ma?= =?UTF-8?q?ster=20vorbereiten?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../extrusion/expand_layers_arte.cpp | 8114 ++++++++++++++++- .../algorithms/extrusion/expand_layers_arte.h | 35 +- 2 files changed, 8143 insertions(+), 6 deletions(-) diff --git a/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.cpp b/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.cpp index 6a3134911..d8292b7b0 100644 --- a/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.cpp +++ b/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.cpp @@ -1,13 +1,40 @@ /* * expand_layers_arte.cpp * - * Created on: 11.07.2024 - * Author: mknodel + * Created on: 5.8.2024 + * Author: Markus M. Knodel + * This file is part of UG4. + * + * UG4 is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License version 3 (as published by the + * Free Software Foundation) with the following additional attribution + * requirements (according to LGPL/GPL v3 §7): + * + * (1) The following notice must be displayed in the Appropriate Legal Notices + * of covered and combined works: "Based on UG4 (www.ug4.org/license)". + * + * (2) The following notice must be displayed at a prominent place in the + * terminal output of covered works: "Based on UG4 (www.ug4.org/license)". + * + * (3) The following bibliography is recommended for citation and must be + * preserved in all covered files: + * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively + * parallel geometric multigrid solver on hierarchically distributed grids. + * Computing and visualization in science 16, 4 (2013), 151-164" + * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel + * flexible software system for simulating pde based models on high performance + * computers. Computing and visualization in science 16, 4 (2013), 165-179" + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. */ #include #include "expand_layers.h" +#include "expand_layers_arte.h" #include "lib_grid/algorithms/geom_obj_util/geom_obj_util.h" #include "lib_grid/callbacks/callbacks.h" #include "lib_grid/grid/grid_util.h" @@ -20,15 +47,8094 @@ #include #include #include +#include +#include #include "support.h" + +using namespace std; + namespace ug{ -bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, std::vector const & fracInfos, - bool expandInnerFracBnds, bool expandOuterFracBnds ) + + +using VertFracTrip = VertexFractureTriple; + +//using VecVertFracTrip = std::vector; + +//using VvftIterator = VecVertFracTrip::iterator; + +using AttVrtVec = Attachment >; + +//using VertexOfFaceInfo = VertexFractureTriple< std::pair, Face*, std::pair >; +// +//using SegmentsFractExtrus = std::vector; + +using IndexType = unsigned short; + +//using ShiftInfoBasis = std::pair; +// +//using ShiftInfoSegment = std::pair; + +//using CrossVertInf = CrossingVertexInfo; +//using CrossVertInf = CrossingVertexInfo; +using CrossVertInf = CrossingVertexInfo; //, Edge* >; + + + + +// for cases with one fracture and no crossing points +template +bool expandSingleFractureAtGivenSide( vector3 const & nOne, vector3 const & nTwo, + Edge * edgeOne, Edge * edgeTwo, + Face * facOne, Face * facTwo, + vector const & fracInfosBySubset, + vector3 const & posOldVrt, + Grid::VertexAttachmentAccessor & aaPos, + Grid & grid, SubsetHandler & sh, + ASOF const & assoFaces, + std::vector const & nextFracVrt, + Grid::FaceAttachmentAccessor & aaVrtVecFace, + int & dbg_flachen_passiert, + Vertex * iterV ) +{ + + CrossVertInf cvi( nullptr, 0 ); + + return expandSingleFractureAtGivenSide( nOne, nTwo, + edgeOne, edgeTwo, + facOne, facTwo, + fracInfosBySubset, + posOldVrt, + aaPos, + grid, sh, + assoFaces, + nextFracVrt, + aaVrtVecFace, + dbg_flachen_passiert, + iterV, + cvi, + false + ); +} + +// for the case of crossing points +template +bool expandSingleFractureAtGivenSide( vector3 const & nOne, vector3 const & nTwo, + Edge * edgeOne, Edge * edgeTwo, + Face * facOne, Face * facTwo, + vector const & fracInfosBySubset, + vector3 const & posOldVrt, + Grid::VertexAttachmentAccessor & aaPos, + Grid & grid, SubsetHandler & sh, + ASOF const & assoFaces, + std::vector const & nextFracVrt, + Grid::FaceAttachmentAccessor & aaVrtVecFace, + int & dbg_flachen_passiert, + Vertex * iterV, + CrossVertInf & crossVrtInf, + bool insertCrossVrtInf = true + ) +{ + +#if 1 + // gleiche Seite vermutet oder gegeben + + // average the normals -- das wird wohl der Fehler sein, wenn n1 und n2 nicht fast parallel sind, wenn man davon ausgehend + // bestimmt, auf welcher Seite benachbarte Dreiecke liegen, zur Berechnung des Verschiebevektors ist es aber gut + + vector3 normSum; + + VecAdd( normSum, nOne, nTwo ); + + vector3 normSumNormed; + + VecNormalize(normSumNormed, normSum); + + UG_LOG("averaged normal " << normSumNormed << std::endl); + + std::vector attEdg; + std::vector attFac; + + attEdg.push_back( edgeOne ); + attEdg.push_back( edgeTwo ); + + attFac.push_back( facOne ); + attFac.push_back( facTwo ); + + // jetzt neuen Vertex erzeugen in Richtung der Normalen + // sonst ist das attachment Schwachsinn! + + vector3 posNewVrt; + + vector3 moveVrt; + + auto subsIndEdgOne = sh.get_subset_index(edgeOne); + + auto subsIndEdgTwo = sh.get_subset_index(edgeTwo); + + if( subsIndEdgOne != subsIndEdgTwo ) + { + UG_THROW("subsets passen nicht Vereinheitlichung" << std::endl ); + } + + number width = fracInfosBySubset.at(subsIndEdgOne).width; + + // FALSCH + // der Faktor ist Käse und muss noch aus den Eingaben übernommen werden + VecScale(moveVrt, normSumNormed, width/2. ); + + VecAdd(posNewVrt, posOldVrt, moveVrt ); + + UG_LOG("neuer Vertex " << posNewVrt << std::endl ); + + // TODO FIXME hier ist das PROBLEM, SEGFAULT durch create regular vertex + + Vertex * newShiftVrtx = *grid.create(); + aaPos[newShiftVrtx] = posNewVrt; + + sh.assign_subset(newShiftVrtx, subsIndEdgOne ); + + if( insertCrossVrtInf ) + { + crossVrtInf.addShiftVrtx(newShiftVrtx, true); + } + // only needed in case of crossing vertices + + + + // alle anhängenden faces müssen noch zu wissen bekommen + // dass es diesen neuen Vertex gibt, nicht nur die + // an den edges anhängenden + // vielleicht gibt es einen Loop über attached faces des + // Vertex, für die schon bekannten direkt angehängten klar + // wenn auch dort vermerkt werden muss im Attachment von Seb + // bei den anderen, die keine Edge haben von der Kluft + // da muss man die Normale ins Zentrum bestimmen + // um heraus zu finden, ob sie auf dieser seite sind + // am besten dann das Attachment der faces für vertizes + // von Seb recyclen + + // loop über assosciated faces des vertex am besten + // vermutlich auch noch assosciated edges, um + // zu markieren, welche weg fallen sollen, wenn + // nicht von Kluft selber, sondern quasi verschoben + // und neu erzeugt + + int dbg_FaceIterator = 0; + + for( auto const & ifac : assoFaces ) + { + + bool isFromFrac = false; + + int dbg_innterFacFracIt = 0; + + for( auto const & facFrac : attFac ) + { + + static_assert( std::is_same< decltype( (facFrac) ), decltype ( ifac ) >::value ); + + if( ifac == facFrac ) + { + isFromFrac = true; + + static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value ); + static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value ); + + } + } + +// if( ifac == facOne || ifac == facTwo ) +// isFromFrac = true; + +// if( FaceContains(facOne,edgeOne) || FaceContains(facTwo,edgeTwo) ) +// isFromFrac = true; + + + bool atRightSide = false; + + if( isFromFrac ) + atRightSide = true; + + if( !isFromFrac ) + { + // check if on same side of edge where the normal points to: compute cosinus between vector of face center + // perpendicular to the edge + // hier liegt wohl aber ein Fehler vor, wenn die beiden Ecken in einem Winkel zueinander stehen, der nicht fast parallel ist + + vector3 facCenter = CalculateCenter( ifac, aaPos ); + + vector3 perpendicu; + + constexpr bool decideSideBasedOnAveragedEdges = false; + + if( nextFracVrt.size() != 2 ) + { + UG_THROW("komische Groesse" << std::endl); + } + + if( decideSideBasedOnAveragedEdges ) + { + DropAPerpendicular(perpendicu, facCenter, aaPos[nextFracVrt[0]], aaPos[nextFracVrt[1]]); + + vector3 tmpN; + + VecSubtract(tmpN, facCenter, perpendicu ); + + VecNormalize(tmpN, tmpN); + + UG_LOG("Normale zum Face ist " << tmpN << std::endl); + + number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, normSumNormed ); + + UG_LOG("Cosinus zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); + + if( cosBetwFracEdgAndDirection2Face > 0 ) + { + UG_LOG("assuming face to be on richt side" << std::endl); + + atRightSide = true; + + +#if ESTABLISH_DEBUG_SUDOS + + Vertex * otherFacCent = *grid.create(); + aaPos[otherFacCent] = facCenter; + // sh.assign_subset(otherFacCent, 5 ); + sh.assign_subset(otherFacCent, sh.num_subsets() ); + + Vertex * pp = *grid.create(); + aaPos[pp] = perpendicu; + sh.assign_subset(pp, sh.num_subsets() ); + // sh.assign_subset(pp, 6 ); + + // sh.assign_subset(*iterFac,7); + sh.assign_subset( *iterFac, sh.num_subsets() ); +#endif + + } + else + { + UG_LOG("assuming face to be on wrong side" << std::endl); + } + } + else // vielleicht besser so? + { + + // dicide first to which of the edges the center is more close + + vector3 perpendOne, perpendTwo; + + DropAPerpendicular(perpendOne, facCenter, aaPos[edgeOne->vertex(0)], aaPos[edgeOne->vertex(1)] ); + DropAPerpendicular(perpendTwo, facCenter, aaPos[edgeTwo->vertex(0)], aaPos[edgeTwo->vertex(1)] ); + + vector3 distOne, distTwo; + + VecSubtract(distOne, facCenter, perpendOne ); + VecSubtract(distOne, facCenter, perpendTwo ); + + auto lengthOne = VecLength(distOne); + auto lengthTwo = VecLength(distTwo); + + // hier umgedreht, bewirkt Verbewwerung, wieso das? + bool oneSmallerThanTwo = ( lengthOne < lengthTwo ); + // correct assumption? + //Edge * closerEdge = ( lengthOne > lengthTwo ) ? edgeTwo : edgeOne; + vector3 distMin = oneSmallerThanTwo ? distTwo : distOne; + vector3 distNorm; + VecNormalize(distNorm, distMin); + + UG_LOG("Normale zum Face ist " << distNorm << std::endl); + + vector3 normMin = oneSmallerThanTwo ? nTwo : nOne; + number cosBetwFracEdgAndDirection2Face = VecDot(distNorm, normMin ); + + UG_LOG("Cosinus zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); + + if( cosBetwFracEdgAndDirection2Face > 0 ) + { + UG_LOG("assuming face to be on richt side" << std::endl); + + atRightSide = true; + + +#if ESTABLISH_DEBUG_SUDOS + + Vertex * otherFacCent = *grid.create(); + aaPos[otherFacCent] = facCenter; + // sh.assign_subset(otherFacCent, 5 ); + sh.assign_subset(otherFacCent, sh.num_subsets() ); + + Vertex * pp = *grid.create(); + aaPos[pp] = perpendicu; + sh.assign_subset(pp, sh.num_subsets() ); + // sh.assign_subset(pp, 6 ); + + // sh.assign_subset(*iterFac,7); + sh.assign_subset( *iterFac, sh.num_subsets() ); +#endif + } + + } + + dbg_flachen_passiert++; + } + + if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein + { + + // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! + vector& newVrts4Fac = aaVrtVecFace[ ifac ]; + + IndexType vrtxFnd = 0; + + for(size_t indVrt = 0; indVrt < (ifac)->num_vertices(); indVrt++ ) + { + Vertex* facVrt = (ifac)->vertex(indVrt); + + if( facVrt == iterV ) + { + newVrts4Fac[ indVrt ] = newShiftVrtx; + vrtxFnd++; + } + } + +// if( insertCrossVrtInf ) +// { +//// crossVrtInf.setShiftVrtx(newVrts4Fac); +// crossVrtInf.addShiftVrtx(newVrts4Fac, true); +// } +// // only needed in case of crossing vertices + + if( vrtxFnd <= 0 ) + { + UG_THROW("vertex not found!" << std::endl); + } + else if( vrtxFnd > 1 ) + { + UG_THROW("vertex zu oft gefunden " << vrtxFnd << std::endl ); + } + else if ( vrtxFnd == 1 ) + { + } + else + { + UG_THROW("vertex finden komisch " << std::endl); + } + + + } + + dbg_innterFacFracIt++; + + + + dbg_FaceIterator++; + + } +#endif + + return true; + +} + +#if 0 +void createShiftVertexPassingClefts( vector3 const & nOne, vector3 const nTwo, Vertex * & newShiftVrtx, SubsetHandler & sh, + vector3 const & posOldVrt, bool subsEqual = true ) +{ + + auto subsIndEdgOne = sh.get_subset_index(edgeOne); + + auto subsIndEdgTwo = sh.get_subset_index(edgeTwo); + + if( subsIndEdgOne != subsIndEdgTwo && subsEqual ) + { + UG_THROW("subsets passen nicht Vereinheitlichung" << std::endl ); + } + + vector3 moveVrt; + + number cosinus = VecDot(nOne,nTwo); + + number pi = 3.1415926535897932385; + + number cosinusLim = std::cos( pi/8. ); + + if( cosinus > cosinusLim ) + { + vector3 normSum; + + VecAdd( normSum, nOne, nTwo ); + + vector3 normSumNormed; + + VecNormalize(normSumNormed, normSum); + + UG_LOG("averaged normal " << normSumNormed << std::endl); + + std::vector attEdg; + std::vector attFac; + + attEdg.push_back( edgeOne ); + attEdg.push_back( edgeTwo ); + + attFac.push_back( facOne ); + attFac.push_back( facTwo ); + + // jetzt neuen Vertex erzeugen in Richtung der Normalen + // sonst ist das attachment Schwachsinn! + + number widthOne = fracInfosBySubset.at(subsIndEdgOne).width; + number widthTwo = fracInfosBySubset.at(subsIndEdgTwo).width; + + number width = ( widthOne + widthTwo ) /2.; + + // FALSCH + // der Faktor ist Käse und muss noch aus den Eingaben übernommen werden + VecScale(moveVrt, normSumNormed, width/2. ); + + } + else // abknickende Fractures + { + + } + + vector3 posNewVrt; + + VecAdd(posNewVrt, posOldVrt, moveVrt ); + + UG_LOG("neuer Vertex " << posNewVrt << std::endl ); + + // TODO FIXME hier ist das PROBLEM, SEGFAULT durch create regular vertex + + newShiftVrtx = *grid.create(); + aaPos[newShiftVrtx] = posNewVrt; + + sh.assign_subset(newShiftVrtx, subsIndEdgOne ); +} +#endif + +using VecVertFracTrip = std::vector; + +// needed for crossing points +using VertexOfFaceInfo = VertexFractureTriple< std::pair, Face*, std::pair >; +// all edges of the attached face - must always be two, the face itself, and the normal vectors of the face in direction of the two edges +// the size of the normal vector vector also must be two +// however, if an edge of the face is not a fracture edge, we do not compute the normal, but assign zero as norm +// for those edges and faces which are Kluft edges, we assign the normal known from the info computed before, vertex fracture triple + +using VecVertexOfFaceInfo = std::vector; + +using SegmentsFractExtrus = std::vector; + + + + +template <> +// for the case of crossing points +bool expandSingleFractureAtGivenSide + ( vector3 const & nOne, vector3 const & nTwo, + Edge * edgeOne, Edge * edgeTwo, + Face * facOne, Face * facTwo, + vector const & fracInfosBySubset, + vector3 const & posOldVrt, + Grid::VertexAttachmentAccessor & aaPos, + Grid & grid, SubsetHandler & sh, + VecVertexOfFaceInfo const & segPart, + std::vector const & nextFracVrt, + Grid::FaceAttachmentAccessor & aaVrtVecFace, + int & dbg_flachen_passiert, + Vertex * crossPt, + CrossVertInf & crossVrtInf, + bool insertCrossVrtInf + ) +// +// ( vector3 const & nOne, vector3 const & nTwo, +// Edge * edgeOne, Edge * edgeTwo, +// Face * facOne, Face * facTwo, +// vector const & fracInfosBySubset, +// vector3 const & posOldVrt, +// Grid::VertexAttachmentAccessor & aaPos, +// Grid & grid, SubsetHandler & sh, +// VecVertexOfFaceInfo const & segPart, +// std::vector const & nextFracVrt, +// Grid::FaceAttachmentAccessor & aaVrtVecFace, +// int & dbg_flachen_passiert, +// Vertex const * & crossPt, +// CrossVertInf & crossVrtInf, +// bool insertCrossVrtInf // = true +// ) { + // gleiche Seite gegeben + + // average the normals -- das wird wohl der Fehler sein, wenn n1 und n2 nicht fast parallel sind, wenn man davon ausgehend + // bestimmt, auf welcher Seite benachbarte Dreiecke liegen, zur Berechnung des Verschiebevektors ist es aber gut + + // TODO FIXME fuer grossere Winkel die Methode von XCross Projektionen übernehmen!!! + + vector3 normSum; + + VecAdd( normSum, nOne, nTwo ); + + vector3 normSumNormed; + + VecNormalize(normSumNormed, normSum); + + UG_LOG("averaged normal " << normSumNormed << std::endl); + + std::vector attEdg; + std::vector attFac; + + attEdg.push_back( edgeOne ); + attEdg.push_back( edgeTwo ); + + attFac.push_back( facOne ); + attFac.push_back( facTwo ); + + // jetzt neuen Vertex erzeugen in Richtung der Normalen + // sonst ist das attachment Schwachsinn! + + vector3 posNewVrt; + + vector3 moveVrt; + + auto subsIndEdgOne = sh.get_subset_index(edgeOne); + + auto subsIndEdgTwo = sh.get_subset_index(edgeTwo); + + if( subsIndEdgOne != subsIndEdgTwo ) + { + UG_THROW("subsets passen nicht Vereinheitlichung" << std::endl ); + } + + number width = fracInfosBySubset.at(subsIndEdgOne).width; + + // FALSCH + // der Faktor ist Käse und muss noch aus den Eingaben übernommen werden + VecScale(moveVrt, normSumNormed, width/2. ); + + VecAdd(posNewVrt, posOldVrt, moveVrt ); + + UG_LOG("neuer Vertex " << posNewVrt << std::endl ); + + // TODO FIXME hier ist das PROBLEM, SEGFAULT durch create regular vertex + + Vertex * newShiftVrtx = *grid.create(); + aaPos[newShiftVrtx] = posNewVrt; + + sh.assign_subset(newShiftVrtx, subsIndEdgOne ); + + if( insertCrossVrtInf ) + { + crossVrtInf.addShiftVrtx(newShiftVrtx, true); + } + // only needed in case of crossing vertices + + + + // alle anhängenden faces müssen noch zu wissen bekommen + // dass es diesen neuen Vertex gibt, nicht nur die + // an den edges anhängenden + // vielleicht gibt es einen Loop über attached faces des + // Vertex, für die schon bekannten direkt angehängten klar + // wenn auch dort vermerkt werden muss im Attachment von Seb + // bei den anderen, die keine Edge haben von der Kluft + // da muss man die Normale ins Zentrum bestimmen + // um heraus zu finden, ob sie auf dieser seite sind + // am besten dann das Attachment der faces für vertizes + // von Seb recyclen + + // loop über assosciated faces des vertex am besten + // vermutlich auch noch assosciated edges, um + // zu markieren, welche weg fallen sollen, wenn + // nicht von Kluft selber, sondern quasi verschoben + // und neu erzeugt + + // TODO FIXME in eigene Funktion stecken, taucht exakt gleich bei XCross auf am Ende! + + for( VertexOfFaceInfo const & vertFracInfoSeg : segPart ) + { + Face * fac = vertFracInfoSeg.getFace(); + +// sh.assign_subset(fa,newSubsToAdd); + + + // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! + vector& newVrts4Fac = aaVrtVecFace[ fac ]; + + IndexType vrtxFnd = 0; + + for(size_t indVrt = 0; indVrt < (fac)->num_vertices(); indVrt++ ) + { + Vertex* facVrt = (fac)->vertex(indVrt); + + if( facVrt == crossPt ) + { + newVrts4Fac[ indVrt ] = newShiftVrtx; + vrtxFnd++; + + + } + } + + if( vrtxFnd <= 0 ) + { + UG_THROW("vertex not found !" << std::endl); + } + else if( vrtxFnd > 1 ) + { + UG_THROW("vertex zu oft gefunden " << vrtxFnd << std::endl ); + } + else if ( vrtxFnd == 1 ) + { + } + else + { + UG_THROW("vertex finden komisch " << std::endl); + } + + } + return true; + } + + +template <> +// for cases with one fracture and no crossing points +bool expandSingleFractureAtGivenSide + ( vector3 const & nOne, vector3 const & nTwo, + Edge * edgeOne, Edge * edgeTwo, + Face * facOne, Face * facTwo, + vector const & fracInfosBySubset, + vector3 const & posOldVrt, + Grid::VertexAttachmentAccessor & aaPos, + Grid & grid, SubsetHandler & sh, + VecVertexOfFaceInfo const & segPart, + std::vector const & nextFracVrt, + Grid::FaceAttachmentAccessor & aaVrtVecFace, + int & dbg_flachen_passiert, + Vertex * iterV + ) +{ + + CrossVertInf cvi( nullptr, 0 ); + + return expandSingleFractureAtGivenSide( nOne, nTwo, + edgeOne, edgeTwo, + facOne, facTwo, + fracInfosBySubset, + posOldVrt, + aaPos, + grid, sh, + segPart, + nextFracVrt, + aaVrtVecFace, + dbg_flachen_passiert, + iterV, + cvi, + false + ); } + + +using VecEdge = std::vector; +using VecFace = std::vector; + +using ExpandCrossFracInfo = VertexFractureTriple< std::pair, Face*, std::pair >; +// Vertex nullptr wo original fracture, und shift vertex, wo Keilecke, die weg soll - Fall X Cross + +using VecExpandCrossFracInfo = std::vector; + +// leider erst ab 17er Standard möglich +//template +//template < typename SHIVET > distinguish shiftVrtcs for TEnd and XCross, using static conxtexpr for isXCross in calling +// TODO FIXME change once std 17 available in UG4 +bool SortFaces4DiamondCreation( SubsetHandler& sh, std::vector & assoFacCrossCop, Edge * & firstEdgeFac, Edge * & secondEdgeFac, + Face * & assoFacConsider, VecEdge const & origFracEdg, + std::vector const & shiftVrtcs, +// std::vector const & shiftVrtcs, + Vertex * const & crossPt, Edge * & assoFacEdgBeg2Fix, Edge * & assoFacEdgEnd2Fix, Grid& grid, + VecExpandCrossFracInfo & vecExpCrossFI, + bool isXCross = true // if false, then isTEnd, no other possibility + ) +{ + + // done noch die Abweichungen für den TEnd Fall einbauen + + bool atStartSort = true; + + bool boundAtShiftVrtEdg = isXCross; // false in case of TEnd at beginning + +// auto shiftVrtcsCop = shiftVrtcs; + +// UG_LOG("starting Rundlauf " << std::endl); + + IndexType dbg_rndl = 0; + + while( assoFacCrossCop.size() != 0 ) + { + // UG_LOG("Debug Rundlauf " << dbg_rndl << std::endl); + + dbg_rndl++; + + // Original X Cross ganz einfach +// secondEdgeFac = nullptr; + + // stattdessen bei T End +// if( ! atStartSort ) +// { +// secondEdgeFac = nullptr; +// } + +// zusammengefasst, hoffentlich richtig so: + if( isXCross || ( ! isXCross && ! atStartSort ) ) + secondEdgeFac = nullptr; + + // leider erst ab std 17, zu cool für älteren Standard +// constexpr bool isXCross = std::is_same::value; +// +// +// if constexpr ( std::is_same::value ) +// { +// secondEdgeFac = nullptr; +// } +// +// if constexpr ( std::is_same< VRTCOMB, std::pair ) +// { +// if( ! atStartSort ) +// secondEdgeFac = nullptr; +// } + + + Edge * fracEdge = nullptr; + Edge * shiftVrtxEdg = nullptr; + + // IndexType fndEdgEnd = 0; + + std::vector edgesThisFac; + + edgesThisFac.clear(); + + // IndexType eoeo = edgesThisFac.size(); + // + // auto eiei = eoeo; + + // UG_LOG("Edges this fac Orig Orig " << eiei << " " << dbg_rndl << std::endl); + + + // UG_LOG("Debug Ecken " << std::endl); + + IndexType dbg_itEd = 0; + + for( std::vector::iterator iterEdgF = grid.associated_edges_begin(assoFacConsider); + iterEdgF != grid.associated_edges_end(assoFacConsider); iterEdgF++ ) + { + edgesThisFac.push_back(*iterEdgF); + + // UG_LOG("und noch eines dazu " << dbg_itEd << " " << dbg_rndl << std::endl); + + //IndexType sudos = sh.num_subsets(); + + //sh.assign_subset(*iterEdgF,sudos); + } + + // IndexType effsOrig = edgesThisFac.size(); + + // auto efeu = effsOrig; + + // UG_LOG("Edges this fac Orig " << efeu << dbg_rndl << std::endl); + + + // figure out original fracture edge + + IndexType fndFracEdg = 0; + + for( auto const & etf : edgesThisFac ) + { + for( auto const & ofe : origFracEdg ) + { + if( etf == ofe ) + { + fndFracEdg++; + fracEdge = etf; + } + } + } + + // UG_LOG("Debug Ofen " << std::endl); + + if( fracEdge == nullptr || fndFracEdg != 1 ) + { + UG_LOG("Frac Orig Ecke nicht gefunden oder falsche Zahl " << fndFracEdg << " " << isXCross << std::endl ); + // return false; + UG_THROW("Frac Orig Ecke nicht gefunden oder falsche Zahl " << fndFracEdg << " " << isXCross << std::endl ); + } + + + // find expanded shift vertex + + Vertex * shiftVrtxFound = nullptr; + IndexType fndVrt = 0; + + // IndexType suse = sh.num_subsets(); + + //sh.assign_subset(crossPt,suse); + + // for( auto & sv : shiftVrtcsCop ) + // { + // IndexType suseV = sh.num_subsets(); + // //sh.assign_subset(sv,suseV); + // } + + // return true; + + // UG_LOG("Debug Entfernene " << std::endl); + + IndexType dbg_edgnum = 0; + + IndexType helpVarEdges = 0; + + // IndexType effs = edgesThisFac.size(); + // IndexType shiffs = shiftVrtcs.size(); + + // UG_LOG("Edges this fac " << effs << dbg_rndl << std::endl); + // UG_LOG("Shift Vectors " << shiffs << dbg_rndl << std::endl); + + + for( auto const & etf : edgesThisFac ) + { + + if( helpVarEdges >= edgesThisFac.size() ) + { + UG_LOG("Indexueberschreitung Edges" << " " << isXCross << std::endl); + break; + } + + helpVarEdges++; + + dbg_edgnum++; + + IndexType helpShiVaNum = 0; + + IndexType dbg_shiVe = 0; + + // for( Vertex * const & sv : shiftVrtcs ) + for( auto const & sv : shiftVrtcs ) + { + + if( helpShiVaNum >= shiftVrtcs.size() ) + { + UG_LOG("Shift Vertex Index Verletzung " << " " << isXCross << std::endl); + break; + } + + helpShiVaNum++; + + dbg_shiVe++; + + if( EdgeContains(etf, crossPt ) && EdgeContains( etf, sv ) ) + { + shiftVrtxFound = sv; + fndVrt++; + shiftVrtxEdg = etf; + +// UG_LOG("Shift Vertex " << aaPos[shiftVrtxFound] << " " << dbg_edgnum << " " << dbg_shiVe << " " << dbg_rndl << std::endl); +// UG_LOG("Cross Vertex " << aaPos[crossPt] << " " << dbg_edgnum << " " << dbg_shiVe << " " << dbg_rndl << std::endl ); +// +// UG_LOG("dbg edgenu shive " << dbg_edgnum << " " << dbg_shiVe << " " << dbg_rndl << std::endl); + +// isAtFreeSideShiVe = svwi.second; + } + + +// for( IndexType i = 0; i < 2; i++ ) +// { +// +// // done ersetzen durch ElementContains Funktion +// // if( ( etf->vertex(i) == crossPt && etf->vertex((i+1)%2) == sv ) || (etf->vertex((i+1)%2) == crossPt && etf->vertex(i) == sv )) +// if( etf->vertex(i) == crossPt && etf->vertex((i+1)%2) == sv ) +// { +// shiftVrtxFound = sv; +// fndVrt++; +// shiftVrtxEdg = etf; +// +// // UG_LOG("Shift Vertex " << aaPos[shiftVrtxFound] << " " << dbg_edgnum << " " << dbg_shiVe << " " << dbg_rndl << std::endl); +// // UG_LOG("Cross Vertex " << aaPos[crossPt] << " " << dbg_edgnum << " " << dbg_shiVe << " " << dbg_rndl << std::endl ); +// // +// // UG_LOG("dbg edgenu shive " << dbg_edgnum << " " << dbg_shiVe << " " << dbg_rndl << std::endl); +// } +// } + } + } + + // UG_LOG("Debug Entfert durch " << std::endl); + + + if( fndVrt != 1 || shiftVrtxFound == nullptr || shiftVrtxEdg == nullptr ) + { + UG_LOG("shift vertex komische Zahl oder null " << fndVrt << " " << isXCross << std::endl); + // return false; + UG_THROW("shift vertex komische Zahl oder null " << fndVrt << " " << isXCross << std::endl); + } + + // UG_LOG("Debug Entfert Text durch " << std::endl); + + + // for( std::vector::iterator itV = shiftVrtcsCop.begin(); itV != shiftVrtcsCop.end(); itV++ ) + // { + // Vertex * vrt = *itV; + // + // if( vrt == shiftVrtxFound ) + // { + // shiftVrtcsCop.erase(itV); + // break; + // } + // } + // + // UG_LOG("Debug Rasieren durch " << std::endl); + + +// if( atStartSort && isXCross ) +// { +// assoFacEdgBeg2Fix = fracEdge; +// } +// +// if( atStartSort && ! isXCross ) +// { +// assoFacEdgBeg2Fix = fracEdge; +// atStartSort = false; +// } + + + if( atStartSort ) + { + if( isXCross ) + { + assoFacEdgBeg2Fix = fracEdge; + } + else + { + if( fracEdge != secondEdgeFac || shiftVrtxEdg != firstEdgeFac || assoFacEdgBeg2Fix != shiftVrtxEdg ) + UG_THROW("ALler Anfang ist schwer TEnd " << std::endl); + } + + atStartSort = false; + } + + + + // Edge * firstEdgeFac = fracEdge; + // Edge * secondEdgeFac = shiftEdge; + firstEdgeFac = fracEdge; + secondEdgeFac = shiftVrtxEdg; + + + Vertex * firstVrt = nullptr; + Vertex * secondVrt = shiftVrtxFound; + + if( !boundAtShiftVrtEdg ) + { + firstEdgeFac = shiftVrtxEdg; + secondEdgeFac = fracEdge; + + firstVrt = shiftVrtxFound; + secondVrt = nullptr; + } + + // UG_LOG("Debug Paarbildung " << std::endl); + + + std::pair edgesFac( firstEdgeFac, secondEdgeFac ); + + std::pair vrtcsSF( firstVrt, secondVrt ); + + ExpandCrossFracInfo startFacInf( edgesFac, assoFacConsider, vrtcsSF ); + + vecExpCrossFI.push_back(startFacInf); + +// if( !isXCross ) +// { +// IndexType sui = sh.num_subsets(); +// +// sh.assign_subset(assoFacConsider,sui); +// } + + // UG_LOG("Debug Paarbildung Rasieren " << std::endl); + + IndexType dbg_it_er = 0; + + for( std::vector::iterator itFac = assoFacCrossCop.begin(); itFac != assoFacCrossCop.end(); itFac++ ) + { + Face * iFa = *itFac; + + // UG_LOG("interieren " << dbg_it_er << std::endl ); + + dbg_it_er++; + + // UG_LOG("ifa " << iFa << std::endl ); + // UG_LOG("assoFac " << assoFacConsider << std::endl ); + + // bool enthaltung = FaceContains( iFa, firstEdgeFac ); + // + //// UG_LOG("Enthaltung " << std::endl); + // + // bool entzwei = FaceContains(iFa, secondEdgeFac); + // + //// UG_LOG("Entzweiung " << std::endl); + + + if( iFa == assoFacConsider && FaceContains( iFa, firstEdgeFac ) && FaceContains(iFa, secondEdgeFac) ) + { + // UG_LOG("Erasieren " << std::endl); + assoFacCrossCop.erase(itFac); + break; + } + } + + // UG_LOG("Debug Paarbildung Rasieren durch " << std::endl); + + + if( assoFacCrossCop.size() == 0 ) + { + if( secondEdgeFac != assoFacEdgBeg2Fix ) + { + UG_LOG("Gesichter Diamant leer, aber keine Anfangsecke gefunden" << " " << isXCross << std::endl); + //return true; + UG_THROW("Gesichter Diamant leer, aber keine Anfangsecke gefunden" << " " << isXCross << std::endl); + } + else + { + assoFacEdgEnd2Fix = secondEdgeFac; + + break; // while loop zu Ende, raus aus dem while loop, den Rest nicht mehr machen, würde schief gehen zwingendermassen + } + + } + + // figure out the next face + + firstEdgeFac = secondEdgeFac; + secondEdgeFac = nullptr; + + IndexType nextFaceFound = 0; + + for( std::vector::iterator itFac = assoFacCrossCop.begin(); itFac != assoFacCrossCop.end(); itFac++ ) + { + Face * iFa = *itFac; + + if( FaceContains(iFa, firstEdgeFac ) ) + { + nextFaceFound++; + } + } + + if( nextFaceFound != 1 ) + { + UG_LOG("folgendes Gesicht in falscher Anztahl gefunden Diamant " << nextFaceFound << " " << isXCross << std::endl); + // return false; + UG_THROW("folgendes Gesicht in falscher Anztahl gefunden Diamant " << nextFaceFound << " " << isXCross << std::endl); + } + + for( std::vector::iterator itFac = assoFacCrossCop.begin(); itFac != assoFacCrossCop.end(); itFac++ ) + { + Face * iFa = *itFac; + + if( FaceContains(iFa, firstEdgeFac ) ) + { + assoFacConsider = iFa; + break; + } + } + + + boundAtShiftVrtEdg = ! boundAtShiftVrtEdg; + + } + + if( assoFacEdgEnd2Fix != assoFacEdgBeg2Fix || assoFacEdgEnd2Fix == nullptr || assoFacEdgBeg2Fix == nullptr ) + { + UG_THROW("Anfang und Ende stimmen nicht ueberein " << isXCross << std::endl); +// return false; + UG_THROW("Anfang und Ende stimmen nicht ueberein " << isXCross << std::endl); + } + +// if( shiftVrtcsCop.size() != 0 ) +// { +// UG_LOG("Shift vertizes nicht alle gefinden " << std::endl); +// return false; +// UG_THROW("Shift vertizes nicht alle gefinden " << std::endl); +// } + + if( assoFacCrossCop.size() != 0 ) + { + UG_LOG("nicht alle asso facs gefunden " << isXCross << std::endl); +// return false; + UG_THROW("nicht alle asso facs gefunden " << isXCross << std::endl); + } + + + return true; +} + +void computeDiamondPointXCrossType( ExpandCrossFracInfo & expCFIBeforeFracEdg, ExpandCrossFracInfo & expCFIAfterFracEdg, + Vertex * const & crossPt, Grid::VertexAttachmentAccessor & aaPos, + SubsetHandler & sh, Grid & grid, IndexType const & diamantSubsNum, + vector3 & distVecNewVrt2SCrossPt +// vector3 & distVecNewVrt2ShiVeBefore = vector3(), vector3 & distVecNewVrt2ShiVeAfter = vector3(), +// bool computeDistancesNewVrtsToOldShiVe = false +) +{ + // compute cross point + + std::pair edgesCrossSegBefore = expCFIBeforeFracEdg.getEdge(); + std::pair edgesCrossSegAfter = expCFIAfterFracEdg.getEdge(); + + Edge * beforeShiftEdg = edgesCrossSegBefore.first; + Edge * beforeFracEdg = edgesCrossSegBefore.second; + Edge * afterFracEdg = edgesCrossSegAfter.first; + Edge * afterShiftEdg = edgesCrossSegAfter.second; + + std::pair vrtcsCrossSegBefore = expCFIBeforeFracEdg.getNormal(); + std::pair vrtcsCrossSegAfter = expCFIAfterFracEdg.getNormal(); + + Vertex * shiftBefore = vrtcsCrossSegBefore.first; + Vertex * shiftAfter = vrtcsCrossSegAfter.second; + + // zur Zielsetzung +// Vertex * toBeEstablishedCutEdgeVrtBefore = vrtcsCrossSegBefore.second; +// Vertex * toBeEstablishedCutEdgeVrtAfter = vrtcsCrossSegAfter.first; + + if( vrtcsCrossSegBefore.second != nullptr || vrtcsCrossSegAfter.first != nullptr + || shiftBefore == nullptr || shiftAfter == nullptr +// if( toBeEstablishedCutEdgeVrtBefore != nullptr || toBeEstablishedCutEdgeVrtAfter != nullptr +// || shiftBefore == nullptr || shiftAfter == nullptr + ) + UG_THROW("Nullpointer fehlen oder zu viel " << std::endl); + + if( beforeFracEdg != afterFracEdg || beforeFracEdg == nullptr || afterFracEdg == nullptr + || beforeShiftEdg == nullptr || afterShiftEdg == nullptr + ) + UG_LOG("Ecken Nullpunkter " << std::endl); + + // determin cut point of line between the shift vertices and the frac edge + + Edge * fracEdge = beforeFracEdg; // muss gleich sein offenkundig afterFracEdge, ist getestet auch + + // Gerade bestimmen, die durch fracEdge bestimmt wird, und Gerade, die durch Verbindungsvektor shift Verzices bestimmt wird + + // figure out frac vertex which is the cross point + + IndexType fracEdgInd = -1; + + for( IndexType fiv = 0; fiv < 2; fiv++ ) + { + if( fracEdge->vertex(fiv) == crossPt ) + fracEdgInd = fiv; + } + + if( fracEdgInd < 0 || fracEdgInd > 1 ) + UG_THROW("cross point nicht Teil von fracture edge" << std::endl ); + + Vertex * fracEdgEnd = fracEdge->vertex( ( fracEdgInd + 1 ) % 2 ); + + vector3 posCrossPt = aaPos[ crossPt ]; + vector3 posFracEnd = aaPos[ fracEdgEnd ]; + + vector3 posShiftBefore = aaPos[ shiftBefore ]; + vector3 posShiftAfter = aaPos[ shiftAfter ]; + +// vector3 directionFrac; +// +// VecSubtract(directionFrac, posFracEnd, posCrossPt ); + + vector3 directionShiftBefore; + + VecSubtract(directionShiftBefore, posShiftBefore, posCrossPt); + + vector3 directionShiftAfter; + + VecSubtract(directionShiftAfter, posShiftAfter, posCrossPt ); + + vector3 sumShift; + + VecAdd(sumShift, directionShiftBefore, directionShiftAfter); + + vector3 halfSumShift; + + VecScale(halfSumShift,sumShift,0.5); + + vector3 posNewVrtOnEdg; + + VecAdd( posNewVrtOnEdg, posCrossPt, halfSumShift ); + + Vertex * newEdgVrtx = *grid.create(); + aaPos[newEdgVrtx] = posNewVrtOnEdg; + + IndexType sudoEdg = sh.get_subset_index(fracEdge); + + Face * faceBefore = expCFIBeforeFracEdg.getFace(); + Face * faceAfter = expCFIAfterFracEdg.getFace(); + + IndexType sudoBefore = sh.get_subset_index(faceBefore); + IndexType sudoAfter = sh.get_subset_index(faceAfter); + + if( sudoEdg != sudoBefore || sudoBefore != sudoAfter ) + UG_THROW("komische sudos vor Diamant " << std::endl); + +// sh.assign_subset(newEdgVrtx, sudoEdg); + sh.assign_subset(newEdgVrtx, diamantSubsNum ); + + + UG_LOG("neuer Diamant Vorbereitungs Vertex " << posNewVrtOnEdg << std::endl); + + // Vertex * toBeEstablishedCutEdgeVrtBefore = vrtcsCrossSegBefore.second; + // Vertex * toBeEstablishedCutEdgeVrtAfter = vrtcsCrossSegAfter.first; + + + + // gleich neue Faces erzeugen? +// std::pair vrtcsCrossSegBefore = expCFIBeforeFracEdg.getNormal(); +// std::pair vrtcsCrossSegAfter = expCFIAfterFracEdg.getNormal(); + + // insert the newly established vertex into the vertex info of the ExpandCrossFracInfo of the face +//// vrtcsCrossSegBefore.second = newEdgVrtx; +//// vrtcsCrossSegAfter.first = newEdgVrtx; +//// +// std::pair vrtcsCrossSegBeforeNew( vrtcsCrossSegBefore.first, newEdgVrtx ); +// std::pair vrtcsCrossSegAfterNew( newEdgVrtx, vrtcsCrossSegAfter.second ); +// +// +// expCFIBeforeFracEdg.setNewNormal( vrtcsCrossSegBeforeNew ); +// expCFIAfterFracEdg.setNewNormal( vrtcsCrossSegAfterNew ); + + vrtcsCrossSegBefore.second = newEdgVrtx; + vrtcsCrossSegAfter.first = newEdgVrtx; + expCFIBeforeFracEdg.setNewNormal( vrtcsCrossSegBefore ); + expCFIAfterFracEdg.setNewNormal( vrtcsCrossSegAfter ); + + VecSubtract(distVecNewVrt2SCrossPt, posCrossPt, posNewVrtOnEdg ); + + // only needed for TEnd case +// if( computeDistancesNewVrtsToOldShiVe ) +// { +// VecSubtract(distVecNewVrt2ShiVeBefore, posShiftBefore, posNewVrtOnEdg ); +// VecSubtract(distVecNewVrt2ShiVeAfter, posShiftAfter, posNewVrtOnEdg ); +// } +} + + + +void createNewFacesForExtXCrossFracs( ExpandCrossFracInfo const & ecf, std::vector & newFracFaceVec, + bool & boundAtShiftVrtEdg, //bool & atStartSort, + SubsetHandler & sh, Grid & grid, Vertex * const & crossPt, + std::vector const & subdomList + ) +{ + // get new vertex at the original fracture edge + + // extract this functionality to own function + + + std::pair edgesCrossSeg = ecf.getEdge(); + + Face * facSeg = ecf.getFace(); + + std::pair vertcsCrossSeg = ecf.getNormal(); + + std::pair vertcsCrossSegWithNewV = ecf.getNewNormal(); + + +// if( atStartSort || boundAtShiftVrtEdg ) + if( boundAtShiftVrtEdg ) + { + if( vertcsCrossSeg.first != nullptr || vertcsCrossSeg.second == nullptr ) + UG_THROW("Verwechslung " << vertcsCrossSeg.first << " " << vertcsCrossSeg.second << std::endl); + } + +// atStartSort = false; + + Edge * fracEdge = boundAtShiftVrtEdg ? edgesCrossSeg.first : edgesCrossSeg.second; + Edge * shiftVrtEdge = boundAtShiftVrtEdg ? edgesCrossSeg.second : edgesCrossSeg.first; + + Vertex * fracVrtNew = boundAtShiftVrtEdg ? vertcsCrossSegWithNewV.first : vertcsCrossSegWithNewV.second; // should be nullptr at first segment, to be assigned afterwards / shifted + Vertex * shiftVrt = boundAtShiftVrtEdg ? vertcsCrossSeg.second : vertcsCrossSeg.first; + Vertex * shiftVrtTest = boundAtShiftVrtEdg ? vertcsCrossSegWithNewV.second : vertcsCrossSegWithNewV.first; + + if( shiftVrtTest != shiftVrt ) + UG_THROW("Shift Vertex verloren gegangen " << std::endl); + + IndexType sudoFac = sh.get_subset_index(facSeg); + + IndexType sudoFracEdge = sh.get_subset_index(fracEdge); + + if( sudoFac != sudoFracEdge ) + { + UG_THROW("subdoms frac edge und face nicht gleich " << std::endl); + } + + // get all vertices of face, check if both known ones are contained, delete the face, create + // the additional needed edge, and create new face with new vertex + + + std::vector vrtcsFace; + // assign first old vertices, then replace +// std::vector vrtcsNewFaceFrac = vrtcsFace; +// std::vector vrtcsNewFaceDiam = vrtcsFace; + + // all new vertices have been assigned to newVrts. + // Note that if newVrts[i] == NULL, then we have to take the + // old vertex sf->vertex(i). + // now expand the fracture edges of sf to faces. + for(size_t iVrt = 0; iVrt < facSeg->num_vertices(); iVrt++ ) + { + + Vertex * vrt = facSeg->vertex(iVrt); + vrtcsFace.push_back( vrt ); +// vrtcsNewFaceFrac.push_back( vrt ); +// vrtcsNewFaceDiam.push_back( vrt ); + } + + std::vector vrtcsNewFaceFrac = vrtcsFace; +// std::vector vrtcsNewFaceDiam = vrtcsFace; + + + // check if known vertices are contained + + IndexType fraVeNuInd = -1; + IndexType shiftVeNuInd = -1; + + IndexType cntr = 0; + + for( auto const & vf : vrtcsFace ) + { + if( vf == fracVrtNew ) + { + fraVeNuInd = cntr; + UG_THROW("wie kann man hierher kommen?" << std::endl); + } + + if( vf == crossPt ) + { + fraVeNuInd = cntr; + } + +// + if( vf == shiftVrt ) + shiftVeNuInd = cntr; + + cntr++; + } + + if( fraVeNuInd < 0 || shiftVeNuInd < 0 ) + UG_THROW("frac vertex oder shift vertex not contained " << std::endl); + + UG_LOG("neuer frac vertex " << fraVeNuInd << " " << shiftVeNuInd << std::endl ); + + // replace vrtcs + vrtcsNewFaceFrac[fraVeNuInd] = fracVrtNew; + + // compute shift of center vertex along frac edge + + // check subdom of frac vertex and check if in subdom List of X cross + + IndexType sudoOther = -1; + + IndexType foundSudoOther = 0; + IndexType foundSudoFac = 0; + + for( auto const & sd : subdomList ) + { + if( sd != sudoFac ) + { + sudoOther = sd; + foundSudoOther++; + } + else if( sd == sudoFac ) + { + foundSudoFac++; + } + else + { + UG_THROW("Sudo not from frac and not from other?" << std::endl); + } + } + + if( foundSudoFac != 1 && foundSudoOther != 1 ) + UG_THROW("sudo zu oft oder zu selten gefunden " << std::endl); + + // establish new edges and new faces + + if( vrtcsNewFaceFrac.size() != 4 ) + UG_LOG("komische Groesse Gesicht " << std::endl); + + for( IndexType i = 0; i < vrtcsNewFaceFrac.size(); i++ ) + { + if( vrtcsNewFaceFrac[i] == nullptr ) + { + UG_THROW("null auf " << i << std::endl); + } +// else +// { +// UG_LOG("kein null auf " << i << std::endl ); +// } + } + + + UG_LOG("neue Gesichter ausserhalb Diamant Ziel " << std::endl); + +// int a = 1 + 2; +// + Face * newFracFace = nullptr; + + if(vrtcsNewFaceFrac.size() == 3 ) + { + newFracFace = + *grid.create( TriangleDescriptor( vrtcsNewFaceFrac[0], vrtcsNewFaceFrac[1], + vrtcsNewFaceFrac[2] + ) ); + + } + else if( vrtcsNewFaceFrac.size() == 4 ) + { + newFracFace = + *grid.create( QuadrilateralDescriptor( vrtcsNewFaceFrac[0], vrtcsNewFaceFrac[1], + vrtcsNewFaceFrac[2], vrtcsNewFaceFrac[3] + ) ); + + } + else + { + UG_THROW("komisches Gesicht " << std::endl); + } + + if( newFracFace != nullptr ) + { + sh.assign_subset(newFracFace, sh.get_subset_index(facSeg) ); + // sh.assign_subset(newFracFace, diamantSubsNum ); testweise + + newFracFaceVec.push_back(newFracFace); + } + else + { + UG_THROW("Gesicht ist nicht enstanden " << std::endl); + } + + + boundAtShiftVrtEdg = ! boundAtShiftVrtEdg; + + +} + +void createDiamondFacesXCrossType( ExpandCrossFracInfo & expCFIBeforeFracEdg, ExpandCrossFracInfo & expCFIAfterFracEdg, + std::vector & newDiamFaceVec, SubsetHandler & sh, Grid & grid, IndexType diamantSubsNum, Vertex * & crossPt, + bool isFreeTEnd = false ) +{ + + Face * facBefore = expCFIBeforeFracEdg.getFace(); + Face * facAfter = expCFIAfterFracEdg.getFace(); + + std::vector vrtcsFaceBefore; + std::vector vrtcsFaceAfter; + + for(size_t iVrt = 0; iVrt < facBefore->num_vertices(); iVrt++ ) + { + Vertex * vrt = facBefore->vertex(iVrt); + vrtcsFaceBefore.push_back( vrt ); + } + + for(size_t iVrt = 0; iVrt < facAfter->num_vertices(); iVrt++ ) + { + Vertex * vrt = facAfter->vertex(iVrt); + vrtcsFaceAfter.push_back( vrt ); + } + + Vertex * newVrtBefore = expCFIBeforeFracEdg.getNewNormal().first; + Vertex * shiftVrt = expCFIBeforeFracEdg.getNewNormal().second; + Vertex * newVrtAfter = expCFIAfterFracEdg.getNewNormal().second; + + if( expCFIBeforeFracEdg.getNewNormal().second != expCFIBeforeFracEdg.getNormal().second + || expCFIBeforeFracEdg.getNewNormal().second == nullptr + || expCFIBeforeFracEdg.getNewNormal().second != expCFIAfterFracEdg.getNewNormal().first + || expCFIAfterFracEdg.getNewNormal().first == nullptr + || expCFIAfterFracEdg.getNewNormal().first != expCFIAfterFracEdg.getNormal().first + ) + { + UG_LOG("Vektoren " << expCFIBeforeFracEdg.getNewNormal().second << " != " << expCFIBeforeFracEdg.getNormal().second << std::endl + << expCFIBeforeFracEdg.getNewNormal().second << std::endl + << expCFIBeforeFracEdg.getNewNormal().second << " != " << expCFIAfterFracEdg.getNewNormal().first << std::endl + << expCFIAfterFracEdg.getNewNormal().first << std::endl + << expCFIAfterFracEdg.getNewNormal().first << " != " << expCFIAfterFracEdg.getNormal().first << std::endl ); + +#if 0 + Vektoren 0x591e03ec9c90 != 0x591e03ec9c90 + 0x591e03ec9c90 + 0x591e03ec9c90 != 0x591e03d00fa0 + 0x591e03d00fa0 + 0x591e03d00fa0 != 0x591e03d00fa0 + Execution of tool Expand Layers 2d Arte failed with the following message: +#endif + + UG_THROW("Vektorchaos " << std::endl); + } + + if( ! isFreeTEnd ) // standard XCross case, also applicable for TEnd apart from the free end + { + std::vector vrtxSmallDiam; + + vrtxSmallDiam.push_back( crossPt ); + vrtxSmallDiam.push_back( newVrtBefore ); + vrtxSmallDiam.push_back( shiftVrt ); + vrtxSmallDiam.push_back( newVrtAfter ); + + Face * newFracFace = + *grid.create( QuadrilateralDescriptor( vrtxSmallDiam[0], vrtxSmallDiam[1], + vrtxSmallDiam[2], vrtxSmallDiam[3] + ) ); + + sh.assign_subset(newFracFace, diamantSubsNum ); + + newDiamFaceVec.push_back(newFracFace); + + } + else + { + std::vector vrtxSmallDiamBefore; + std::vector vrtxSmallDiamAfter; + + vrtxSmallDiamBefore.push_back( crossPt ); + vrtxSmallDiamBefore.push_back( newVrtBefore ); + vrtxSmallDiamBefore.push_back( shiftVrt ); + + vrtxSmallDiamAfter.push_back( crossPt ); + vrtxSmallDiamAfter.push_back( shiftVrt ); + vrtxSmallDiamAfter.push_back( newVrtAfter ); + + + Face * newFracFaceBefore = + *grid.create( TriangleDescriptor( vrtxSmallDiamBefore[0], vrtxSmallDiamBefore[1], vrtxSmallDiamBefore[2] ) ); + + Face * newFracFaceAfter = + *grid.create( TriangleDescriptor( vrtxSmallDiamAfter[0], vrtxSmallDiamAfter[1], vrtxSmallDiamAfter[2] ) ); + + + sh.assign_subset(newFracFaceBefore, diamantSubsNum ); + sh.assign_subset(newFracFaceAfter, diamantSubsNum ); + + newDiamFaceVec.push_back(newFracFaceBefore); + newDiamFaceVec.push_back(newFracFaceAfter); + + } + + +} + +void assignFaceSubsetToClosedFace( std::vector & faceVec, Grid & grid, SubsetHandler & sh ) +{ + + for( auto const & nF : faceVec ) + { + for(size_t iEdge = 0; iEdge < nF->num_edges(); iEdge++ ) + { + Edge* edg = grid.get_edge(nF, iEdge); + + sh.assign_subset( edg, sh.get_subset_index(nF) ); + + } + + for( size_t iVrt = 0; iVrt < nF->num_vertices(); iVrt++ ) + { + Vertex * vrt = nF->vertex(iVrt); + + sh.assign_subset( vrt, sh.get_subset_index(nF) ); + } + + } + +} + + +//using VecVertFracTrip = std::vector; +// +//// needed for crossing points +//using VertexOfFaceInfo = VertexFractureTriple< std::pair, Face*, std::pair >; +//// all edges of the attached face - must always be two, the face itself, and the normal vectors of the face in direction of the two edges +//// the size of the normal vector vector also must be two +//// however, if an edge of the face is not a fracture edge, we do not compute the normal, but assign zero as norm +//// for those edges and faces which are Kluft edges, we assign the normal known from the info computed before, vertex fracture triple +// +//using VecVertexOfFaceInfo = std::vector; +// +//using SegmentsFractExtrus = std::vector; + + +bool determineOrderOfFaces( //CrossVertInf & crossVrtInf, + VecVertFracTrip const & vecVertFracTrip, + VecFace const & assoFaces, VecVertexOfFaceInfo & orderedFaces, + SegmentsFractExtrus & segments, + // single components always from one fracture edge to the next one + //VecVertexOfFaceInfo & segmentPart, + // note: we do not attach this info to the vertex, as we only need it local; in principle, in case of further need, it would + // be usful to establish some sort of attachment, + //VertFracTrip & startVertFracTrip, + IndexType startIndex, + std::vector const & allAssoEdges, + SubsetHandler & sh, + Grid::EdgeAttachmentAccessor const & aaMarkEdgeB, + std::vector const & adjBndEdgs = std::vector(), // to allow for boundary constrained regions + Face * const & attFaceOf1stBndEdg = nullptr + ) +{ + IndexType countedCrossingFracEdgs = 0; + // copies of all faces and of fractured ones + auto aF = assoFaces; // caution: COPY, not reference! + auto vVFT = vecVertFracTrip; // caution: COPY, not reference! + + UG_LOG("Gesamtanzahl faces um Knoten " << aF.size() << std::endl ); + + // erstmal die ganzen anhaengenden Faces ordnen, dass wir wissen, in welcher Reihenfolge wir durchlaufen muessen + // jede Edge hat ein bool attachment schon, das weiss, ob sie Fracture edge ist oder nicht + // Reihenfolge der faces und die edges auch dazu, vielleicht neues Triple oder dergleiche, dabei zwei edges und zwei normals + // und wie gesagt, die edges wissen, ob sie fractures sind, dazu keine neuen Variablen notwendig + + // using VertexOfFaceInfo = VertexFractureTriple< std::pair, Face*, std::pair >; + + // all edges of the attached face - must always be two, the face itself, and the normal vectors of the face in direction of the two edges + // the size of the normal vector vector also must be two + // however, if an edge of the face is not a fracture edge, we do not compute the normal, but assign zero as norm + // for those edges and faces which are Kluft edges, we assign the normal known from the info computed before, vertex fracture triple + + + if( vVFT.size() == 0 ) + UG_THROW("vertex frac triple zu klein an Kreuzung " << std::endl); + + IndexType numbIncorpBnds = adjBndEdgs.size(); + + if( numbIncorpBnds != 0 && numbIncorpBnds != 2 ) + UG_THROW("komische Grenzstruktur" << numbIncorpBnds << std::endl); + + bool isNormalNoBndCase = ( numbIncorpBnds != 2 ); + + bool atFirstTriple = true; + + vector3 nuVe(0,0,0); + + Face* fracFac = nullptr; + Edge* fracEdg = nullptr; + vector3 fracNorm = nuVe; + + Edge * originalStartEdge = nullptr; + Edge * targetedEndEdge = nullptr; + + if( isNormalNoBndCase ) + { + // we start with the first fracture face edge stuff, copy it, and delete this immidiately + VertFracTrip startVertFracTrip = vVFT[startIndex]; + + vVFT.erase( vVFT.begin() + startIndex ); + + atFirstTriple = true; + + fracFac = startVertFracTrip.getFace(); + fracEdg = startVertFracTrip.getEdge(); + fracNorm = startVertFracTrip.getNormal(); + + originalStartEdge = startVertFracTrip.getEdge(); + targetedEndEdge = originalStartEdge; + } + else // boundary edge start + { + atFirstTriple = false; + + // misleading names fracFac and fracEdg, as on boundary edge no fracture assumed, but to keep code overviewable + fracFac = attFaceOf1stBndEdg; + fracEdg = adjBndEdgs[0]; +// fracNorm = startVertFracTrip.getNormal(); - assumed to be nullvector + + originalStartEdge = adjBndEdgs[0]; + targetedEndEdge = adjBndEdgs[1]; + + + } + + + if( fracEdg != nullptr ) + { + countedCrossingFracEdgs++; + } + + // do not change this pointer + Edge* startEdg = fracEdg; + Face* startFace = fracFac; + + vector3 startNormal = fracNorm; + + Face* nextFace = NULL; + + UG_LOG("Gesamtanzahl faces um Knoten vor while " << aF.size() << std::endl ); + + VecVertexOfFaceInfo segmentPart; + + while( aF.size() != 0 ) + { + + UG_LOG("Gesamtanzahl faces um Knoten Anfang while " << aF.size() << std::endl ); + + + Face* face2Append = startFace; + Edge* startEdg2Append = startEdg; + + + IndexType fndCommEdg = 0; +// vector3 nuVe(0,0,0); + + Edge* nextEdge = NULL; + + std::pair edge2Append( startEdg2Append, nextEdge ); + std::pair normal2Append( startNormal, nuVe ); + + + // if start face and start edge from a triple, then has to be erased this triple, exept for the entire start, as already erased + if( ! atFirstTriple ) + { + for( VecVertFracTrip::iterator itAttVFT = vVFT.begin(); itAttVFT != vVFT.end(); itAttVFT++ ) + { + auto vft = *itAttVFT; + + Edge * edgIt = vft.getEdge(); + + Face * facIt = vft.getFace(); + + if( edgIt == startEdg && facIt == startFace ) + { + // the first edge if from a fracture and the face is connected to it + + vVFT.erase(itAttVFT); + + normal2Append.first = vft.getNormal(); + + if( ! FaceContains( facIt, startEdg )) + { + UG_THROW("Face does not contain start edge of its edge" << std::endl); + } + + break; + } + } + + } + else // we can save the investigation if we have a triple, and we do not need to erase, as already erased..... + { + atFirstTriple = false; + } + + + for( auto const & iE : allAssoEdges ) // werden nicht gelöscht, deswegen Zugriff auf attachment direkt + { + if( FaceContains(face2Append, iE) ) + { + fndCommEdg++; + + if( iE != startEdg ) + { + nextEdge = iE; + + edge2Append.second = iE; + + } + } + + + } + + if( fndCommEdg != 2 ) + { + UG_THROW("komische Anzahl gemeinsamer Ecke " << fndCommEdg << std::endl); + } + + if( nextEdge == NULL ) + { + UG_THROW("wieso keine zweite Ecke gefunden???? " << std::endl); + } + + if( edge2Append.first == NULL || edge2Append.second == NULL ) + { + UG_THROW("null immer noch?" << std::endl); + } + + // erase the face from the list + + IndexType faceFound = 0; + + for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ ) + { + Face * iFa = *itFac; + + if( iFa == startFace && FaceContains( iFa, nextEdge ) && FaceContains(iFa, startEdg)) + { + faceFound++; + } + } + + int totalSubsNum = sh.num_subsets(); + + int newSubsToAdd = totalSubsNum; + + if( faceFound != 1 ) + { + + + sh.assign_subset(startFace,newSubsToAdd++); + sh.assign_subset(startEdg,newSubsToAdd++); + sh.assign_subset(nextEdge,newSubsToAdd++); + + int faNum = aF.size(); + + UG_LOG("Gesamtzahl faces vor Absturz " << faNum << std::endl); + + UG_LOG("Gesicht in falscher Anztahl gefunden " << faceFound << std::endl); + + // return true; + + UG_THROW("Gesicht in falscher Anztahl gefunden " << faceFound << std::endl); + + return false; + + } + else + { + // sh.assign_subset(startFace,newSubsToAdd++); + // sh.assign_subset(startEdg,newSubsToAdd++); + // sh.assign_subset(nextEdge,newSubsToAdd++); + + int faNum = aF.size(); + + UG_LOG("Gesamtzahl faces ohne Absturz " << faNum << std::endl); + + } + + for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ ) + { + Face * iFa = *itFac; + + if( iFa == startFace && FaceContains( iFa, nextEdge ) && FaceContains(iFa, startEdg) ) + { + aF.erase(itFac); + break; + } + } + + + bool sndEdgIsFracEdge = aaMarkEdgeB[nextEdge]; + + bool tripFound = false; + + if( sndEdgIsFracEdge ) + { + + if( nextEdge != originalStartEdge || ! isNormalNoBndCase ) + countedCrossingFracEdgs++; + + // we need to have a look for the next triple + + // check if the next normal is a frac normal which contains the face as well + + for( VecVertFracTrip::iterator itAttVFT = vVFT.begin(); itAttVFT != vVFT.end(); itAttVFT++ ) + { + auto vft = *itAttVFT; + + Edge * edgIt = vft.getEdge(); + + Face * facIt = vft.getFace(); + + if( edgIt == nextEdge && facIt == face2Append ) + { + // the second edge if from a fracture and the face is connected to it + + tripFound = true; + + vVFT.erase(itAttVFT); + + normal2Append.second = vft.getNormal(); + + if( ! FaceContains( facIt, nextEdge )) + { + UG_THROW("Face does not contain edge of its edge" << std::endl); + } + + break; + } + } + + } + + if( ! tripFound && sndEdgIsFracEdge ) + { + UG_THROW("Triple nicht gefunden trotz markierter Edge" << std::endl); + } + + + // check if aF or vVFT still contain the former or the next face - must not be the case! + + VertexOfFaceInfo vOFI( edge2Append, face2Append, normal2Append ); + + orderedFaces.push_back( vOFI ); + + segmentPart.push_back( vOFI ); + + if( sndEdgIsFracEdge ) + { + segments.push_back( segmentPart ); + + segmentPart.clear(); + } + + + // what is next face, what is next edge? + // wie kriegen wir es hin, auch das nächste Triple zu erasen, wenn es jetzt kommt als nächstes? + + + startNormal = nuVe; + startEdg = nextEdge; + + if( aF.size() == 0 ) + { +// if( nextEdge != originalStartEdge ) + if( nextEdge != targetedEndEdge ) + { + UG_THROW("Gesichter leer, aber keine Anfangsecke gefunden" << std::endl); + } + else + { + + if( ! isNormalNoBndCase ) + { + segments.push_back( segmentPart ); + + segmentPart.clear(); + } + + break; // while loop zu Ende, raus aus dem while loop, den Rest nicht mehr machen, würde schief gehen zwingendermassen + } + + } + + + // bleibt noch das nächste Gesicht heraus zu finden, dafür kommt eigentlich nur noch eines in Frage, da das zweite Gesicht vom edge + // geloescht sein muss in aF, es muss das einzig übrige face sein, das die jetzt start edge enthält, davon darf es nur eines geben, wir löschen aber noch nicht + + IndexType nextFaceFound = 0; + + for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ ) + { + Face * iFa = *itFac; + + if( FaceContains(iFa, startEdg ) ) + { + nextFaceFound++; + } + } + + if( nextFaceFound != 1 ) + { + UG_THROW("folgendes Gesicht in falscher Anztahl gefunden " << nextFaceFound << std::endl); + } + + for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ ) + { + Face * iFa = *itFac; + + if( FaceContains(iFa, startEdg ) ) + { + startFace = iFa; + break; + } + } + + + } + + if( vVFT.size() != 0 ) + { + UG_THROW("not all triples found! " << std::endl); + } + + if( aF.size() != 0 ) + UG_THROW("not all faces found " << std::endl); + +// if( startEdg != originalStartEdge ) + if( startEdg != targetedEndEdge ) + { + UG_THROW("wir sind nicht am Anfang wieder angekommen" << std::endl); + } + + + if( segmentPart.size() != 0 ) + { + UG_THROW("die Segmentteile muessen alle verarbeitet sein" << std::endl); + } + + UG_LOG("Kreislauf geschlossen" << std::endl); + + + return true; +} + + +void teachAssoFacesNewVrtx( VecVertexOfFaceInfo const & segPart, Grid::FaceAttachmentAccessor & aaVrtVecFace, + Vertex * const & crossPt, Vertex * const & newShiftVrtx ) +{ + for( VertexOfFaceInfo const & vertFracInfoSeg : segPart ) + { + Face * fac = vertFracInfoSeg.getFace(); + +// sh.assign_subset(fa,newSubsToAdd); + + // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu SR! nicht später falsche verwenden! + vector& newVrts4Fac = aaVrtVecFace[ fac ]; + + IndexType vrtxFnd = 0; + + for(size_t indVrt = 0; indVrt < (fac)->num_vertices(); indVrt++ ) + { + Vertex* facVrt = (fac)->vertex(indVrt); + + if( facVrt == crossPt ) + { + newVrts4Fac[ indVrt ] = newShiftVrtx; + vrtxFnd++; + + } + } + + if( vrtxFnd <= 0 ) + { + UG_THROW("vertex not found kreuzung!" << std::endl); + } + else if( vrtxFnd > 1 ) + { + UG_THROW("vertex zu oft gefunden kreuzung " << vrtxFnd << std::endl ); + } + else if ( vrtxFnd == 1 ) + { + } + else + { + UG_THROW("vertex finden komisch kreuzung " << std::endl); + } + + } + +} + + + +#ifndef WORKAROUND_ARTE_SEGFAULT +#define WORKAROUND_ARTE_SEGFAULT 1 +#endif + +#ifndef ESTABLISH_DEBUG_SUDOS +#define ESTABLISH_DEBUG_SUDOS 0 +#endif + +#ifndef FORMER_PROMESH_FINITE_CLEFT_TECHNIQUE +#define FORMER_PROMESH_FINITE_CLEFT_TECHNIQUE 0 +#endif + +bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, vector const & fracInfos, + bool expandInnerFracBnds, bool expandOuterFracBnds) +{ + +// for(EdgeIterator iter = sh.begin(1); iter != sh.end(1); ++iter) +// { +// size_t sm = sh.num_subsets(); +// +// sh.assign_subset(*iter,sm); +// +// SplitEdge(grid,*iter,true); +// +// UG_LOG("vertex gesplittet" << std::endl); +// +// return true; +// +// } + + +// static constexpr bool dehneInnereKluftGrenzpunkteAus = false; + +// expandInnerFracBnds = false; + +// expandOuterFracBnds = true; + +// access position attachment + if(!grid.has_vertex_attachment(aPosition)){ + UG_LOG("Error in ExpandFractures 2D Arte: Missing position attachment"); + return false; + } + Grid::VertexAttachmentAccessor aaPos(grid, aPosition); + + if(!grid.option_is_enabled(FACEOPT_AUTOGENERATE_EDGES)){ + UG_LOG("WARNING in Arte 2D CalculateCreaseNormal: grid option FACEOPT_AUTOGENERATE_EDGES autoenabled.\n"); + grid.enable_options(FACEOPT_AUTOGENERATE_EDGES); + } + + + +// objects for temporary results + FaceDescriptor fd; + vector edges; // used for temporary results. + vector faces; // used for temporary results. + +// vectors that allow to access fracture properties by subset index + vector fracInfosBySubset(sh.num_subsets(), FractureInfo(-1, -1, 0)); + for(size_t i = 0; i < fracInfos.size(); ++i){ + if(fracInfos[i].subsetIndex >= sh.num_subsets()){ + throw(UGError("Bad subsetIndex in given fracInfos.")); + } + + fracInfosBySubset[fracInfos[i].subsetIndex] = fracInfos[i]; + } + +//////////////////////////////// +// Collect surrounding faces of all fractures in a selector +// and select edges and vertices too. + Selector sel(grid); + sel.enable_autoselection(false); + sel.enable_selection_inheritance(false); + +#if FORMER_PROMESH_FINITE_CLEFT_TECHNIQUE + AInt aAdjMarker; // used to mark how many adjacent fractures a vertex has. + // 0: no frac, 1: frac-boundary, >1: inner frac vertex + // TODO FIXME das sieht komisch aus, ist das immer so, wenn z.B. an einer Grenze sich zwei fracs treffen? + grid.attach_to_vertices_dv(aAdjMarker, 0); + Grid::VertexAttachmentAccessor aaMarkVRT(grid, aAdjMarker); + grid.attach_to_edges_dv(aAdjMarker, 0); + Grid::EdgeAttachmentAccessor aaMarkEDGE(grid, aAdjMarker); +#endif + +// using IndexType = unsigned short; + using AttVerFracProp = Attachment >; + // attachment pair boundary is fracture, number fractures crossing + + AttVerFracProp aAdjMarkerVFP; + + VertexFractureProperties vfp0( false, 0 ); + // default value: no boundary fracture, no fractures crossing + + grid.attach_to_vertices_dv(aAdjMarkerVFP, vfp0 ); + Grid::VertexAttachmentAccessor aaMarkVrtVFP(grid, aAdjMarkerVFP); + + ABool aAdjMarkerB; // used to know if an edge is frac edge + grid.attach_to_edges_dv(aAdjMarkerB, false); + Grid::EdgeAttachmentAccessor aaMarkEdgeB(grid, aAdjMarkerB); + + + // die Vertizes, Faces und Edges, die mit einer Kluft zu tun haben + +// using VertFracTrip = VertexFractureTriple; +// +// using VecVertFracTrip = std::vector; + + VecVertFracTrip vertexNoInfo; + + using AttVecVertFracTrip = Attachment; + + AttVecVertFracTrip aAdjInfoAVVFT; + + grid.attach_to_vertices_dv( aAdjInfoAVVFT, vertexNoInfo ); + Grid::VertexAttachmentAccessor aaVrtInfoFraTri(grid, aAdjInfoAVVFT ); + + +// using VecEdge = std::vector; +// using VecFace = std::vector; + + using AttVecEdge = Attachment; + using AttVecFace = Attachment; + + VecEdge noEdge; + VecFace noFace; + AttVecEdge aAdjInfoEdges; + AttVecFace aAdjInfoFaces; + + grid.attach_to_vertices_dv( aAdjInfoEdges, noEdge ); + Grid::VertexAttachmentAccessor aaVrtInfoAssoEdges( grid, aAdjInfoEdges ); + + grid.attach_to_vertices_dv( aAdjInfoFaces, noFace ); + Grid::VertexAttachmentAccessor aaVrtInfoAssoFaces( grid, aAdjInfoFaces ); + + + // das ist Käse, ich brauche für jeden Vertex ein Attachment der Form + // class VertexTriple, bzw std vektoren von solchen vertex triplen + // da weiss dann jeder Vertex das triple + // Kante (damit subdom) - Face - normal (von Kante in Face rein) + // dann kann man nämlich anhand des Winkels von zwei Normalen + // von solchen Vertizes bestimmtn, ob sie auf die gleiche Seite der Kante zeigen + // und dann kann man sie mitteln, sofern die Vertizes keine Kreuzungs Vertizes sind + // oder keine äusseren Vertizes - ob sie dsa sind, dafür haben wir schon attachments! + + // TODO FIXME diese komischen accessoren sollen jetzt so zugewiesen + // werden, dass + /* + * jeder Kluftvertex soll wissen, welche Kluftedges ihm anliegen, und welche faces + * jede Kluftedge soll wissen, welche Vertizes ihr anliegen, und welche faces + * jedes Face, das an eine Kluft anliegt, soll wissen, welche Vertizes und Edges + * ihm anliegen + * letzteres muss man vielleicht noch ausdehnen, indem man subdomain indizes + * dazu bringt + * das kann auch notwendig sein fuer alle anderen - wirklich? + * die edges und faces kennen ihre subdomain + * nur beim Vertex kann in Kreuzungspunkten ein Problem sein + * zudem ist die subdomain der faces EGAL, im Zweifel entscheidet die subdomain + * der edges, die anliegen bzw der edge, die anliegt! + * + */ + +// iterate over the given fracture infos and select all fracture edges +// and fracture vertices. + for(size_t i_fi = 0; i_fi < fracInfos.size(); ++i_fi) + { + int fracInd = fracInfos[i_fi].subsetIndex; + + for(EdgeIterator iter = sh.begin(fracInd); iter != sh.end(fracInd); ++iter) + { + // mark edge and vertices + sel.select(*iter); + +#if FORMER_PROMESH_FINITE_CLEFT_TECHNIQUE + aaMarkEDGE[*iter] = 1; +#endif + + aaMarkEdgeB[*iter] = true; + + // select associated vertices + for(size_t i = 0; i < 2; ++i) + { + Vertex* v = (*iter)->vertex(i); + sel.select(v); + + // wird in jedem Fall inkrimiert, da der Vertex auf jeden Fall mit einer Kante einer frac verbunden sein muss, sonst darf der loop gar nicht darüber gehen + aaMarkVrtVFP[v]++; + + if( IsBoundaryVertex2D(grid, v) ) + aaMarkVrtVFP[v].setIsBndFracVertex(); + + +#if FORMER_PROMESH_FINITE_CLEFT_TECHNIQUE + // das ist Sebastians loop, den nicht mehr lassen lassen + // if fracture boundaries are expanded, we'll regard all fracture vertices + // as inner vertices + if(expandInnerFracBnds) + { + if(!expandOuterFracBnds) + { + if(IsBoundaryVertex2D(grid, v)) + aaMarkVRT[v]++; + else + aaMarkVRT[v] = 2; + } + else + aaMarkVRT[v] = 2; + } + else + aaMarkVRT[v]++; +#endif + + } + } + } + + +#if FORMER_PROMESH_FINITE_CLEFT_TECHNIQUE +// Make sure that selected vertices that lie on the boundary of the geometry +// are treated as inner fracture vertices. +// This is only required if frac-boundaries are not expanded anyways. + if(expandOuterFracBnds && !expandInnerFracBnds){ + for(VertexIterator iter = sel.vertices_begin(); + iter != sel.vertices_end(); ++iter) + { + Vertex* v = *iter; + if(aaMarkVRT[v] == 1){ + if(IsBoundaryVertex2D(grid, v)) + aaMarkVRT[v] = 2; + } + } + } + // TODO FIXME was soll das fuer ein Kaese sein? +#endif + + int dbg_flachen_passiert = 0; + + for(VertexIterator iter = sel.begin(); iter != sel.end(); ++iter) + { + + bool wahl = true; + + + // so stimmt es vielleicht, aber ist auch ein komischer Fall, innen expandieren und aussen nicht...... die Frage ist, ob es oonst Sinn macht..... + if( expandInnerFracBnds && !expandOuterFracBnds && aaMarkVrtVFP[*iter].getIsBndFracVertex() ) + wahl = false; + + static_assert( std::is_same< decltype(*iter), Vertex * >::value ); + + bool isBnd = aaMarkVrtVFP[ *iter ].getIsBndFracVertex(); + auto numCrosFrac = aaMarkVrtVFP[ *iter ].getNumberFracEdgesInVertex(); + + if( ! isBnd && numCrosFrac == 1 ) + { + wahl = false; + } + +// if( ! dehneInnereKluftGrenzpunkteAus ) +// { +// if( numCrosFrac == 1 ) // inner frac boundary vertex +// { +// wahl = false; +// } +// } + + + if( wahl ) + { + sel.select(grid.associated_edges_begin(*iter), + grid.associated_edges_end(*iter)); + sel.select(grid.associated_faces_begin(*iter), + grid.associated_faces_end(*iter)); + + // TODO FIXME hier ein attachment der associated faces und vertizes, am besten als Klasse, die std vertizes davon frisst, an jeden Vertex anhängen + // so muss man später nicht nochmal über alle Faces und Edges laufen, sondern hat die angehängten schon zur Hand + // im Fall, dass eine Kreuzung vorliegt, das Ganze irgendwann ordnen, dass nebeneinander liegende Faces und edges in eine verkettete Liste kommen + // vielleicht das aber nur bei den Schnittvertizes später + // und vielleicht sollen die Faces Zeiger auf ihre Edges bekommen, und die edges auf die faces, aber wird irgendwann zu wild verzeigert..... + // vielleicht einfach attachment von faces und edges unabhängig an jeden Fracture Vertex...... + + // testen, ob ein Schnittvertex vor liegt, indem die Anzahl der touches getestet wird, anhand einfacher Geometrien testen, was die Anzahl ist + + // mit UG_LOG ausgeben, was die Koordinaten sind, und die Anzahl der hits + + VecFace assFac; + VecEdge assEdg; + +// UG_LOG("----------" << std::endl); + + for( std::vector::iterator iterFac = grid.associated_faces_begin(*iter); iterFac != grid.associated_faces_end(*iter); iterFac++ ) + { + assFac.push_back(*iterFac); +// vector3 facCenter = CalculateCenter( *iterFac, aaPos ); +// UG_LOG("fac center " << facCenter << std::endl); + +// sh.assign_subset(*iterFac, 10); + } + +// UG_LOG("----------" << std::endl); + + for( std::vector::iterator iterEdg = grid.associated_edges_begin(*iter); iterEdg != grid.associated_edges_end(*iter); iterEdg++ ) + { + assEdg.push_back(*iterEdg); +// sh.assign_subset(*iterEdg,10); + } + + aaVrtInfoAssoFaces[*iter] = assFac; + aaVrtInfoAssoEdges[*iter] = assEdg; + + UG_LOG("marked vertex wahl: " << aaPos[*iter] << " is bnd " << isBnd << " number cross frac " << numCrosFrac << std::endl ); + + // fuer Nicht Boundary Vertizes muessen wir durch 2 teilen, damit wir richtige Anzahl der + // Fracs haben, die durch den spezifischen Vertex durch geht + // FALSCH war mal so, ist schon abgestellt, es wird angezeigt, wieviele Ecken von Kanten rein kommen + + } + else + { + UG_LOG("marked vertex unwahl: " << aaPos[*iter] << " is bnd " << isBnd << " number cross frac " << numCrosFrac << std::endl ); + } + + } + +// return true; + + using pairIndDbl = std::pair; + + std::vector< pairIndDbl > fracSubdom_facePerpendMinVal; + + for( auto const & pf: fracInfos ) + { + fracSubdom_facePerpendMinVal.push_back( pairIndDbl( pf.subsetIndex, std::numeric_limits::max() ) ); + } + + T_min minDistPerpOverall( std::numeric_limits::max() ); + +// for( auto fI : fracInfos ) +// for( size_t fraInfInd = 0; fraInfInd < fracInfos.size(); fraInfInd++ ) + for( auto & fsfpmv : fracSubdom_facePerpendMinVal ) + { +// int fracInd = fracInfos[fraInfInd].subsetIndex; +// int fracInd = fI.subsetIndex; + + auto fracInd = fsfpmv.first; + + T_min minDistPerpThisFrac( fsfpmv.second ); + + for(EdgeIterator iterEdg = sh.begin(fracInd); iterEdg != sh.end(fracInd); iterEdg++ ) + { + + // get subdomain of edge + + auto sudoEdg = sh.get_subset_index(*iterEdg); + + static_assert( std::is_same< decltype(sudoEdg), int >::value ); + + // get vertices of edge, always 2 + + std::vector verticesEdg; + + static_assert( std::is_same< Vertex*, decltype( (*iterEdg)->vertex(0) ) >::value ); + + for( size_t i = 0; i < 2; ++i ) + verticesEdg.push_back( (*iterEdg)->vertex(i) ); + + // get attached faces + +#if 0 + std::vector assFace; + + // TODO FIXME dieser loop kann vielleicht vereinfacht werden, wenn dieser ganze loop umgebaut wird + // denn die Vertizes kennen dann die assosciated faces schon + // der Name AssociatedFaceIterator ist sowieso verwirrend, hat mit assosciated nix zu tun, bezieht sich auf alle std Vektoren von Face * + UG_LOG("XXXXXXXXXXXX" << std::endl); + for(Grid::AssociatedFaceIterator iterAFI = grid.associated_faces_begin( verticesEdg[0] ); + iterAFI != grid.associated_faces_end( verticesEdg[0] ); + iterAFI++ ) + { + + if(FaceContains( *iterAFI, *iterEdg )) + { + assFace.push_back( *iterAFI ); + + + vector3 facCenter = CalculateCenter( *iterAFI, aaPos ); + UG_LOG("fac center " << facCenter << std::endl); + + + +// sh.assign_subset( *iterAFI, sh.get_subset_index(*iterEdg)); + } + + } + UG_LOG("XXXXXXXXX" << std::endl); +#else + + std::vector & assFaceVrt0 = aaVrtInfoAssoFaces[verticesEdg[0]]; + + std::vector assFace; + +// static_assert( std::is_same< decltype( aaVrtInfoAssoFaces[verticesEdg[0]] )[0], std::vector >::value ); + //static_assert( std::is_same< decltype( *(aaVrtInfoAssoFaces[verticesEdg[0]]) ), Face * >::value ); + +// UG_LOG("XXXXXXXXXXXX" << std::endl); + + for( auto const & ifa : assFaceVrt0 ) + { + if(FaceContains( ifa, *iterEdg )) + { + assFace.push_back( ifa ); + +// vector3 facCenter = CalculateCenter( ifa, aaPos ); +// UG_LOG("fac center " << facCenter << std::endl); + } + } + + std::vector & assFaceVrt1 = aaVrtInfoAssoFaces[verticesEdg[1]]; + + for( auto const & ifa : assFaceVrt1 ) + { + if(FaceContains( ifa, *iterEdg )) + { + bool faceContained = false; + + for( auto const & afa : assFace ) + { + if( afa == ifa ) + faceContained = true; + } + + if( !faceContained ) + { + bool faceAlreadyIncluded = false; + + for( auto const & af : assFace ) + { + if( ifa == af ) + faceAlreadyIncluded = true; + } + + if( ! faceAlreadyIncluded ) + assFace.push_back( ifa ); + } + } + } + + +// UG_LOG("XXXXXXXXX" << std::endl); + +#endif + // von hier lernen: + // VecFace & assoFaces = aaVrtInfoAssoFaces[*iterV ist verticesEdg[0] ]; + // for( auto const & ifac : assoFaces ) + // { + // static_assert( std::is_same< decltype( ifac ), Face * const & >::value ); + // } + + + + // compute normal of edge + + std::vector< vector3 > edgeNormals; + + std::vector perpendDistances; + + for( auto const & fac : assFace ) + { + vector3 facCenter = CalculateCenter( fac, aaPos ); + + vector3 perpendicu; + + DropAPerpendicular(perpendicu, facCenter, aaPos[verticesEdg[0]], aaPos[verticesEdg[1]]); + + double perpendDist = VecLength( perpendicu ); // betrag perpendicu + + perpendDistances.push_back( perpendDist ); + + minDistPerpThisFrac( perpendDist ); + + + // vector from projection to center is the unnormalized normal + vector3 tmpN; + + VecSubtract(tmpN, facCenter, perpendicu ); + + VecNormalize(tmpN, tmpN); + + edgeNormals.push_back( tmpN ); + + static_assert( std::is_same< Edge*, decltype(*iterEdg) >::value ); + + static_assert( std::is_same< Face * const &, decltype(fac) >::value ); + static_assert( std::is_same< Face *, decltype( const_cast(fac) ) >::value ); + static_assert( std::is_same< vector3, decltype( tmpN ) >::value ); + + VertFracTrip infoVertizesThisEdge( *iterEdg, fac, tmpN ); + +// UG_LOG("TypE Fac " << typeid(const_cast(fac) ).name() << std::endl); +// UG_LOG("TypE Edg " << typeid( *iterEdg ).name() << std::endl); +// UG_LOG("TypE Vec " << typeid( tmpN ).name() << std::endl); + + + for( auto const & v : verticesEdg ) + { + static_assert( std::is_same< decltype(v), Vertex * const & >::value ); + static_assert( std::is_same< decltype(const_cast(v)), Vertex * >::value ); + aaVrtInfoFraTri[v].push_back( infoVertizesThisEdge ); + +// VecVertFracTrip allInfosVrtxThisEdg = aaVrtInfoFraTri[v]; + +// static_assert( std::is_same< decltype( aaVrtInfoFraTri[v] ), VecVertFracTrip >::value ); + +// UG_LOG("type Fac " << typeid( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getFace() ).name() << std::endl); +// UG_LOG("type Edg " << typeid( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getEdge() ).name() << std::endl); +// UG_LOG("type Vec " << typeid( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getNormal() ).name() << std::endl); + + static_assert( std::is_same< decltype( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getFace() ), Face * >::value ); + static_assert( std::is_same< decltype( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getEdge() ), Edge * >::value ); + static_assert( std::is_same< decltype( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getNormal() ), vector3 const >::value ); + } + + } + + // damit speichern wir die plus und minus Normale, und das ist alles, und auch + // gleich wieder weg + // TODO FIXME besser, wir speichern die gemittelte Normale an den Vertizes + // vielleihct als attachment pair, das die subdom kennt der frac und die Normale dazu? + // ziemlich nutzlos, die Normale wie hier gemacht in einen kurzen Vektor zu speichern, der schnell + // wieder weg ist...... + // wir brauchen alle Normalen zu jeder fracture an jedem fracture Vertex, also die Mittelung vermutlich + // diese Mittelung kann aber erst stattfinden, wenn wir nachher über die vertizes loopen, + // hier kennen wir nur die Vertizes, die an derselben Edge anliegen + + UG_LOG("EDGE NORMALS: " << sh.get_subset_index(*iterEdg) << " -> "); + + int j = 0; + + for( auto const & en: edgeNormals ) + { + + for( size_t i = 0; i < 3; i++ ) + UG_LOG( en[i] << ", " ); + + + UG_LOG(" --- " << perpendDistances[j] << " ///////// " ); + + j++; + } + + UG_LOG(std::endl); + + } + + fsfpmv.second = minDistPerpThisFrac(); + + minDistPerpOverall( fsfpmv.second ); + + UG_LOG("first " << fsfpmv.first << " second " << fsfpmv.second << std::endl); + } + + for( auto const & fsfpmv : fracSubdom_facePerpendMinVal ) + { + UG_LOG("min dist sd " << fsfpmv.first << " -> " << fsfpmv.second << std::endl ); + } + + UG_LOG("overall min dist " << minDistPerpOverall() << std::endl); + + + + // von Sebastian teilweise das Prinzip übernommen, dass die Faces wissen können, was ihre neuen Vertizes sein sollen + // create new vertices + + // we have to associate a vector of vertices with each node in the fracture. + // since an empty vector is quite small, we can associate one with each vertex in + // the whole grid. This could be optimized if required, by using subset attachments. + + // es reicht vielleicht, hier statt einem Vektor einfach nur einen Vertex * zu storen +// using AttVrtVec = Attachment >; + AttVrtVec attVrtVec; + + // we associate a vector of vertices for each face adjacent to the frac. + // it will store a set of vertices. An entry contains the new vertex, if the + // corresponding vertex is an inner fracture vertex, and NULL if not. + grid.attach_to_faces(attVrtVec); + Grid::FaceAttachmentAccessor aaVrtVecFace(grid, attVrtVec); + + + // iterate over all surrounding faces to enable face changes, this loop taken from SR but shortened + for(FaceIterator iterSurrFac = sel.faces_begin(); iterSurrFac != sel.faces_end(); ++iterSurrFac ) + { + Face* sf = *iterSurrFac; + + std::vector& newVrts = aaVrtVecFace[sf]; + newVrts.resize(sf->num_vertices()); + + for(size_t i_vrt = 0; i_vrt < sf->num_vertices(); ++i_vrt) + { + newVrts[i_vrt] = NULL; + } + // erstmal so tun, als ob keine neuen Vertizes erzeugt werden an den alten Vertizes + } + + + // attachment to allow fracture vertizes to know the newly created vertizes + // due to extrusion which are related to them, in connection with + // the normals which are an average of the related edges and the faces + // defining the original normal + + // usage: store edges and associated faces in SAME order in std vectors! + using ExpandVertexMultiplett = VertexFractureTriple< std::vector, std::vector, vector3 >; + // holds the averaged normal of the related edges and their corresponding faces which give direction + + using VecExpandVertexMultiplett = std::vector; + + + VecExpandVertexMultiplett vertexMultiplettEmpty; + + using AttVecExpandVertexMultiplett = Attachment; + + AttVecExpandVertexMultiplett aAdjInfoVVEVM; + + grid.attach_to_vertices_dv( aAdjInfoVVEVM, vertexMultiplettEmpty ); + Grid::VertexAttachmentAccessor aaVrtExpMP(grid, aAdjInfoVVEVM ); + + + // am Ende dieser Prozedur sollten alle Vertizes wissen, welche Tripel vom Typ Edge - Face - Normal zum Face hin an ihnen angelagert sind + + // damit weiss, wenn es stimmt, jeder Vertex, der an einer Fracture ist, wieviele Schnittpunkte von Fractures er hat, + // ob er ein boundary vertex ist, und was für einen Vektor von Tripeln an ihm angehängt sind + // die subdomain der Fracture muss anhand der subdomain der edge bestimmt werden immer + + UG_LOG("loop over all marked vertizes " << std::endl); + + int dbg_vertizesPassiert = 0; + +// std::vector crossVrts; +// std::vector teeVrts; + +// using CrossVertInf = CrossingVertexInfo; + +// std::vector > vecCrossVrtInf; + std::vector vecCrossVrtInf; + +// // needed for crossing points +// using VertexOfFaceInfo = VertexFractureTriple< std::pair, Face*, std::pair >; +// // all edges of the attached face - must always be two, the face itself, and the normal vectors of the face in direction of the two edges +// // the size of the normal vector vector also must be two +// // however, if an edge of the face is not a fracture edge, we do not compute the normal, but assign zero as norm +// // for those edges and faces which are Kluft edges, we assign the normal known from the info computed before, vertex fracture triple +// +// using VecVertexOfFaceInfo = std::vector; +// +// using SegmentsFractExtrus = std::vector; + + + // jetzt können wir alle Vertizes ablaufen und an ihnen neue Vertizes erzeugen, die anhand der gemittelten Normalen von den Vertizes weg gehen + // ob zwei anhängende Faces auf der gleichen Seite liegen, wenn es kein Schnittvertex von zwei oder mehr Klüften ist + // das kann man anhand des Winkels zwischen zwei face Normalen unterscheiden vermutlich + // dabei müssen die edges sowieso disjunkt sein, sonst ist man sowieso sicher auf verschiedenen Seiten + // wenn wir es mit einem boundary Vertex zu tun haben, müssen wir weiter überlegen, wie wir die Verschiebung auf die äussere Kante projizieren + // muss auch mit dem Winkel zu tun haben + for(VertexIterator iterV = sel.begin(); iterV != sel.end(); ++iterV) + { + + // POsition dieses Vertex + vector3 posOldVrt = aaPos[*iterV]; + + // vielleicht muss man, wenn die neuen Vertizes da sind, diese auch gleich mit den umliegenden Knoten per neuer Kanten verbinden + // und die neuen faces erzeugen nach Löschen der alten? + // oder alle neuen Vertizes wie bei Prof Reiter in einen std Vektor, der als attachment den bisherigen Face Vertizes angehängt wird + // und Edge Vernichtung und Erzeugung neuer edges und faces wie bei Prof Reiter in Folgeschritten? + + VecVertFracTrip & vecVertFracTrip = aaVrtInfoFraTri[*iterV]; + + std::vector & allAssoEdges = aaVrtInfoAssoEdges[*iterV]; + + static_assert( std::is_same< decltype( vecVertFracTrip[ vecVertFracTrip.size() - 1 ].getFace() ), Face * >::value ); + static_assert( std::is_same< decltype( vecVertFracTrip[ vecVertFracTrip.size() - 1 ].getEdge() ), Edge * >::value ); + static_assert( std::is_same< decltype( vecVertFracTrip[ vecVertFracTrip.size() - 1 ].getNormal() ), vector3 const >::value ); + + for( auto const & vft : vecVertFracTrip ) + { + static_assert( std::is_same< decltype( vft.getFace() ), Face * >::value ); + static_assert( std::is_same< decltype( vft.getEdge() ), Edge * >::value ); + static_assert( std::is_same< decltype( vft.getNormal() ), vector3 const >::value ); + + Face * f = vft.getFace(); + Edge * e = vft.getEdge(); + vector3 n = vft.getNormal(); + + } + + using VvftIterator = VecVertFracTrip::iterator; + + VecFace & assoFaces = aaVrtInfoAssoFaces[*iterV]; + // TODO FIXME hier braucht man das nicht zu ordnen + // aber bei Kreuzpunkten von Klueften muss es so geordnet werden, wie es nebeneinander liegt + // bei den Edges gibt es auch die benachbarten, und die edges haben das attachment, ob sie Kluftedges sind + +// for( auto const & ifac : assoFaces ) +// { +// static_assert( std::is_same< decltype( ifac ), Face * const & >::value ); +// } + + + + // Anzahl der Kreuzungspunkte auslesen und danach unterscheiden, erstmal keine Kreuzung! TODO FIXME + + // irgendwie muessen wir diese Infos jetzt verwerten, um als erstes neue Vertizes zu erzeugen, anfangs für eine Kluft nur + // und danach die alten Edges und faces löschen und an neuer Stelle neu erzeugen, plus die sowieso neuen, + // oder Edges verschieben, wenn es möglich ist, die Vertizes zu verschieben, und die Edges und in Folge faces passen sich an, + // dann müssen nur die neuen edges und faces neu erzeugt werden + // verschieben der Position des Vertex löst Kaskade aus, dass Edge und Face auch verschoben werden, kann also angewendet werden + // allerdings Problem, dass die Vertizes dafür verdoppelt werden müssen und die Kanten, sonst kann man sie nicht nach aussen verschieben + // also doch komplette Neuerzeugung vermutlich..... oder doppeltes Klonen, und das alte bleibt in der Mitte..... + + vector3 posThisVrt = aaPos[*iterV]; + + UG_LOG("vertex at " << posThisVrt << std::endl ); + + bool vrtxIsBndVrt = aaMarkVrtVFP[*iterV].getIsBndFracVertex(); + // alternativ wäre möglich: IsBoundaryVertex2D(grid, *iterV) + + UG_LOG("is bndry " << vrtxIsBndVrt << std::endl); + + IndexType numFracsCrossAtVrt = aaMarkVrtVFP[*iterV].getNumberFracEdgesInVertex(); + + UG_LOG("number crossing fracs " << numFracsCrossAtVrt << std::endl); + + size_t numbAttTripl = vecVertFracTrip.size(); + + UG_LOG("sizes of vft " << numbAttTripl << std::endl ); + + if( ! vrtxIsBndVrt ) + { + +#if 0 + CrossVertInf crossVrtInf( *iterV, numFracsCrossAtVrt ); + + // using VecVertexOfFaceInfo = std::vector; + VecVertexOfFaceInfo orderedFaces; + +// using SegmentsFractExtrus = std::vector; + + SegmentsFractExtrus segments; + // single components always from one fracture edge to the next one + + VecVertexOfFaceInfo segmentPart; + + // note: we do not attach this info to the vertex, as we only need it local; in principle, in case of further need, it would + // be usful to establish some sort of attachment + + // fixed: diesen Sortierungsalgorithmus bei allen inneren Knoten anwenden, + // um zweifelsfrei alle anhängenden Faces der richtigen Seite zuordnen zu können!!!! + + // VecVertFracTrip & vecVertFracTrip = aaVrtInfoFraTri[*iterV]; + // VecFace & assoFaces = aaVrtInfoAssoFaces[*iterV]; + + IndexType startIndex = 0; + + if( numFracsCrossAtVrt > 1 ) + { + determineOrderOfFaces( // crossVrtInf, + vecVertFracTrip, assoFaces, orderedFaces, + segments, segmentPart, startIndex, allAssoEdges, + sh, aaMarkEdgeB + ); + } +#endif + if( numFracsCrossAtVrt < 1 ) + { + UG_THROW("no fracs crossing but marked vertex? << std::endl"); + } + else if( numFracsCrossAtVrt == 1 ) + { + + // do nothing + +// if( numbAttTripl != 0 ) +// { +// UG_THROW("Anzahl der angehaengten Triples kann nicht stimmen, Vertex einer Kluft ohne Schnittpunkte, nicht am Rand, Kluftende " << std::endl); +// } + + + + UG_LOG("END THIS VERTEX NORMAL INNER ENDING CLEFT" << std::endl); + + +// if( ! dehneInnereKluftGrenzpunkteAus ) +// { +// break; +// } + // inner vertex where fracture ends + // TODO FIXME + + // in this case, we have two attached edges, and each of these edges has two attached faces + // the faces have a naormal, and based on the normal, we can decide which faces belong to the same side of the edges + +#if 0 + + if( numbAttTripl != 2 ) + { + UG_THROW("Anzahl der angehaengten Triples kann nicht stimmen, Vertex einer Kluft ohne Schnittpunkte, nicht am Rand, Kluftende " << std::endl); + } + + // Zuordnung der Edges und Faces, die auf der gleichen Seite der fracture sind + + // und gleich auch Erzeugung der neuen Knoten, die dann + // in einem Doublett zusammen mit ihren Normalen an die alten Vertizes + // angehängt werden; der Winkel zur Normalen hilft später, die Seite + // heraus zu finden, Seite von den Edges + + int dbg_iteratorAblaufen = 0; + + +#if WORKAROUND_ARTE_SEGFAULT + + int dbg_laenge = 0; + + for( auto const & vft : vecVertFracTrip ) + { + dbg_laenge++; + + UG_LOG("VERTEXFRACTRIP" << std::endl); + + vector3 ve = vft.getNormal(); + + UG_LOG("NORMAL " << ve << std::endl); + + UG_LOG("laenge " << dbg_laenge << std::endl ); + } + + int dbg_laenge_eins = 0; + +#endif + + + + for( VvftIterator vvftV = vecVertFracTrip.begin(); + vvftV != vecVertFracTrip.end(); + vvftV++ + ) + { + +#if WORKAROUND_ARTE_SEGFAULT + dbg_laenge_eins++; + + if( dbg_laenge_eins > dbg_laenge ) + { + break; + } + +#endif + + vector3 nV = vvftV->getNormal(); + + Edge * edgeV = vvftV->getEdge(); + + + +#if WORKAROUND_ARTE_SEGFAULT + + UG_LOG("NORMAL " << vvftV->getNormal() << std::endl); + UG_LOG("LAENGE EINZ " << dbg_laenge_eins << std::endl ); +#endif + + Vertex * nextFracVrt; + + IndexType foundThisVrt = 0; + + for( size_t i = 0; i < 2; ++i ) + { + Vertex * vrtEdgEnd = edgeV->vertex(i); + + if( vrtEdgEnd == *iterV ) + { + foundThisVrt++; + } + else + { + nextFracVrt = vrtEdgEnd ; + } + + } + + if( foundThisVrt != 1 ) + { + UG_THROW("zu viel zu wenig vertizex one " << std::endl); + } + + + + // Klasse schreiben, die als attachment an einen Fracture-Vertex + // die neuen Vertizes samt ihrer gemittelten Normalen speichert + // also std::vector von dieser neuen Klasse als Vertex attachment + + std::vector attEdg; + std::vector attFac; + + attEdg.push_back( edgeV ); + + Face * facV = vvftV->getFace(); + + attFac.push_back( facV ); + + // jetzt neuen Vertex erzeugen in Richtung der Normalen + // sonst ist das attachment Schwachsinn! + + vector3 posNewVrt; + + vector3 moveVrt; + + auto subsIndEdgV = sh.get_subset_index(edgeV); + + number width = fracInfosBySubset.at(subsIndEdgV).width; + +// if( expandInnerFracBnds ) +// { +// // der Faktor ist Käse und muss noch aus den Eingaben übernommen werden +// VecScale(moveVrt, nV, width/2. ); +// } +// else +// { +// // auf Annes Wunsch hin werden die Normalen innendrin an einer endenen Kluft zu Null gesetzt +// +// VecScale(moveVrt, nV, 0. ); +// +// } + + VecScale(moveVrt, nV, width/2. ); + + VecAdd(posNewVrt, posOldVrt, moveVrt ); + + UG_LOG("neuer Vertex " << posNewVrt << std::endl ); + + // TODO FIXME hier ist das PROBLEM, SEGFAULT durch create regular vertex + + + + Vertex * newShiftVrtx = *grid.create(); + aaPos[newShiftVrtx] = posNewVrt; + + sh.assign_subset(newShiftVrtx, subsIndEdgV ); + + + + // fuer was braucheh wir das eigentlich? selber schon vergessen..... + + ExpandVertexMultiplett vrtMtpl( attEdg, attFac, nV ); + + aaVrtExpMP[ *iterV ].push_back( vrtMtpl ); + + + + // alle anhängenden faces müssen noch zu wissen bekommen + // dass es diesen neuen Vertex gibt, nicht nur die + // an den edges anhängenden + // vielleicht gibt es einen Loop über attached faces des + // Vertex, für die schon bekannten direkt angehängten klar + // wenn auch dort vermerkt werden muss im Attachment von Seb + // bei den anderen, die keine Edge haben von der Kluft + // da muss man die Normale ins Zentrum bestimmen + // um heraus zu finden, ob sie auf dieser seite sind + // am besten dann das Attachment der faces für vertizes + // von Seb recyclen + + // loop über assosciated faces des vertex am besten + // vermutlich auch noch assosciated edges, um + // zu markieren, welche weg fallen sollen, wenn + // nicht von Kluft selber, sondern quasi verschoben + // und neu erzeugt + + int dbg_FaceIterator = 0; + + + + for( auto const & ifac : assoFaces ) + { + bool isFromFrac = false; + + for( auto const & facFrac : attFac ) + { + +// static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype ( ifac ) >::value ); + static_assert( std::is_same< decltype( (facFrac) ), decltype ( ifac ) >::value ); + + if( ifac == facFrac ) + { + isFromFrac = true; + +// static_assert( std::is_same< decltype( const_cast(facFrac) ), Face * & >::value ); + static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value ); +// static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype( ifac ) >::value ); + static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value ); + + } + } + + + bool atRightSide = false; + + if( isFromFrac ) + atRightSide = true; + + if( !isFromFrac ) + { + // check if on same side of edge where the normal points to: compute cosinus between vector of face center + // perpendicular to the edge + + + + + vector3 facCenter = CalculateCenter( ifac, aaPos ); + + vector3 perpendicu; + + +// UG_LOG("pos 0 " << aaPos[nextFracVrt[0]] << std::endl); +// UG_LOG("pos 1 " << aaPos[*iterV] << std::endl); +// UG_LOG("fac ce " << facCenter << std::endl); + + DropAPerpendicular(perpendicu, facCenter, aaPos[nextFracVrt], aaPos[*iterV]); + +// if( dbg_FaceIterator == 1 ) +// { +// UG_LOG("huhu a0" << std::endl); +// return true; +// } + + + vector3 tmpN; + + VecSubtract(tmpN, facCenter, perpendicu ); + + VecNormalize(tmpN, tmpN); + + UG_LOG("Normale zum Face ist " << tmpN << std::endl); + + number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, nV ); + + UG_LOG("Cosinus zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); + +// if( dbg_FaceIterator == 1 ) +// { +// UG_LOG("huhu a" << std::endl); +//// return true; +// } + + + if( cosBetwFracEdgAndDirection2Face > 0 ) + { + UG_LOG("assuming face to be on richt side" << std::endl); + + atRightSide = true; + +#if ESTABLISH_DEBUG_SUDOS + + Vertex * otherFacCent = *grid.create(); + aaPos[otherFacCent] = facCenter; + sh.assign_subset(otherFacCent, 6 ); + + Vertex * pp = *grid.create(); + aaPos[pp] = perpendicu; + sh.assign_subset(pp, 7 ); + + sh.assign_subset(ifac,8); + +#endif + + } + else + { + UG_LOG("assuming face to be on wrong side" << std::endl); + } + + + dbg_flachen_passiert++; + } + + +// if( dbg_FaceIterator == 1 ) +// { +// UG_LOG("huhu b" << std::endl); +//// return true; +// } + + + + if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein + { + + // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! + vector& newVrts4Fac = aaVrtVecFace[ ifac ]; + + IndexType vrtxFnd = 0; + + for(size_t indVrt = 0; indVrt < (ifac)->num_vertices(); indVrt++ ) + { + Vertex* facVrt = (ifac)->vertex(indVrt); + + if( facVrt == *iterV ) + { + newVrts4Fac[ indVrt ] = newShiftVrtx; + vrtxFnd++; + } + } + + + if( vrtxFnd <= 0 ) + { + UG_THROW("vertex not found!" << std::endl); + } + else if( vrtxFnd > 1 ) + { + UG_THROW("vertex zu oft gefunden " << vrtxFnd << std::endl ); + } + else if ( vrtxFnd == 1 ) + { + } + else + { + UG_THROW("vertex finden komisch " << std::endl); + } + + + } + + dbg_FaceIterator++; + + } + + + + + + + + + } + + + + dbg_iteratorAblaufen++; + + + +// // Ziel: die beiden parallelen Normalen mitteln, und in die jeweiligen beiden Richtungen je einen neuen Vertex erzeugen +// // irgendwie muss der Vertex oder die Edge besser sogar wissen, dass sie einen neuen Verschiebevertex bekommen hat +// // denn später müssen neue Edges und neue Faces basierend auf den neuen Vertizes erzeugt werden +// // vielleicht braucht die edge und das face ein Attachment, das ihnen das sagt, ähnlihc wie VertexTrible std Vektoren? +// +// +// + UG_LOG("END THIS VERTEX NORMAL INNER ENDING CLEFT" << std::endl); + +#endif + + +// return true; + + + } +// else if( numFracsCrossAtVrt == 2 ) // free line of fracture, no crossing point, not at boundary + else if( false ) // free line of fracture, no crossing point, not at boundary + { + // in this case, we have two attached edges, and each of these edges has two attached faces + // the faces have a naormal, and based on the normal, we can decide which faces belong to the same side of the edges + + + if( numbAttTripl != 4 ) + { + + UG_LOG("NUMBER OF TRIPLETTS " << numbAttTripl << std::endl); + +// return true; + + UG_THROW("Anzahl der angehaengten Triples kann nicht stimmen, Vertex einer Kluft ohne Schnittpunkte, nicht am Rand " << std::endl); + } + + // Zuordnung der Edges und Faces, die auf der gleichen Seite der fracture sind + + // und gleich auch Erzeugung der neuen Knoten, die dann + // in einem Doublett zusammen mit ihren Normalen an die alten Vertizes + // angehängt werden; der Winkel zur Normalen hilft später, die Seite + // heraus zu finden, Seite von den Edges + + + + int dbg_iteratorAblaufen = 0; + +#if WORKAROUND_ARTE_SEGFAULT + + int dbg_laenge = 0; + + for( auto const & vft : vecVertFracTrip ) + { + dbg_laenge++; + + UG_LOG("VERTEXFRACTRIP" << std::endl); + + vector3 ve = vft.getNormal(); + + UG_LOG("NORMAL " << ve << std::endl); + + UG_LOG("laenge " << dbg_laenge << std::endl ); + } + + + UG_LOG("SINGLE" << std::endl); + + + for( VvftIterator vvftOne = vecVertFracTrip.begin(); + vvftOne != vecVertFracTrip.end() - 1; + vvftOne++ + ) + { + + + Edge * edgeOne = vvftOne->getEdge(); + vector3 nOne = vvftOne->getNormal(); + + + for( VvftIterator vvftTwo = vvftOne + 1; + vvftTwo != vecVertFracTrip.end(); + vvftTwo++ + ) + { + Edge * edgeTwo = vvftTwo->getEdge(); + vector3 nTwo = vvftTwo->getNormal(); + + number cosinus = VecDot( nOne, nTwo ); + + if( edgeOne != edgeTwo ) + { + UG_LOG("COSI between " << nOne << " and " << nTwo << " -> " << cosinus << std::endl ); + } + + } + } + + UG_LOG("SINGLE END" << std::endl); + + int dbg_laenge_eins = 0; + +#endif + + + for( VvftIterator vvftOne = vecVertFracTrip.begin(); + vvftOne != vecVertFracTrip.end() - 1; + vvftOne++ + ) + { + +#if WORKAROUND_ARTE_SEGFAULT + dbg_laenge_eins++; + + if( dbg_laenge_eins > dbg_laenge ) + { + break; + } + + int dbg_laenge_zwei = dbg_laenge_eins; +#endif + int dbg_zweiterIteratorAblaufen = 0; + + vector3 nOne = vvftOne->getNormal(); + + Edge * edgeOne = vvftOne->getEdge(); + + + + for( VvftIterator vvftTwo = vvftOne + 1; + vvftTwo != vecVertFracTrip.end(); + vvftTwo++ + ) + { + +#if WORKAROUND_ARTE_SEGFAULT + dbg_laenge_zwei++; + + if( dbg_laenge_zwei > dbg_laenge ) + { + break; + } + + UG_LOG("NORMAL ONE " << vvftOne->getNormal() << std::endl); + UG_LOG("NORMAL TWO " << vvftTwo->getNormal() << std::endl); + UG_LOG("LAENGE EINZ ZWO " << dbg_laenge_eins << " " << dbg_laenge_zwei << std::endl ); +#endif + + // dieselben brauchen wir nicht vergleichen + if( vvftOne == vvftTwo ) + { + // sollte nie vorkommen! + UG_THROW("Unsinn " << std::endl); + } + else + { + + Edge * edgeTwo = vvftTwo->getEdge(); + + // noch testen, ob nicht die Kante dieselbe ist, geht das? + // bei der gleichen Ecke ist es unnötig, da es gegensätzlich sein muss + + + + if( edgeOne != edgeTwo ) + { + + std::vector nextFracVrt; + + IndexType foundThisVrtOne = 0; + + for( size_t i = 0; i < 2; ++i ) + { + Vertex * vrtEdgEnd = edgeOne->vertex(i); + + if( vrtEdgEnd == *iterV ) + { + foundThisVrtOne++; + } + else + { + nextFracVrt.push_back( vrtEdgEnd ); + } + + } + + if( foundThisVrtOne != 1 ) + { + UG_THROW("zu viel zu wenig vertizex one " << std::endl); + } + + + IndexType foundThisVrtTwo = 0; + + for( size_t i = 0; i < 2; ++i ) + { + Vertex * vrtEdgEnd = edgeTwo->vertex(i); + + if( vrtEdgEnd == *iterV ) + { + foundThisVrtTwo++; + } + else + { + nextFracVrt.push_back( vrtEdgEnd ); + } + + } + + if( foundThisVrtTwo != 1 ) + { + UG_THROW("zu viel zu wenig vertizex two " << std::endl); + } + + + + vector3 nTwo = vvftTwo->getNormal(); + + number cosinus = VecDot( nOne, nTwo ); + +// bool vz = ! std::signbit(cosinus); + + UG_LOG("cosinus " << dbg_vertizesPassiert << " between " << nOne << " and " << nTwo << " -> " << cosinus << std::endl ); + //UG_LOG("sign between " << nOne << " and " << nTwo << " -> " << vz << std::endl ); + + + if( cosinus > 0 ) + { + // gleiche Seite vermutet + + // sind die edges dieselben? pruefen! gleiche unnoetig - wird oben schon abgefragt + + // Klasse schreiben, die als attachment an einen Fracture-Vertex + // die neuen Vertizes samt ihrer gemittelten Normalen speichert + // also std::vector von dieser neuen Klasse als Vertex attachment + +#if 1 + + Face * facOne = vvftOne->getFace(); + Face * facTwo = vvftTwo->getFace(); + + expandSingleFractureAtGivenSide( nOne, nTwo, + edgeOne, edgeTwo, + facOne, facTwo, + fracInfosBySubset, + posOldVrt, + aaPos, + grid, sh, + assoFaces, + nextFracVrt, + aaVrtVecFace, + dbg_flachen_passiert, + *iterV + ); + +#else + + // average the normals + + vector3 normSum; + + VecAdd( normSum, nOne, nTwo ); + + vector3 normSumNormed; + + VecNormalize(normSumNormed, normSum); + + UG_LOG("averaged normal " << normSumNormed << std::endl); + + std::vector attEdg; + std::vector attFac; + + attEdg.push_back( edgeOne ); + attEdg.push_back( edgeTwo ); + +// Face * facOne = vvftOne->getFace(); +// Face * facTwo = vvftTwo->getFace(); + + attFac.push_back( facOne ); + attFac.push_back( facTwo ); + + // jetzt neuen Vertex erzeugen in Richtung der Normalen + // sonst ist das attachment Schwachsinn! + + vector3 posNewVrt; + + vector3 moveVrt; + + auto subsIndEdgOne = sh.get_subset_index(edgeOne); + + auto subsIndEdgTwo = sh.get_subset_index(edgeTwo); + + + if( subsIndEdgOne != subsIndEdgTwo ) + { + UG_THROW("subsets passen nicht" << std::endl ); + } + + + + + number width = fracInfosBySubset.at(subsIndEdgOne).width; + + // der Faktor ist Käse und muss noch aus den Eingaben übernommen werden + VecScale(moveVrt, normSumNormed, width/2. ); + + VecAdd(posNewVrt, posOldVrt, moveVrt ); + + UG_LOG("neuer Vertex " << posNewVrt << std::endl ); + + // TODO FIXME hier ist das PROBLEM, SEGFAULT durch create regular vertex + + Vertex * newShiftVrtx = *grid.create(); + aaPos[newShiftVrtx] = posNewVrt; + + sh.assign_subset(newShiftVrtx, subsIndEdgOne ); + + + + // fuer was braucheh wir das eigentlich? selber schon vergessen..... + + ExpandVertexMultiplett vrtMtpl( attEdg, attFac, normSumNormed ); + + aaVrtExpMP[ *iterV ].push_back( vrtMtpl ); + + + + // alle anhängenden faces müssen noch zu wissen bekommen + // dass es diesen neuen Vertex gibt, nicht nur die + // an den edges anhängenden + // vielleicht gibt es einen Loop über attached faces des + // Vertex, für die schon bekannten direkt angehängten klar + // wenn auch dort vermerkt werden muss im Attachment von Seb + // bei den anderen, die keine Edge haben von der Kluft + // da muss man die Normale ins Zentrum bestimmen + // um heraus zu finden, ob sie auf dieser seite sind + // am besten dann das Attachment der faces für vertizes + // von Seb recyclen + + // loop über assosciated faces des vertex am besten + // vermutlich auch noch assosciated edges, um + // zu markieren, welche weg fallen sollen, wenn + // nicht von Kluft selber, sondern quasi verschoben + // und neu erzeugt + + int dbg_FaceIterator = 0; + +#if 0 +// for( auto iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ ) + for( std::vector::iterator iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ ) + { + bool isFromFrac = false; + +// for( std::vector::iterator iterF2 = attFac.begin(); iterF2 != attFac.end(); iterF2++ ) +// { +// static_assert( std::is_same< decltype( *iterF2 ), decltype ( *iterFac ) >::value ); +// +// } + + int dbg_innterFacFracIt = 0; + + for( auto const & facFrac : attFac ) + { + + +// UG_LOG("type iter facFrac " << typeid( facFrac ).name() << std::endl); +// +// UG_LOG("type iter Fac " << typeid( *iterFac ).name() << std::endl); + + static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype ( *iterFac ) >::value ); + + + + + if( *iterFac == facFrac ) + { + isFromFrac = true; + + static_assert( std::is_same< decltype( const_cast(facFrac) ), Face * & >::value ); + static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype( * iterFac ) >::value ); + + } + } + + bool atRightSide = false; + + if( isFromFrac ) + atRightSide = true; + + if( !isFromFrac ) + { + // check if on same side of edge where the normal points to: compute cosinus between vector of face center + // perpendicular to the edge + // TODO FIXME + // KAESE!!! + + vector3 facCenter = CalculateCenter( *iterFac, aaPos ); + + vector3 perpendicu; + + if( nextFracVrt.size() != 2 ) + { + UG_THROW("komische Groesse" << std::endl); + } + + DropAPerpendicular(perpendicu, facCenter, aaPos[nextFracVrt[0]], aaPos[nextFracVrt[1]]); + + vector3 tmpN; + + VecSubtract(tmpN, facCenter, perpendicu ); + + VecNormalize(tmpN, tmpN); + + UG_LOG("Normale zum Face ist " << tmpN << std::endl); + + number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, normSumNormed ); + + UG_LOG("Cosinus zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); + + if( cosBetwFracEdgAndDirection2Face > 0 ) + { + UG_LOG("assuming face to be on richt side" << std::endl); + + atRightSide = true; + +#if ESTABLISH_DEBUG_SUDOS + + Vertex * otherFacCent = *grid.create(); + aaPos[otherFacCent] = facCenter; + sh.assign_subset(otherFacCent, 5 ); + + Vertex * pp = *grid.create(); + aaPos[pp] = perpendicu; + sh.assign_subset(pp, 6 ); + + sh.assign_subset(*iterFac,7); +#endif + + } + else + { + UG_LOG("assuming face to be on wrong side" << std::endl); + } + +// if( dbg_flachen_passiert == 0 ) +// { +// UG_LOG("passiert " << dbg_flachen_passiert << std::endl); +// +// Vertex * otherFacCent = *grid.create(); +// aaPos[otherFacCent] = facCenter; +// sh.assign_subset(otherFacCent, 5 ); +// +// Vertex * pp = *grid.create(); +// aaPos[pp] = perpendicu; +// sh.assign_subset(pp, 6 ); +// +// sh.assign_subset(*iterFac,7); +// +// +// sh.assign_subset(*iterFac,3); +// +// UG_LOG("is from frac " << isFromFrac << std::endl); +// +// return true; +// } + + + dbg_flachen_passiert++; + } + + + if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein + { + + + // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! + vector& newVrts4Fac = aaVrtVecFace[ * iterFac ]; + + IndexType vrtxFnd = 0; + + for(size_t indVrt = 0; indVrt < (*iterFac)->num_vertices(); indVrt++ ) + { + Vertex* facVrt = (*iterFac)->vertex(indVrt); + + if( facVrt == *iterV ) + { + newVrts4Fac[ indVrt ] = newShiftVrtx; + // UG_LOG("vertex found " << indVrt << std::endl ); + vrtxFnd++; + } + } + + + if( vrtxFnd <= 0 ) + { + UG_THROW("vertex not found!" << std::endl); + } + else if( vrtxFnd > 1 ) + { + UG_THROW("vertex zu oft gefunden " << vrtxFnd << std::endl ); + } + else if ( vrtxFnd == 1 ) + { + // UG_LOG("vertex found abgeschlossen" << std::endl); + } + else + { + UG_THROW("vertex finden komisch " << std::endl); + } + + + } + + dbg_innterFacFracIt++; + + + +// +// +// if( ! isFromFrac ) +// { +// // Vektor zum Zentrum von KNoten aus berechnen und Winkel zur Normalen bestimmen zur Unterscheidung der Seite +// // wenn auf richtiger Seite, zuweisen +// } + + dbg_FaceIterator++; + + } +#else +// std::vector & assFaceVrt = aaVrtInfoAssoFaces[*iterV]; + + // VecFace & assoFaces = aaVrtInfoAssoFaces[*iterV]; + // TODO FIXME hier braucht man das nicht zu ordnen + // aber bei Kreuzpunkten von Klueften muss es so geordnet werden, wie es nebeneinander liegt + // bei den Edges gibt es auch die benachbarten, und die edges haben das attachment, ob sie Kluftedges sind + + // for( auto const & ifac : assoFaces ) + // { + // static_assert( std::is_same< decltype( ifac ), Face * const & >::value ); + // + // // TODO FIXME folgenden loop durch diesen ersetzen + // // Achtung: Zeigerproblematik, Referenzen, etc..... + // // *iterFac ersetzen durch ifac vermutlich, aber wer weiss + // } + + + // for( auto iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ ) + //for( std::vector::iterator iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ ) + for( auto const & ifac : assoFaces ) + { + bool isFromFrac = false; + + + int dbg_innterFacFracIt = 0; + + for( auto const & facFrac : attFac ) + { + +// static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype ( ifac ) >::value ); + static_assert( std::is_same< decltype( (facFrac) ), decltype ( ifac ) >::value ); + + if( ifac == facFrac ) + { + isFromFrac = true; + +// static_assert( std::is_same< decltype( const_cast(facFrac) ), Face * & >::value ); + static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value ); +// static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype( ifac ) >::value ); + static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value ); + + } + } + + bool atRightSide = false; + + if( isFromFrac ) + atRightSide = true; + + if( !isFromFrac ) + { + // check if on same side of edge where the normal points to: compute cosinus between vector of face center + // perpendicular to the edge + + vector3 facCenter = CalculateCenter( ifac, aaPos ); + + vector3 perpendicu; + + if( nextFracVrt.size() != 2 ) + { + UG_THROW("komische Groesse" << std::endl); + } + + DropAPerpendicular(perpendicu, facCenter, aaPos[nextFracVrt[0]], aaPos[nextFracVrt[1]]); + + vector3 tmpN; + + VecSubtract(tmpN, facCenter, perpendicu ); + + VecNormalize(tmpN, tmpN); + + UG_LOG("Normale zum Face ist " << tmpN << std::endl); + + number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, normSumNormed ); + + UG_LOG("Cosinus zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); + + if( cosBetwFracEdgAndDirection2Face > 0 ) + { + UG_LOG("assuming face to be on richt side" << std::endl); + + atRightSide = true; + +#if ESTABLISH_DEBUG_SUDOS + + Vertex * otherFacCent = *grid.create(); + aaPos[otherFacCent] = facCenter; + sh.assign_subset(otherFacCent, 5 ); + + Vertex * pp = *grid.create(); + aaPos[pp] = perpendicu; + sh.assign_subset(pp, 6 ); + + sh.assign_subset(*iterFac,7); +#endif + + } + else + { + UG_LOG("assuming face to be on wrong side" << std::endl); + } + + + dbg_flachen_passiert++; + } + + + if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein + { + + // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! + vector& newVrts4Fac = aaVrtVecFace[ ifac ]; + + IndexType vrtxFnd = 0; + + for(size_t indVrt = 0; indVrt < (ifac)->num_vertices(); indVrt++ ) + { + Vertex* facVrt = (ifac)->vertex(indVrt); + + if( facVrt == *iterV ) + { + newVrts4Fac[ indVrt ] = newShiftVrtx; + vrtxFnd++; + } + } + + + if( vrtxFnd <= 0 ) + { + UG_THROW("vertex not found!" << std::endl); + } + else if( vrtxFnd > 1 ) + { + UG_THROW("vertex zu oft gefunden " << vrtxFnd << std::endl ); + } + else if ( vrtxFnd == 1 ) + { + } + else + { + UG_THROW("vertex finden komisch " << std::endl); + } + + + } + + dbg_innterFacFracIt++; + + + + dbg_FaceIterator++; + + } + +#endif + +#endif + + } + else + { + // andere Seite vermutet, nichts tun! + } + + + } + + + } + + dbg_zweiterIteratorAblaufen++; + + } + + dbg_iteratorAblaufen++; + + } + + +// // Ziel: die beiden parallelen Normalen mitteln, und in die jeweiligen beiden Richtungen je einen neuen Vertex erzeugen +// // irgendwie muss der Vertex oder die Edge besser sogar wissen, dass sie einen neuen Verschiebevertex bekommen hat +// // denn später müssen neue Edges und neue Faces basierend auf den neuen Vertizes erzeugt werden +// // vielleicht braucht die edge und das face ein Attachment, das ihnen das sagt, ähnlihc wie VertexTrible std Vektoren? +// +// +// + + + UG_LOG("END THIS VERTEX NORMAL COSINE" << std::endl); + + + + } +// else // two fractures completely crossing, numFracsCrossAtVrt >= 3, i.e. T crossing and two fractures completely crossing + else // two fractures completely crossing, numFracsCrossAtVrt >= 2, i.e. durchgehend, T crossing and two fractures completely crossing + { + + + CrossVertInf crossVrtInf( *iterV, numFracsCrossAtVrt ); + VecVertexOfFaceInfo orderedFaces; + SegmentsFractExtrus segments; +// VecVertexOfFaceInfo segmentPart; + + // note: we do not attach this info to the vertex, as we only need it local; in principle, in case of further need, it would + // be usful to establish some sort of attachment + + IndexType startIndex = 0; + + determineOrderOfFaces( + vecVertFracTrip, assoFaces, orderedFaces, + segments, //segmentPart, + startIndex, allAssoEdges, + sh, aaMarkEdgeB + ); + +// CrossingVertexInfo crossVrtInf( *iterV, numFracsCrossAtVrt ); + + UG_LOG("number fracs " << numFracsCrossAtVrt << std::endl); + + + UG_LOG("Nummer vorbei " << std::endl); + +// for( auto const & aae : allAssoEdges ) +// { +// crossVrtInf.addOriginalFracEdge( aae ); +// } + +// crossVrtInf.setOriginalFracEdge(allAssoEdges); + + // in case of three fractures, we have to use the method for eine durchgehende fracture + // auf der Seite, wo die zweite fracture NICHT rein geht + + // kreuzende Fractures im Innenraum -> Arte in Reinform implementieren + + // verkettete Liste der anhängenden fractures in Reihenfolge + // der Anhängung mit INfo, ob eine Kluft vorliegt + +// for( auto const & attVFT : vecVertFracTrip ) +// { +// Edge * edg = attVFT.getEdge(); +// Face * fac = attVFT.getFace(); +// vector3 nv = attVFT.getNormal(); +// } + +// // hier werden ALLE attached Faces benötigt, auch die, die zwischen den direkt an den fractures liegenden Faces sind +// + // copies of all faces and of fractured ones +// auto vVFT = vecVertFracTrip; // caution: COPY, not reference! +// auto aF = assoFaces; // caution: COPY, not reference! + +// UG_LOG("Gesamtanzahl faces um Knoten " << aF.size() << std::endl ); + + // erstmal die ganzen anhaengenden Faces ordnen, dass wir wissen, in welcher Reihenfolge wir durchlaufen muessen + // jede Edge hat ein bool attachment schon, das weiss, ob sie Fracture edge ist oder nicht + // Reihenfolge der faces und die edges auch dazu, vielleicht neues Triple oder dergleiche, dabei zwei edges und zwei normals + // und wie gesagt, die edges wissen, ob sie fractures sind, dazu keine neuen Variablen notwendig + +// using VertexOfFaceInfo = VertexFractureTriple< std::pair, Face*, std::pair >; +// // all edges of the attached face - must always be two, the face itself, and the normal vectors of the face in direction of the two edges +// // the size of the normal vector vector also must be two +// // however, if an edge of the face is not a fracture edge, we do not compute the normal, but assign zero as norm +// // for those edges and faces which are Kluft edges, we assign the normal known from the info computed before, vertex fracture triple +// +#if 0 + CrossVertInf crossVrtInf( *iterV, numFracsCrossAtVrt ); + + // using VecVertexOfFaceInfo = std::vector; + + VecVertexOfFaceInfo orderedFaces; + +// using SegmentsFractExtrus = std::vector; + + SegmentsFractExtrus segments; + // single components always from one fracture edge to the next one + + VecVertexOfFaceInfo segmentPart; + + // note: we do not attach this info to the vertex, as we only need it local; in principle, in case of further need, it would + // be usful to establish some sort of attachment + + // fixed diesen Sortierungsalgorithmus bei allen inneren Knoten anwenden, + // um zweifelsfrei alle anhängenden Faces der richtigen Seite zuordnen zu können!!!! + + // VecVertFracTrip & vecVertFracTrip = aaVrtInfoFraTri[*iterV]; + // VecFace & assoFaces = aaVrtInfoAssoFaces[*iterV]; + + IndexType startIndex = 0; + + determineOrderOfFaces( crossVrtInf, vecVertFracTrip, assoFaces, orderedFaces, + segments, segmentPart, startIndex, allAssoEdges, + sh, aaMarkEdgeB + ); +#endif + +#if 0 + + IndexType countedCrossingFracEdgs = 0; + + if( vVFT.size() == 0 ) + UG_THROW("vertex frac triple zu klein an Kreuzung " << std::endl); + + // we start with the first fracture face edge stuff, copy it, and delete this immidiately + VertFracTrip startVertFracTrip = vVFT[0]; + + vVFT.erase(vVFT.begin()); + + bool atFirstTriple = true; + + Face* fracFac = startVertFracTrip.getFace(); + Edge* fracEdg = startVertFracTrip.getEdge(); + vector3 fracNorm = startVertFracTrip.getNormal(); + + Edge* originalStartEdge = startVertFracTrip.getEdge(); + + if( fracEdg != 0 ) + { + countedCrossingFracEdgs++; + } + + // do not change this pointer + Edge* startEdg = fracEdg; + Face* startFace = fracFac; + + vector3 startNormal = fracNorm; + + Face* nextFace = NULL; + + UG_LOG("Gesamtanzahl faces um Knoten vor while " << aF.size() << std::endl ); + + while( aF.size() != 0 ) + { + + UG_LOG("Gesamtanzahl faces um Knoten Anfang while " << aF.size() << std::endl ); + + + Face* face2Append = startFace; + Edge* startEdg2Append = startEdg; + + + IndexType fndCommEdg = 0; + vector3 nuVe(0,0,0); + + Edge* nextEdge = NULL; + + std::pair edge2Append( startEdg2Append, nextEdge ); + std::pair normal2Append( startNormal, nuVe ); + + + // if start face and start edge from a triple, then has to be erased this triple, exept for the entire start, as already erased + if( ! atFirstTriple ) + { + for( VecVertFracTrip::iterator itAttVFT = vVFT.begin(); itAttVFT != vVFT.end(); itAttVFT++ ) + { + auto vft = *itAttVFT; + + Edge * edgIt = vft.getEdge(); + + Face * facIt = vft.getFace(); + + if( edgIt == startEdg && facIt == startFace ) + { + // the first edge if from a fracture and the face is connected to it + + vVFT.erase(itAttVFT); + + normal2Append.first = vft.getNormal(); + + if( ! FaceContains( facIt, startEdg )) + { + UG_THROW("Face does not contain start edge of its edge" << std::endl); + } + + break; + } + } + + } + else // we can save the investigation if we have a triple, and we do not need to erase, as already erased..... + { + atFirstTriple = false; + } + + + for( auto const & iE : allAssoEdges ) // werden nicht gelöscht, deswegen Zugriff auf attachment direkt + { + if( FaceContains(face2Append, iE) ) + { + fndCommEdg++; + + if( iE != startEdg ) + { + nextEdge = iE; + + edge2Append.second = iE; + + } + } + + + } + + if( fndCommEdg != 2 ) + { + UG_THROW("komische Anzahl gemeinsamer Ecke " << fndCommEdg << std::endl); + } + + if( nextEdge == NULL ) + { + UG_THROW("wieso keine zweite Ecke gefunden???? " << std::endl); + } + + if( edge2Append.first == NULL || edge2Append.second == NULL ) + { + UG_THROW("null immer noch?" << std::endl); + } + + // erase the face from the list + + IndexType faceFound = 0; + + for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ ) + { + Face * iFa = *itFac; + + if( iFa == startFace && FaceContains( iFa, nextEdge ) && FaceContains(iFa, startEdg)) + { + faceFound++; + } + } + + int totalSubsNum = sh.num_subsets(); + + int newSubsToAdd = totalSubsNum; + + if( faceFound != 1 ) + { + + + sh.assign_subset(startFace,newSubsToAdd++); + sh.assign_subset(startEdg,newSubsToAdd++); + sh.assign_subset(nextEdge,newSubsToAdd++); + + int faNum = aF.size(); + + UG_LOG("Gesamtzahl faces vor Absturz " << faNum << std::endl); + + UG_LOG("Gesicht in falscher Anztahl gefunden " << faceFound << std::endl); + +// return true; + + + + UG_THROW("Gesicht in falscher Anztahl gefunden " << faceFound << std::endl); + } + else + { +// sh.assign_subset(startFace,newSubsToAdd++); +// sh.assign_subset(startEdg,newSubsToAdd++); +// sh.assign_subset(nextEdge,newSubsToAdd++); + + int faNum = aF.size(); + + UG_LOG("Gesamtzahl faces ohne Absturz " << faNum << std::endl); + + } + + for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ ) + { + Face * iFa = *itFac; + + if( iFa == startFace && FaceContains( iFa, nextEdge ) && FaceContains(iFa, startEdg) ) + { + aF.erase(itFac); + break; + } + } + + + + + bool sndEdgIsFracEdgeAlso = aaMarkEdgeB[nextEdge]; + + bool tripFound = false; + + if( sndEdgIsFracEdgeAlso ) + { + + if( nextEdge != originalStartEdge ) + countedCrossingFracEdgs++; + + // we need to have a look for the next triple + + // check if the next normal is a frac normal which contains the face as well + + for( VecVertFracTrip::iterator itAttVFT = vVFT.begin(); itAttVFT != vVFT.end(); itAttVFT++ ) + { + auto vft = *itAttVFT; + + Edge * edgIt = vft.getEdge(); + + Face * facIt = vft.getFace(); + + if( edgIt == nextEdge && facIt == face2Append ) + { + // the second edge if from a fracture and the face is connected to it + + tripFound = true; + + vVFT.erase(itAttVFT); + + normal2Append.second = vft.getNormal(); + + if( ! FaceContains( facIt, nextEdge )) + { + UG_THROW("Face does not contain edge of its edge" << std::endl); + } + + break; + } + } + + } + + if( ! tripFound && sndEdgIsFracEdgeAlso ) + { + UG_THROW("Triple nicht gefunden trotz markierter Edge" << std::endl); + } + + + // check if aF or vVFT still contain the former or the next face - must not be the case! + + VertexOfFaceInfo vOFI( edge2Append, face2Append, normal2Append ); + + orderedFaces.push_back( vOFI ); + + segmentPart.push_back( vOFI ); + + if( sndEdgIsFracEdgeAlso ) + { + segments.push_back( segmentPart ); + + segmentPart.clear(); + } + + + // what is next face, what is next edge? + // wie kriegen wir es hin, auch das nächste Triple zu erasen, wenn es jetzt kommt als nächstes? + + + startNormal = nuVe; + startEdg = nextEdge; + + if( aF.size() == 0 ) + { + if( nextEdge != originalStartEdge ) + { + UG_THROW("Gesichter leer, aber keine Anfangsecke gefunden" << std::endl); + } + else + { + break; // while loop zu Ende, raus aus dem while loop, den Rest nicht mehr machen, würde schief gehen zwingendermassen + } + + } + + + // bleibt noch das nächste Gesicht heraus zu finden, dafür kommt eigentlich nur noch eines in Frage, da das zweite Gesicht vom edge + // geloescht sein muss in aF, es muss das einzig übrige face sein, das die jetzt start edge enthält, davon darf es nur eines geben, wir löschen aber noch nicht + + IndexType nextFaceFound = 0; + + for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ ) + { + Face * iFa = *itFac; + + if( FaceContains(iFa, startEdg ) ) + { + nextFaceFound++; + } + } + + if( nextFaceFound != 1 ) + { + UG_THROW("folgendes Gesicht in falscher Anztahl gefunden " << nextFaceFound << std::endl); + } + + for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ ) + { + Face * iFa = *itFac; + + if( FaceContains(iFa, startEdg ) ) + { + startFace = iFa; + break; + } + } + + + } + + if( vVFT.size() != 0 ) + { + UG_THROW("not all triples found! " << std::endl); + } + + if( aF.size() != 0 ) + UG_THROW("not all faces found " << std::endl); + + if( startEdg != originalStartEdge ) + { + UG_THROW("wir sind nicht am Anfang wieder angekommen" << std::endl); + } + + + if( segmentPart.size() != 0 ) + { + UG_THROW("die Segmentteile muessen alle verarbeitet sein" << std::endl); + } + + UG_LOG("Kreislauf geschlossen" << std::endl); + +#endif + + // test if the segments and their partition produce sumething useful, for debug purposes + + // als nächstes muss man die Klassen von durch Klüften abgetrennten ordered Faces durchgehen, und die Verschiebevertizes erzeugen + // als nächstes die verschiedenen Sektionen durch gehen, eventuell nochmal extra Objekte dafür erzeugen + // oder gleich beim Durchgehen die neuen Vertizes erzeugen, Startsignal durch ein Face mit erster Edge KLuft, und dann die nächste + // Kluftedge finden, egal ob vom gleihen face oder von einem späteren face im kreis + + // now figure out to which face this next edge belongs, and if this is a fracture edge, then we have the triple and the normal info + // else we let the normal zero + + // figure out if second edge is also frac edge, i.e. if it belongs to an edge of the remaining vVFT elements + // first easily asking if it is marked as frac edge, simplifies research + + // in principle from here on need to loop through all triples and through all faces, find out some way to construct next edge and to + // build one element after the other of the ordered faces vector, still even the first element is not completed + + // TODO FIXME kreuzende Fractures im Innenraum -> Arte in Reinform implementieren + // later assign somehow next edge to start edge, or use new variable, when we have figured out next face + // at end, chech if we have arrived again at original first edge + + + int totalSubsNum = sh.num_subsets(); + +// int newSubsToAdd = totalSubsNum; + +// for( VertexOfFaceInfo const & vertFracInfo : orderedFaces ) +// { +//// Face * fa = vertFracInfo.getFace(); +//// +//// sh.assign_subset(fa,newSubsToAdd++); +// } + + number totAnglsEdg = 0; + number totAnglsNrm = 0; + + for( VecVertexOfFaceInfo const & segPart : segments ) + { +// newSubsToAdd++; + + IndexType numbTriangs = segPart.size(); + + if( numbAttTripl == 0 ) + { + UG_THROW("zu wenig Dreiecke " << std::endl); + } + + VertexOfFaceInfo const & vFISBegin = segPart[0]; + VertexOfFaceInfo const & vFISEnd = segPart[numbTriangs-1]; + + std::pair edgesBegin = vFISBegin.getEdge(); + std::pair edgesEnd = vFISEnd.getEdge(); + + std::pair normalBegin = vFISBegin.getNormal(); + std::pair normalEnd = vFISEnd.getNormal(); + + Edge* edgeFracOne = edgesBegin.first; + Edge* edgeFracTwo = edgesEnd.second; + + auto subsIndFracOne = sh.get_subset_index(edgeFracOne); + auto subsIndFracTwo = sh.get_subset_index(edgeFracTwo); + + vector3 normalFracOne = normalBegin.first; + vector3 normalFracTwo = normalEnd.second; + +// sh.assign_subset(edgeFracOne, newSubsToAdd); +// +// if( edgeFracTwo != originalStartEdge ) +// sh.assign_subset(edgeFracTwo, newSubsToAdd); + + // neue Punkte erzeugen + + number cosBetweenNormals = VecDot( normalFracOne, normalFracTwo ); + + constexpr bool useOldMethodeNotAngleDep = false; + + if( useOldMethodeNotAngleDep ) + { + + if( subsIndFracOne == subsIndFracTwo ) + { + // if( numFracsCrossAtVrt != 3 ) + if( numFracsCrossAtVrt != 2 && numFracsCrossAtVrt != 3 ) + { + // UG_THROW("Fracture Segment an beiden Seiten gleiche sudo, aber keine T Kreuzung?" << std::endl); + UG_THROW("Fracture Segment an beiden Seiten gleiche sudo, aber keine durchgehende Kluft?" << std::endl); + } + + // dieselben Methoden wie im Fall von einer durchgehenden Kluft an einem Vertex, dort kopieren + // bzw Funktion schreiben, die beides macht + + // hier wird der Fall abgezweigt, dass wir auf der durchgehenden Seite einer Kluft sind + // wenn wir eine T-Kreuzung haben + + std::vector nextFracVrt; + + IndexType foundThisVrtOne = 0; + + for( size_t i = 0; i < 2; ++i ) + { + Vertex * vrtEdgEnd = edgeFracOne->vertex(i); + + if( vrtEdgEnd == *iterV ) + { + foundThisVrtOne++; + } + else + { + nextFracVrt.push_back( vrtEdgEnd ); + } + + } + + if( foundThisVrtOne != 1 ) + { + UG_THROW("zu viel zu wenig vertizex one " << std::endl); + } + + + IndexType foundThisVrtTwo = 0; + + for( size_t i = 0; i < 2; ++i ) + { + Vertex * vrtEdgEnd = edgeFracTwo->vertex(i); + + if( vrtEdgEnd == *iterV ) + { + foundThisVrtTwo++; + } + else + { + nextFracVrt.push_back( vrtEdgEnd ); + } + + } + + if( foundThisVrtTwo != 1 ) + { + UG_THROW("zu viel zu wenig vertizex two " << std::endl); + } + + Face * faceBegin = vFISBegin.getFace(); + Face * faceEnd = vFISEnd.getFace(); + + + // TODO FIXME hier die Segmentinformation übergeben, da die Faces bekannt sind, die dran hängen!!!!! + // expandSingleFractureAtGivenSide( normalFracTwo, normalFracTwo, + // edgeFracOne, edgeFracTwo, + // faceBegin, faceEnd, + // fracInfosBySubset, + // posOldVrt, + // aaPos, + // grid, sh, + // assoFaces, + // nextFracVrt, + // aaVrtVecFace, + // dbg_flachen_passiert, + // *iterV, + // crossVrtInf, + // ( numFracsCrossAtVrt == 3 ) + // ); + expandSingleFractureAtGivenSide( normalFracOne, normalFracTwo, + edgeFracOne, edgeFracTwo, + faceBegin, faceEnd, + fracInfosBySubset, + posOldVrt, + aaPos, + grid, sh, + segPart, + nextFracVrt, + aaVrtVecFace, + dbg_flachen_passiert, + *iterV, + crossVrtInf, + ( numFracsCrossAtVrt == 3 ) + ); + + + + } + else + { + + // create normal vectors into direction of relevant edges + + vector3 alongEdgeOne; + vector3 alongEdgeTwo; + + Vertex * vrtEdgeOneBegin = nullptr; + Vertex * vrtEdgeTwoBegin = nullptr; + Vertex * vrtEdgeOneEnd = nullptr; + Vertex * vrtEdgeTwoEnd = nullptr; + + + for( size_t i = 0; i < 2; ++i ) + { + Vertex * vrtFromEdgeOne = edgeFracOne->vertex(i); + Vertex * vrtFromEdgeTwo = edgeFracTwo->vertex(i); + + if( vrtFromEdgeOne == *iterV ) + { + vrtEdgeOneBegin = vrtFromEdgeOne; + } + else + { + vrtEdgeOneEnd = vrtFromEdgeOne; + } + + if( vrtFromEdgeTwo == *iterV ) + { + vrtEdgeTwoBegin = vrtFromEdgeTwo; + } + else + { + vrtEdgeTwoEnd = vrtFromEdgeTwo; + } + + } + + if( vrtEdgeOneBegin == NULL || vrtEdgeTwoBegin == NULL || vrtEdgeOneEnd == NULL || vrtEdgeTwoEnd == NULL ) + { + UG_THROW("lauter Nullen vertizes" << std::endl); + } + + vector3 fracVrtPos = aaPos[*iterV]; + + vector3 fracEdgOneEndPos = aaPos[ vrtEdgeOneEnd ]; + vector3 fracEdgTwoEndPos = aaPos[ vrtEdgeTwoEnd ]; + + vector3 directionEdgOne; + VecSubtract(directionEdgOne, fracEdgOneEndPos, fracVrtPos); + + vector3 directionEdgTwo; + VecSubtract(directionEdgTwo, fracEdgTwoEndPos, fracVrtPos); + + vector3 nrmdVecEdgOne; + VecNormalize(nrmdVecEdgOne, directionEdgOne); + + vector3 nrmdVecEdgTwo; + VecNormalize(nrmdVecEdgTwo, directionEdgTwo); + + number cosBetweenEdges = VecDot(nrmdVecEdgOne,nrmdVecEdgTwo); + + // TODO FIXME wenn Winkel zu klein, dann die Methode verwenden der Mittelung der beiden Normalen!!!! + + number angleEdges = std::acos( cosBetweenEdges ); + number angleNormls = std::acos( cosBetweenNormals ); + + totAnglsEdg += angleEdges; + totAnglsNrm += angleNormls; + + UG_LOG("cosinus Edges Normals " << cosBetweenEdges << " " << cosBetweenNormals << std::endl); + UG_LOG("angles edges normals " << angleEdges << " " << angleNormls << std::endl); + + // prject normal 1 onto edge 2 and normal 2 on edge 1, scale with width one half resp with width two half + + + number cosBetweenNrmFraOneEdgTwo = VecDot(normalFracOne,nrmdVecEdgTwo); + number cosBetweenNrmFraTwoEdgOne = VecDot(normalFracTwo,nrmdVecEdgOne); + + vector3 projectNrmFraOneToEdgTwoDirection; + VecScale(projectNrmFraOneToEdgTwoDirection, nrmdVecEdgTwo, 1./cosBetweenNrmFraOneEdgTwo); + + vector3 projectNrmFraTwoToEdgOneDirection; + VecScale(projectNrmFraTwoToEdgOneDirection, nrmdVecEdgOne, 1./cosBetweenNrmFraTwoEdgOne); + + // auto subsIndFracOne = sh.get_subset_index(edgeFracOne); + // auto subsIndFracTwo = sh.get_subset_index(edgeFracTwo); + + number shiftOne = fracInfosBySubset.at( subsIndFracOne ).width / 2. ; + number shiftTwo = fracInfosBySubset.at( subsIndFracTwo ).width / 2. ; + + vector3 shiftAlongEdgeTwo; + VecScale(shiftAlongEdgeTwo, projectNrmFraOneToEdgTwoDirection, shiftOne); + + vector3 shiftAlongEdgeOne; + VecScale(shiftAlongEdgeOne, projectNrmFraTwoToEdgOneDirection, shiftTwo); + + vector3 shiftPart; + VecAdd(shiftPart, fracVrtPos, shiftAlongEdgeTwo); + + vector3 posNewVrt; + VecAdd( posNewVrt, shiftPart, shiftAlongEdgeOne); + + UG_LOG("neuer Vertex Kreuzung " << posNewVrt << std::endl ); + + Vertex * newShiftVrtx = *grid.create(); + aaPos[newShiftVrtx] = posNewVrt; + + // sh.assign_subset(newShiftVrtx, newSubsToAdd ); + sh.assign_subset(newShiftVrtx, subsIndFracOne ); + // could also be two, but have to select one, no Kompromiss possible...... + + crossVrtInf.addShiftVrtx(newShiftVrtx); + + // UG_LOG("ADDED SHIFT VECTOR " << aaPos[newShiftVrtx] << std::endl); + + // TODO FIXME eigene Funktion, da bei 2 und 3 Klüften exakt dieselbe Routine, mit copy und paste übernommen worden + + for( VertexOfFaceInfo const & vertFracInfoSeg : segPart ) + { + Face * fac = vertFracInfoSeg.getFace(); + + // sh.assign_subset(fa,newSubsToAdd); + + + // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden! + vector& newVrts4Fac = aaVrtVecFace[ fac ]; + + IndexType vrtxFnd = 0; + + for(size_t indVrt = 0; indVrt < (fac)->num_vertices(); indVrt++ ) + { + Vertex* facVrt = (fac)->vertex(indVrt); + + if( facVrt == *iterV ) + { + newVrts4Fac[ indVrt ] = newShiftVrtx; + vrtxFnd++; + + // crossVrtInf.addShiftVrtx(newShiftVrtx); + // + // UG_LOG("ADDED SHIFT VECTOR " << aaPos[newShiftVrtx] << std::endl); + + } + } + + // crossVrtInf.setShiftVrtx(newVrts4Fac); + + if( vrtxFnd <= 0 ) + { + UG_THROW("vertex not found kreuzung!" << std::endl); + } + else if( vrtxFnd > 1 ) + { + UG_THROW("vertex zu oft gefunden kreuzung " << vrtxFnd << std::endl ); + } + else if ( vrtxFnd == 1 ) + { + } + else + { + UG_THROW("vertex finden komisch kreuzung " << std::endl); + } + + } + } + } + else // angle dependent, new method + { + if( subsIndFracOne == subsIndFracTwo ) + { + // if( numFracsCrossAtVrt != 3 ) + if( numFracsCrossAtVrt != 2 && numFracsCrossAtVrt != 3 ) + { + // UG_THROW("Fracture Segment an beiden Seiten gleiche sudo, aber keine T Kreuzung?" << std::endl); + UG_THROW("Fracture Segment an beiden Seiten gleiche sudo, aber keine durchgehende Kluft?" << std::endl); + } + } + + if( subsIndFracOne != subsIndFracTwo && numFracsCrossAtVrt == 2 ) + { + UG_THROW("subsets passen nicht Vereinheitlichung" << std::endl ); + } + + vector3 moveVrt; + + number pi = 3.1415926535897932385; + + number cosinusLim = std::cos( pi/8. ); + + vector3 posNewVrt; + + if( cosBetweenNormals > cosinusLim ) + { + // dieselben Methoden wie im Fall von einer durchgehenden Kluft an einem Vertex, dort kopieren + // bzw Funktion schreiben, die beides macht + + // hier wird der Fall abgezweigt, dass wir auf der durchgehenden Seite einer Kluft sind + // wenn wir eine T-Kreuzung haben + + std::vector nextFracVrt; + + IndexType foundThisVrtOne = 0; + + for( size_t i = 0; i < 2; ++i ) + { + Vertex * vrtEdgEnd = edgeFracOne->vertex(i); + + if( vrtEdgEnd == *iterV ) + { + foundThisVrtOne++; + } + else + { + nextFracVrt.push_back( vrtEdgEnd ); + } + + } + + if( foundThisVrtOne != 1 ) + { + UG_THROW("zu viel zu wenig vertizex one " << std::endl); + } + + + IndexType foundThisVrtTwo = 0; + + for( size_t i = 0; i < 2; ++i ) + { + Vertex * vrtEdgEnd = edgeFracTwo->vertex(i); + + if( vrtEdgEnd == *iterV ) + { + foundThisVrtTwo++; + } + else + { + nextFracVrt.push_back( vrtEdgEnd ); + } + + } + + if( foundThisVrtTwo != 1 ) + { + UG_THROW("zu viel zu wenig vertizex two " << std::endl); + } + + Face * faceBegin = vFISBegin.getFace(); + Face * faceEnd = vFISEnd.getFace(); + + + vector3 normSum; + + VecAdd( normSum, normalFracOne, normalFracTwo ); + + vector3 normSumNormed; + + VecNormalize(normSumNormed, normSum); + + UG_LOG("averaged normal " << normSumNormed << std::endl); + + std::vector attEdg; + std::vector attFac; + + attEdg.push_back( edgeFracOne ); + attEdg.push_back( edgeFracTwo ); + + attFac.push_back( faceBegin ); + attFac.push_back( faceEnd ); + + // jetzt neuen Vertex erzeugen in Richtung der Normalen + // sonst ist das attachment Schwachsinn! + + number widthOne = fracInfosBySubset.at(subsIndFracOne).width; + number widthTwo = fracInfosBySubset.at(subsIndFracTwo).width; + + number width = ( widthOne + widthTwo ) /2.; + + // FALSCH + // der Faktor ist Käse und muss noch aus den Eingaben übernommen werden + VecScale(moveVrt, normSumNormed, width/2. ); + +// vector3 posNewVrt; + + VecAdd(posNewVrt, posOldVrt, moveVrt ); + + UG_LOG("neuer Vertex " << posNewVrt << std::endl ); + + // TODO FIXME hier ist das PROBLEM, SEGFAULT durch create regular vertex + + } + else + { + // create normal vectors into direction of relevant edges + + vector3 alongEdgeOne; + vector3 alongEdgeTwo; + + Vertex * vrtEdgeOneBegin = nullptr; + Vertex * vrtEdgeTwoBegin = nullptr; + Vertex * vrtEdgeOneEnd = nullptr; + Vertex * vrtEdgeTwoEnd = nullptr; + + + for( size_t i = 0; i < 2; ++i ) + { + Vertex * vrtFromEdgeOne = edgeFracOne->vertex(i); + Vertex * vrtFromEdgeTwo = edgeFracTwo->vertex(i); + + if( vrtFromEdgeOne == *iterV ) + { + vrtEdgeOneBegin = vrtFromEdgeOne; + } + else + { + vrtEdgeOneEnd = vrtFromEdgeOne; + } + + if( vrtFromEdgeTwo == *iterV ) + { + vrtEdgeTwoBegin = vrtFromEdgeTwo; + } + else + { + vrtEdgeTwoEnd = vrtFromEdgeTwo; + } + + } + + if( vrtEdgeOneBegin == NULL || vrtEdgeTwoBegin == NULL || vrtEdgeOneEnd == NULL || vrtEdgeTwoEnd == NULL ) + { + UG_THROW("lauter Nullen vertizes" << std::endl); + } + + vector3 fracVrtPos = aaPos[*iterV]; + + vector3 fracEdgOneEndPos = aaPos[ vrtEdgeOneEnd ]; + vector3 fracEdgTwoEndPos = aaPos[ vrtEdgeTwoEnd ]; + + vector3 directionEdgOne; + VecSubtract(directionEdgOne, fracEdgOneEndPos, fracVrtPos); + + vector3 directionEdgTwo; + VecSubtract(directionEdgTwo, fracEdgTwoEndPos, fracVrtPos); + + vector3 nrmdVecEdgOne; + VecNormalize(nrmdVecEdgOne, directionEdgOne); + + vector3 nrmdVecEdgTwo; + VecNormalize(nrmdVecEdgTwo, directionEdgTwo); + + number cosBetweenEdges = VecDot(nrmdVecEdgOne,nrmdVecEdgTwo); + + // TODO FIXME wenn Winkel zu klein, dann die Methode verwenden der Mittelung der beiden Normalen!!!! + + number angleEdges = std::acos( cosBetweenEdges ); + number angleNormls = std::acos( cosBetweenNormals ); + + totAnglsEdg += angleEdges; + totAnglsNrm += angleNormls; + + UG_LOG("cosinus Edges Normals " << cosBetweenEdges << " " << cosBetweenNormals << std::endl); + UG_LOG("angles edges normals " << angleEdges << " " << angleNormls << std::endl); + + // prject normal 1 onto edge 2 and normal 2 on edge 1, scale with width one half resp with width two half + + + number cosBetweenNrmFraOneEdgTwo = VecDot(normalFracOne,nrmdVecEdgTwo); + number cosBetweenNrmFraTwoEdgOne = VecDot(normalFracTwo,nrmdVecEdgOne); + + vector3 projectNrmFraOneToEdgTwoDirection; + VecScale(projectNrmFraOneToEdgTwoDirection, nrmdVecEdgTwo, 1./cosBetweenNrmFraOneEdgTwo); + + vector3 projectNrmFraTwoToEdgOneDirection; + VecScale(projectNrmFraTwoToEdgOneDirection, nrmdVecEdgOne, 1./cosBetweenNrmFraTwoEdgOne); + + // auto subsIndFracOne = sh.get_subset_index(edgeFracOne); + // auto subsIndFracTwo = sh.get_subset_index(edgeFracTwo); + + number shiftOne = fracInfosBySubset.at( subsIndFracOne ).width / 2. ; + number shiftTwo = fracInfosBySubset.at( subsIndFracTwo ).width / 2. ; + + vector3 shiftAlongEdgeTwo; + VecScale(shiftAlongEdgeTwo, projectNrmFraOneToEdgTwoDirection, shiftOne); + + vector3 shiftAlongEdgeOne; + VecScale(shiftAlongEdgeOne, projectNrmFraTwoToEdgOneDirection, shiftTwo); + + vector3 shiftPart; + VecAdd(shiftPart, fracVrtPos, shiftAlongEdgeTwo); + +// vector3 posNewVrt; + VecAdd( posNewVrt, shiftPart, shiftAlongEdgeOne); + + UG_LOG("neuer Vertex Kreuzung " << posNewVrt << std::endl ); + } + + Vertex * newShiftVrtx = *grid.create(); + aaPos[newShiftVrtx] = posNewVrt; + + sh.assign_subset(newShiftVrtx, subsIndFracOne ); + + + if( numFracsCrossAtVrt > 2 ) + { + bool isAtFreeTEnd = false; + + if( numFracsCrossAtVrt == 3 && subsIndFracOne == subsIndFracTwo ) + isAtFreeTEnd = true; + + crossVrtInf.addShiftVrtx(newShiftVrtx, isAtFreeTEnd ); + } + +#if 1 + teachAssoFacesNewVrtx( segPart, aaVrtVecFace, *iterV, newShiftVrtx ); + +#else + for( VertexOfFaceInfo const & vertFracInfoSeg : segPart ) + { + Face * fac = vertFracInfoSeg.getFace(); + + // sh.assign_subset(fa,newSubsToAdd); + + // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu SR! nicht später falsche verwenden! + vector& newVrts4Fac = aaVrtVecFace[ fac ]; + + IndexType vrtxFnd = 0; + + for(size_t indVrt = 0; indVrt < (fac)->num_vertices(); indVrt++ ) + { + Vertex* facVrt = (fac)->vertex(indVrt); + + if( facVrt == *iterV ) + { + newVrts4Fac[ indVrt ] = newShiftVrtx; + vrtxFnd++; + +// UG_LOG("ADDED SHIFT VECTOR " << aaPos[newShiftVrtx] << std::endl); + + } + } + + if( vrtxFnd <= 0 ) + { + UG_THROW("vertex not found kreuzung!" << std::endl); + } + else if( vrtxFnd > 1 ) + { + UG_THROW("vertex zu oft gefunden kreuzung " << vrtxFnd << std::endl ); + } + else if ( vrtxFnd == 1 ) + { + } + else + { + UG_THROW("vertex finden komisch kreuzung " << std::endl); + } + + } +#endif + } + + } + + UG_LOG("sum angles edges normals " << totAnglsEdg << " " << totAnglsNrm << std::endl); + +// return true; + +#if 0 + // das folgende ist vermutlich Unsinn TODO FIXME, waren wohl Versuche am Anfang..... nochmal prüfen!!!! + + // get starting point of the "rotation" around the vertex where fractures are crossing +// for( auto & attVFT : vVFT ) // not const, as we need to erase found elements! + for( VecVertFracTrip::iterator itAttVFT = vVFT.begin(); itAttVFT != vVFT.end(); ) + { + Face * facAtVrtWithFrac = itAttVFT->getFace(); + + bool facFound = false; + +// for( auto const & ifac : assoFaces ) // not const, as we need to erase found elements! + for( std::vector::iterator itFac = aF.begin(); itFac != aF.end(); ) + { + if( *itFac == facAtVrtWithFrac ) + { + // found a starting face + // copy first the found info, then delete the original one + auto attVFTCop = *itAttVFT; // copy, not reference! + + vVFT.erase(itAttVFT); + aF.erase(itFac); + + // TODO FIXME erase ifac and attVFT, how to do? + + Face * startFace = facAtVrtWithFrac; + + // now determine the common edge(s), the first edge of the vector must be a frac edge, the second one might be one + + Edge * startEdg = attVFTCop.getEdge(); + + // unnecessary check, but for test purposes at beginning, later should be removed + if( !FaceContains(facAtVrtWithFrac, startEdg )) + { + UG_THROW("face hat ecke nicht, die es haben soll" << std::endl); + } + + // loop around the edges of the ifac face attached to the vertex + + // determin second edge of the startFace, not stored in the vecVertFracTrip information + // check number of common edges containing the same vertex + + IndexType fndCommEdg = 0; + std::vector assoEdg2Fac; + + assoEdg2Fac.push_back( startEdg ); + + std::vector assoNorm; + + vector3 norm2Frac = attVFTCop.getNormal(); + + Edge * secondEdge; + secondEdge = NULL; + + for( auto const & iE : allAssoEdges ) // werden nicht gelöscht, deswegen Zugriff auf attachment direkt + { + if( FaceContains(facAtVrtWithFrac, iE) ) + { + fndCommEdg++; + if( iE != startEdg ) + { + secondEdge = iE; + } + } + + if( fndCommEdg != 2 ) + { + UG_THROW("komische Anzahl gemeinsamer Ecke " << fndCommEdg << std::endl); + } + + if( secondEdge == NULL ) + { + UG_THROW("wieso keine zweite Ecke gefunden???? " << std::endl); + } + + assoEdg2Fac.push_back(secondEdge); + + // check, if second edge belongs to anothter fracture fac, i.e. if it is also a fracture edge + + // check if second edge is edge of a fracture face, i.e. either this edge, or another one is from a fracture + + bool scndEdgIsFracEdg = aaMarkEdgeB[secondEdge]; + + if( scndEdgIsFracEdg ) + { + // TODO FIXME figure out second vertex fracture info, in this case, we have found the next part of the chain! + + for( VecVertFracTrip::iterator itAttVFTTwo = vVFT.begin(); itAttVFTTwo != vVFT.end(); ) + { + // need to erase also this element soon, also in the list of all attached elements + + Face* vFTTwoFac = itAttVFTTwo->getFace(); + + if( FaceContains( vFTTwoFac, secondEdge)) + { + auto vVFT2 = *itAttVFTTwo; + vVFT.erase( itAttVFTTwo ); + + Face * nextFace = vFTTwoFac; + + if( secondEdge != vVFT2.getEdge() ) + { + UG_THROW("Ecke nicht Ecke " << std::endl); + } + + + } + } + } + else // find the next attached face, either from the + { + + } + } + + break; + } + + if( ! facFound ) + { + UG_THROW("Gesicht unauffindbar" << std::endl); + } + + break; + } + } + + while( vVFT.size() != 0 ) + { + while( aF.size() != 0 ) + { + + } + } + +#endif + +// if( numFracsCrossAtVrt == 3 ) +// { +// teeVrts.push_back(*iterV); +// } +// else if( numFracsCrossAtVrt == 4 ) +// { +// crossVrts.push_back(*iterV); +// } + + IndexType groesseShiVe = crossVrtInf.getVecShiftedVrts().size(); + + auto gro = groesseShiVe; + + UG_LOG("GROESSE SHIFT VECTORS " << gro << std::endl); + + vecCrossVrtInf.push_back(crossVrtInf); + + } + + } +// // // different treatment for boundary vertizes + else + { + + // es muss wohl noch ein Problem mit den Verschiebungen bei boundary Vertizes geben..... + + + if( numFracsCrossAtVrt < 1 ) + { + UG_THROW("no fracs crossing but marked vertex at boundary? << std::endl"); + } + else if( numFracsCrossAtVrt == 1 ) // no crossing point at boundary + { + // in this case, we have ONE attached edges, the edges has two attached faces + // the faces have a normal, and based on the normal, we can decide which faces belong to the same side of the edges + + if( numbAttTripl != 2 ) + { + UG_THROW("Anzahl der angehaengten Triples kann nicht stimmen, Vertex einer Kluft ohne Schnittpunkte am Rand " << std::endl); + } + + VecVertexOfFaceInfo orderedFaces; + SegmentsFractExtrus segments; + //VecVertexOfFaceInfo segmentPart; + + // Zuordnung der Edges und Faces, die auf der gleichen Seite der fracture sind + + // und gleich auch Erzeugung der neuen Knoten, die dann + // in einem Doublett zusammen mit ihren Normalen an die alten Vertizes + // angehängt werden; der Winkel zur Normalen hilft später, die Seite + // heraus zu finden, Seite von den Edges + + // get edges adjacent to this vertex which lie on the boundary of the domain + + std::vector adjBndEdgs; + +// std::vector & allAssoEdges = aaVrtInfoAssoEdges[*iterV]; + +// for( std::vector::iterator iterBVEdg = grid.associated_edges_begin(*iterV); iterBVEdg != grid.associated_edges_end(*iterV); iterBVEdg++ ) +// { +// if( IsBoundaryEdge2D(grid,*iterBVEdg) ) +// { +// adjBndEdgs.push_back( *iterBVEdg ); +// } +// } + for( auto const & iBVE : allAssoEdges ) + { + if( IsBoundaryEdge2D(grid, iBVE ) ) + { + adjBndEdgs.push_back( iBVE ); + } + } + + if( adjBndEdgs.size() != 2 ) + UG_THROW("how many boundary edges????" << std::endl); + + IndexType startInd = -1; // to avoid errornous use + + Face * attFaceOf1stBndEdg = nullptr; // TODO FIXME bestimmen sofort!!! + + Edge * begOrdEdg = adjBndEdgs[0]; + + IndexType fndBndFac = 0; + + for( std::vector::iterator itFa = grid.associated_faces_begin(begOrdEdg); + itFa < grid.associated_faces_end(begOrdEdg); + itFa++ ) + { + attFaceOf1stBndEdg = *itFa; + fndBndFac++; + } + + if( fndBndFac != 1 || attFaceOf1stBndEdg == nullptr ) + { + UG_THROW("Grenzgesicht nicht gefunden " << fndBndFac << std::endl); + } + + determineOrderOfFaces( vecVertFracTrip, assoFaces, orderedFaces, + segments, //segmentPart, + startInd, + allAssoEdges, + sh, + aaMarkEdgeB, + adjBndEdgs, + attFaceOf1stBndEdg + ); + +// for( auto const & segPart : segments ) +// { +// for( auto const & vi : segPart ) +// { +// Face * fac = vi.getFace(); +// +// IndexType sudoNew = sh.num_subsets(); +// +// sh.assign_subset(fac, sudoNew); +// } +// } +// +// return true; + + // to compute the normals, compute the vector of the edge and normalize it + std::vector bndEdgeDirection; + + for( auto const & bE : adjBndEdgs ) + { + + // get vertices, i.e. get seocnd vertex, first one must be known + +// std::vector verticesEdg; + + static_assert( std::is_same< Edge* const &, decltype( bE ) >::value ); + + static_assert( std::is_same< Vertex*, decltype( bE->vertex(0) ) >::value ); + + IndexType fndIV = 0; + + Vertex * vrtOtherEdg; + vrtOtherEdg = NULL; + + for( size_t i = 0; i < 2; ++i ) + { +// verticesEdg.push_back( adjBndEdgs.vertex(i) ); + + Vertex * vrtOfEdg = bE->vertex(i); + + if( vrtOfEdg == *iterV ) + { + fndIV++; + } + else + { + vrtOtherEdg = vrtOfEdg; + } + } + + vector3 posOtherVrt = aaPos[vrtOtherEdg]; + + UG_LOG("BOUNDARY EDGE VERTIZES " << posOldVrt << ", " << posOtherVrt << std::endl); + + vector3 fromIterV2Other; + + VecSubtract(fromIterV2Other, posOtherVrt, posOldVrt); + + vector3 nV; + + VecNormalize(nV, fromIterV2Other); + + bndEdgeDirection.push_back(nV); + } + + + constexpr bool useOldBndryOdering = false; + + if( useOldBndryOdering ) + { + +#if WORKAROUND_ARTE_SEGFAULT + + IndexType dbg_lim = vecVertFracTrip.size(); + + int dbg_cnt = 0; +#endif + + // TODO FIXME HHHHHHHHH hier die Sortierungsroutine einbauen, um die attachten faces sicher richtig zu zu ordnen!!! + + for( VvftIterator vvftAtBnd = vecVertFracTrip.begin(); + vvftAtBnd != vecVertFracTrip.end(); + vvftAtBnd++ + ) + { +#if WORKAROUND_ARTE_SEGFAULT + + if( dbg_lim == dbg_cnt ) + { + UG_LOG("DARF NICHT SEIN" << std::endl); + break; + } + + dbg_cnt++; +#endif + + // Ziel: den parallelen Anteil der Normalen auf die jeweilige Randkante projizieren + + vector3 nrmEdg = vvftAtBnd->getNormal(); + + Edge * edgeOfFrac = vvftAtBnd->getEdge(); + + // figure out the adjoint boundary edge into the same direction + + // the normal in both directions have to be compared with the vectors in direction of boundary edges + for( auto bED : bndEdgeDirection ) + { + // check orientation of boundary edges wrt the normals + + number cosinus = VecDot( nrmEdg, bED ); + + UG_LOG("BOUNDARY COSINUS between " << nrmEdg << " and " << bED << " -> " << cosinus << std::endl); + + if( cosinus > 0 ) + { + // gleiche Seite vermutet + + // muessen wissen, wie lange das gestreckt werden soll + + vector3 alongEdgV; + + auto subsIndEdgOF = sh.get_subset_index(edgeOfFrac); + + number width = fracInfosBySubset.at(subsIndEdgOF).width; + + number scal = width / 2. / cosinus; + + VecScale( alongEdgV, bED, scal ); + + vector3 posNewVrtOnBnd; + + VecAdd(posNewVrtOnBnd, posOldVrt, alongEdgV ); + + UG_LOG("neuer Vertex Edge " << posNewVrtOnBnd << std::endl ); + + Vertex * newShiftEdgVrtx = *grid.create(); + aaPos[newShiftEdgVrtx] = posNewVrtOnBnd; + + sh.assign_subset(newShiftEdgVrtx, subsIndEdgOF ); + + std::vector attEdg; + std::vector attFac; + + attEdg.push_back(edgeOfFrac); + + Face * facFrac = vvftAtBnd->getFace(); + + attFac.push_back( facFrac ); + + // we store the boundary edge direction for boundary verzizes rather than the normal, in contrast to inner vertizes, where we store the averaged normal + ExpandVertexMultiplett vrtMtpl( attEdg, attFac, bED ); + + aaVrtExpMP[ *iterV ].push_back( vrtMtpl ); + +#if 0 + // the attached faces need to know that they need a new vertex to be shifted + for( std::vector::iterator iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ ) + { + bool isFromFrac = false; + + for( auto const & facFrac : attFac ) + { + if( *iterFac == facFrac ) + { + isFromFrac = true; + } + } + + bool atRightSide = false; + + if( isFromFrac ) + atRightSide = true; + + if( !isFromFrac ) + { + + // check if on same side of edge where the normal points to: compute cosinus between vector of face center + // perpendicular to the edge + // TODO FIXME + + vector3 facCenter = CalculateCenter( *iterFac, aaPos ); + + vector3 perpendicu; + + DropAPerpendicular(perpendicu, facCenter, aaPos[edgeOfFrac->vertex(0)], aaPos[edgeOfFrac->vertex(1)]); + + vector3 tmpN; + + VecSubtract(tmpN, facCenter, perpendicu ); + + VecNormalize(tmpN, tmpN); + + UG_LOG("Normale Boundary zum Face ist " << tmpN << std::endl); + + number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, nrmEdg ); + + UG_LOG("Cosinus Boundary zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); + + if( cosBetwFracEdgAndDirection2Face > 0 ) + { + UG_LOG("assuming boundary face to be on richt side" << std::endl); + + atRightSide = true; + +#if ESTABLISH_DEBUG_SUDOS + Vertex * otherFacCent = *grid.create(); + aaPos[otherFacCent] = facCenter; + sh.assign_subset(otherFacCent, 5 ); + + Vertex * pp = *grid.create(); + aaPos[pp] = perpendicu; + sh.assign_subset(pp, 6 ); + + sh.assign_subset(*iterFac,7); +#endif + + + } + else + { + UG_LOG("assuming boundary face to be on wrong side" << std::endl); + } + + } + + if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein + { + + + vector& newVrts4Fac = aaVrtVecFace[ * iterFac ]; + + IndexType vrtxFnd = 0; + + for(size_t indVrt = 0; indVrt < (*iterFac)->num_vertices(); indVrt++ ) + { + Vertex* facVrt = (*iterFac)->vertex(indVrt); + + if( facVrt == *iterV ) + { + newVrts4Fac[ indVrt ] = newShiftEdgVrtx; + vrtxFnd++; + } + } + + + + if( vrtxFnd <= 0 ) + { + UG_THROW("vertex not found bnd!" << std::endl); + } + else if( vrtxFnd > 1 ) + { + UG_THROW("vertex zu oft gefunden bnd " << vrtxFnd << std::endl ); + } + else if ( vrtxFnd == 1 ) + { + // UG_LOG("vertex found abgeschlossen" << std::endl); + } + else + { + UG_THROW("vertex finden bnd komisch " << std::endl); + } + } + + } +#else + + // TODO FIXME HHHHHHHHH hier die Sortierungsroutine einbauen, um die attachten faces sicher richtig zu zu ordnen!!! + + for( auto const & ifac : assoFaces ) + { + bool isFromFrac = false; + + for( auto const & facFrac : attFac ) + { + if( ifac == facFrac ) + { + isFromFrac = true; + } + } + + bool atRightSide = false; + + if( isFromFrac ) + atRightSide = true; + + if( !isFromFrac ) + { + + // check if on same side of edge where the normal points to: compute cosinus between vector of face center + // perpendicular to the edge + // TODO FIXME + + vector3 facCenter = CalculateCenter( ifac, aaPos ); + + vector3 perpendicu; + + DropAPerpendicular(perpendicu, facCenter, aaPos[edgeOfFrac->vertex(0)], aaPos[edgeOfFrac->vertex(1)]); + + vector3 tmpN; + + VecSubtract(tmpN, facCenter, perpendicu ); + + VecNormalize(tmpN, tmpN); + + UG_LOG("Normale Boundary zum Face ist " << tmpN << std::endl); + + number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, nrmEdg ); + + UG_LOG("Cosinus Boundary zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl); + + if( cosBetwFracEdgAndDirection2Face > 0 ) + { + UG_LOG("assuming boundary face to be on richt side" << std::endl); + + atRightSide = true; + +#if ESTABLISH_DEBUG_SUDOS + + // IndexType suNu = sh.num_subsets(); + + Vertex * otherFacCent = *grid.create(); + aaPos[otherFacCent] = facCenter; + sh.assign_subset(otherFacCent, sh.num_subsets() ); + // sh.assign_subset(otherFacCent, 5 ); + + Vertex * pp = *grid.create(); + aaPos[pp] = perpendicu; + // sh.assign_subset(pp, 6 ); + sh.assign_subset(pp, sh.num_subsets() ); + + // sh.assign_subset(*iterFac,7); + sh.assign_subset(*iterFac, sh.num_subsets() ); +#endif + + + } + else + { + UG_LOG("assuming boundary face to be on wrong side" << std::endl); + } + + } + + if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein + { + + + vector& newVrts4Fac = aaVrtVecFace[ ifac ]; + + IndexType vrtxFnd = 0; + + for(size_t indVrt = 0; indVrt < (ifac)->num_vertices(); indVrt++ ) + { + Vertex* facVrt = (ifac)->vertex(indVrt); + + if( facVrt == *iterV ) + { + newVrts4Fac[ indVrt ] = newShiftEdgVrtx; + vrtxFnd++; + } + } + + + + if( vrtxFnd <= 0 ) + { + UG_THROW("vertex not found bnd!" << std::endl); + } + else if( vrtxFnd > 1 ) + { + UG_THROW("vertex zu oft gefunden bnd " << vrtxFnd << std::endl ); + } + else if ( vrtxFnd == 1 ) + { + // UG_LOG("vertex found abgeschlossen" << std::endl); + } + else + { + UG_THROW("vertex finden bnd komisch " << std::endl); + } + } + } + +#endif + } + } + } + } + else // sicher ordnungsbasiertes Arbeiten + { + + IndexType numbSegments = segments.size(); + + if( numbSegments != 2 ) + UG_THROW("only two segments possible at boundary as long as only one ending fracture " << std::endl;) + + bool beforeFrac = true; + + IndexType segInd = 0; + + // TODO FIXME ausfuellen + for( VecVertexOfFaceInfo const & segPart : segments ) + { + + IndexType numbTriangs = segPart.size(); + + VertexOfFaceInfo const & vFISBegin = segPart[0]; + VertexOfFaceInfo const & vFISEnd = segPart[numbTriangs-1]; + + Face * fracFace = vFISEnd.getFace(); + + std::pair edgesBegin = vFISBegin.getEdge(); + std::pair edgesEnd = vFISEnd.getEdge(); + + std::pair normalBegin = vFISBegin.getNormal(); + std::pair normalEnd = vFISEnd.getNormal(); + + Edge* edgeBnd = edgesBegin.first; + Edge* edgeFrac = edgesEnd.second; + + vector3 normalBnd = normalBegin.first; + vector3 normalFrac = normalEnd.second; + + if( ! beforeFrac ) + { + fracFace = vFISBegin.getFace(); + + edgeBnd = edgesEnd.second; + edgeFrac = edgesBegin.first; + + normalBnd = normalEnd.second; + normalFrac = normalBegin.first; + } + + if( edgeBnd != adjBndEdgs[segInd] ) + UG_THROW("Boundary edge does not fit " << segInd << std::endl); + +// auto const & vft = vecVertFracTrip[segInd]; +// +// if( normalFrac != vft.getNormal()) +// UG_THROW("Normale nicht gegeben " << segInd << std::endl); +// +// if( edgeFrac != vft.getEdge() ) +// UG_THROW("Kante nicht bekannt " << segInd << std::endl); +// +// if( fracFace != vft.getFace() ) +// UG_THROW("Gesicht nicht bekannt " << segInd << std::endl); + + // check if belonging to one vertFracTrip of bnd vrtx + + IndexType fndNormal = 0; + IndexType fndEdge = 0; + IndexType fndFace = 0; + + for( auto const & vft : vecVertFracTrip ) + { + if( vft.getNormal() == normalFrac ) + fndNormal++; + + if( vft.getEdge() == edgeFrac ) + fndEdge++; + + if( vft.getFace() == fracFace ) + fndFace++; + } + + if( fndNormal != 1 || fndEdge != 2 || fndFace != 1 ) + UG_THROW("Findungen komisch " << fndNormal << " " << fndEdge << " " << fndFace << std::endl); + + auto subsIndFrac = sh.get_subset_index(edgeFrac); + + // neue Punkte erzeugen + + auto & bED = bndEdgeDirection[segInd]; + + static_assert( std::is_same< decltype( bED), vector3 & >::value ); + + vector3 & nrmEdg = normalFrac; //normalBnd; + + Edge * edgeOfFrac = edgeFrac; + + number cosinus = VecDot( nrmEdg, bED ); + + UG_LOG("BOUNDARY COSINUS between " << nrmEdg << " and " << bED << " -> " << cosinus << std::endl); + + if( cosinus < 0 ) + { + // andere Seite vermutet + + UG_THROW("check if really on same side " << std::endl); + } + + // gleiche Seite muss es sein + + // muessen wissen, wie lange das gestreckt werden soll + + vector3 alongEdgV; + + auto subsIndEdgOF = sh.get_subset_index(edgeOfFrac); + + number width = fracInfosBySubset.at(subsIndEdgOF).width; + + number scal = width / 2. / cosinus; + + VecScale( alongEdgV, bED, scal ); + + vector3 posNewVrtOnBnd; + + VecAdd(posNewVrtOnBnd, posOldVrt, alongEdgV ); + + UG_LOG("neuer Vertex Edge " << posNewVrtOnBnd << std::endl ); + + Vertex * newShiftEdgVrtx = *grid.create(); + aaPos[newShiftEdgVrtx] = posNewVrtOnBnd; + + sh.assign_subset(newShiftEdgVrtx, subsIndEdgOF ); + + teachAssoFacesNewVrtx( segPart, aaVrtVecFace, *iterV, newShiftEdgVrtx ); + + segInd++; + + beforeFrac = ! beforeFrac; // more complicated eventual if more than one ending frac, but no topic so far + } + + } + +// return true; + + } + else // fractures are crossing at boundary even + { + UG_THROW("not implemented so far: multiple fractures crossing at boundary " << std::endl); + } + + + UG_LOG("END THIS BOUNDARY VERTEX" << std::endl); + } + + dbg_vertizesPassiert++; + + } + + +// // neue Vertizes in der Entfernung der Klüfte von den Klüften weg erzeugen, +// // basierend auf den Normalen multipliziert mit der halben Kluftdicke +// //für eine Kluft erstmal nur +// // die neuen Kanten und Faces erzeugen, die alten falschen Kanten löschen und ebenso die alten Faces +// // später auf mehr Klüfte ausdehnen, mit Problemstelle Kreuzung, aber erst, wenn eine Kluft funktioniert +// + +// return true; + + // jetzt Seb Sachen beinahe unverändert + + //////////////////////////////// + // create new elements + + // first we create new edges from selected ones which are connected to + // inner vertices. This allows to preserve old subsets. + // Since we have to make sure that we use the right vertices, + // we have to iterate over the selected faces and perform all actions on the edges + // of those faces. + for(FaceIterator iter_sf = sel.faces_begin(); iter_sf != sel.faces_end(); ++iter_sf) + { + Face* sf = *iter_sf; + // check for each edge whether it has to be copied. + for(size_t i_edge = 0; i_edge < sf->num_edges(); ++i_edge) + { + Edge* e = grid.get_edge(sf, i_edge); + + if(sel.is_selected(e)) + { + // check the associated vertices through the volumes aaVrtVecVol attachment. + // If at least one has an associated new vertex and if no edge between the + // new vertices already exists, we'll create the new edge. + size_t ind0 = i_edge; + size_t ind1 = (i_edge + 1) % sf->num_edges(); + + Vertex* nv0 = (aaVrtVecFace[sf])[ind0]; + Vertex* nv1 = (aaVrtVecFace[sf])[ind1]; + + if(nv0 || nv1) + { + // if one vertex has no associated new one, then we use the vertex itself + if(!nv0) + nv0 = sf->vertex(ind0); + if(!nv1) + nv1 = sf->vertex(ind1); + + // create the new edge if it not already exists. + if(!grid.get_edge(nv0, nv1)) + grid.create_by_cloning(e, EdgeDescriptor(nv0, nv1), e); + } + } + } + } + + + std::vector newFaces; + std::vector subsOfNewFaces; + + // iterate over all surrounding faces and create new vertices. + // Since faces are replaced on the fly, we have to take care with the iterator. + for(FaceIterator iter_sf = sel.faces_begin(); iter_sf != sel.faces_end();) + { + Face* sf = *iter_sf; + ++iter_sf; + + std::vector newVrts = aaVrtVecFace[sf]; + + // all new vertices have been assigned to newVrts. + // Note that if newVrts[i] == NULL, then we have to take the + // old vertex sf->vertex(i). + // now expand the fracture edges of sf to faces. + for(size_t i_vrt = 0; i_vrt < sf->num_vertices(); ++i_vrt) + { + size_t iv1 = i_vrt; + size_t iv2 = (i_vrt + 1) % sf->num_vertices(); + + Edge* tEdge = grid.get_edge(sf->vertex(iv1), sf->vertex(iv2)); + + if(tEdge) + { + if( aaMarkEdgeB[tEdge] ) + { + Face* expFace = NULL; + if(newVrts[iv1] && newVrts[iv2]) + { + // create a new quadrilateral + expFace = *grid.create( + QuadrilateralDescriptor(sf->vertex(iv1), sf->vertex(iv2), + newVrts[iv2], newVrts[iv1])); + } + else if(newVrts[iv1]) + { + // create a new triangle + expFace = *grid.create( + TriangleDescriptor(sf->vertex(iv1), sf->vertex(iv2), newVrts[iv1])); + } + else if(newVrts[iv2]) + { + // create a new triangle + expFace = *grid.create( + TriangleDescriptor(sf->vertex(iv1), sf->vertex(iv2), newVrts[iv2])); + } + else + { + +//// sh.assign_subset(*iter_sf,10); +//// sh.assign_subset(tEdge,11); +// +// return true; +// // this code-block should never be entered. If it is entered then +// // we selected the wrong faces. This is would be a BUG!!! +// // remove the temporary attachments and throw an error +// +// // remove the temporary attachments +//#if FORMER_PROMESH_FINITE_CLEFT_TECHNIQUE +// grid.detach_from_vertices(aAdjMarker); +// grid.detach_from_edges(aAdjMarker); +//#endif +// grid.detach_from_vertices(aAdjMarkerVFP); +// grid.detach_from_edges(aAdjMarkerB); +// +// grid.detach_from_vertices( aAdjInfoAVVFT ); +// grid.detach_from_faces(attVrtVec); +// +// grid.detach_from_vertices( aAdjInfoEdges ); +// grid.detach_from_vertices( aAdjInfoFaces ); +// +// +// // TODO FIXME auch die weiteren Marker und INfos, alle Attachments, detachen!!!! +// +// throw(UGError("Implementation error in ExpandFractures2d Arte.")); + } + + // TODO FIXME selektion closen irgendwie, damit auch alle Randkanten zum subset gehoeren!!! + + if( expFace ) + { + sh.assign_subset(expFace, fracInfosBySubset.at(sh.get_subset_index(tEdge)).newSubsetIndex); + + int subs = fracInfosBySubset.at(sh.get_subset_index(tEdge)).newSubsetIndex; + + subsOfNewFaces.push_back( subs ); + + newFaces.push_back( expFace ); + } + } + } + } + + + + + // now set up a new face descriptor and replace the face. + if(fd.num_vertices() != sf->num_vertices()) + fd.set_num_vertices(sf->num_vertices()); + + for(size_t i_vrt = 0; i_vrt < sf->num_vertices(); ++i_vrt) + { + if(newVrts[i_vrt]) + fd.set_vertex(i_vrt, newVrts[i_vrt]); + else + fd.set_vertex(i_vrt, sf->vertex(i_vrt)); + } + + grid.create_by_cloning(sf, fd, sf); + grid.erase(sf); + } + + // we have to clean up unused edges. + // All selected edges with mark 0 have to be deleted. + for(EdgeIterator iter = sel.edges_begin(); iter != sel.edges_end();) + { + // be careful with the iterator + Edge* e = *iter; + ++iter; + + if(!aaMarkEdgeB[e]) + grid.erase(e); + } + + if( subsOfNewFaces.size() != newFaces.size() ) + { + UG_THROW("andere zahl neue faces als subdoms " << std::endl); + } + + IndexType nfn = 0; + + for( auto const & nf : newFaces ) + { + for(size_t i_edge = 0; i_edge < nf->num_edges(); ++i_edge) + { + Edge* edg = grid.get_edge(nf, i_edge); + + sh.assign_subset( edg, subsOfNewFaces[nfn] ); + + } + + for( size_t iVrt = 0; iVrt < nf->num_vertices(); iVrt++ ) + { + Vertex * vrt = nf->vertex(iVrt); + + sh.assign_subset( vrt, subsOfNewFaces[nfn] ); + } + + nfn++; + } + + // sollen die Boundary Edges zur boundary gehören, oder zur Kluft? + // wie ist es mit den Knoten, sind die alle richtig zugewiesen bezüglich subset? + + // jetzt muss noch der Diamant erzeugt werden + // Ziel: KluftInnen erzeugen + + + // remove the temporary attachments + +#if FORMER_PROMESH_FINITE_CLEFT_TECHNIQUE + grid.detach_from_vertices(aAdjMarker); + grid.detach_from_edges(aAdjMarker); +#endif +// grid.detach_from_vertices(aAdjMarkerVFP); +// grid.detach_from_edges(aAdjMarkerB); +// +// grid.detach_from_vertices( aAdjInfoAVVFT ); +// grid.detach_from_faces(attVrtVec); +// +// grid.detach_from_vertices( aAdjInfoEdges ); +// grid.detach_from_vertices(aAdjInfoFaces ); + + + grid.detach_from_vertices(aAdjMarkerVFP ); + grid.detach_from_edges(aAdjMarkerB); + grid.detach_from_vertices( aAdjInfoAVVFT ); + grid.detach_from_vertices( aAdjInfoEdges ); + grid.detach_from_vertices( aAdjInfoFaces ); + grid.detach_from_faces(attVrtVec); + grid.detach_from_vertices( aAdjInfoVVEVM ); + +// sel.clear(); + +// return true; + + // alles detachen, was noch attached ist, da ist einiges hinzu gekommen! + + + // Keilstruktur entfernen und durch den gewünschten Diamanten ersetzen + + // new vertices which divide the fracture edges + +// AVertex aAdjVert; // used to know if an edge is frac edge and in the old faces +// grid.attach_to_edges_dv( aAdjVert, nullptr ); +// grid.attach_to_faces_dv( aAdjVert, nullptr ); +// Grid::EdgeAttachmentAccessor aaEdgeVert( grid, aAdjVert ); +// Grid::FaceAttachmentAccessor aaFaceVert( grid, aAdjVert ); + + for( auto const & cfi : vecCrossVrtInf ) + { + +// IndexType nuCroFra = cfi.getNumbCrossFracs(); + CrossVertInf::FracTyp fracTyp = cfi.getFracTyp(); + + if( fracTyp == CrossVertInf::SingleFrac ) + continue; + + Vertex * crossPt = cfi.getCrossVertex(); + + std::vector shiftVrtcs = cfi.getVecShiftedVrts(); + +// IndexType shiffsOrig = shiftVrtcs.size(); +// +// auto soc = shiffsOrig; + + VecEdge origFracEdg; // = cfi.getVecOrigFracEdges(); + + // all edges associated to the crossing point + VecEdge allAssoEdgCP; + + for( std::vector::iterator iterEdg = grid.associated_edges_begin(crossPt); iterEdg != grid.associated_edges_end(crossPt); iterEdg++ ) + { + + allAssoEdgCP.push_back(*iterEdg); + + bool hasShiftedVrtx = false; + + for( IndexType i = 0; i < 2; i++ ) + { + Vertex * side = (*iterEdg)->vertex(i); + + for( auto const & vrt : shiftVrtcs ) + { + if( side == vrt ) + hasShiftedVrtx = true; + } + + } + + if( ! hasShiftedVrtx ) + origFracEdg.push_back(*iterEdg); + } + + +// UG_LOG("Shift Vectors Orig " << soc << std::endl); + +// // aim: old cross vertex first, shift vertex second, new established vertex third +// using VrtxPair = std::pair; +// +// using DiamondVertexInfo = VertexFractureTriple; +// +// using VecDiamondVertexInfo = std::vector; +// +// VecDiamondVertexInfo vecDiamVrtInfo; + + // need to know the subsets of all faces! + std::vector subdomList; + + // all faces associated to the crossing point + std::vector assoFacCross; + + for( std::vector::iterator iterFac = grid.associated_faces_begin(crossPt); iterFac != grid.associated_faces_end(crossPt); iterFac++ ) + { + assoFacCross.push_back(*iterFac); + + bool sudoAlreadyThere = false; + + IndexType sudo = sh.get_subset_index(*iterFac); + + for( auto sl : subdomList ) + { + if( sl == sudo ) + sudoAlreadyThere = true; + } + + if( !sudoAlreadyThere ) + subdomList.push_back(sudo); + } + + if( subdomList.size() != 2 ) + UG_THROW("wieviele Subdoms um Kreuz herum? " << subdomList.size() << std::endl ); + + + // finales Ziel: alle neuen faces entfernen, die an den Schnittknoten anhängen + // ein Test noch + + for( auto const & afc : assoFacCross ) + { + // figure out respective original frac edge, need to know all edges and all vertices of this fracture + + // was sind die Ecken und Kanten dieses Faces? welche Ecke davon ist die originale Fracture edge? + // was ist die subdomain der originalen Fracture edge? klar das ist die subdomain des faces + + auto subdom = sh.get_subset_index(afc); + + bool subdomFnd = false; + + for( auto const & sd : subdomList ) + { + if( subdom == sd ) + subdomFnd = true; + } + + if( ! subdomFnd ) + UG_THROW("SUBDOM NOT found" << std::endl); + +// for( auto const & ) +// AssociatedEdgeIterator associated_edges_begin(Face* face);///< DO NOT INVOKE! Subject to change. +// AssociatedEdgeIterator associated_edges_end(Face* face);/// + +// std::vector edgesThisFac; +// +// for( std::vector::iterator iterEdgF = grid.associated_edges_begin(afc); +// iterEdgF != grid.associated_edges_end(afc); iterEdgF++ ) +// { +// edgesThisFac.push_back(*iterEdgF); +// } + + + } + +// // for( auto const & edg : origFracEdg ) +// for( auto edg : origFracEdg ) +// { +// +// static_assert( std::is_same< decltype( edg ), Edge * >::value ); +// // static_assert( std::is_same< const_cast(decltype( edg )), Edge * >::value ); +// +// // //Vertex* vrtSpliEd = +// // if( edg != nullptr ) +// // SplitEdge( grid, static_cast(edg) ); +// //// else +// //// UG_LOG("Nullptr getroffen " << std::endl); +// // +// //// size_t numSubs = sh.num_subsets(); +// //// +// //// sh.assign_subset(edg, numSubs ); +// // +// // //SplitEdge +// // +// // return true; +// +// } + + + + + // different Vorgehensweisen for T End and X Cross + +// using ExpandCrossFracInfo = VertexFractureTriple< std::pair, Face*, std::pair >; +// // Vertex nullptr wo original fracture, und shift vertex, wo Keilecke, die weg soll +// +// using VecExpandCrossFracInfo = std::vector; + + Edge * avoidToDeleteEdge = nullptr; + + VecExpandCrossFracInfo vecExpCrossFI; + + // if( nuCroFra == 3 ) + if( fracTyp == CrossVertInf::TEnd ) + { + + std::vector> shiftVertcsWithTI = cfi.getVecShiftedVrtsWithTypInfo(); + + // test if the vertex vector is the same as the vertex vector without info + + if( shiftVertcsWithTI.size() != shiftVrtcs.size() ) + UG_THROW("Unterschiedlich grosse shift vertices " << shiftVertcsWithTI.size() << " != " << shiftVrtcs.size() << std::endl); + + for( IndexType i = 0; i < shiftVertcsWithTI.size(); i++ ) + { + if( shiftVertcsWithTI[i].first != shiftVrtcs[i] ) + UG_THROW("komische Shift vertizes" << std::endl); + } + + // aim: sorting faces + auto assoFacTEndCop = assoFacCross; + + // figure out that shift vertex that is at the T End + + // start at defined face or edge + // start sorted faces at one of the faces which belong to the T End , i.e. that side where no fracture sorts + // figure out the corresponding index + + int indxFrcWithTE = -1; + IndexType indxFnd = 0; + IndexType startEdgeFnd = 0; + IndexType endEdgFnd = 0; + + IndexType cntr = 0; + + // muss sofort festgelegt werden - Startecke und zweite Ecke des gewählten faces + Edge * shiftVrtxAtFirstFacEdg = nullptr; + Edge * fracVrtxAtFirstFacEdg = nullptr; + + Vertex * shiftVrtxAtFreeEnd = nullptr; + + for( auto const & aft : assoFacTEndCop ) + { + for( auto const & svwi : shiftVertcsWithTI ) + { + if( svwi.second == true ) + { + + shiftVrtxAtFreeEnd = svwi.first; + +// if( FaceContains(aft, svwi.first ) ) + if( FaceContains(aft, shiftVrtxAtFreeEnd ) ) + { + indxFrcWithTE = cntr; + indxFnd++; + + for( std::vector::iterator iterEdgF = grid.associated_edges_begin(aft); + iterEdgF != grid.associated_edges_end(aft); iterEdgF++ ) + { + +// bool edgCntsShiVe = EdgeContains(*iterEdgF, svwi.first); + bool edgCntsShiVe = EdgeContains(*iterEdgF, shiftVrtxAtFreeEnd); + bool edgCntsCrsPt = EdgeContains(*iterEdgF,crossPt); + +// if( EdgeContains(*iterEdgF, svwi.first) && EdgeContains(*iterEdgF,crossPt) ) + if( edgCntsShiVe && edgCntsCrsPt ) + { + shiftVrtxAtFirstFacEdg = *iterEdgF; + startEdgeFnd++; + } + else if( edgCntsCrsPt && ! edgCntsShiVe ) + { + fracVrtxAtFirstFacEdg = *iterEdgF; + endEdgFnd++; + } + } + + } + } + } + + cntr++; + } + + // we hit twice, and finally take the second one, as we also want to count + + if( indxFrcWithTE < 0 || indxFrcWithTE >= assoFacTEndCop.size() ) + UG_THROW("Start nicht gefunden, freies Ende verloren " << std::endl); + + if( indxFnd != 2 || startEdgeFnd != 2 || endEdgFnd != 2 ) + UG_THROW("Index Free point or edge not found correct number " << indxFnd << " " << startEdgeFnd << " " << endEdgFnd << std::endl); + + Edge * firstEdgeFac = shiftVrtxAtFirstFacEdg; + Edge * secondEdgeFac = fracVrtxAtFirstFacEdg; + + if( firstEdgeFac == nullptr || secondEdgeFac == nullptr ) + UG_THROW("nullecke am Anfang?" << std::endl); + + Face * assoFacTEndConsider = assoFacTEndCop[ indxFrcWithTE ]; + + if( ! FaceContains(assoFacTEndConsider, firstEdgeFac )) + UG_THROW("Ecke verloren geangen T " << std::endl); + +// bool atStartSort = true; + + // already fixed in contrast to XCross case! + Edge * assoFacEdgBeg2Fix = firstEdgeFac; + + // soll erst ganz am Schluss festgelegt werden + Edge * assoFacEdgEnd2Fix = nullptr; + + if( ! SortFaces4DiamondCreation( sh, assoFacTEndCop, firstEdgeFac, secondEdgeFac, + assoFacTEndConsider, origFracEdg, shiftVrtcs, + crossPt, assoFacEdgBeg2Fix, assoFacEdgEnd2Fix, grid, vecExpCrossFI + , false + ) + ) + UG_THROW("Ordnen Diamant TEnd schief gegangen " << std::endl); + + UG_LOG("Kreis des Diamanten T End Fall geschlossen " << std::endl); + +// for( auto const & ecf : vecExpCrossFI ) +// { +// Face * fac = ecf.getFace(); +// +// IndexType sudos = sh.num_subsets(); +// +// sh.assign_subset(fac,sudos); +// } + + // erfuellt, aber keine so gute Idee + // im Falle von gekrümmten Fractures: + // first shift the free end shift vertex along prolongation of T End incoming edge, else later problematic + + + +#if 0 + IndexType faceOrderNumber = 0; + + // TODO FIXME hier muss die FUnkiton verwendet und angepasst werden! + while( assoFacTEndCop.size() != 0 ) + { + Edge * fracEdge = nullptr; + Edge * shiftVrtxEdg = nullptr; + + std::vector edgesThisFac; + + edgesThisFac.clear(); + + for( std::vector::iterator iterEdgF = grid.associated_edges_begin(assoFacTConsider); + iterEdgF != grid.associated_edges_end(assoFacTConsider); iterEdgF++ ) + { + edgesThisFac.push_back(*iterEdgF); + } + + if( ! atStartSort ) + { + secondEdgeFac = nullptr; + } + + IndexType fndFracEdg = 0; + + for( auto const & etf : edgesThisFac ) + { + for( auto const & ofe : origFracEdg ) + { + if( etf == ofe ) + { + fndFracEdg++; + fracEdge = etf; + } + } + } + + if( fracEdge == nullptr || fndFracEdg != 1 ) + { + UG_LOG("Frac Orig Ecke nicht gefunden oder falsche Zahl " << fndFracEdg << std::endl ); +// return false; + UG_THROW("Frac Orig Ecke nicht gefunden oder falsche Zahl " << fndFracEdg << std::endl ); + } + + // find expanded shift vertex + + Vertex * shiftVrtxFound = nullptr; + IndexType fndVrt = 0; + IndexType helpVarEdges = 0; + + bool isAtFreeSideShiVe = false; + + for( auto const & etf : edgesThisFac ) + { + if( helpVarEdges >= edgesThisFac.size() ) + { + UG_LOG("Indexueberschreitung Edges" << std::endl); + break; + } + + helpVarEdges++; + + IndexType helpShiVaNum = 0; + + for( auto const & svwi : shiftVertcsWithTI ) + { + Vertex * sv = svwi.first; + + if( helpShiVaNum >= shiftVrtcs.size() ) + { + UG_LOG("Shift Vertex Index Verletzung T " << std::endl); + break; + } + + helpShiVaNum++; + +// for( IndexType i = 0; i < 2; i++ ) +// { +// if( etf->vertex(i) == crossPt && etf->vertex((i+1)%2) == sv ) +// { +// shiftVrtxFound = sv; +// fndVrt++; +// shiftVrtxEdg = etf; +// +// } +// } + + // TODO FIXME expand this construct also to X Cross, so far loop + if( EdgeContains(etf, crossPt ) && EdgeContains( etf, sv ) ) + { + shiftVrtxFound = sv; + fndVrt++; + shiftVrtxEdg = etf; + + isAtFreeSideShiVe = svwi.second; + } + } + } + + if( fndVrt != 1 || shiftVrtxFound == nullptr || shiftVrtxEdg == nullptr ) + { + UG_LOG("shift vertex komische Zahl oder null T " << fndVrt << std::endl); +// return false; + UG_THROW("shift vertex komische Zahl oder null T " << fndVrt << std::endl); + } + + + Vertex * firstVrt = shiftVrtxFound; + Vertex * secondVrt = nullptr; + + if( atStartSort ) + { + + if( fracEdge != secondEdgeFac || shiftVrtxEdg != firstEdgeFac ) + UG_THROW("ALler Anfang ist schwer " << std::endl); + + atStartSort = false; + } + else + { + bool setShftVrtFirst = false; +// bool boundAtShiftVrtEdg = true; TODO FIXME ist das global am Anfang vom while loop setzbar wie im anderen Fall? + + // TODO FIXME erfuellt durch den Wechsel, sowieso die Funktion anpassen oben +// switch ( faceOrderNumber ) +// { +// case 2: +// setShftVrtFirst = false; +// break; +// case 3: +// setShftVrtFirst = true; +// break; +// case 4: +// break; +// case 5: +// break; +// default: +// UG_THROW("zu grosse Ordnungsnummer " << std::endl); +// break; +// } + + if( setShftVrtFirst ) + { + + } + else + { + + } + +// firstEdgeFac = fracEdge; +// secondEdgeFac = shiftVrtxEdg; + + +// if( isAtFreeSideShiVe ) // obviously not at start +// { +// +// firstEdgeFac = fracEdge; +// secondEdgeFac = shiftVrtxEdg; +// +// } +// firstEdgeFac = shiftVrtxEdg; +// secondEdgeFac = fracEdge; +// +// firstVrt = shiftVrtxFound; +// secondVrt = nullptr; +// } +// + // UG_LOG("Debug Paarbildung " << std::endl); + + + + } + +// std::pair edgesFac( firstEdgeFac, secondEdgeFac ); +// +// std::pair vrtcsSF( firstVrt, secondVrt ); +// ExpandCrossFracInfo startFacInf( edgesFac, assoFacConsider, vrtcsSF ); + + + faceOrderNumber++; + + } + +#endif + + // create new vertex + + // for the ending frac region, the same algorithm applies as for the X Cross in all 4 branches + // for the free end, no new vertex, but new vertices along the durchgehende fracture + // repectively along the original edges of the durchgehende fracture + + + + IndexType sizeECF = vecExpCrossFI.size(); + + if( sizeECF != 6 ) + UG_THROW("Momische Länge TEnd " << std::endl); + + for( IndexType i = 0; i < sizeECF; i = i + 2 ) + { + if( vecExpCrossFI[i].getNormal().first != vecExpCrossFI[(i+sizeECF-1) % sizeECF].getNormal().second ) + UG_THROW("Kleberei TEnd schief gegangen " << std::endl); + } +// +// // new vertex between face 0 and 1 and between face 4 and 5 +// +// // first those along the passing fracture +// +//// ExpandCrossFracInfo & alongFreeEndStartF = vecExpCrossFI[0]; +//// ExpandCrossFracInfo & closeToEndingCleftBeginF = vecExpCrossFI[1]; +//// ExpandCrossFracInfo & endingCleftBeginF = vecExpCrossFI[2]; +//// ExpandCrossFracInfo & endingCleftEndF = vecExpCrossFI[3]; +//// ExpandCrossFracInfo & closeToEndingCleftEndF = vecExpCrossFI[4]; +//// ExpandCrossFracInfo & alongFreeEndEndF = vecExpCrossFI[5]; +//// +//// Vertex * remainVrtx = alongFreeEndStartF.getNormal().first; +//// Vertex * shiftVrtxOne = closeToEndingCleftBeginF.getNormal().second; +//// Vertex * shiftVrtxTwo = endingCleftEndF.getNomal().first; +//// +//// vector3 posVRem = aaPos[remainVrtx]; +//// vector3 posVOne = aaPos[shiftVrtxOne]; +//// vector3 posVTwo = aaPos[shiftVrtxTwo]; +//// +//// vector3 distOne; +//// VecSubtract(distOne, posVOne, posVRem); +//// +//// vector3 distTwo; +//// VecSubtract(distTwo, posVTwo, posVRem); +//// +//// vector3 distOneHalf, distTwoHalf; +//// VecScale(distOneHalf, distOne, 0.5 ); +//// VecScale(distTwoHalf, distTwo, 0.5 ); +//// +//// vector3 posNewVrtOne, posNewVrtTwo; +//// VecAdd(posNewVrtOne, posVRem, distOneHalf); +//// VecAdd(posNewVrtTwo, posVRem, distTwoHalf); +//// +//// Vertex * newVrtOne = *grid.create(); +//// Vertex * newVrtTwo = *grid.create(); +//// +//// aaPos[newVrtOne] = posNewVrtOne; +//// aaPos[newVrtTwo] = posNewVrtTwo; +//// +//// IndexType sudoTEnd = sh.num_subsets(); +//// +//// sh.assign_subset(newVrtOne, sudoTEnd); +//// sh.assign_subset(newVrtTwo, sudoTEnd); +//// +//// +//// std::pair vrtcsAlongFreeEndStartF = alongFreeEndStartF.getNormal(); +//// std::pair vrtcsCloseToEndingCleftBeginF = closeToEndingCleftBeginF.getNormal(); +//// std::pair vrtcsEndingCleftBeginF = endingCleftBeginF.getNormal(); +//// std::pair vrtcsEndingCleftEndF = endingCleftEndF.getNormal(); +//// std::pair vrtcsCloseToEndingCleftEndF = closeToEndingCleftEndF.getNormal(); +//// std::pair vrtcsAlongFreeEndEndF = alongFreeEndEndF.getNormal(); +//// +//// +//// alongFreeEndStartF.setNewNormal( vrtcsAlongFreeEndStartF ); +//// closeToEndingCleftBeginF.setNewNormal( vrtcsCloseToEndingCleftBeginF ); +//// endingCleftBeginF.setNewNormal( vrtcsEndingCleftBeginF ); +//// endingCleftEndF.setNewNormal( vrtcsEndingCleftEndF ); +//// closeToEndingCleftEndF.setNewNormal( vrtcsCloseToEndingCleftEndF ); +//// alongFreeEndEndF.setNewNormal( vrtcsAlongFreeEndEndF ); +// + IndexType sudoTEnd = sh.num_subsets(); + + // gemeinsame Funktion wie bei XCross neue Punkte erzeugen und anwenden in dem einzigen speziellen Fall hier! + + IndexType indBeforeT = sizeECF / 2 - 1; + IndexType indAfterT = sizeECF / 2; + + ExpandCrossFracInfo & expCFIBeforeFracEdg = vecExpCrossFI[ indBeforeT ]; + ExpandCrossFracInfo & expCFIAfterFracEdg = vecExpCrossFI[ indAfterT ]; + + vector3 distVecNewVrt2SCrossPt; + + // new vertex in ending frac + +// computeDiamondPointXCrossType( expCFIBeforeFracEdg, expCFIAfterFracEdg, crossPt, aaPos, sh, grid, sudoTEnd, distVecNewVrt2SCrossPt ); + + // shift of free shift point to virtual prolongation of ending fracture center line + + computeDiamondPointXCrossType( expCFIBeforeFracEdg, expCFIAfterFracEdg, crossPt, aaPos, sh, grid, sudoTEnd, distVecNewVrt2SCrossPt ); + + constexpr bool shiftFreePt = false; + + if( shiftFreePt ) + { +// computeDiamondPointXCrossType( expCFIBeforeFracEdg, expCFIAfterFracEdg, crossPt, aaPos, sh, grid, sudoTEnd, distVecNewVrt2SCrossPt ); + + vector3 posCrossPt = aaPos[crossPt]; + + vector3 newPosFreeShiftPt; + + VecAdd(newPosFreeShiftPt,posCrossPt,distVecNewVrt2SCrossPt); + + // assign this position to shift vertex at free end + + aaPos[shiftVrtxAtFreeEnd] = newPosFreeShiftPt; + + + for( IndexType i = 0; i < sizeECF; i = i + ( sizeECF ) / 2 + 1 ) + { + bool atStart = ( i < sizeECF / 2 ); + + IndexType firstInd = atStart ? ( i ) % sizeECF: ( i + 1 ) % sizeECF; + IndexType secndInd = atStart ? ( i + 1 ) % sizeECF : ( i ) % sizeECF; + + UG_LOG("indices " << firstInd << " " << secndInd << std::endl); + + ExpandCrossFracInfo & alongFreeEndF = vecExpCrossFI[firstInd]; + ExpandCrossFracInfo & closeToTEndF = vecExpCrossFI[secndInd]; + + std::pair freeEdgs = alongFreeEndF.getEdge(); + std::pair tEndEdgs = closeToTEndF.getEdge(); + + Edge * freeCommEdg = atStart ? freeEdgs.second : freeEdgs.first; + Edge * closTCommEdg = atStart ? tEndEdgs.first : tEndEdgs.second; + + if( freeCommEdg != closTCommEdg || freeCommEdg == nullptr || closTCommEdg == nullptr ) + UG_THROW("freie und geschlossene Ecke ungleich oder null " << freeCommEdg << " " << closTCommEdg << std::endl); + + std::pair freeVrtcs = alongFreeEndF.getNormal(); + std::pair tEndVrtcs = closeToTEndF.getNormal(); + + Vertex * remainVrtx = atStart ? freeVrtcs.first : freeVrtcs.second; + Vertex * shiftTVrt = atStart ? tEndVrtcs.second : tEndVrtcs.first; + + Vertex * freeNull = atStart ? freeVrtcs.second : freeVrtcs.first; + Vertex * teNull = atStart ? tEndVrtcs.first : tEndVrtcs.second; + + if( freeNull != nullptr || teNull != nullptr || remainVrtx == nullptr || shiftTVrt == nullptr ) + { + // UG_THROW("TEnd schon falsch zugewiesene Vertizex" << std::endl); + UG_LOG("TEnd schon falsch zugewiesene Vertizex" << std::endl); + + UG_LOG("Falsch feee null " << freeNull << " T " << teNull << " R " << remainVrtx << " S " << shiftTVrt << std::endl); + + UG_THROW("TEnd schon falsch zugewiesene Vertizex" << std::endl); + + UG_THROW("Falsch feee null " << freeNull << " T " << teNull << " R " << remainVrtx << " S " << shiftTVrt << std::endl); + } + else + { + UG_LOG("TEnd richtig zugewiesene Vertizex" << std::endl); + + UG_LOG("Richtig feee null " << freeNull << " T " << teNull << " R " << remainVrtx << " S " << shiftTVrt << std::endl); + + } + + vector3 posVRem = aaPos[remainVrtx]; + vector3 posShiVe = aaPos[shiftTVrt]; + + // UG_LOG("pos T " << posVRem << " " << posShiVe << std::endl); + // + vector3 dist; + VecSubtract(dist, posShiVe, posVRem); + // + // UG_LOG("dist TR " << dist << std::endl); + // + vector3 distHalf; + VecScale(distHalf, dist, 0.5); + // + // UG_LOG("dist half TR " << distHalf << std::endl); + // + vector3 posNewVrt; + VecAdd(posNewVrt, posVRem, distHalf); + // + // UG_LOG("neuer Vertex Position " << posNewVrt << std::endl); + // + + Vertex * newVrt = *grid.create(); + aaPos[newVrt] = posNewVrt; + + sh.assign_subset(newVrt, sudoTEnd); + // + if( atStart ) + { + freeVrtcs.second = newVrt; + tEndVrtcs.first = newVrt; + } + else + { + freeVrtcs.first = newVrt; + tEndVrtcs.second = newVrt; + } + // + alongFreeEndF.setNewNormal( freeVrtcs ); + closeToTEndF.setNewNormal( tEndVrtcs ); + + } + + } + else // go to left and right from crossPt at same distance as where the ending cleft enters the durchgehende one + { + +// vector3 distVecNewVrt2ShiVeBefore; +// vector3 distVecNewVrt2ShiVeAfter; + + +// computeDiamondPointXCrossType( expCFIBeforeFracEdg, expCFIAfterFracEdg, crossPt, aaPos, sh, grid, sudoTEnd, +// distVecNewVrt2SCrossPt. distVecNewVrt2ShiVeBefore, distVecNewVrt2ShiVeAfter, true ); + // VecSubtract(distVecNewVrt2ShiVeBefore, posShiftBefore, posNewVrtOnEdg ); + + + for( IndexType i = 0; i < sizeECF; i = i + ( sizeECF ) / 2 + 1 ) + { + bool atStart = ( i < sizeECF / 2 ); + + IndexType firstInd = atStart ? ( i ) % sizeECF: ( i + 1 ) % sizeECF; + IndexType secndInd = atStart ? ( i + 1 ) % sizeECF : ( i ) % sizeECF; + + UG_LOG("indices " << firstInd << " " << secndInd << std::endl); + + ExpandCrossFracInfo & alongFreeEndF = vecExpCrossFI[firstInd]; + ExpandCrossFracInfo & closeToTEndF = vecExpCrossFI[secndInd]; + + std::pair freeEdgs = alongFreeEndF.getEdge(); + std::pair tEndEdgs = closeToTEndF.getEdge(); + + Edge * freeCommEdg = atStart ? freeEdgs.second : freeEdgs.first; + Edge * closTCommEdg = atStart ? tEndEdgs.first : tEndEdgs.second; + + if( freeCommEdg != closTCommEdg || freeCommEdg == nullptr || closTCommEdg == nullptr ) + UG_THROW("freie und geschlossene Ecke ungleich oder null " << freeCommEdg << " " << closTCommEdg << std::endl); + + std::pair freeVrtcs = alongFreeEndF.getNormal(); + std::pair tEndVrtcs = closeToTEndF.getNormal(); + + Vertex * remainVrtx = atStart ? freeVrtcs.first : freeVrtcs.second; + Vertex * shiftTVrt = atStart ? tEndVrtcs.second : tEndVrtcs.first; + + Vertex * freeNull = atStart ? freeVrtcs.second : freeVrtcs.first; + Vertex * teNull = atStart ? tEndVrtcs.first : tEndVrtcs.second; + + if( freeNull != nullptr || teNull != nullptr || remainVrtx == nullptr || shiftTVrt == nullptr ) + { + // UG_THROW("TEnd schon falsch zugewiesene Vertizex" << std::endl); + UG_LOG("TEnd schon falsch zugewiesene Vertizex" << std::endl); + + UG_LOG("Falsch feee null " << freeNull << " T " << teNull << " R " << remainVrtx << " S " << shiftTVrt << std::endl); + + UG_THROW("TEnd schon falsch zugewiesene Vertizex" << std::endl); + + UG_THROW("Falsch feee null " << freeNull << " T " << teNull << " R " << remainVrtx << " S " << shiftTVrt << std::endl); + } + else + { + UG_LOG("TEnd richtig zugewiesene Vertizex" << std::endl); + + UG_LOG("Richtig feee null " << freeNull << " T " << teNull << " R " << remainVrtx << " S " << shiftTVrt << std::endl); + + } + + vector3 posCrossPt = aaPos[crossPt]; + vector3 posShiVe = aaPos[shiftTVrt]; + + vector3 posNewVrtOnFrctrsTouchEdg; + VecSubtract( posNewVrtOnFrctrsTouchEdg, posCrossPt, distVecNewVrt2SCrossPt ); + + vector3 distNewTouchEdgVrt2ShiVe; + VecSubtract(distNewTouchEdgVrt2ShiVe, posShiVe, posNewVrtOnFrctrsTouchEdg); + + number distNrm = VecLength(distNewTouchEdgVrt2ShiVe); + + // go along old frac edge with this length + + Vertex * endEdgFracV = nullptr; + + IndexType fndCr = 0; + + for( IndexType i = 0; i < 2; i++ ) + { + + Vertex * tV = closTCommEdg->vertex(i); + + if( tV == crossPt ) + fndCr++; + else + endEdgFracV = tV; + } + + if( fndCr != 1 || endEdgFracV == nullptr ) + UG_THROW("ENde nicht gefunden " << std::endl); + + vector3 posEndPt = aaPos[endEdgFracV]; + + vector3 crsPt2EndPt; + VecSubtract(crsPt2EndPt, posEndPt, posCrossPt); + + vector3 unitAlong; + VecNormalize(unitAlong, crsPt2EndPt); + + vector3 scaAlong; + VecScale(scaAlong, unitAlong, distNrm); + + vector3 posNewVrt; + + VecAdd(posNewVrt, posCrossPt, scaAlong); + + Vertex * newVrt = *grid.create(); + aaPos[newVrt] = posNewVrt; + + sh.assign_subset(newVrt, sudoTEnd); + // + if( atStart ) + { + freeVrtcs.second = newVrt; + tEndVrtcs.first = newVrt; + } + else + { + freeVrtcs.first = newVrt; + tEndVrtcs.second = newVrt; + } + // + alongFreeEndF.setNewNormal( freeVrtcs ); + closeToTEndF.setNewNormal( tEndVrtcs ); + + } + + } + + + // create new edges and new faces + + std::vector newFracFaceVec = std::vector(); + + bool boundAtShiftVrtEdg = false; +// bool atStartSort = false; + +// for( IndexType i = indBeforeT; i <= indAfterT; i++ ) + for( auto const & ecf : vecExpCrossFI ) + { +// createNewFacesForExtXCrossFracs( vecExpCrossFI[i], newFracFaceVec, boundAtShiftVrtEdg, atStartSort, sh, grid, crossPt, subdomList ); + createNewFacesForExtXCrossFracs( ecf, newFracFaceVec, boundAtShiftVrtEdg, sh, grid, crossPt, subdomList ); + } + + std::vector newDiamFaceVec = std::vector(); + +// ExpandCrossFracInfo & expCFIBeforeFracEdg = vecExpCrossFI[ indBeforeT ]; +// ExpandCrossFracInfo & expCFIAfterFracEdg = vecExpCrossFI[ indAfterT ]; + + +// createDiamondFacesXCrossType( expCFIAfterFracEdg, expCFIBeforeFracEdg, +// newDiamFaceVec, sh, grid, sudoTEnd, crossPt ); + + // only the non free part +// for( int indC = 1; indC < sizeECF-2; indC = indC + 2 ) + for( int indC = -1; indC < sizeECF-2; indC = indC + 2 ) + { + + // Create Spitze at free side + bool isAtFreeEnd = ( indC == -1 ); + + IndexType indBefore = ( indC + sizeECF ) % sizeECF; + IndexType indAfter = ( indC + 1 + sizeECF ) % sizeECF; + + + ExpandCrossFracInfo & expCFIBeforeFracEdg = vecExpCrossFI[ indBefore ]; + ExpandCrossFracInfo & expCFIAfterFracEdg = vecExpCrossFI[ indAfter ]; + + + createDiamondFacesXCrossType( expCFIBeforeFracEdg, expCFIAfterFracEdg, + newDiamFaceVec, sh, grid, sudoTEnd, crossPt, isAtFreeEnd ); + + } + + + std::string diamNam = std::string("spitzDiam_") + std::string(const_cast( sh.get_subset_name( subdomList[0] ) )) + + std::string("_") + std::string(const_cast( sh.get_subset_name( subdomList[1] ) )); + + sh.set_subset_name(diamNam.c_str(),sudoTEnd); + + assignFaceSubsetToClosedFace( newFracFaceVec, grid, sh ); + assignFaceSubsetToClosedFace( newDiamFaceVec, grid, sh ); + +// for( auto const & fdel : vecExpCrossFI ) +// { +// Face * fac2BeDeleted = fdel.getFace(); +// +// if( fac2BeDeleted != nullptr ) +// grid.erase(fac2BeDeleted); +// else +// UG_THROW("hier fehlt ein Gesicht " << std::endl); +// } +// +// for( auto const & edg : allAssoEdgCP ) +// { +//// Edge * e2D = oEdg; +// +// if( edg != nullptr && edg != shiftVrtxAtFirstFacEdg ) +// { +// UG_LOG("will erasieren " << edg << std::endl ); +// grid.erase(edg); +// +//// sh.assign_subset( e2D, subsNumNow ); +//// sh.assign_subset( e2D, subsNumNow ); +// } +// else +// { +// UG_LOG("hier fehlt eine Ecke " << std::endl); +// } +// } + + avoidToDeleteEdge = shiftVrtxAtFirstFacEdg; + + UG_LOG("T End Kreis fertig an " << aaPos[crossPt] << std::endl ); + + } + // else if( nuCroFra == 4 ) + else if( fracTyp == CrossVertInf::XCross ) + { + // sort faces and corresponding edges, start with an oririnal fracture edge and select the next edge which + // has a newly created shift vertex + + auto assoFacXCrossCop = assoFacCross; + + // "durchdrehen" + +// Face * assoFacConsider = *(assoFacXCrossCop.begin()); + Face * assoFacConsider = assoFacXCrossCop[0]; + + // soll einmal am Anfang festgelegt werden und dann bleiben + Edge * assoFacEdgBeg2Fix = nullptr; + // soll erst ganz am Schluss festgelegt werden + Edge * assoFacEdgEnd2Fix = nullptr; + + // soll in jedem Lauf aktualisiert werden + Edge * firstEdgeFac = assoFacEdgBeg2Fix; + Edge * secondEdgeFac = nullptr; + +// bool atStartSort = true; + +// using ExpandCrossFracInfo = VertexFractureTriple< std::pair, Face*, std::pair >; +// // Vertex nullptr wo original fracture, und shift vertex, wo Keilecke, die weg soll +// +// using VecExpandCrossFracInfo = std::vector; + +// VecExpandCrossFracInfo vecExpCrossFI; + +// bool boundAtShiftVrtEdg = true; + +// auto shiftVrtcsCop = shiftVrtcs; + +// UG_LOG("starting Rundlauf " << std::endl); + +// IndexType dbg_rndl = 0; + + if( ! SortFaces4DiamondCreation( sh, assoFacXCrossCop, firstEdgeFac, secondEdgeFac, + assoFacConsider, origFracEdg, shiftVrtcs, + crossPt, assoFacEdgBeg2Fix, assoFacEdgEnd2Fix, grid, vecExpCrossFI + , true + ) + ) + UG_THROW("Ordnen Diamant X Cross schief gegangen " << std::endl); + +#if 0 + while( assoFacXCrossCop.size() != 0 ) + { + +// UG_LOG("Debug Rundlauf " << dbg_rndl << std::endl); + + dbg_rndl++; + + secondEdgeFac = nullptr; + + Edge * fracEdge = nullptr; + Edge * shiftVrtxEdg = nullptr; + +// IndexType fndEdgEnd = 0; + + std::vector edgesThisFac; + + edgesThisFac.clear(); + +// IndexType eoeo = edgesThisFac.size(); +// +// auto eiei = eoeo; + +// UG_LOG("Edges this fac Orig Orig " << eiei << " " << dbg_rndl << std::endl); + + +// UG_LOG("Debug Ecken " << std::endl); + + IndexType dbg_itEd = 0; + + for( std::vector::iterator iterEdgF = grid.associated_edges_begin(assoFacConsider); + iterEdgF != grid.associated_edges_end(assoFacConsider); iterEdgF++ ) + { + edgesThisFac.push_back(*iterEdgF); + +// UG_LOG("und noch eines dazu " << dbg_itEd << " " << dbg_rndl << std::endl); + + //IndexType sudos = sh.num_subsets(); + + //sh.assign_subset(*iterEdgF,sudos); + } + +// IndexType effsOrig = edgesThisFac.size(); + +// auto efeu = effsOrig; + +// UG_LOG("Edges this fac Orig " << efeu << dbg_rndl << std::endl); + + + // figure out original fracture edge + + IndexType fndFracEdg = 0; + + for( auto const & etf : edgesThisFac ) + { + for( auto const & ofe : origFracEdg ) + { + if( etf == ofe ) + { + fndFracEdg++; + fracEdge = etf; + } + } + } + +// UG_LOG("Debug Ofen " << std::endl); + + + if( fracEdge == nullptr || fndFracEdg != 1 ) + { + UG_LOG("Frac Orig Ecke nicht gefunden oder falsche Zahl " << fndFracEdg << std::endl ); +// return false; + UG_THROW("Frac Orig Ecke nicht gefunden oder falsche Zahl " << fndFracEdg << std::endl ); + } + + + // find expanded shift vertex + + Vertex * shiftVrtxFound = nullptr; + IndexType fndVrt = 0; + +// IndexType suse = sh.num_subsets(); + + //sh.assign_subset(crossPt,suse); + +// for( auto & sv : shiftVrtcsCop ) +// { +// IndexType suseV = sh.num_subsets(); +// //sh.assign_subset(sv,suseV); +// } + +// return true; + +// UG_LOG("Debug Entfernene " << std::endl); + + IndexType dbg_edgnum = 0; + + IndexType helpVarEdges = 0; + +// IndexType effs = edgesThisFac.size(); +// IndexType shiffs = shiftVrtcs.size(); + +// UG_LOG("Edges this fac " << effs << dbg_rndl << std::endl); +// UG_LOG("Shift Vectors " << shiffs << dbg_rndl << std::endl); + + + for( auto const & etf : edgesThisFac ) + { + + if( helpVarEdges >= edgesThisFac.size() ) + { + UG_LOG("Indexueberschreitung Edges" << std::endl); + break; + } + + helpVarEdges++; + + dbg_edgnum++; + + IndexType helpShiVaNum = 0; + + IndexType dbg_shiVe = 0; + +// for( Vertex * const & sv : shiftVrtcs ) + for( auto const & sv : shiftVrtcs ) + { + + if( helpShiVaNum >= shiftVrtcs.size() ) + { + UG_LOG("Shift Vertex Index Verletzung " << std::endl); + break; + } + + helpShiVaNum++; + + dbg_shiVe++; + + for( IndexType i = 0; i < 2; i++ ) + { +// if( ( etf->vertex(i) == crossPt && etf->vertex((i+1)%2) == sv ) || (etf->vertex((i+1)%2) == crossPt && etf->vertex(i) == sv )) + if( etf->vertex(i) == crossPt && etf->vertex((i+1)%2) == sv ) + { + shiftVrtxFound = sv; + fndVrt++; + shiftVrtxEdg = etf; + +// UG_LOG("Shift Vertex " << aaPos[shiftVrtxFound] << " " << dbg_edgnum << " " << dbg_shiVe << " " << dbg_rndl << std::endl); +// UG_LOG("Cross Vertex " << aaPos[crossPt] << " " << dbg_edgnum << " " << dbg_shiVe << " " << dbg_rndl << std::endl ); +// +// UG_LOG("dbg edgenu shive " << dbg_edgnum << " " << dbg_shiVe << " " << dbg_rndl << std::endl); + } + } + } + } + +// UG_LOG("Debug Entfert durch " << std::endl); + + + if( fndVrt != 1 || shiftVrtxFound == nullptr || shiftVrtxEdg == nullptr ) + { + UG_LOG("shift vertex komische Zahl oder null " << fndVrt << std::endl); +// return false; + UG_THROW("shift vertex komische Zahl oder null " << fndVrt << std::endl); + } + +// UG_LOG("Debug Entfert Text durch " << std::endl); + + +// for( std::vector::iterator itV = shiftVrtcsCop.begin(); itV != shiftVrtcsCop.end(); itV++ ) +// { +// Vertex * vrt = *itV; +// +// if( vrt == shiftVrtxFound ) +// { +// shiftVrtcsCop.erase(itV); +// break; +// } +// } +// +// UG_LOG("Debug Rasieren durch " << std::endl); + + + if( atStartSort ) + { + assoFacEdgBeg2Fix = fracEdge; + atStartSort = false; + } + +// Edge * firstEdgeFac = fracEdge; +// Edge * secondEdgeFac = shiftEdge; + firstEdgeFac = fracEdge; + secondEdgeFac = shiftVrtxEdg; + + + Vertex * firstVrt = nullptr; + Vertex * secondVrt = shiftVrtxFound; + + if( !boundAtShiftVrtEdg ) + { + firstEdgeFac = shiftVrtxEdg; + secondEdgeFac = fracEdge; + + firstVrt = shiftVrtxFound; + secondVrt = nullptr; + } + +// UG_LOG("Debug Paarbildung " << std::endl); + + + std::pair edgesFac( firstEdgeFac, secondEdgeFac ); + + std::pair vrtcsSF( firstVrt, secondVrt ); + + ExpandCrossFracInfo startFacInf( edgesFac, assoFacConsider, vrtcsSF ); + + vecExpCrossFI.push_back(startFacInf); + +// IndexType sui = sh.num_subsets(); +// +// sh.assign_subset(assoFacConsider,sui); + +// UG_LOG("Debug Paarbildung Rasieren " << std::endl); + + IndexType dbg_it_er = 0; + + for( std::vector::iterator itFac = assoFacXCrossCop.begin(); itFac != assoFacXCrossCop.end(); itFac++ ) + { + Face * iFa = *itFac; + +// UG_LOG("interieren " << dbg_it_er << std::endl ); + + dbg_it_er++; + +// UG_LOG("ifa " << iFa << std::endl ); +// UG_LOG("assoFac " << assoFacConsider << std::endl ); + +// bool enthaltung = FaceContains( iFa, firstEdgeFac ); +// +//// UG_LOG("Enthaltung " << std::endl); +// +// bool entzwei = FaceContains(iFa, secondEdgeFac); +// +//// UG_LOG("Entzweiung " << std::endl); + + + if( iFa == assoFacConsider && FaceContains( iFa, firstEdgeFac ) && FaceContains(iFa, secondEdgeFac) ) + { +// UG_LOG("Erasieren " << std::endl); + assoFacXCrossCop.erase(itFac); + break; + } + } + +// UG_LOG("Debug Paarbildung Rasieren durch " << std::endl); + + + if( assoFacXCrossCop.size() == 0 ) + { + if( secondEdgeFac != assoFacEdgBeg2Fix ) + { + UG_LOG("Gesichter Diamant leer, aber keine Anfangsecke gefunden" << std::endl); +// return false; + UG_THROW("Gesichter Diamant leer, aber keine Anfangsecke gefunden" << std::endl); + } + else + { + assoFacEdgEnd2Fix = secondEdgeFac; + + break; // while loop zu Ende, raus aus dem while loop, den Rest nicht mehr machen, würde schief gehen zwingendermassen + } + + } + + // figure out the next face + + firstEdgeFac = secondEdgeFac; + secondEdgeFac = nullptr; + + IndexType nextFaceFound = 0; + + for( std::vector::iterator itFac = assoFacXCrossCop.begin(); itFac != assoFacXCrossCop.end(); itFac++ ) + { + Face * iFa = *itFac; + + if( FaceContains(iFa, firstEdgeFac ) ) + { + nextFaceFound++; + } + } + + if( nextFaceFound != 1 ) + { + UG_LOG("folgendes Gesicht in falscher Anztahl gefunden Diamant " << nextFaceFound << std::endl); +// return false; + UG_THROW("folgendes Gesicht in falscher Anztahl gefunden Diamant " << nextFaceFound << std::endl); + } + + for( std::vector::iterator itFac = assoFacXCrossCop.begin(); itFac != assoFacXCrossCop.end(); itFac++ ) + { + Face * iFa = *itFac; + + if( FaceContains(iFa, firstEdgeFac ) ) + { + assoFacConsider = iFa; + break; + } + } + + + boundAtShiftVrtEdg = ! boundAtShiftVrtEdg; + } + + + if( assoFacEdgEnd2Fix != assoFacEdgBeg2Fix || assoFacEdgEnd2Fix == nullptr || assoFacEdgBeg2Fix == nullptr ) + { + UG_THROW("Anfang und Ende stimmen nicht ueberein " << std::endl); +// return false; + UG_THROW("Anfang und Ende stimmen nicht ueberein " << std::endl); + } + +// if( shiftVrtcsCop.size() != 0 ) +// { +// UG_LOG("Shift vertizes nicht alle gefinden " << std::endl); +// return false; +// UG_THROW("Shift vertizes nicht alle gefinden " << std::endl); +// } + + if( assoFacXCrossCop.size() != 0 ) + { + UG_LOG("nicht alle asso facs gefunden " << std::endl); +// return false; + UG_THROW("nicht alle asso facs gefunden " << std::endl); + } +#endif + + UG_LOG("Kreis des Diamanten X Fall geschlossen " << std::endl); + + // create new vertices and new edges and new faces, delete the old ones at end not to forget + +// IndexType vecfis = vecExpCrossFI.size(); +// +// UG_LOG("Punkte werden erzeugt " << vecfis << std::endl); +// +// for( IndexType i = -1; i < 8; i = i + 2 ) +// UG_LOG("iiii " << i << std::endl); +// +// for( IndexType indC = -1; indC < 8; indC = indC + 2 ) +// { +// +// UG_LOG("Punkterzeugung Test " << indC << std::endl ); +// +// } +// +// return true; + + // IndexType diamantSubsNum = sh.num_subsets()+1; // +1 notwendig? TODO FIXME wieso nicht +1? + IndexType diamantSubsNum = sh.num_subsets(); // +1 notwendig? TODO FIXME + + int vecfis = vecExpCrossFI.size(); + +// for( int indC = -1; indC < vecfis; indC = indC + 2 ) +// UG_LOG("Punkterzeugung " << indC << std::endl ); +// + +// for( int indC = -1; indC < vecExpCrossFI.size(); indC = indC + 2 ) + for( int indC = -1; indC < vecfis-2; indC = indC + 2 ) + { + +// UG_LOG("Punkterzeugung X " << indC << std::endl ); + + + IndexType indBefore = ( indC + vecExpCrossFI.size() ) % vecExpCrossFI.size(); + IndexType indAfter = ( indC + 1 + vecExpCrossFI.size() ) % vecExpCrossFI.size(); + + // TODO FIXME ab hier in externe Funktion stecken, damit auch für TEnd endende Frac Seite verwendbar!!!! + + ExpandCrossFracInfo & expCFIBeforeFracEdg = vecExpCrossFI[ indBefore ]; + ExpandCrossFracInfo & expCFIAfterFracEdg = vecExpCrossFI[ indAfter ]; + + vector3 distVecNewVrt2SCrossPt; // not ot interest here, but only with c++17 possible to rule out computation in a clever way + + computeDiamondPointXCrossType( expCFIBeforeFracEdg, expCFIAfterFracEdg, crossPt, aaPos, sh, grid, diamantSubsNum, distVecNewVrt2SCrossPt ); + +#if 0 + + + // compute cross point + + std::pair edgesCrossSegBefore = expCFIBeforeFracEdg.getEdge(); + std::pair edgesCrossSegAfter = expCFIAfterFracEdg.getEdge(); + + Edge * beforeShiftEdg = edgesCrossSegBefore.first; + Edge * beforeFracEdg = edgesCrossSegBefore.second; + Edge * afterFracEdg = edgesCrossSegAfter.first; + Edge * afterShiftEdg = edgesCrossSegAfter.second; + + std::pair vrtcsCrossSegBefore = expCFIBeforeFracEdg.getNormal(); + std::pair vrtcsCrossSegAfter = expCFIAfterFracEdg.getNormal(); + + Vertex * shiftBefore = vrtcsCrossSegBefore.first; + Vertex * shiftAfter = vrtcsCrossSegAfter.second; + + // zur Zielsetzung +// Vertex * toBeEstablishedCutEdgeVrtBefore = vrtcsCrossSegBefore.second; +// Vertex * toBeEstablishedCutEdgeVrtAfter = vrtcsCrossSegAfter.first; + + if( vrtcsCrossSegBefore.second != nullptr || vrtcsCrossSegAfter.first != nullptr + || shiftBefore == nullptr || shiftAfter == nullptr +// if( toBeEstablishedCutEdgeVrtBefore != nullptr || toBeEstablishedCutEdgeVrtAfter != nullptr +// || shiftBefore == nullptr || shiftAfter == nullptr + ) + UG_THROW("Nullpointer fehlen oder zu viel " << std::endl); + + if( beforeFracEdg != afterFracEdg || beforeFracEdg == nullptr || afterFracEdg == nullptr + || beforeShiftEdg == nullptr || afterShiftEdg == nullptr + ) + UG_LOG("Ecken Nullpunkter " << std::endl); + + // determin cut point of line between the shift vertices and the frac edge + + Edge * fracEdge = beforeFracEdg; // muss gleich sein offenkundig afterFracEdge, ist getestet auch + + // Gerade bestimmen, die durch fracEdge bestimmt wird, und Gerade, die durch Verbindungsvektor shift Verzices bestimmt wird + + // figure out frac vertex which is the cross point + + IndexType fracEdgInd = -1; + + for( IndexType fiv = 0; fiv < 2; fiv++ ) + { + if( fracEdge->vertex(fiv) == crossPt ) + fracEdgInd = fiv; + } + + if( fracEdgInd < 0 || fracEdgInd > 1 ) + UG_THROW("cross point nicht Teil von fracture edge" << std::endl ); + + Vertex * fracEdgEnd = fracEdge->vertex( ( fracEdgInd + 1 ) % 2 ); + + vector3 posCrossPt = aaPos[ crossPt ]; + vector3 posFracEnd = aaPos[ fracEdgEnd ]; + + vector3 posShiftBefore = aaPos[ shiftBefore ]; + vector3 posShiftAfter = aaPos[ shiftAfter ]; + + vector3 directionFrac; + + VecSubtract(directionFrac, posFracEnd, posCrossPt ); + + vector3 directionShiftBefore; + + VecSubtract(directionShiftBefore, posShiftBefore, posCrossPt); + + vector3 directionShiftAfter; + + VecSubtract(directionShiftAfter, posShiftAfter, posCrossPt ); + + vector3 sumShift; + + VecAdd(sumShift, directionShiftBefore, directionShiftAfter); + + vector3 halfSumShift; + + VecScale(halfSumShift,sumShift,0.5); + + vector3 posNewVrtOnEdg; + + VecAdd( posNewVrtOnEdg, posCrossPt, halfSumShift ); + + Vertex * newEdgVrtx = *grid.create(); + aaPos[newEdgVrtx] = posNewVrtOnEdg; + + IndexType sudoEdg = sh.get_subset_index(fracEdge); + + Face * faceBefore = expCFIBeforeFracEdg.getFace(); + Face * faceAfter = expCFIAfterFracEdg.getFace(); + + IndexType sudoBefore = sh.get_subset_index(faceBefore); + IndexType sudoAfter = sh.get_subset_index(faceAfter); + + if( sudoEdg != sudoBefore || sudoBefore != sudoAfter ) + UG_THROW("komische sudos vor Diamant " << std::endl); + + sh.assign_subset(newEdgVrtx, sudoEdg); + + UG_LOG("neuer Diamant Vorbereitungs Vertex " << posNewVrtOnEdg << std::endl); + + // Vertex * toBeEstablishedCutEdgeVrtBefore = vrtcsCrossSegBefore.second; + // Vertex * toBeEstablishedCutEdgeVrtAfter = vrtcsCrossSegAfter.first; + + + + // gleich neue Faces erzeugen? +// std::pair vrtcsCrossSegBefore = expCFIBeforeFracEdg.getNormal(); +// std::pair vrtcsCrossSegAfter = expCFIAfterFracEdg.getNormal(); + + // insert the newly established vertex into the vertex info of the ExpandCrossFracInfo of the face +//// vrtcsCrossSegBefore.second = newEdgVrtx; +//// vrtcsCrossSegAfter.first = newEdgVrtx; +//// +// std::pair vrtcsCrossSegBeforeNew( vrtcsCrossSegBefore.first, newEdgVrtx ); +// std::pair vrtcsCrossSegAfterNew( newEdgVrtx, vrtcsCrossSegAfter.second ); +// +// +// expCFIBeforeFracEdg.setNewNormal( vrtcsCrossSegBeforeNew ); +// expCFIAfterFracEdg.setNewNormal( vrtcsCrossSegAfterNew ); + + vrtcsCrossSegBefore.second = newEdgVrtx; + vrtcsCrossSegAfter.first = newEdgVrtx; + expCFIBeforeFracEdg.setNewNormal( vrtcsCrossSegBefore ); + expCFIAfterFracEdg.setNewNormal( vrtcsCrossSegAfter ); + +#endif + +// vecExpCrossFI[ indBefore ].setNewEdgVertex(newEdgVrtx); +// vecExpCrossFI[ indAfter ].setNewEdgVertex(newEdgVrtx); + +// DiamondVertexInfo dviBefore(); +// DiamondVertexInfo dviAfter(); + + } + + + // create new edges and new faces + + std::vector newFracFaceVec = std::vector(); + + bool boundAtShiftVrtEdg = true; +// bool atStartSort = true; + + // ecf typ: ExpandCrossFracInfo + + for( auto const & ecf : vecExpCrossFI ) + { + + static_assert( std::is_same< ExpandCrossFracInfo const &, decltype( ecf ) >::value ); + // get new vertex at the original fracture edge + + // extract this functionality to own function + +// void createNewFacesForExtXCrossFracs( ExpandCrossFracInfo const & ecf, +// std::vector & newFracFaceVec, +// +// ) + +// createNewFacesForExtXCrossFracs( ecf, newFracFaceVec, boundAtShiftVrtEdg, atStartSort, sh, grid, crossPt, subdomList ); + createNewFacesForExtXCrossFracs( ecf, newFracFaceVec, boundAtShiftVrtEdg, sh, grid, crossPt, subdomList ); + +#if 0 + std::pair edgesCrossSeg = ecf.getEdge(); + + Face * facSeg = ecf.getFace(); + + std::pair vertcsCrossSeg = ecf.getNormal(); + + std::pair vertcsCrossSegWithNewV = ecf.getNewNormal(); + + + if( atStartSort || boundAtShiftVrtEdg ) + { + if( vertcsCrossSeg.first != nullptr || vertcsCrossSeg.second == nullptr ) + UG_THROW("Verwechslung " << vertcsCrossSeg.first << " " << vertcsCrossSeg.second << std::endl); + } + + atStartSort = false; + + Edge * fracEdge = boundAtShiftVrtEdg ? edgesCrossSeg.first : edgesCrossSeg.second; + Edge * shiftVrtEdge = boundAtShiftVrtEdg ? edgesCrossSeg.second : edgesCrossSeg.first; + + Vertex * fracVrtNew = boundAtShiftVrtEdg ? vertcsCrossSegWithNewV.first : vertcsCrossSegWithNewV.second; // should be nullptr at first segment, to be assigned afterwards / shifted + Vertex * shiftVrt = boundAtShiftVrtEdg ? vertcsCrossSeg.second : vertcsCrossSeg.first; + Vertex * shiftVrtTest = boundAtShiftVrtEdg ? vertcsCrossSegWithNewV.second : vertcsCrossSegWithNewV.first; + + if( shiftVrtTest != shiftVrt ) + UG_THROW("Shift Vertex verloren gegangen " << std::endl); + + IndexType sudoFac = sh.get_subset_index(facSeg); + + IndexType sudoFracEdge = sh.get_subset_index(fracEdge); + + if( sudoFac != sudoFracEdge ) + { + UG_THROW("subdoms frac edge und face nicht gleich " << std::endl); + } + + // get all vertices of face, check if both known ones are contained, delete the face, create + // the additional needed edge, and create new face with new vertex + + + std::vector vrtcsFace; + // assign first old vertices, then replace +// std::vector vrtcsNewFaceFrac = vrtcsFace; +// std::vector vrtcsNewFaceDiam = vrtcsFace; + + // all new vertices have been assigned to newVrts. + // Note that if newVrts[i] == NULL, then we have to take the + // old vertex sf->vertex(i). + // now expand the fracture edges of sf to faces. + for(size_t iVrt = 0; iVrt < facSeg->num_vertices(); iVrt++ ) + { + + Vertex * vrt = facSeg->vertex(iVrt); + vrtcsFace.push_back( vrt ); +// vrtcsNewFaceFrac.push_back( vrt ); +// vrtcsNewFaceDiam.push_back( vrt ); + } + + std::vector vrtcsNewFaceFrac = vrtcsFace; +// std::vector vrtcsNewFaceDiam = vrtcsFace; + + + // check if known vertices are contained + + IndexType fraVeNuInd = -1; + IndexType shiftVeNuInd = -1; + + IndexType cntr = 0; + + for( auto const & vf : vrtcsFace ) + { + if( vf == fracVrtNew ) + { + fraVeNuInd = cntr; + UG_THROW("wie kann man hierher kommen?" << std::endl); + } + + if( vf == crossPt ) + { + fraVeNuInd = cntr; + } + +// + if( vf == shiftVrt ) + shiftVeNuInd = cntr; + + cntr++; + } + + if( fraVeNuInd < 0 || shiftVeNuInd < 0 ) + UG_THROW("frac vertex oder shift vertex not contained " << std::endl); + + UG_LOG("neuer frac vertex " << fraVeNuInd << " " << shiftVeNuInd << std::endl ); + + // replace vrtcs + vrtcsNewFaceFrac[fraVeNuInd] = fracVrtNew; + + // compute shift of center vertex along frac edge + + // check subdom of frac vertex and check if in subdom List of X cross + + IndexType sudoOther = -1; + + IndexType foundSudoOther = 0; + IndexType foundSudoFac = 0; + + for( auto const & sd : subdomList ) + { + if( sd != sudoFac ) + { + sudoOther = sd; + foundSudoOther++; + } + else if( sd == sudoFac ) + { + foundSudoFac++; + } + else + { + UG_THROW("Sudo not from frac and not from other?" << std::endl); + } + } + + if( foundSudoFac != 1 && foundSudoOther != 1 ) + UG_THROW("sudo zu oft oder zu selten gefunden " << std::endl); + + // establish new edges and new faces + + if( vrtcsNewFaceFrac.size() != 4 ) + UG_LOG("komische Groesse Gesicht " << std::endl); + + for( IndexType i = 0; i < vrtcsNewFaceFrac.size(); i++ ) + { + if( vrtcsNewFaceFrac[i] == nullptr ) + { + UG_THROW("null auf " << i << std::endl); + } +// else +// { +// UG_LOG("kein null auf " << i << std::endl ); +// } + } + + + UG_LOG("neue Gesichter ausserhalb Diamant Ziel " << std::endl); + +// int a = 1 + 2; +// + Face * newFracFace = + *grid.create( QuadrilateralDescriptor( vrtcsNewFaceFrac[0], vrtcsNewFaceFrac[1], + vrtcsNewFaceFrac[2], vrtcsNewFaceFrac[3] + ) ); + + sh.assign_subset(newFracFace, sh.get_subset_index(facSeg) ); +// sh.assign_subset(newFracFace, diamantSubsNum ); testweise + + newFracFaceVec.push_back(newFracFace); + + boundAtShiftVrtEdg = ! boundAtShiftVrtEdg; +#endif + + } + + UG_LOG("neue Gesichter ausserhalb Diamant erzeugt " << std::endl); + + std::vector newDiamFaceVec = std::vector(); + + for( int indC = 0; indC < vecfis-1; indC = indC + 2 ) + { +// IndexType indBefore = ( indC + vecExpCrossFI.size() ) % vecExpCrossFI.size(); +// IndexType indAfter = ( indC + 1 + vecExpCrossFI.size() ) % vecExpCrossFI.size(); + IndexType indBefore = ( indC + vecfis ) % vecfis; + IndexType indAfter = ( indC + 1 + vecfis ) % vecfis; + + + ExpandCrossFracInfo & expCFIBeforeFracEdg = vecExpCrossFI[ indBefore ]; + ExpandCrossFracInfo & expCFIAfterFracEdg = vecExpCrossFI[ indAfter ]; + + // auslagern + +// createDiamondFacesXCrossType( ExpandCrossFracInfo & expCFIBeforeFracEdg, ExpandCrossFracInfo & expCFIAfterFracEdg, +// std::vector newDiamFaceVec ) + +#if 1 + createDiamondFacesXCrossType( expCFIBeforeFracEdg, expCFIAfterFracEdg, + newDiamFaceVec, sh, grid, diamantSubsNum, crossPt ); + +#else + Face * facBefore = expCFIBeforeFracEdg.getFace(); + Face * facAfter = expCFIAfterFracEdg.getFace(); + + std::vector vrtcsFaceBefore; + std::vector vrtcsFaceAfter; + + + for(size_t iVrt = 0; iVrt < facBefore->num_vertices(); iVrt++ ) + { + Vertex * vrt = facBefore->vertex(iVrt); + vrtcsFaceBefore.push_back( vrt ); + } + + for(size_t iVrt = 0; iVrt < facAfter->num_vertices(); iVrt++ ) + { + Vertex * vrt = facAfter->vertex(iVrt); + vrtcsFaceAfter.push_back( vrt ); + } + + Vertex * newVrtBefore = expCFIBeforeFracEdg.getNewNormal().first; + Vertex * shiftVrt = expCFIBeforeFracEdg.getNewNormal().second; + Vertex * newVrtAfter = expCFIAfterFracEdg.getNewNormal().second; + + if( expCFIBeforeFracEdg.getNewNormal().second != expCFIBeforeFracEdg.getNormal().second + || expCFIBeforeFracEdg.getNewNormal().second == nullptr + || expCFIBeforeFracEdg.getNewNormal().second != expCFIAfterFracEdg.getNewNormal().first + || expCFIAfterFracEdg.getNewNormal().first == nullptr + || expCFIAfterFracEdg.getNewNormal().first != expCFIAfterFracEdg.getNormal().first + ) + { + UG_THROW("Vektorchaos " << std::endl); + } + + std::vector vrtxSmallDiam; + + vrtxSmallDiam.push_back( crossPt ); + vrtxSmallDiam.push_back( newVrtBefore ); + vrtxSmallDiam.push_back( shiftVrt ); + vrtxSmallDiam.push_back( newVrtAfter ); + + Face * newFracFace = + *grid.create( QuadrilateralDescriptor( vrtxSmallDiam[0], vrtxSmallDiam[1], + vrtxSmallDiam[2], vrtxSmallDiam[3] + ) ); + + sh.assign_subset(newFracFace, diamantSubsNum ); + + newDiamFaceVec.push_back(newFracFace); + +#endif + + } + +// sh.get_subset_name() XXXXX + +// auto sunam = sh.get_subset_name(subdomList[0]); +// +// for( auto const & su : subdomList ) +// { +// +// } + +// using SuNaTyp = decltype( sh.get_subset_name(0) ); + + static_assert( std::is_same::value ); + + std::string diamNam = std::string("diamant_") + std::string(const_cast( sh.get_subset_name( subdomList[0] ) )) + + std::string("_") + std::string(const_cast( sh.get_subset_name( subdomList[1] ) )); + + sh.set_subset_name(diamNam.c_str(),diamantSubsNum); + + // TODO FIXME in extra Funktion packen, vielfach aufgerufen in der Art! + + assignFaceSubsetToClosedFace( newFracFaceVec, grid, sh ); + +// for( auto const & nF : newFracFaceVec ) +// { +// for(size_t iEdge = 0; iEdge < nF->num_edges(); iEdge++ ) +// { +// Edge* edg = grid.get_edge(nF, iEdge); +// +// sh.assign_subset( edg, sh.get_subset_index(nF) ); +// +// } +// +// for( size_t iVrt = 0; iVrt < nF->num_vertices(); iVrt++ ) +// { +// Vertex * vrt = nF->vertex(iVrt); +// +// sh.assign_subset( vrt, sh.get_subset_index(nF) ); +// } +// +// } + + assignFaceSubsetToClosedFace( newDiamFaceVec, grid, sh ); + + +// for( auto const & nF : newDiamFaceVec ) +// { +// for(size_t iEdge = 0; iEdge < nF->num_edges(); iEdge++ ) +// { +// Edge* edg = grid.get_edge(nF, iEdge); +// +// sh.assign_subset( edg, sh.get_subset_index(nF) ); +// +// } +// +// for( size_t iVrt = 0; iVrt < nF->num_vertices(); iVrt++ ) +// { +// Vertex * vrt = nF->vertex(iVrt); +// +// sh.assign_subset( vrt, sh.get_subset_index(nF) ); +// } +// +// } + + +#if 0 + // at end delete all fracture edges which are too long + + for( auto const & fdel : vecExpCrossFI ) + { + Face * fac2BeDeleted = fdel.getFace(); + + if( fac2BeDeleted != nullptr ) + grid.erase(fac2BeDeleted); + else + UG_THROW("hier fehlt ein Gesicht " << std::endl); + } + +// IndexType subsNumNow = sh.num_subsets(); +// +//// IndexType susu = subsNumNow; +// +//// UG_LOG("subs num " << susu << std::endl); +// UG_LOG("subs num " << subsNumNow << std::endl); +// + for( auto const & edg : allAssoEdgCP ) + { +// Edge * e2D = oEdg; + + if( edg != nullptr ) + { + UG_LOG("will erasieren " << edg << std::endl ); + grid.erase(edg); + +// sh.assign_subset( e2D, subsNumNow ); +// sh.assign_subset( e2D, subsNumNow ); + } + else + { + UG_LOG("hier fehlt eine Ecke " << std::endl); + } + } + + UG_LOG("ALles erasiert " << std::endl); +#endif +// for( auto & afc : assoFacCross ) +// { +// grid.erase(afc); +// } +// +// // von den Edges, die vom Schnittknoten ausgehen, die anderen Endvertizes merken, dann edges löschen +// +// std::vector assoEdgCross; +// std::vector endVertices; +// +// for( std::vector::iterator iterEdg = grid.associated_edges_begin(crossPt); iterEdg != grid.associated_edges_end(crossPt); iterEdg++ ) +// { +// assoEdgCross.push_back(*iterEdg); +// +// for( size_t i = 0; i < 2; i++ ) +// { +// Vertex * vrtEdgEnd = (*iterEdg)->vertex(i); +// +// if( vrtEdgEnd != crossPt ) +// { +// endVertices.push_back( vrtEdgEnd ); +// } +// } +// } +// +//#if 0 +// vector3 shiftPart; +// VecAdd(shiftPart, fracVrtPos, shiftAlongEdgeTwo); +// +// vector3 posNewVrt; +// VecAdd( posNewVrt, shiftPart, shiftAlongEdgeOne); +// +// UG_LOG("neuer Vertex Kreuzung " << posNewVrt << std::endl ); +// +// Vertex * newShiftVrtx = *grid.create(); +// aaPos[newShiftVrtx] = posNewVrt; +// +//#endif +// +// for( auto & aec : assoEdgCross ) +// { +// grid.erase(aec); +// } + + + } + +#if 1 + for( auto const & fdel : vecExpCrossFI ) + { + Face * fac2BeDeleted = fdel.getFace(); + + if( fac2BeDeleted != nullptr ) + grid.erase(fac2BeDeleted); + else + UG_THROW("hier fehlt ein Gesicht " << std::endl); + } + + for( auto const & edg : allAssoEdgCP ) + { + if( edg != nullptr && edg != avoidToDeleteEdge ) + { + UG_LOG("will erasieren " << edg << std::endl ); + grid.erase(edg); + + } + else + { + UG_LOG("hier fehlt eine Ecke " << std::endl); + } + } + + UG_LOG("ALles erasiert " << std::endl); +#endif + } + +// grid.detach_from_edges( aAdjVert ); + + // die frac vertices entfernen noch + +// for( auto const & cfi : vecCrossVrtInf ) +// { +// IndexType nuCroFra = cfi.getNumbCrossFracs(); +// +// VecEdge origFracEdg = cfi.getVecOrigFracEdges(); +// +// +// if( nuCroFra == 3 ) +// { +// +// } +// else if( nuCroFra == 4 ) +// { +// IndexType subsNumNow = sh.num_subsets(); +// +// // IndexType susu = subsNumNow; +// +// // UG_LOG("subs num " << susu << std::endl); +// UG_LOG("subs num " << subsNumNow << std::endl); +// +// for( auto const & oEdg : origFracEdg ) +// { +// Edge * e2D = oEdg; +// +// if( e2D != nullptr ) +// { +// // grid.erase(edg2BeDel); +// UG_LOG("will erasieren " << e2D << std::endl ); +// +// sh.assign_subset( e2D, subsNumNow ); +// // sh.assign_subset( e2D, subsNumNow ); +// } +// else +// { +// UG_LOG("hier fehlt eine Ecke " << std::endl); +// } +// } +// +// } +// } + + UG_LOG("zu Ende gekommen mit Arte 2D" << std::endl); + + return true; + + // ENDE NEUES ZEUG SELEKTION + + + + + + + +#if FORMER_PROMESH_FINITE_CLEFT_TECHNIQUE + // TODO FIXME von diesem Loop kann man noch für oben die calculate crease normal lernen, vielleicht minimal abgewandelt, vielleicht exakt gleich + + // a callback that returns true if the edge is a fracture edge, neues System + AttachmentUnequal > isFracEdgeB(aaMarkEdgeB, false); + + // iterate over all surrounding faces and create new vertices. + for(FaceIterator iter_sf = sel.faces_begin(); iter_sf != sel.faces_end(); ++iter_sf) + { + Face* sf = *iter_sf; + + // check for each vertex whether it lies in the fracture + // (aaMarkVRT > 1 in this case) + // if so, we have to copy or create a vertex from/in aaVrtVec[vrt] which is + // associated with the crease normal on the side of sf. + for(size_t i_vrt = 0; i_vrt < sf->num_vertices(); ++i_vrt) + { + Vertex* vrt = sf->vertex(i_vrt); + if(aaMarkVRT[vrt] > 1) + { + // calculate the normal on this side of the frac + // TODO FIXME so eine Funktion brauchen wir vielleicht oben auch zur Vereinfachung des Codes!!! + vector3 n_v2 = CalculateCreaseNormal(grid, sf, vrt, isFracEdgeB, aaPos); + // das calculate crease normal scheint mir ein Schwachsinn zu sein + // aber vielleicht doch nicht? + + UG_LOG("calculated crease normal v2: " << n_v2 << endl); + + } + } +#endif + + + + + + + +} + + + +}// end of namespace + diff --git a/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.h b/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.h index d38c7fb52..f2b17fbc9 100644 --- a/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.h +++ b/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.h @@ -1,13 +1,43 @@ /* * expand_layers_arte.h * - * Created on: 11.07.2024 - * Author: mknodel + * Created on: 5.8.2024 + * Author: Markus M. Knodel + * This file is part of UG4. + * + * UG4 is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License version 3 (as published by the + * Free Software Foundation) with the following additional attribution + * requirements (according to LGPL/GPL v3 §7): + * + * (1) The following notice must be displayed in the Appropriate Legal Notices + * of covered and combined works: "Based on UG4 (www.ug4.org/license)". + * + * (2) The following notice must be displayed at a prominent place in the + * terminal output of covered works: "Based on UG4 (www.ug4.org/license)". + * + * (3) The following bibliography is recommended for citation and must be + * preserved in all covered files: + * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively + * parallel geometric multigrid solver on hierarchically distributed grids. + * Computing and visualization in science 16, 4 (2013), 151-164" + * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel + * flexible software system for simulating pde based models on high performance + * computers. Computing and visualization in science 16, 4 (2013), 165-179" + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. */ #ifndef UGBASE_LIB_GRID_ALGORITHMS_EXTRUSION_EXPAND_LAYERS_ARTE_H_ #define UGBASE_LIB_GRID_ALGORITHMS_EXTRUSION_EXPAND_LAYERS_ARTE_H_ +#include +#include "lib_grid/lg_base.h" +#include "expand_layers.h" + namespace ug { @@ -23,3 +53,4 @@ bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, std::vector Date: Mon, 5 Aug 2024 02:02:50 +0200 Subject: [PATCH 47/58] additional help classes for arte implementation --- .../lib_grid/algorithms/extrusion/support.h | 125 ++++++++++++++++-- 1 file changed, 117 insertions(+), 8 deletions(-) diff --git a/ugbase/lib_grid/algorithms/extrusion/support.h b/ugbase/lib_grid/algorithms/extrusion/support.h index a424f010e..a641f81ab 100644 --- a/ugbase/lib_grid/algorithms/extrusion/support.h +++ b/ugbase/lib_grid/algorithms/extrusion/support.h @@ -1,3 +1,12 @@ +/* + * support.h + * + * Created on: 5.8.2024 + * Author: Markus M. Knodel +* help classes to implement the Arte algorithm + */ + + #ifndef __SUPPORT_H__ #define __SUPPORT_H__ @@ -202,7 +211,7 @@ class VertexFractureTriple public: VertexFractureTriple( ECKENTYP const & edge, GESICHTSTYP const & face, SENKRECHTENTYP const & normal ) - : m_edge(edge), m_face(face), m_normal(normal) + : m_edge(edge), m_face(face), m_normal(normal), m_newNormal(normal) { }; @@ -212,11 +221,15 @@ class VertexFractureTriple SENKRECHTENTYP const getNormal() const { return m_normal; } + void setNewNormal( SENKRECHTENTYP const & chNorml ) { m_newNormal = chNorml; } + SENKRECHTENTYP const getNewNormal() const { return m_newNormal; } + private: ECKENTYP m_edge; GESICHTSTYP m_face; SENKRECHTENTYP m_normal; + SENKRECHTENTYP m_newNormal; VertexFractureTriple() {}; @@ -226,39 +239,135 @@ class VertexFractureTriple ////////////////////////////////////////////////////////////////// -template < typename VRT, typename IndTyp > //, typename EDG > +template < typename VRT, typename IndTyp > //, typename EDG > //, typename SHIFTINFO > //, typename FAC > class CrossingVertexInfo { + public: + enum FracTyp { SingleFrac = 2, TEnd = 3, XCross = 4 }; + CrossingVertexInfo( VRT const & crossVrt, IndTyp numbCrossFracs ) - : m_crossVrt(crossVrt), m_numbCrossFracs( numbCrossFracs ), m_vecShiftedVrts(std::vector()) - //,m_vecOrigEdges(std::vector()) + : m_crossVrt(crossVrt), m_numbCrossFracs( numbCrossFracs ), + m_vecShiftedVrts(std::vector()) //, m_vecOrigEdges(std::vector()) //, m_vecAdjFracFac( std::vector() ) +// m_shiftInfo(std::vector()) + , m_vecShiftedVrtsWithTypInf(std::vector>()) + , m_numberAtFreeSide(0) { - + if( numbCrossFracs == 2 ) + { + m_fracTyp = SingleFrac; + } + if( numbCrossFracs == 3 ) + { + m_fracTyp = TEnd; + } + else if( numbCrossFracs == 4 ) + { + m_fracTyp = XCross; + } + else + { + UG_LOG("frac typ wrong " << numbCrossFracs << std::endl); + } } VRT getCrossVertex() const { return m_crossVrt; } - IndTyp getNumbCrossFracs() const { return m_numbCrossFracs; } +// IndTyp getNumbCrossFracs() const { return m_numbCrossFracs; } + FracTyp getFracTyp() const { return m_fracTyp; } - void addShiftVrtx( VRT const & vrt ) + void addShiftVrtx( VRT const & vrt, bool isAtFreeSide = false ) { +// if( m_fracTyp == XCross ) m_vecShiftedVrts.push_back(vrt); + +// if( isAtFreeSide ) +// UG_THROW("XCross ohne freie Seite " << std::endl); + + if( m_fracTyp == TEnd ) + { + std::pair addSVI( vrt, isAtFreeSide ); + m_vecShiftedVrtsWithTypInf.push_back(addSVI); + + if( isAtFreeSide ) + m_numberAtFreeSide++; + + if( m_numberAtFreeSide > 1 ) + UG_THROW("was ist das fuer ein T Ende" << std::endl); + } + } // void addOriginalFracEdge( EDG const & edg ) { m_vecOrigEdges.push_back(edg); } - std::vector getVecShiftedVrts() const { return m_vecShiftedVrts; } +// void addShiftInfo( SHIFTINFO const & shi ) { m_shiftInfo.push_back(shi); } + +// void addAdjntFracFaces( FAC const & fac ) { m_vecAdjFracFac.push_back(fac); } + + void setShiftVrtx( std::vector const & vecVrt ) { m_vecShiftedVrts = vecVrt; } + +// void setOriginalFracEdge( std::vector const & vecEdg ) { m_vecOrigEdges = vecEdg; } + +// void setShiftInfo( SHIFTINFO const & vecShi ) { m_shiftInfo = vecShi; } + +// void setAdjntFracFaces( std::vector const & vecFac ) { m_vecAdjFracFac = vecFac; } + +// void addShiftVectors( vector3 const & projectNrmFraOneToEdgTwoDirection, vector3 const & projectNrmFraTwoToEdgOneDirection, IndexType segmentNum ) +// { +// m_projectNrmFraOneToEdgTwoDirection = projectNrmFraOneToEdgTwoDirection; +// m_projectNrmFraTwoToEdgOneDirection = projectNrmFraTwoToEdgOneDirection; +// } + + + + std::vector getVecShiftedVrts() const + { +// if( m_fracTyp != XCross ) +// UG_LOG("fuer Kreuz nicht erlaubt " << std::endl); + + return m_vecShiftedVrts; + } + + std::vector> getVecShiftedVrtsWithTypInfo() const + { + if( m_fracTyp != TEnd ) + UG_THROW("fuer Kreuz nicht erlaubt " << std::endl); + + return m_vecShiftedVrtsWithTypInf; + } + // std::vector getVecOrigFracEdges() const { return m_vecOrigEdges; } +// std::vector getShiftInfo() const { return m_shiftInfo; } + + + +// std::vector getVecAdjntFracFaces() const { return m_vecAdjFracFac; } + +// std::pair getShiftVectors( ) const +// { +// std::pair shiVe; +// +// shiVe.first = m_projectNrmFraOneToEdgTwoDirection; +// shiVe.second = m_projectNrmFraTwoToEdgOneDirection; +// +// return shiVe; +// } + private: VRT m_crossVrt; IndTyp m_numbCrossFracs; std::vector m_vecShiftedVrts; + std::vector> m_vecShiftedVrtsWithTypInf; // std::vector m_vecOrigEdges; +// std::vector m_vecAdjFracFac; +// vector3 m_projectNrmFraOneToEdgTwoDirection, m_projectNrmFraTwoToEdgOneDirection; +// std::vector m_shiftInfo; + FracTyp m_fracTyp; + IndTyp m_numberAtFreeSide; }; From 4361651b102c5540bfb6b5c103e90a360bc6b084 Mon Sep 17 00:00:00 2001 From: Markus Date: Mon, 5 Aug 2024 02:13:19 +0200 Subject: [PATCH 48/58] static asserts auskommentiert --- .../extrusion/expand_layers_arte.cpp | 100 +++++++++--------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.cpp b/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.cpp index d8292b7b0..1c66a54db 100644 --- a/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.cpp +++ b/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.cpp @@ -234,14 +234,14 @@ bool expandSingleFractureAtGivenSide( vector3 const & nOne, vector3 const & nTwo for( auto const & facFrac : attFac ) { - static_assert( std::is_same< decltype( (facFrac) ), decltype ( ifac ) >::value ); + // DEBUG ASSERT TEST static_assert( std::is_same< decltype( (facFrac) ), decltype ( ifac ) >::value ); if( ifac == facFrac ) { isFromFrac = true; - static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value ); - static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value ); + // DEBUG ASSERT TEST static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value ); + // DEBUG ASSERT TEST static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value ); } } @@ -2377,7 +2377,7 @@ bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, vector if( expandInnerFracBnds && !expandOuterFracBnds && aaMarkVrtVFP[*iter].getIsBndFracVertex() ) wahl = false; - static_assert( std::is_same< decltype(*iter), Vertex * >::value ); + // DEBUG ASSERT TEST static_assert( std::is_same< decltype(*iter), Vertex * >::value ); bool isBnd = aaMarkVrtVFP[ *iter ].getIsBndFracVertex(); auto numCrosFrac = aaMarkVrtVFP[ *iter ].getNumberFracEdgesInVertex(); @@ -2484,13 +2484,13 @@ bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, vector auto sudoEdg = sh.get_subset_index(*iterEdg); - static_assert( std::is_same< decltype(sudoEdg), int >::value ); + // DEBUG ASSERT TEST static_assert( std::is_same< decltype(sudoEdg), int >::value ); // get vertices of edge, always 2 std::vector verticesEdg; - static_assert( std::is_same< Vertex*, decltype( (*iterEdg)->vertex(0) ) >::value ); + // DEBUG ASSERT TEST static_assert( std::is_same< Vertex*, decltype( (*iterEdg)->vertex(0) ) >::value ); for( size_t i = 0; i < 2; ++i ) verticesEdg.push_back( (*iterEdg)->vertex(i) ); @@ -2530,8 +2530,8 @@ bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, vector std::vector assFace; -// static_assert( std::is_same< decltype( aaVrtInfoAssoFaces[verticesEdg[0]] )[0], std::vector >::value ); - //static_assert( std::is_same< decltype( *(aaVrtInfoAssoFaces[verticesEdg[0]]) ), Face * >::value ); +// // DEBUG ASSERT TEST static_assert( std::is_same< decltype( aaVrtInfoAssoFaces[verticesEdg[0]] )[0], std::vector >::value ); + //// DEBUG ASSERT TEST static_assert( std::is_same< decltype( *(aaVrtInfoAssoFaces[verticesEdg[0]]) ), Face * >::value ); // UG_LOG("XXXXXXXXXXXX" << std::endl); @@ -2584,7 +2584,7 @@ bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, vector // VecFace & assoFaces = aaVrtInfoAssoFaces[*iterV ist verticesEdg[0] ]; // for( auto const & ifac : assoFaces ) // { - // static_assert( std::is_same< decltype( ifac ), Face * const & >::value ); + // // DEBUG ASSERT TEST static_assert( std::is_same< decltype( ifac ), Face * const & >::value ); // } @@ -2619,11 +2619,11 @@ bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, vector edgeNormals.push_back( tmpN ); - static_assert( std::is_same< Edge*, decltype(*iterEdg) >::value ); + // DEBUG ASSERT TEST static_assert( std::is_same< Edge*, decltype(*iterEdg) >::value ); - static_assert( std::is_same< Face * const &, decltype(fac) >::value ); - static_assert( std::is_same< Face *, decltype( const_cast(fac) ) >::value ); - static_assert( std::is_same< vector3, decltype( tmpN ) >::value ); + // DEBUG ASSERT TEST static_assert( std::is_same< Face * const &, decltype(fac) >::value ); + // DEBUG ASSERT TEST static_assert( std::is_same< Face *, decltype( const_cast(fac) ) >::value ); + // DEBUG ASSERT TEST static_assert( std::is_same< vector3, decltype( tmpN ) >::value ); VertFracTrip infoVertizesThisEdge( *iterEdg, fac, tmpN ); @@ -2634,21 +2634,21 @@ bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, vector for( auto const & v : verticesEdg ) { - static_assert( std::is_same< decltype(v), Vertex * const & >::value ); - static_assert( std::is_same< decltype(const_cast(v)), Vertex * >::value ); + // DEBUG ASSERT TEST static_assert( std::is_same< decltype(v), Vertex * const & >::value ); + // DEBUG ASSERT TEST static_assert( std::is_same< decltype(const_cast(v)), Vertex * >::value ); aaVrtInfoFraTri[v].push_back( infoVertizesThisEdge ); // VecVertFracTrip allInfosVrtxThisEdg = aaVrtInfoFraTri[v]; -// static_assert( std::is_same< decltype( aaVrtInfoFraTri[v] ), VecVertFracTrip >::value ); +// // DEBUG ASSERT TEST static_assert( std::is_same< decltype( aaVrtInfoFraTri[v] ), VecVertFracTrip >::value ); // UG_LOG("type Fac " << typeid( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getFace() ).name() << std::endl); // UG_LOG("type Edg " << typeid( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getEdge() ).name() << std::endl); // UG_LOG("type Vec " << typeid( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getNormal() ).name() << std::endl); - static_assert( std::is_same< decltype( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getFace() ), Face * >::value ); - static_assert( std::is_same< decltype( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getEdge() ), Edge * >::value ); - static_assert( std::is_same< decltype( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getNormal() ), vector3 const >::value ); + // DEBUG ASSERT TEST static_assert( std::is_same< decltype( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getFace() ), Face * >::value ); + // DEBUG ASSERT TEST static_assert( std::is_same< decltype( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getEdge() ), Edge * >::value ); + // DEBUG ASSERT TEST static_assert( std::is_same< decltype( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getNormal() ), vector3 const >::value ); } } @@ -2806,15 +2806,15 @@ bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, vector std::vector & allAssoEdges = aaVrtInfoAssoEdges[*iterV]; - static_assert( std::is_same< decltype( vecVertFracTrip[ vecVertFracTrip.size() - 1 ].getFace() ), Face * >::value ); - static_assert( std::is_same< decltype( vecVertFracTrip[ vecVertFracTrip.size() - 1 ].getEdge() ), Edge * >::value ); - static_assert( std::is_same< decltype( vecVertFracTrip[ vecVertFracTrip.size() - 1 ].getNormal() ), vector3 const >::value ); + // DEBUG ASSERT TEST static_assert( std::is_same< decltype( vecVertFracTrip[ vecVertFracTrip.size() - 1 ].getFace() ), Face * >::value ); + // DEBUG ASSERT TEST static_assert( std::is_same< decltype( vecVertFracTrip[ vecVertFracTrip.size() - 1 ].getEdge() ), Edge * >::value ); + // DEBUG ASSERT TEST static_assert( std::is_same< decltype( vecVertFracTrip[ vecVertFracTrip.size() - 1 ].getNormal() ), vector3 const >::value ); for( auto const & vft : vecVertFracTrip ) { - static_assert( std::is_same< decltype( vft.getFace() ), Face * >::value ); - static_assert( std::is_same< decltype( vft.getEdge() ), Edge * >::value ); - static_assert( std::is_same< decltype( vft.getNormal() ), vector3 const >::value ); + // DEBUG ASSERT TEST static_assert( std::is_same< decltype( vft.getFace() ), Face * >::value ); + // DEBUG ASSERT TEST static_assert( std::is_same< decltype( vft.getEdge() ), Edge * >::value ); + // DEBUG ASSERT TEST static_assert( std::is_same< decltype( vft.getNormal() ), vector3 const >::value ); Face * f = vft.getFace(); Edge * e = vft.getEdge(); @@ -2831,7 +2831,7 @@ bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, vector // for( auto const & ifac : assoFaces ) // { -// static_assert( std::is_same< decltype( ifac ), Face * const & >::value ); +// // DEBUG ASSERT TEST static_assert( std::is_same< decltype( ifac ), Face * const & >::value ); // } @@ -3113,17 +3113,17 @@ bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, vector for( auto const & facFrac : attFac ) { -// static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype ( ifac ) >::value ); - static_assert( std::is_same< decltype( (facFrac) ), decltype ( ifac ) >::value ); +// // DEBUG ASSERT TEST static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype ( ifac ) >::value ); + // DEBUG ASSERT TEST static_assert( std::is_same< decltype( (facFrac) ), decltype ( ifac ) >::value ); if( ifac == facFrac ) { isFromFrac = true; -// static_assert( std::is_same< decltype( const_cast(facFrac) ), Face * & >::value ); - static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value ); -// static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype( ifac ) >::value ); - static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value ); +// // DEBUG ASSERT TEST static_assert( std::is_same< decltype( const_cast(facFrac) ), Face * & >::value ); + // DEBUG ASSERT TEST static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value ); +// // DEBUG ASSERT TEST static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype( ifac ) >::value ); + // DEBUG ASSERT TEST static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value ); } } @@ -3627,7 +3627,7 @@ bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, vector // for( std::vector::iterator iterF2 = attFac.begin(); iterF2 != attFac.end(); iterF2++ ) // { -// static_assert( std::is_same< decltype( *iterF2 ), decltype ( *iterFac ) >::value ); +// // DEBUG ASSERT TEST static_assert( std::is_same< decltype( *iterF2 ), decltype ( *iterFac ) >::value ); // // } @@ -3641,7 +3641,7 @@ bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, vector // // UG_LOG("type iter Fac " << typeid( *iterFac ).name() << std::endl); - static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype ( *iterFac ) >::value ); + // DEBUG ASSERT TEST static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype ( *iterFac ) >::value ); @@ -3650,8 +3650,8 @@ bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, vector { isFromFrac = true; - static_assert( std::is_same< decltype( const_cast(facFrac) ), Face * & >::value ); - static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype( * iterFac ) >::value ); + // DEBUG ASSERT TEST static_assert( std::is_same< decltype( const_cast(facFrac) ), Face * & >::value ); + // DEBUG ASSERT TEST static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype( * iterFac ) >::value ); } } @@ -3810,7 +3810,7 @@ bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, vector // for( auto const & ifac : assoFaces ) // { - // static_assert( std::is_same< decltype( ifac ), Face * const & >::value ); + // // DEBUG ASSERT TEST static_assert( std::is_same< decltype( ifac ), Face * const & >::value ); // // // TODO FIXME folgenden loop durch diesen ersetzen // // Achtung: Zeigerproblematik, Referenzen, etc..... @@ -3830,17 +3830,17 @@ bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, vector for( auto const & facFrac : attFac ) { -// static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype ( ifac ) >::value ); - static_assert( std::is_same< decltype( (facFrac) ), decltype ( ifac ) >::value ); +// // DEBUG ASSERT TEST static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype ( ifac ) >::value ); + // DEBUG ASSERT TEST static_assert( std::is_same< decltype( (facFrac) ), decltype ( ifac ) >::value ); if( ifac == facFrac ) { isFromFrac = true; -// static_assert( std::is_same< decltype( const_cast(facFrac) ), Face * & >::value ); - static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value ); -// static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype( ifac ) >::value ); - static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value ); +// // DEBUG ASSERT TEST static_assert( std::is_same< decltype( const_cast(facFrac) ), Face * & >::value ); + // DEBUG ASSERT TEST static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value ); +// // DEBUG ASSERT TEST static_assert( std::is_same< decltype( const_cast(facFrac) ), decltype( ifac ) >::value ); + // DEBUG ASSERT TEST static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value ); } } @@ -5340,9 +5340,9 @@ bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, vector // std::vector verticesEdg; - static_assert( std::is_same< Edge* const &, decltype( bE ) >::value ); + // DEBUG ASSERT TEST static_assert( std::is_same< Edge* const &, decltype( bE ) >::value ); - static_assert( std::is_same< Vertex*, decltype( bE->vertex(0) ) >::value ); + // DEBUG ASSERT TEST static_assert( std::is_same< Vertex*, decltype( bE->vertex(0) ) >::value ); IndexType fndIV = 0; @@ -5791,7 +5791,7 @@ bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, vector auto & bED = bndEdgeDirection[segInd]; - static_assert( std::is_same< decltype( bED), vector3 & >::value ); + // DEBUG ASSERT TEST static_assert( std::is_same< decltype( bED), vector3 & >::value ); vector3 & nrmEdg = normalFrac; //normalBnd; @@ -6241,8 +6241,8 @@ bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, vector // for( auto edg : origFracEdg ) // { // -// static_assert( std::is_same< decltype( edg ), Edge * >::value ); -// // static_assert( std::is_same< const_cast(decltype( edg )), Edge * >::value ); +// // DEBUG ASSERT TEST static_assert( std::is_same< decltype( edg ), Edge * >::value ); +// // // DEBUG ASSERT TEST static_assert( std::is_same< const_cast(decltype( edg )), Edge * >::value ); // // // //Vertex* vrtSpliEd = // // if( edg != nullptr ) @@ -7602,7 +7602,7 @@ bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, vector for( auto const & ecf : vecExpCrossFI ) { - static_assert( std::is_same< ExpandCrossFracInfo const &, decltype( ecf ) >::value ); + // DEBUG ASSERT TEST static_assert( std::is_same< ExpandCrossFracInfo const &, decltype( ecf ) >::value ); // get new vertex at the original fracture edge // extract this functionality to own function @@ -7868,7 +7868,7 @@ bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, vector // using SuNaTyp = decltype( sh.get_subset_name(0) ); - static_assert( std::is_same::value ); + // DEBUG ASSERT TEST static_assert( std::is_same::value ); std::string diamNam = std::string("diamant_") + std::string(const_cast( sh.get_subset_name( subdomList[0] ) )) + std::string("_") + std::string(const_cast( sh.get_subset_name( subdomList[1] ) )); From cb6afd42e8c34736522073b7a30c70093c8e1433 Mon Sep 17 00:00:00 2001 From: Moritz Kowalski Date: Thu, 15 Aug 2024 16:28:03 +0200 Subject: [PATCH 49/58] Add every status in PBS scheduler --- scripts/shell/schedulers/pbs-generic | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/scripts/shell/schedulers/pbs-generic b/scripts/shell/schedulers/pbs-generic index 921d21f72..c49b3a4c8 100755 --- a/scripts/shell/schedulers/pbs-generic +++ b/scripts/shell/schedulers/pbs-generic @@ -110,13 +110,15 @@ function UJS_Info sub(/\..*$/, "", $1) status = $10 - if (status == "R") { + if (status == "R" || status == "E") { status = "RUNNING" - } else if (status == "Q") { + } else if (status == "Q" || status == "H" || status == "W" || status == "T" || status == "S") { + status = "PENDING" + } else { status = "PENDING" } print $1, $2, $3, $4, $5, $6, $7, $8, $9, status, $11 - }' # change status to RUNNING or PENDING + }' # change every status to RUNNING or PENDING, fallback to PENDING ) | column -t # format output as table } From dfb323acba452fba2bd82a6151942476bf71af8c Mon Sep 17 00:00:00 2001 From: Dmitriy Logashenko Date: Sun, 1 Sep 2024 15:26:17 +0300 Subject: [PATCH 50/58] Tools for conversion of different Lua types to ConstUserData objects. --- scripts/util/user_data_util.lua | 102 +++++++++++++++++++++++++++----- 1 file changed, 86 insertions(+), 16 deletions(-) diff --git a/scripts/util/user_data_util.lua b/scripts/util/user_data_util.lua index 742aafde3..d0bded56e 100644 --- a/scripts/util/user_data_util.lua +++ b/scripts/util/user_data_util.lua @@ -111,9 +111,79 @@ function FreeUserData() collectgarbage("collect") end +-------------------------------------------------------------------------------- +-- Conversion of types +-------------------------------------------------------------------------------- + +function ToUserNumber (o, my_dim) + if my_dim == nil then my_dim = GetUGDim() end + + if type(o) == "number" then + return _G["ConstUserNumber"..my_dim.."d"](o) + elseif type(o) == "function" then + return _G["LuaUserNumber"..my_dim.."d"](o) + elseif type(o) == "string" then + return _G["LuaUserNumber"..my_dim.."d"](_G[o]) -- we assume a function as the argument + elseif type(o) == "userdata" then -- ToDo: Provide a better condition! + return o + end + return nil -- this indicates an error +end +function ToUserVector (o, my_dim) + if my_dim == nil then my_dim = GetUGDim() end + + if type(o) == "table" then + return _G["ConstUserVector"..my_dim.."d"](o) + elseif type(o) == "function" then + return _G["LuaUserVector"..my_dim.."d"](o) + elseif type(o) == "string" then + return _G["LuaUserVector"..my_dim.."d"](_G[o]) -- we assume a function as the argument + elseif type(o) == "userdata" then -- ToDo: Provide a better condition! + return o + end + return nil -- this indicates an error +end -function __ug__CheckUserDataArgType(r, l) +function ToUserMatrix (o, my_dim) + if my_dim == nil then my_dim = GetUGDim() end + + if type(o) == "number" then + return _G["ConstUserMatrix"..my_dim.."d"](o) + elseif type(o) == "table" then + local i, j + local m = _G["ConstUserMatrix"..my_dim.."d"]() + for i = 0, my_dim-1 do + if type(o[i+1]) ~= "table" then + print ("Illegal specification of a matrix by a table: Specify the rows as subtables.\n") + return nil + end + for j = 0, my_dim-1 do + local val = o [i+1] [j+1] + if type(val) ~= "number" then + print ("Illegal specification of a matrix by a table at (" .. i+1 .. ", " .. j+1 ..").\n") + return nil + end + m:set_entry (i, j, val) + end + end + return m + elseif type(o) == "function" then + return LuaUserMatrix(o) + elseif type(o) == "string" then + return LuaUserMatrix(_G[o]) + elseif type(o) == "userdata" then -- ToDo: Provide a better condition! + return o + end + return nil -- this indicates an error +end + +-------------------------------------------------------------------------------- +---- Overloading Lua arithmetics operators for UserData +-------------------------------------------------------------------------------- + + +local function __ug__CheckUserDataArgType(r, l) local rType = ug_class_name(r) local lType = ug_class_name(l) local rDim = -1 @@ -175,11 +245,11 @@ function __ug__CheckUserDataArgType(r, l) end -------------------------------------------------------------------------------- --- Function to add/subtract UserData +-- Function to Add/Subtract UserData -------------------------------------------------------------------------------- --! functions user when '+/-' is called on an UserData (or a derived implementation) -function __ug__UserNumber_sum(lScale, l, rScale, r) +local function __ug__UserNumber_sum(lScale, l, rScale, r) local rType, lType, rDim, lDim, Dim, rData, lData, Data = __ug__CheckUserDataArgType(r, l) if l == nil or r == nil then @@ -253,12 +323,12 @@ function __ug__UserNumber_sum(lScale, l, rScale, r) end --! functions used when '+' is called on an UserData (or a derived implementation) -function __ug__UserNumber_add(l,r) +local function __ug__UserNumber_add(l,r) return __ug__UserNumber_sum(1.0, l, 1.0, r) end --! functions used when '-' is called on an UserData (or a derived implementation) -function __ug__UserNumber_sub(l,r) +local function __ug__UserNumber_sub(l,r) return __ug__UserNumber_sum(1.0, l, -1.0, r) end @@ -267,7 +337,7 @@ end -------------------------------------------------------------------------------- --! functions user when '*' is called on an UserData (or a derived implementation) -function __ug__UserNumber_mul(l, r) +local function __ug__UserNumber_mul(l, r) local rType, lType, rDim, lDim, Dim, rData, lData, Data = __ug__CheckUserDataArgType(r, l) if l == nil or r == nil then @@ -321,7 +391,7 @@ function __ug__UserNumber_mul(l, r) end --! functions user when '/' is called on an UserData (or a derived implementation) -function __ug__UserNumber_div(l, r) +local function __ug__UserNumber_div(l, r) local rType, lType, rDim, lDim, Dim, rData, lData, Data = __ug__CheckUserDataArgType(r, l) if l == nil or r == nil then @@ -382,11 +452,11 @@ function __ug__UserNumber_div(l, r) end -------------------------------------------------------------------------------- --- Function to Multiply/Devide UserData +-- Function to Raise UserData to a power -------------------------------------------------------------------------------- --! functions user when '^' is called on an UserData (or a derived implementation) -function __ug__UserNumber_pow(l, r) +local function __ug__UserNumber_pow(l, r) if l == nil or r == nil then error("Error in '^': nil value (possibly uninitialized value?)") end @@ -430,28 +500,28 @@ function __ug__UserNumber_pow(l, r) end -------------------------------------------------------------------------------- --- Loop to set the __add functions for UserData +-- Loop to set the arithmetic functions for UserData -------------------------------------------------------------------------------- -function set_user_data_overloads(name) +local function set_user_data_overloads(name) -- request metatable for the classname mt = ug_get_metatable(name) if mt == nil then return end -- set __add function in metatable - mt.__add = _G["__ug__UserNumber_add"] + mt.__add = __ug__UserNumber_add -- set __sub function in metatable - mt.__sub = _G["__ug__UserNumber_sub"] + mt.__sub = __ug__UserNumber_sub -- set __mul function in metatable - mt.__mul = _G["__ug__UserNumber_mul"] + mt.__mul = __ug__UserNumber_mul -- set __div function in metatable - mt.__div = _G["__ug__UserNumber_div"] + mt.__div = __ug__UserNumber_div -- set __pow function in metatable - mt.__pow = _G["__ug__UserNumber_pow"] + mt.__pow = __ug__UserNumber_pow end -- loop some kinds of UserData implementation From 617b0ffd100ec4cdc27db69557c85f7d8a9ed907 Mon Sep 17 00:00:00 2001 From: Dmitriy Logashenko Date: Thu, 5 Sep 2024 15:00:48 +0300 Subject: [PATCH 51/58] An auxiliary function to check if a point is in a bounding box. --- .../math/math_vector_matrix/math_vector_functions.h | 6 ++++++ .../math_vector_functions_common_impl.hpp | 12 ++++++++++++ 2 files changed, 18 insertions(+) diff --git a/ugbase/common/math/math_vector_matrix/math_vector_functions.h b/ugbase/common/math/math_vector_matrix/math_vector_functions.h index 87bfee811..908cd2d0a 100644 --- a/ugbase/common/math/math_vector_matrix/math_vector_functions.h +++ b/ugbase/common/math/math_vector_matrix/math_vector_functions.h @@ -405,6 +405,12 @@ inline bool VecAbsIsLess(const vector_t& v1, const typename vector_t::value_type s); +/// checks if the given point is in the bounding box given by two other points +template +inline +bool +VecIsInBB(const vector_t& v, const vector_t& low, const vector_t& high); + }// end of namespace //////////////////////////////////////////////////////////////////////// diff --git a/ugbase/common/math/math_vector_matrix/math_vector_functions_common_impl.hpp b/ugbase/common/math/math_vector_matrix/math_vector_functions_common_impl.hpp index 5be0bfa8c..6749dfeee 100644 --- a/ugbase/common/math/math_vector_matrix/math_vector_functions_common_impl.hpp +++ b/ugbase/common/math/math_vector_matrix/math_vector_functions_common_impl.hpp @@ -694,6 +694,18 @@ VecAbsIsLess(const vector_t& v1, const typename vector_t::value_type s) return true; } +/// checks if the given point is in the bounding box given by two other points +template +inline +bool +VecIsInBB(const vector_t& v, const vector_t& low, const vector_t& high) +{ + for(typename vector_t::size_type i = 0; i < v.size(); ++i) + if (v[i] < low[i] || high[i] < v[i]) + return false; + return true; +} + }// end of namespace #endif /* __H__COMMON__MathVector_FUNCTIONS_COMMON_IMPL__ */ From 9b30e51d15b8fcae7800c6cbcf473dba53bb56e1 Mon Sep 17 00:00:00 2001 From: Arne Naegel Date: Tue, 10 Sep 2024 19:20:35 +0200 Subject: [PATCH 52/58] Protecting LUA specific. --- ugbase/bindings/lua/lua_user_data_impl.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ugbase/bindings/lua/lua_user_data_impl.h b/ugbase/bindings/lua/lua_user_data_impl.h index 276942437..c989f8941 100644 --- a/ugbase/bindings/lua/lua_user_data_impl.h +++ b/ugbase/bindings/lua/lua_user_data_impl.h @@ -33,7 +33,9 @@ #ifndef __H__UG_BRIDGE__BRIDGES__USER_DATA__USER_DATA_IMPL_ #define __H__UG_BRIDGE__BRIDGES__USER_DATA__USER_DATA_IMPL_ +#ifdef UG_FOR_LUA #include "lua_user_data.h" +#endif #include "lib_disc/spatial_disc/user_data/linker/linker_traits.h" #include "lib_disc/spatial_disc/user_data/const_user_data.h" From 670e01fd64236204e9d829eddf0e8e73e1d28bd6 Mon Sep 17 00:00:00 2001 From: Dmitriy Logashenko Date: Thu, 12 Sep 2024 15:45:52 +0300 Subject: [PATCH 53/58] Bug fix: The bug prevented the subset handlers to be registered in the domain. --- ugbase/lib_disc/domain_util.cpp | 22 ++++++-------------- ugbase/lib_grid/file_io/file_io_ugx_impl.hpp | 2 +- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/ugbase/lib_disc/domain_util.cpp b/ugbase/lib_disc/domain_util.cpp index af233cc1e..f97ddf402 100644 --- a/ugbase/lib_disc/domain_util.cpp +++ b/ugbase/lib_disc/domain_util.cpp @@ -59,23 +59,13 @@ void LoadDomain(TDomain& domain, const char* filename, int procId) //domain.create_additional_subset_handler("markSH"); vector additionalSHNames = domain.additional_subset_handler_names(); SPProjectionHandler ph = make_sp(new ProjectionHandler(domain.geometry3d(), domain.subset_handler())); + vector > ash(additionalSHNames.size()); - if(additionalSHNames.size()>0){ - SmartPtr sh; - vector> ash(additionalSHNames.size()); - for(size_t i_name = 0; i_name < additionalSHNames.size(); ++i_name){ - SmartPtr sh = domain.additional_subset_handler(additionalSHNames[i_name]); - ash[i_name]= sh; - } - - if(!LoadGridFromFile(*domain.grid(), ph, num_ph, *domain.subset_handler(), additionalSHNames, ash, - filename, domain.position_attachment(), procId)) - { - UG_THROW("LoadDomain: Could not load file: "< 0){ + if((num_ph = ugxReader.num_projection_handlers(0)) != 0){ ugxReader.projection_handler(*ph, 0, 0); size_t shIndex = ugxReader.get_projection_handler_subset_handler_index(0, 0); std::string shName2; From 6b8c7d47787be20c168dbf36e90167f75ce8d469 Mon Sep 17 00:00:00 2001 From: Dmitriy Logashenko Date: Thu, 12 Sep 2024 16:31:42 +0300 Subject: [PATCH 54/58] Some cosmetics to the previous bug fix. Note that the bug fix is due to Shuai Lu. --- ugbase/lib_disc/domain_util.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ugbase/lib_disc/domain_util.cpp b/ugbase/lib_disc/domain_util.cpp index f97ddf402..1f853dd79 100644 --- a/ugbase/lib_disc/domain_util.cpp +++ b/ugbase/lib_disc/domain_util.cpp @@ -70,10 +70,8 @@ void LoadDomain(TDomain& domain, const char* filename, int procId) UG_THROW("LoadDomain: Could not load file: "< 0) - { + if(num_ph != 0) domain.set_refinement_projector(ph); - } } From ea1bb5fe2ea1f3b545866b23c16830a47982bf28 Mon Sep 17 00:00:00 2001 From: Arne Naegel Date: Thu, 26 Sep 2024 23:24:33 +0200 Subject: [PATCH 55/58] NULL => nullptr --- .../spatial_disc/disc_util/conv_shape.h | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/ugbase/lib_disc/spatial_disc/disc_util/conv_shape.h b/ugbase/lib_disc/spatial_disc/disc_util/conv_shape.h index 7422f5057..0f486374a 100644 --- a/ugbase/lib_disc/spatial_disc/disc_util/conv_shape.h +++ b/ugbase/lib_disc/spatial_disc/disc_util/conv_shape.h @@ -140,8 +140,8 @@ update(const TFVGeom* geo, const MathMatrix* DiffDisp, bool computeDeriv) { - UG_ASSERT(geo != NULL, "Null pointer"); - UG_ASSERT(Velocity != NULL, "Null pointer"); + UG_ASSERT(geo != nullptr, "Null pointer"); + UG_ASSERT(Velocity != nullptr, "Null pointer"); // \todo: think about: this should be something like scvf.num_sh() const size_t numSH = geo->num_sh(); @@ -280,8 +280,8 @@ update(const TFVGeom* geo, const MathMatrix* DiffDisp, bool computeDeriv) { - UG_ASSERT(geo != NULL, "Null pointer"); - UG_ASSERT(Velocity != NULL, "Null pointer"); + UG_ASSERT(geo != nullptr, "Null pointer"); + UG_ASSERT(Velocity != nullptr, "Null pointer"); // \todo: think about: this should be something like scvf.num_sh() const size_t numSH = geo->num_sh(); @@ -456,8 +456,8 @@ update(const TFVGeom* geo, const MathMatrix* DiffDisp, bool computeDeriv) { - UG_ASSERT(geo != NULL, "Null pointer"); - UG_ASSERT(Velocity != NULL, "Null pointer"); + UG_ASSERT(geo != nullptr, "Null pointer"); + UG_ASSERT(Velocity != nullptr, "Null pointer"); // \todo: think about: this should be something like scvf.num_sh() const size_t numSH = geo->num_sh(); @@ -618,9 +618,9 @@ update(const TFVGeom* geo, const MathMatrix* DiffDisp, bool computeDeriv) { - UG_ASSERT(geo != NULL, "Null pointer"); - UG_ASSERT(Velocity != NULL, "Null pointer"); -// UG_ASSERT(DiffDisp != NULL, "Null pointer"); + UG_ASSERT(geo != nullptr, "Null pointer"); + UG_ASSERT(Velocity != nullptr, "Null pointer"); +// UG_ASSERT(DiffDisp != nullptr, "Null pointer"); // Compute Volume of Element // typedef typename TFVGeom::ref_elem_type ref_elem_type; @@ -644,7 +644,7 @@ update(const TFVGeom* geo, number lambda = -1; // if DiffDisp-Tensor passed, compute lambda - if(DiffDisp != NULL) + if(DiffDisp != nullptr) { // Get Gradients MathVector DiffGrad; @@ -679,7 +679,7 @@ update(const TFVGeom* geo, // Case 1: // full upwind is used /////////////////////////////////////////////////////////////////// - if(lambda <= 0 || DiffDisp == NULL) + if(lambda <= 0 || DiffDisp == nullptr) { // Choose Upwind corner const size_t up = (flux >= 0) ? scvf.from() : scvf.to(); @@ -902,8 +902,8 @@ bool ConvectionShapesSkewedUpwind:: const MathMatrix *DiffDisp, bool computeDeriv) { - UG_ASSERT(geo != NULL, "Null pointer"); - UG_ASSERT(Velocity != NULL, "Null pointer"); + UG_ASSERT(geo != nullptr, "Null pointer"); + UG_ASSERT(Velocity != nullptr, "Null pointer"); // \todo: think about: this should be something like scvf.num_sh() const size_t numSH = geo->num_sh(); @@ -1071,8 +1071,8 @@ bool ConvectionShapesLinearProfileSkewedUpwind:: const MathMatrix *DiffDisp, bool computeDeriv) { - UG_ASSERT(geo != NULL, "Null pointer"); - UG_ASSERT(Velocity != NULL, "Null pointer"); + UG_ASSERT(geo != nullptr, "Null pointer"); + UG_ASSERT(Velocity != nullptr, "Null pointer"); // \todo: think about: this should be something like scvf.num_sh() const size_t numSH = geo->num_sh(); From 40b43411cf1d13ebe8967f7769b901511b8e51eb Mon Sep 17 00:00:00 2001 From: Arne Naegel Date: Fri, 27 Sep 2024 07:59:26 +0200 Subject: [PATCH 56/58] Member variable m_passOnBehaviour now moved to abstract base. Menat to avoid slicing. --- ugbase/lib_grid/attachments/attachment_pipe.h | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/ugbase/lib_grid/attachments/attachment_pipe.h b/ugbase/lib_grid/attachments/attachment_pipe.h index 500427b43..e5fe83003 100644 --- a/ugbase/lib_grid/attachments/attachment_pipe.h +++ b/ugbase/lib_grid/attachments/attachment_pipe.h @@ -238,19 +238,24 @@ template class UG_API AttachmentDataContainer : public IAttachmentData class UG_API IAttachment : public UID { public: - IAttachment() : m_name("undefined") {} - IAttachment(const char* name) : m_name(name) - {assert(m_name);} + IAttachment() : m_name("undefined"), m_passOnBehaviour(false) {} + IAttachment(const char* name) : m_name(name), m_passOnBehaviour(false) + {assert(m_name);} + protected: + IAttachment(bool passOnBehaviour) : m_name("undefined"), m_passOnBehaviour(passOnBehaviour) {} + IAttachment(const char* name, bool passOnBehaviour) : m_name(name), m_passOnBehaviour(passOnBehaviour) {} + public: virtual ~IAttachment() {} virtual IAttachment* clone() = 0; virtual IAttachmentDataContainer* create_container() = 0; - virtual bool default_pass_on_behaviour() const = 0; + bool default_pass_on_behaviour() const {return m_passOnBehaviour;} const char* get_name() {return m_name;} ///< should only be used for debug purposes. protected: const char* m_name; //only for debug + bool m_passOnBehaviour; }; //////////////////////////////////////////////////////////////////////////////////////////////// @@ -265,19 +270,16 @@ template class UG_API Attachment : public IAttachment typedef AttachmentDataContainer ContainerType; typedef T ValueType; - Attachment() : IAttachment(), m_passOnBehaviour(false) {} - Attachment(bool passOnBehaviour) : IAttachment(), m_passOnBehaviour(passOnBehaviour) {} - Attachment(const char* name) : IAttachment(name), m_passOnBehaviour(false) {} - Attachment(const char* name, bool passOnBehaviour) : IAttachment(name), m_passOnBehaviour(passOnBehaviour) {} + Attachment() : IAttachment() {} + Attachment(bool passOnBehaviour) : IAttachment(passOnBehaviour) {} + Attachment(const char* name) : IAttachment(name) {} + Attachment(const char* name, bool passOnBehaviour) : IAttachment(name, passOnBehaviour) {} virtual ~Attachment() {} - virtual IAttachment* clone() {IAttachment* pA = new Attachment; *pA = *this; return pA;} + virtual IAttachment* clone() {IAttachment* pA = new Attachment(this->m_name, this->m_passOnBehaviour); return pA;} virtual IAttachmentDataContainer* create_container() {return new ContainerType;} - virtual bool default_pass_on_behaviour() const {return m_passOnBehaviour;} - IAttachmentDataContainer* create_container(const T& defaultValue) {return new ContainerType(defaultValue);} - protected: - bool m_passOnBehaviour; + IAttachmentDataContainer* create_container(const T& defaultValue) {return new ContainerType(defaultValue);} }; //////////////////////////////////////////////////////////////////////////////////////////////// From 93e58a8bb3a8f3c83e8debf4595cf00968c2af1c Mon Sep 17 00:00:00 2001 From: Arne Naegel Date: Fri, 27 Sep 2024 10:38:35 +0200 Subject: [PATCH 57/58] Revert "Merge pull request #96 from UG4/95-avoid-slicing" This reverts commit 00fe8050e81c277a7df23148e106cc843395aa52, reversing changes made to ea1bb5fe2ea1f3b545866b23c16830a47982bf28. --- ugbase/lib_grid/attachments/attachment_pipe.h | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/ugbase/lib_grid/attachments/attachment_pipe.h b/ugbase/lib_grid/attachments/attachment_pipe.h index e5fe83003..500427b43 100644 --- a/ugbase/lib_grid/attachments/attachment_pipe.h +++ b/ugbase/lib_grid/attachments/attachment_pipe.h @@ -238,24 +238,19 @@ template class UG_API AttachmentDataContainer : public IAttachmentData class UG_API IAttachment : public UID { public: - IAttachment() : m_name("undefined"), m_passOnBehaviour(false) {} - IAttachment(const char* name) : m_name(name), m_passOnBehaviour(false) - {assert(m_name);} - protected: - IAttachment(bool passOnBehaviour) : m_name("undefined"), m_passOnBehaviour(passOnBehaviour) {} - IAttachment(const char* name, bool passOnBehaviour) : m_name(name), m_passOnBehaviour(passOnBehaviour) {} - public: + IAttachment() : m_name("undefined") {} + IAttachment(const char* name) : m_name(name) + {assert(m_name);} virtual ~IAttachment() {} virtual IAttachment* clone() = 0; virtual IAttachmentDataContainer* create_container() = 0; + virtual bool default_pass_on_behaviour() const = 0; - bool default_pass_on_behaviour() const {return m_passOnBehaviour;} const char* get_name() {return m_name;} ///< should only be used for debug purposes. protected: const char* m_name; //only for debug - bool m_passOnBehaviour; }; //////////////////////////////////////////////////////////////////////////////////////////////// @@ -270,16 +265,19 @@ template class UG_API Attachment : public IAttachment typedef AttachmentDataContainer ContainerType; typedef T ValueType; - Attachment() : IAttachment() {} - Attachment(bool passOnBehaviour) : IAttachment(passOnBehaviour) {} - Attachment(const char* name) : IAttachment(name) {} - Attachment(const char* name, bool passOnBehaviour) : IAttachment(name, passOnBehaviour) {} + Attachment() : IAttachment(), m_passOnBehaviour(false) {} + Attachment(bool passOnBehaviour) : IAttachment(), m_passOnBehaviour(passOnBehaviour) {} + Attachment(const char* name) : IAttachment(name), m_passOnBehaviour(false) {} + Attachment(const char* name, bool passOnBehaviour) : IAttachment(name), m_passOnBehaviour(passOnBehaviour) {} virtual ~Attachment() {} - virtual IAttachment* clone() {IAttachment* pA = new Attachment(this->m_name, this->m_passOnBehaviour); return pA;} + virtual IAttachment* clone() {IAttachment* pA = new Attachment; *pA = *this; return pA;} virtual IAttachmentDataContainer* create_container() {return new ContainerType;} - + virtual bool default_pass_on_behaviour() const {return m_passOnBehaviour;} IAttachmentDataContainer* create_container(const T& defaultValue) {return new ContainerType(defaultValue);} + + protected: + bool m_passOnBehaviour; }; //////////////////////////////////////////////////////////////////////////////////////////////// From ca96fdc0b59e27c3bd51baca8034c24bc347ae89 Mon Sep 17 00:00:00 2001 From: Markus Date: Sun, 6 Oct 2024 22:06:28 +0200 Subject: [PATCH 58/58] Arte 2D ready for use --- .../extrusion/expand_layers_arte.cpp | 107 +++++++++++++++--- .../algorithms/extrusion/expand_layers_arte.h | 2 +- 2 files changed, 93 insertions(+), 16 deletions(-) diff --git a/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.cpp b/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.cpp index 1c66a54db..c89d0c809 100644 --- a/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.cpp +++ b/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.cpp @@ -1183,7 +1183,8 @@ bool SortFaces4DiamondCreation( SubsetHandler& sh, std::vector & assoFac void computeDiamondPointXCrossType( ExpandCrossFracInfo & expCFIBeforeFracEdg, ExpandCrossFracInfo & expCFIAfterFracEdg, Vertex * const & crossPt, Grid::VertexAttachmentAccessor & aaPos, SubsetHandler & sh, Grid & grid, IndexType const & diamantSubsNum, - vector3 & distVecNewVrt2SCrossPt + vector3 & distVecNewVrt2SCrossPt, + bool useTrianglesInDiamonds = false // vector3 & distVecNewVrt2ShiVeBefore = vector3(), vector3 & distVecNewVrt2ShiVeAfter = vector3(), // bool computeDistancesNewVrtsToOldShiVe = false ) @@ -1265,12 +1266,53 @@ void computeDiamondPointXCrossType( ExpandCrossFracInfo & expCFIBeforeFracEdg, E vector3 halfSumShift; - VecScale(halfSumShift,sumShift,0.5); + number scaFa = useTrianglesInDiamonds ? 1 : 0.5; + +// VecScale(halfSumShift, sumShift, 0.5); + VecScale( halfSumShift, sumShift, scaFa ); vector3 posNewVrtOnEdg; VecAdd( posNewVrtOnEdg, posCrossPt, halfSumShift ); + // check if not shifting into the wrong direction TODO FIXME + // if length between posFracEnd and posNewVrtOnEdg bigger than length between posFracEnd and crossPt + // then shifted into the wrong direction, Kommando zurück dann! + +// if( useTrianglesInDiamonds ) +// { + // always + + vector3 distVecOld; + VecSubtract(distVecOld, posFracEnd, posCrossPt ); + vector3 distVecNew; + VecSubtract(distVecNew, posFracEnd, posNewVrtOnEdg); + number oldDistSq = VecLength(distVecOld); + number newDistSq = VecLength(distVecNew); + + if( oldDistSq < newDistSq ) + { + VecScale( halfSumShift, sumShift, - scaFa); + VecAdd(posNewVrtOnEdg, posCrossPt, halfSumShift); + } + else if( oldDistSq == newDistSq ) // cross pt would equal new position + { + if( posNewVrtOnEdg != posCrossPt || distVecNew != distVecOld ) + UG_THROW("Denkfehler, Implementation extemer Spezialfall checken" << std::endl); + + vector3 distCorr; + VecScale( distCorr, distVecOld, 0.05 ); + VecAdd( posNewVrtOnEdg, posCrossPt, distCorr ); + // Versuch, den Punkt ein wenig zu verschieben + } + + // TODO FIXME eventuell noch testen, ob die beiden Punkte in einem kleinen Radius liegen und korrigieren, + // eventuell schon vorher, statt zu werfen + if( posNewVrtOnEdg == posCrossPt ) + UG_THROW("Denkfehler Typ 2, Implementation extemer Spezialfall checken" << std::endl); + +// } + Vertex * newEdgVrtx = *grid.create(); aaPos[newEdgVrtx] = posNewVrtOnEdg; @@ -1326,7 +1368,8 @@ void computeDiamondPointXCrossType( ExpandCrossFracInfo & expCFIBeforeFracEdg, E // } } - +// This function creates the new faces outside the diamond, directly attached to the diamond, +// as part of post processing void createNewFacesForExtXCrossFracs( ExpandCrossFracInfo const & ecf, std::vector & newFracFaceVec, bool & boundAtShiftVrtEdg, //bool & atStartSort, @@ -1529,6 +1572,8 @@ void createNewFacesForExtXCrossFracs( ExpandCrossFracInfo const & ecf, std::vec } +// this function creates the new faces of the diamond center, for XCross, but also for free TEnd type crossing fractures + void createDiamondFacesXCrossType( ExpandCrossFracInfo & expCFIBeforeFracEdg, ExpandCrossFracInfo & expCFIAfterFracEdg, std::vector & newDiamFaceVec, SubsetHandler & sh, Grid & grid, IndexType diamantSubsNum, Vertex * & crossPt, bool isFreeTEnd = false ) @@ -1613,7 +1658,6 @@ void createDiamondFacesXCrossType( ExpandCrossFracInfo & expCFIBeforeFracEdg, Ex vrtxSmallDiamAfter.push_back( shiftVrt ); vrtxSmallDiamAfter.push_back( newVrtAfter ); - Face * newFracFaceBefore = *grid.create( TriangleDescriptor( vrtxSmallDiamBefore[0], vrtxSmallDiamBefore[1], vrtxSmallDiamBefore[2] ) ); @@ -2145,9 +2189,14 @@ void teachAssoFacesNewVrtx( VecVertexOfFaceInfo const & segPart, Grid::FaceAttac #endif bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, vector const & fracInfos, - bool expandInnerFracBnds, bool expandOuterFracBnds) +// bool expandInnerFracBnds, bool expandOuterFracBnds + bool useTrianglesInDiamonds, bool establishDiamonds +) { + constexpr bool expandInnerFracBnds = false; + constexpr bool expandOuterFracBnds = true; + // for(EdgeIterator iter = sh.begin(1); iter != sh.end(1); ++iter) // { // size_t sm = sh.num_subsets(); @@ -6101,6 +6150,10 @@ bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, vector // return true; + // only Keile, basic system + if( ! establishDiamonds ) + return true; + // alles detachen, was noch attached ist, da ist einiges hinzu gekommen! @@ -6692,7 +6745,8 @@ bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, vector // shift of free shift point to virtual prolongation of ending fracture center line - computeDiamondPointXCrossType( expCFIBeforeFracEdg, expCFIAfterFracEdg, crossPt, aaPos, sh, grid, sudoTEnd, distVecNewVrt2SCrossPt ); +// computeDiamondPointXCrossType( expCFIBeforeFracEdg, expCFIAfterFracEdg, crossPt, aaPos, sh, grid, sudoTEnd, distVecNewVrt2SCrossPt ); + computeDiamondPointXCrossType( expCFIBeforeFracEdg, expCFIAfterFracEdg, crossPt, aaPos, sh, grid, sudoTEnd, distVecNewVrt2SCrossPt, useTrianglesInDiamonds ); constexpr bool shiftFreePt = false; @@ -6936,6 +6990,8 @@ bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, vector // create new edges and new faces + // edges and faces outside the diamond, at the crossing fractures attached to the diamond + std::vector newFracFaceVec = std::vector(); bool boundAtShiftVrtEdg = false; @@ -6948,6 +7004,8 @@ bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, vector createNewFacesForExtXCrossFracs( ecf, newFracFaceVec, boundAtShiftVrtEdg, sh, grid, crossPt, subdomList ); } + // edges and faces of the diamond itself respectively its analogon for the TEnd case here + std::vector newDiamFaceVec = std::vector(); // ExpandCrossFracInfo & expCFIBeforeFracEdg = vecExpCrossFI[ indBeforeT ]; @@ -6973,10 +7031,14 @@ bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, vector ExpandCrossFracInfo & expCFIAfterFracEdg = vecExpCrossFI[ indAfter ]; +// createDiamondFacesXCrossType( expCFIBeforeFracEdg, expCFIAfterFracEdg, +// newDiamFaceVec, sh, grid, sudoTEnd, crossPt, isAtFreeEnd ); createDiamondFacesXCrossType( expCFIBeforeFracEdg, expCFIAfterFracEdg, - newDiamFaceVec, sh, grid, sudoTEnd, crossPt, isAtFreeEnd ); + newDiamFaceVec, sh, grid, sudoTEnd, crossPt, isAtFreeEnd || useTrianglesInDiamonds ); } +// } + std::string diamNam = std::string("spitzDiam_") + std::string(const_cast( sh.get_subset_name( subdomList[0] ) )) @@ -7448,7 +7510,8 @@ bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, vector vector3 distVecNewVrt2SCrossPt; // not ot interest here, but only with c++17 possible to rule out computation in a clever way - computeDiamondPointXCrossType( expCFIBeforeFracEdg, expCFIAfterFracEdg, crossPt, aaPos, sh, grid, diamantSubsNum, distVecNewVrt2SCrossPt ); +// computeDiamondPointXCrossType( expCFIBeforeFracEdg, expCFIAfterFracEdg, crossPt, aaPos, sh, grid, diamantSubsNum, distVecNewVrt2SCrossPt ); + computeDiamondPointXCrossType( expCFIBeforeFracEdg, expCFIAfterFracEdg, crossPt, aaPos, sh, grid, diamantSubsNum, distVecNewVrt2SCrossPt, useTrianglesInDiamonds ); #if 0 @@ -7800,8 +7863,11 @@ bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, vector // std::vector newDiamFaceVec ) #if 1 +// createDiamondFacesXCrossType( expCFIBeforeFracEdg, expCFIAfterFracEdg, +// newDiamFaceVec, sh, grid, diamantSubsNum, crossPt ); + createDiamondFacesXCrossType( expCFIBeforeFracEdg, expCFIAfterFracEdg, - newDiamFaceVec, sh, grid, diamantSubsNum, crossPt ); + newDiamFaceVec, sh, grid, diamantSubsNum, crossPt, useTrianglesInDiamonds ); #else Face * facBefore = expCFIBeforeFracEdg.getFace(); @@ -8019,20 +8085,31 @@ bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, vector UG_THROW("hier fehlt ein Gesicht " << std::endl); } - for( auto const & edg : allAssoEdgCP ) + if( ! useTrianglesInDiamonds ) // stamdard case { - if( edg != nullptr && edg != avoidToDeleteEdge ) + for( auto const & edg : allAssoEdgCP ) { - UG_LOG("will erasieren " << edg << std::endl ); - grid.erase(edg); + if( edg != nullptr && edg != avoidToDeleteEdge ) + { + UG_LOG("will erasieren " << edg << std::endl ); + grid.erase(edg); + } + else + { + UG_LOG("hier fehlt eine Ecke " << std::endl); + } } - else + } + else + { + for( auto const & edg : origFracEdg ) { - UG_LOG("hier fehlt eine Ecke " << std::endl); + grid.erase(edg); } } + UG_LOG("ALles erasiert " << std::endl); #endif } diff --git a/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.h b/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.h index f2b17fbc9..ecf584f0f 100644 --- a/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.h +++ b/ugbase/lib_grid/algorithms/extrusion/expand_layers_arte.h @@ -46,7 +46,7 @@ namespace ug * */ bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, std::vector const & fracInfos, - bool expandInnerFracBnds, bool expandOuterFracBnds ); + bool useTrianglesInDiamonds, bool establishDiamonds );