diff --git a/Common/CommandLine.cpp b/Common/CommandLine.cpp index 39873e7f8948fbf66ae067d6505c9deb27962ef3..657db5ce90ef3398c7e21561c533e79f63772f76 100644 --- a/Common/CommandLine.cpp +++ b/Common/CommandLine.cpp @@ -1129,10 +1129,6 @@ void GetOptions(int argc, char *argv[]) else Msg::Fatal("Missing argument"); } - else if(!strcmp(argv[i] + 1, "showCompounds")) { - CTX::instance()->geom.hideCompounds = 0; - i++; - } #endif #if defined(__APPLE__) else if(!strncmp(argv[i] + 1, "psn", 3)) { diff --git a/Common/Context.cpp b/Common/Context.cpp index 2fbfe7d5b762d5e770c5791b295402134278acb7..3b149fb555a1c02b5388f08b8893c8e356044de8 100644 --- a/Common/Context.cpp +++ b/Common/Context.cpp @@ -79,7 +79,6 @@ CTX::CTX() : gamepad(0) // need to initialize these too, since the corresponding opt_XXX routines use // the current value to detect changes - geom.hideCompounds = 1; mesh.changed = 0; mesh.qualityInf = mesh.qualitySup = mesh.qualityType = 0; mesh.radiusInf = mesh.radiusSup = 0; diff --git a/Common/Context.h b/Common/Context.h index b34a23fb508980450620d25193ba7b2ae15b0f7b..c5c361aebb8d519c56f0eac3fa43161c1c74135b 100644 --- a/Common/Context.h +++ b/Common/Context.h @@ -80,7 +80,7 @@ struct contextGeometryOptions { double occScaling; int copyMeshingMethod, exactExtrusion; int matchGeomAndMesh; - int hideCompounds, orientedPhysicals, doubleClickedEntityTag; + int orientedPhysicals, doubleClickedEntityTag; int reparamOnFaceRobust; std::string doubleClickedPointCommand, doubleClickedLineCommand; std::string doubleClickedSurfaceCommand, doubleClickedVolumeCommand; diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h index b46b59db529f3aa31221a8e84b5ae2ea5eda32e3..ffe67a003ff4b06ed14ef47627538b7fd9ae7b29 100644 --- a/Common/DefaultOptions.h +++ b/Common/DefaultOptions.h @@ -836,8 +836,6 @@ StringXNumber GeometryOptions_Number[] = { { F|O, "ExtrudeSplinePoints" , opt_geometry_extrude_spline_points, 5. , "Number of control points for splines created during extrusion" }, - { F|O, "HideCompounds" , opt_geometry_hide_compounds, 1. , - "Hide entities that make up compound entities?" }, { F|O, "HighlightOrphans" , opt_geometry_highlight_orphans, 0. , "Highlight orphan entities (lines connected to a single surface, etc.)?" }, diff --git a/Common/OpenFile.cpp b/Common/OpenFile.cpp index 3d27cbcc645ea550eef605924efaf45dbedd6d93..1be10f3bc3dc6967047b213f261770738a877d8a 100644 --- a/Common/OpenFile.cpp +++ b/Common/OpenFile.cpp @@ -745,7 +745,6 @@ void OpenProject(const std::string &fileName) FlGui::instance()->updateViews(true, false); FlGui::instance()->updateFields(); GModel::current()->setSelection(0); - GModel::current()->setCompoundVisibility(); } #endif } diff --git a/Common/Options.cpp b/Common/Options.cpp index 0dad09c0637618c86705c0bf2311bc22563bddb0..a99ba9bdec715dec004cb7d33e4e380f4f8bbfcb 100644 --- a/Common/Options.cpp +++ b/Common/Options.cpp @@ -4399,28 +4399,6 @@ double opt_geometry_auto_coherence(OPT_ARGS_NUM) return CTX::instance()->geom.autoCoherence; } -double opt_geometry_hide_compounds(OPT_ARGS_NUM) -{ - if(action & GMSH_SET){ - int old = CTX::instance()->geom.hideCompounds; - CTX::instance()->geom.hideCompounds = (int)val; - if(old != (int)val){ - GModel::current()->setCompoundVisibility(); - CTX::instance()->mesh.changed = ENT_ALL; -#if defined(HAVE_FLTK) - if(FlGui::available()) FlGui::instance()->resetVisibility(); -#endif - } - } -#if defined(HAVE_FLTK) - if(FlGui::available() && (action & GMSH_GUI)){ - FlGui::instance()->options->geo.butt[17]->value - (CTX::instance()->geom.hideCompounds); - } -#endif - return CTX::instance()->geom.hideCompounds; -} - double opt_geometry_oriented_physicals(OPT_ARGS_NUM) { if(action & GMSH_SET) diff --git a/Common/Options.h b/Common/Options.h index 95436360dd5dc95b2be5e4345f81d84e16db041a..5cb13d5a000c53e076a3003fc84248fa5721898a 100644 --- a/Common/Options.h +++ b/Common/Options.h @@ -360,7 +360,6 @@ double opt_geometry_offset0(OPT_ARGS_NUM); double opt_geometry_offset1(OPT_ARGS_NUM); double opt_geometry_offset2(OPT_ARGS_NUM); double opt_geometry_auto_coherence(OPT_ARGS_NUM); -double opt_geometry_hide_compounds(OPT_ARGS_NUM); double opt_geometry_oriented_physicals(OPT_ARGS_NUM); double opt_geometry_highlight_orphans(OPT_ARGS_NUM); double opt_geometry_tolerance(OPT_ARGS_NUM); diff --git a/Fltk/optionWindow.cpp b/Fltk/optionWindow.cpp index e2358c070dbbf896caa71cdb692e4f854238cacb..7c0d6e920567ad62e2adab546f0cd5caad74419a 100644 --- a/Fltk/optionWindow.cpp +++ b/Fltk/optionWindow.cpp @@ -429,7 +429,6 @@ static void geometry_options_ok_cb(Fl_Widget *w, void *data) opt_geometry_occ_scaling(0, GMSH_SET, o->geo.value[20]->value()); opt_geometry_light_two_side(0, GMSH_SET, o->geo.butt[14]->value()); - opt_geometry_hide_compounds(0, GMSH_SET, o->geo.butt[17]->value()); opt_geometry_normals(0, GMSH_SET, o->geo.value[0]->value()); opt_geometry_tangents(0, GMSH_SET, o->geo.value[1]->value()); diff --git a/Geo/CMakeLists.txt b/Geo/CMakeLists.txt index 2dff8ae7b53c33b1854a6afcbc1985e42f738224..98236c6c98f498b50dcae10ae7097320f39f9f17 100644 --- a/Geo/CMakeLists.txt +++ b/Geo/CMakeLists.txt @@ -9,8 +9,8 @@ set(SRC intersectCurveSurface.cpp GEntity.cpp STensor3.cpp GVertex.cpp GEdge.cpp GFace.cpp GRegion.cpp - GEdgeLoop.cpp GEdgeCompound.cpp GFaceCompound.cpp - GRegionCompound.cpp GRbf.cpp + GEdgeLoop.cpp + GRbf.cpp gmshVertex.cpp gmshEdge.cpp gmshFace.cpp gmshRegion.cpp gmshSurface.cpp OCCVertex.cpp OCCEdge.cpp OCCFace.cpp OCCRegion.cpp @@ -46,7 +46,6 @@ set(SRC MHexahedron.cpp MPrism.cpp MPyramid.cpp MTrihedron.cpp MElementCut.cpp MSubElement.cpp MZone.cpp MZoneBoundary.cpp Cell.cpp CellComplex.cpp ChainComplex.cpp Homology.cpp Chain.cpp - Curvature.cpp MVertexBoundaryLayerData.cpp ) diff --git a/Geo/Curvature.cpp b/Geo/Curvature.cpp deleted file mode 100644 index 3607cf1416908824f3cb14af3243358791a55a6a..0000000000000000000000000000000000000000 --- a/Geo/Curvature.cpp +++ /dev/null @@ -1,1987 +0,0 @@ -// Gmsh - Copyright (C) 1997-2017 C. Geuzaine, J.-F. Remacle -// -// See the LICENSE.txt file for license information. Please report all -// bugs and problems to the public mailing list <gmsh@onelab.info>. - -#include "Curvature.h" -#include "MElement.h" -#include "MTriangle.h" -#include "GEntity.h" -#include "GFaceCompound.h" -#include "MLine.h" -#include "GRbf.h" -#include "OS.h" -#include "SBoundingBox3d.h" -#include "discreteEdge.h" - -#include<iostream> -#include<fstream> -#include<cmath> - -#define NEXT(i) ((i)<2 ? (i)+1 : (i)-2) -#define PREV(i) ((i)>0 ? (i)-1 : (i)+2) -//======================================================================================================== - -//Initialization of the static variables: -Curvature* Curvature::_instance = 0; -bool Curvature::_destroyed = false; -bool Curvature::_alreadyComputedCurvature = false; - -//======================================================================================================== - -//CONSTRUCTOR -Curvature::Curvature() : _isMapInitialized(false) -{ -} - -// Curvature::Curvature(std::list<GFace*> &myFaces){ - -// std::list<GFace*>::const_iterator it = myFaces.begin(); -// for( ; it != myFaces.end() ; ++it){ -// _ptFinalEntityList.push_back(*it); -// } - -// } - -//======================================================================================================== - -Curvature::~Curvature() -{ - _instance = 0; - _destroyed = true; - -} -//======================================================================================================== -void Curvature::onDeadReference() -{ - std::cout << "Dead reference of Curvature detected" << std::endl; -} -//======================================================================================================== - -Curvature& Curvature::getInstance() -{ - if (!_instance) { - if(_destroyed){ - onDeadReference(); - } - else{ - create(); - } - } - return *_instance; -} -//======================================================================================================== - bool Curvature::valueAlreadyComputed() - { - return _alreadyComputedCurvature; - } - -//======================================================================================================== - - void Curvature::create() - { - static Curvature instance; - _instance = & instance; - } - - //======================================================================================================== - void Curvature::retrieveCompounds() { -#if defined(HAVE_SOLVER) - - /// ------------------------------------------------------------------------------------------- - // Loop over all faces. Check if the face is a compound. If it is, store all of its discrete - // faces in _EntityArray - - std::list<GFace*> global_face_list; - - for(GModel::fiter face_iter = _model->firstFace(); face_iter != _model->lastFace(); ++face_iter) - { - if ( (*face_iter)->geomType() != GEntity::CompoundSurface ){ - if (!(*face_iter)->getCompound()){ - global_face_list.push_back(*face_iter); - } - } - else if ( (*face_iter)->geomType() == GEntity::CompoundSurface ) - { - GFaceCompound* compound = dynamic_cast<GFaceCompound*>(*face_iter); - std::list<GFace*> tempcompounds = compound->getCompounds(); - std::list<GFace*>::iterator surfIterator; - - for(surfIterator = tempcompounds.begin(); surfIterator != tempcompounds.end(); ++surfIterator) - { - if ((*surfIterator)->geomType() == GEntity::DiscreteSurface) - { - global_face_list.push_back(*surfIterator); - } - } - } - - } // Loop over faces of the model - - global_face_list.sort(); - global_face_list.unique(); - _EntityArray.resize(global_face_list.size()); - std::copy(global_face_list.begin(),global_face_list.end(),_EntityArray.begin()); -#endif - } - - //======================================================================================================== - - // Method to detect boundary edges of the mesh. We want to find which edges are on the boundary in order - // to correct the curvature field close to boundaries - - void Curvature::correctOnEdges() - { -#if defined(HAVE_SOLVER) - - if (! _alreadyComputedCurvature ) - { - Msg::Error("Cannot correct the curvature values at the edges because the curvatures weren't computed yet"); - return; - } - // Remark: this can only be used after the call to initializeMap() ! - - buildEdgeList(); - - std::list<MeshEdgeInfo>::iterator VertToEdgeListIter; - - _isOnBoundary.resize(_VertexToInt.size()); - for (unsigned int i = 0; i < _VertexToInt.size(); ++i) - { - _isOnBoundary[i] = 0; - } - - // To detect the nodes on the egdes of a geometry, we create a list of all edges on the mesh. The - // edges which are shared by only one mesh element are boundary edges. Their nodes are tagged by 1 - for (unsigned int i = 0; i < _VertexToInt.size(); ++i) - { - for (VertToEdgeListIter = _VertexToEdgeList[i].begin(); VertToEdgeListIter != _VertexToEdgeList[i].end(); - ++VertToEdgeListIter) - { - if ((*VertToEdgeListIter).NbElemNeighbour == 1) - { - _isOnBoundary[(*VertToEdgeListIter).StartV] = 1; - _isOnBoundary[(*VertToEdgeListIter).EndV] = 1; - } - } - - } - - // We want to find the nodes that are the immediate neighbours of the boundary nodes. Those nodes are - // considered nodes with 'level 2'. The neighbours of neighbours have 'level 3' etc. - // We want to construct levels 1,2,3. Nodes with level 0 are internal nodes of the mesh - //Loop over the vector of edgelist - for (int level = 1; level < 3; ++level) - { - for (unsigned int i = 0; i < _VertexToEdgeList.size(); ++i) - { - for (VertToEdgeListIter = _VertexToEdgeList[i].begin(); VertToEdgeListIter != _VertexToEdgeList[i].end(); - ++VertToEdgeListIter) - { - if (_isOnBoundary[(*VertToEdgeListIter).StartV] == level && _isOnBoundary[(*VertToEdgeListIter).EndV] == 0) - { - _isOnBoundary[(*VertToEdgeListIter).EndV] = level+1; - } - if (_isOnBoundary[(*VertToEdgeListIter).EndV] == level && _isOnBoundary[(*VertToEdgeListIter).StartV] == 0) - { - _isOnBoundary[(*VertToEdgeListIter).StartV] = level+1; - } - } - } - }//Loop over the level of the ring - - - // Check test to see the tag of the nodes on the boundary: -// for (int i = 0; i< _EntityArray.size(); ++i) -// { -// GFace* face = _EntityArray[i]; //List of all the discrete face on which we compute the curvature - -// for (int iElem = 0; iElem < face->getNumMeshElements(); iElem++) -// { -// MElement *e = face->getMeshElement(iElem); - -// // The NEW tag of the corresponding element -// const int E = _ElementToInt[e->getNum()]; - -// // Pointers to vertices of triangle -// MVertex* A = e->getVertex(0); -// MVertex* B = e->getVertex(1); -// MVertex* C = e->getVertex(2); - -// V[0] = _VertexToInt[A->getNum()]; //The new number of the vertex -// V[1] = _VertexToInt[B->getNum()]; -// V[2] = _VertexToInt[C->getNum()]; - -// if (_isOnBoundary[V[0]] == 3) -// { -// std::cout << "Vertex: " << A->getNum() << " -- " << A->x() << "; " << A->y() << "; " << A->z() << std::endl; -// } -// if (_isOnBoundary[V[1]] == 3) -// { -// std::cout << "Vertex: " << B->getNum() << " -- " << B->x() << "; " << B->y() << "; " << B->z() << std::endl; -// } -// if (_isOnBoundary[V[2]] == 3) -// { -// std::cout << "Vertex: " << C->getNum() << " -- " << C->x() << "; " << C->y() << "; " << C->z() << std::endl; -// } -// } -// } - - - // Now we'll propagate the cuvature values from inside nodes with level = 3 close to the boundary - first - // to nodes with level 2, then from nodes with level 2 to nodes with level 1 (on the boundary) - _NbNeighbour.resize(_VertexToInt.size()); - for(unsigned int i = 0; i < _NbNeighbour.size(); ++i) - { - _NbNeighbour[i] = 0; - } - - for (int level = 2; level > 0 ; --level) - { - - for (unsigned int i = 0; i< _NbNeighbour.size(); ++i) - { - _NbNeighbour[i] = 0; - if (_isOnBoundary[i] == level) - { - _VertexCurve[i] = 0.0; - } - } - - - for (unsigned int i = 0; i < _VertexToEdgeList.size(); ++i) - { - for (VertToEdgeListIter = _VertexToEdgeList[i].begin(); VertToEdgeListIter != _VertexToEdgeList[i].end(); - ++VertToEdgeListIter) - { - - if (_isOnBoundary[(*VertToEdgeListIter).StartV] == level && _isOnBoundary[(*VertToEdgeListIter).EndV] == level+1) - { - _VertexCurve[(*VertToEdgeListIter).StartV] += _VertexCurve[(*VertToEdgeListIter).EndV]; - _NbNeighbour[(*VertToEdgeListIter).StartV] ++; - - } - if (_isOnBoundary[(*VertToEdgeListIter).EndV] == level && _isOnBoundary[(*VertToEdgeListIter).StartV] == level+1) - { - _VertexCurve[(*VertToEdgeListIter).EndV] += _VertexCurve[(*VertToEdgeListIter).StartV]; - _NbNeighbour[(*VertToEdgeListIter).EndV] ++; - } - - } - } - - // Correction for a degenerate case when a node has neighbours with the same or lower level, but zero - // neighbours with level+1 - - for (unsigned int i = 0; i < _VertexToEdgeList.size(); ++i) - { - for (VertToEdgeListIter = _VertexToEdgeList[i].begin(); VertToEdgeListIter != _VertexToEdgeList[i].end(); - ++VertToEdgeListIter) - { - - if (_isOnBoundary[(*VertToEdgeListIter).StartV] == level - && _isOnBoundary[(*VertToEdgeListIter).EndV] == level - && _NbNeighbour[(*VertToEdgeListIter).StartV] == 0) - { - _VertexCurve[(*VertToEdgeListIter).StartV] += _VertexCurve[(*VertToEdgeListIter).EndV]; - _NbNeighbour[(*VertToEdgeListIter).StartV] = _NbNeighbour[(*VertToEdgeListIter).EndV]; - } - if (_isOnBoundary[(*VertToEdgeListIter).EndV] == level - && _isOnBoundary[(*VertToEdgeListIter).StartV] == level - && _NbNeighbour[(*VertToEdgeListIter).EndV] == 0) - { - _VertexCurve[(*VertToEdgeListIter).EndV] += _VertexCurve[(*VertToEdgeListIter).StartV]; - _NbNeighbour[(*VertToEdgeListIter).EndV] = _NbNeighbour[(*VertToEdgeListIter).StartV]; - } - } - } - - for (unsigned int i = 0; i < _isOnBoundary.size(); ++i) - { - if (_isOnBoundary[i] == level) - { - if (_NbNeighbour[i] == 0) - { - std::cout << "ERROR: VERTEX " << i << " WITH LEVEL " << level << " HAS 0 NEIGHBOURS" << std::endl; - } - _VertexCurve[i] = _VertexCurve[i]/_NbNeighbour[i]; - } - } - - }//Loop over the levels of the ring - -// for (int i = 0; i < _isOnBoundary.size(); ++i) -// { -// _VertexCurve[i] = _isOnBoundary[i]; -// } - -#endif - } - -//======================================================================================================== - -//INITIALIZATION OF THE MAP AND RENUMBERING OF THE SELECTED ENTITIES: - -void Curvature::initializeMap() -{ - if (! _isMapInitialized) - { - for (unsigned int i = 0; i< _EntityArray.size(); ++i) - { - GFace* face = _EntityArray[i]; - - for (unsigned int iElem = 0; iElem < face->getNumMeshElements(); iElem++) - { - MElement *e = face->getMeshElement(iElem); - const int E = e->getNum(); - _ElementToInt[E] = 1; - - const int A = e->getVertex(0)->getNum(); //Pointer to 1st vertex of the triangle - const int B = e->getVertex(1)->getNum(); - const int C = e->getVertex(2)->getNum(); - - _VertexToInt[A] = 1; - _VertexToInt[B] = 1; - _VertexToInt[C] = 1; - } - } - - /// Set up a new numbering of chosen vertices and triangles - int idx = 0; - - // map between the pointer to vertex and the new numbering of the vertex - std::map<int,int>::iterator vertex_iterator; - // map between the pointer to element and the new numbering of the element - std::map<int,int>::iterator element_iterator; - - for (vertex_iterator = _VertexToInt.begin() ; vertex_iterator !=_VertexToInt.end() ; ++ vertex_iterator, ++idx) - (*vertex_iterator).second = idx; - - idx = 0; - - for (element_iterator = _ElementToInt.begin() ; element_iterator !=_ElementToInt.end() ; ++ element_iterator, ++idx) - (*element_iterator).second = idx; - - _isMapInitialized = true; - - } - -} - -//======================================================================================================== - -//COMPUTE THE NORMAL AT THE VERTEX AND THE AREA AROUND - -void Curvature::computeVertexNormals() -{ - SVector3 vector_AB; - SVector3 vector_AC; - - _TriangleArea.resize(_ElementToInt.size() ); - _VertexArea.resize(_ElementToInt.size() ); - _VertexNormal.resize(_VertexToInt.size()); - - for (unsigned int i = 0; i< _EntityArray.size(); ++i) - { - // face is a pointer to one surface of the group "FinalEntityList" - GFace* face = _EntityArray[i]; - - //Loop over the element all the element of the "myTag"-surface - for (unsigned int iElem = 0; iElem < face->getNumMeshElements(); iElem++) - { - // Pointer to one element - MElement *e = face->getMeshElement(iElem); - // The NEW tag of the corresponding element - const int E = _ElementToInt[e->getNum()]; - // std::cout << "We are now looking at element Nr: " << E << std::endl; - - // Pointers to vertices of triangle - MVertex* A = e->getVertex(0); - MVertex* B = e->getVertex(1); - MVertex* C = e->getVertex(2); - - const int V0 = _VertexToInt[A->getNum()]; //The new number of the vertex - const int V1 = _VertexToInt[B->getNum()]; - const int V2 = _VertexToInt[C->getNum()]; - - vector_AB = SVector3(B->x() - A->x(), B->y() - A->y(), B->z() - A->z() ); - vector_AC = SVector3(C->x() - A->x(), C->y() - A->y(), C->z() - A->z() ); - - const SVector3 cross = crossprod(vector_AB, vector_AC); - - // Area of the triangles: - _TriangleArea[E] = 0.5*cross.norm(); - // std::cout << "The area of the triangle nr: " << e->getNum() << " is: "<< TriangleArea[E] << std::endl; - - _VertexArea[V0] += _TriangleArea[E]; - _VertexArea[V1] += _TriangleArea[E]; - _VertexArea[V2] += _TriangleArea[E]; - - _VertexNormal[V0] += cross; //here we are actually computing the unit normal vector per vertex - _VertexNormal[V1] += cross; - _VertexNormal[V2] += cross; - - } // end of loop over elements of one face - - } //Loop over _ptFinalEntityList - - ///////Normalize the vertex-normals. - for (unsigned int n = 0; n < _VertexToInt.size(); ++ n) - { - _VertexNormal[n].normalize(); - } -} - -//======================================================================================================== - -SVector3 Curvature::vertexNormal (MVertex* A) -{ - const int V0 = _VertexToInt[A->getNum()]; //The new number of the vertex - return _VertexNormal[V0]; -} - -//======================================================================================================== - -void Curvature::curvatureTensor() -{ - - STensor3 TempTensor; - STensor3 TijABTensorProduct; - SVector3 TijAB; - SVector3 vector_AB; - - _CurveTensor.resize(_VertexToInt.size()); - - for (unsigned int i = 0; i< _EntityArray.size(); ++i) - { - GFace* face = _EntityArray[i]; //face is a pointer to one surface of the group "FinalEntityList" - - for (unsigned int iElem = 0; iElem < face->getNumMeshElements(); iElem++) //Loop over the element all the element of the "myTag"-surface - { - MElement *e = face->getMeshElement(iElem); //Pointer to one element - const int E = _ElementToInt[e->getNum()]; //The NEW tag of the corresponding element - - for (unsigned int i = 0; i<3; ++i) // Loop over the 3 edges of each element - { - - MVertex* A = e->getVertex(i); //Pointer to 1st vertex of the edge A-to-B - MVertex* B = e->getVertex((i+1)%3); //Pointer to 2nd vertex of the edge A-to-B - - const int V0 = _VertexToInt[A->getNum()]; //Tag of the 1st vertex of the edge A-to-B - const int V1 = _VertexToInt[B->getNum()]; //Tag of the 2nd vertex of the edge A-to-B - - //Weight for triangle-i-th's contribution to the shape tensor: - const double Wij0 = _TriangleArea[E] / (2 * _VertexArea[V0]); - const double Wij1 = _TriangleArea[E] / (2 * _VertexArea[V1]); - - //Approximate Curvature "kappa" along some tangential vector T: - vector_AB = SVector3(B->x() - A->x(), B->y() - A->y(), B->z() - A->z() ); - const double k_nominator0 = dot(_VertexNormal[V0], vector_AB); //Dot-product of the 2 vectors - const double k_nominator1 = -dot(_VertexNormal[V1], vector_AB); - - const double coeff = 2.0/vector_AB.normSq(); //normSq is the norm to the power 2 - const double KijAB_0 = coeff*k_nominator0; - const double KijAB_1 = coeff*k_nominator1; - - //Projection of the edge vector AB on the tangential plane: - //** For Vertex 0 - tensprod(_VertexNormal[V0], _VertexNormal[V0], TempTensor); - TempTensor *= -1.0; //-N*Nt - TempTensor(0,0) += 1.0; //I-N*Nt - TempTensor(1,1) += 1.0; - TempTensor(2,2) += 1.0; - - for (int m = 0; m<3; ++m) - { - TijAB(m) = 0.0; - for (int n = 0; n<3; ++n) - { - TijAB(m) += TempTensor(m,n) * vector_AB(n); - } - } - - TijAB.normalize(); - tensprod(TijAB, TijAB, TijABTensorProduct); - _CurveTensor[V0] += Wij0*KijAB_0*TijABTensorProduct; - - //** For Vertex 1 - tensprod(_VertexNormal[V1], _VertexNormal[V1], TempTensor); - TempTensor *= -1.0; //-N*Nt - TempTensor(0,0) += 1.0; //I-N*Nt - TempTensor(1,1) += 1.0; - TempTensor(2,2) += 1.0; - - for (int m = 0; m<3; ++m) - { - TijAB(m) = 0.0; - for (int n = 0; n<3; ++n) - { - TijAB(m) += TempTensor(m,n) * vector_AB(n); - } - } - - TijAB.normalize(); - tensprod(TijAB, TijAB, TijABTensorProduct); - _CurveTensor[V1] += Wij1*KijAB_1*TijABTensorProduct; - - }//end of loop over the edges - - }//end of loop over all elements of one GFace - - }//End of loop over ptFinalEntityList - -}//End of method - -//======================================================================================================== - -void Curvature::computeCurvature_Simple() -{ - SVector3 vector_E; - SVector3 vector_A; - SVector3 vector_B; - SVector3 vector_Wvi; - STensor3 Qvi; - STensor3 QviT; - STensor3 Holder; - - initializeMap(); - computeVertexNormals(); - curvatureTensor(); - - _VertexCurve.resize(_VertexToInt.size()); - - for (unsigned int n = 0; n < _VertexToInt.size(); ++ n) //Loop over the vertex - { - vector_E = SVector3(1,0,0); - vector_A = vector_E + _VertexNormal[n]; - vector_B = vector_E - _VertexNormal[n]; - - const double MagA = vector_A.norm(); - const double MagB = vector_B.norm(); - - if (MagB > MagA) - { - vector_Wvi = vector_B; - } - else - { - vector_Wvi = vector_A; - } - - vector_Wvi.normalize(); - //to obtain the Qvi = Id -2*Wvi*Wvi^t - tensprod(vector_Wvi, vector_Wvi, Qvi); //Qvi = Wvi*Wvi^t - Qvi *= -2.0; //-2*Wvi*Wvi^t - Qvi(0,0) += 1.0; //I - 2*Wvi*Wvi^t ==> Householder transformation - Qvi(1,1) += 1.0; - Qvi(2,2) += 1.0; - - //Transpose the matrix: - for (int i = 0; i<3; ++i) - { - for (int j = 0; j<3; ++j) - { - QviT(i,j) = Qvi(j,i); - } - } - - QviT *= _CurveTensor[n]; - QviT *=Qvi; - Holder = QviT; - - //Eigenvalues of the 2*2 minor from the Householder matrix - const double A = 1.0; - const double B = -(Holder(1,1) + Holder(2,2)); - const double C = Holder(1,1)*Holder(2,2) - Holder(1,2)*Holder(2,1); - const double Delta = std::sqrt(B*B-4*A*C); - - if((B*B-4.*A*C) < 0.0) - { - std::cout << "WARNING: negative discriminant: " << B*B-4.*A*C << std::endl; - } - - const double m11 = (-B + Delta)/(2*A); //Eigenvalue of Householder submatrix - const double m22 = (-B - Delta)/(2*A); - - //_VertexCurve[n] = (3*m11-m22)*(3*m22-m11); //Gaussian Curvature - _VertexCurve[n] = ((3*m11-m22) + (3*m22-m11))*0.5; //Mean Curvature - - } -} - -//======================================================================================================== - -//COMPUTE THE NORMAL AT THE VERTEX AND THE AREA AROUND - -void Curvature::computeRusinkiewiczNormals() -{ - SVector3 vector_AB; - SVector3 vector_AC; - SVector3 vector_BC; - - _TriangleArea.resize(_ElementToInt.size() ); - _VertexNormal.resize(_VertexToInt.size()); - - for (unsigned int i = 0; i< _EntityArray.size(); ++i) - { - // face is a pointer to one surface of the group "FinalEntityList" - GFace* face = _EntityArray[i]; - - //Loop over the element all the element of the "myTag"-surface - for (unsigned int iElem = 0; iElem < face->getNumMeshElements(); iElem++) - { - // Pointer to one element - MElement *e = face->getMeshElement(iElem); - const int E = _ElementToInt[e->getNum()]; - - // Pointers to vertices of triangle - MVertex* A = e->getVertex(0); - MVertex* B = e->getVertex(1); - MVertex* C = e->getVertex(2); - - const int V0 = _VertexToInt[A->getNum()]; //The new number of the vertex - const int V1 = _VertexToInt[B->getNum()]; - const int V2 = _VertexToInt[C->getNum()]; - - vector_AB = SVector3(B->x() - A->x(), B->y() - A->y(), B->z() - A->z() ); - vector_AC = SVector3(C->x() - A->x(), C->y() - A->y(), C->z() - A->z() ); - vector_BC = SVector3(C->x() - B->x(), C->y() - B->y(), C->z() - B->z() ); - - const SVector3 cross = crossprod(vector_AB, vector_AC); - - // Area of the triangles: - _TriangleArea[E] = 0.5*cross.norm(); - - const double l_AB = vector_AB.normSq(); - const double l_AC = vector_AC.normSq(); - const double l_BC = vector_BC.normSq(); - - _VertexNormal[V0] += cross * (1.0/ (l_AB*l_AC)); - _VertexNormal[V1] += cross * (1.0/ (l_AB*l_BC)); - _VertexNormal[V2] += cross * (1.0/ (l_AC*l_BC)); - - } // end of loop over elements of one face - - } //Loop over _ptFinalEntityList - - ///////Normalize the vertex-normals. - for (unsigned int n = 0; n < _VertexToInt.size(); ++ n) - { - _VertexNormal[n].normalize(); - } -} - -//======================================================================================================== -// Compute per-vertex point areas -void Curvature::computePointareas(){ - - SVector3 e[3]; - SVector3 l2; - SVector3 ew; - double factor[3]; - - _pointareas.resize(_VertexToInt.size()); - _cornerareas.resize(_ElementToInt.size()); - - for (unsigned int i = 0; i< _EntityArray.size(); ++i) - { - GFace* face = _EntityArray[i]; //face is a pointer to one surface of the group "FinalEntityList" - - for (unsigned int iElem = 0; iElem < face->getNumMeshElements(); iElem++) //Loop over the element all the element of the "myTag"-surface - { - MElement *E = face->getMeshElement(iElem); //Pointer to one element - // The NEW tag of the corresponding element - const int EIdx = _ElementToInt[E->getNum()]; - - MVertex* A = E->getVertex(0); //Pointers to vertices of triangle - MVertex* B = E->getVertex(1); - MVertex* C = E->getVertex(2); - - const int V0 = _VertexToInt[A->getNum()]; - const int V1 = _VertexToInt[B->getNum()]; - const int V2 = _VertexToInt[C->getNum()]; - - factor[0] = 1.0; - factor[1] = 1.0; - factor[2] = 1.0; - // if (_isOnBoundary[V0]) - // { - // factor[0] = 1.0; - // } - // else {factor[0] = 1.0;} - // if (_isOnBoundary[V1]) - // { - // factor[1] = 1.0; - // } - // else {factor[1] = 1.0;} - // if (_isOnBoundary[V2]) - // { - // factor[2] = 1.0; - // } - // else {factor[2] = 1.0;} - -//Edges - e[0] = SVector3(C->x() - B->x(), C->y() - B->y(), C->z() - B->z()); //vector side of a triangular element - e[1] = SVector3(A->x() - C->x(), A->y() - C->y(), A->z() - C->z()); - e[2] = SVector3(B->x() - A->x(), B->y() - A->y(), B->z() - A->z()); - - // Compute corner weights - //SVector3 len = crossprod(e[0], e[1]); - //len = norm - //len2 = normSq - double area = 0.5 * norm(crossprod(e[0], e[1])); //area of a triangle - l2 = SVector3( normSq(e[0]), normSq(e[1]), normSq(e[2]) ); - ew = SVector3( l2[0] * (l2[1] + l2[2] - l2[0]), - l2[1] * (l2[2] + l2[0] - l2[1]), - l2[2] * (l2[0] + l2[1] - l2[2]) ); - - if (ew[0] <= 0.0) - { - _cornerareas[EIdx][1] = -0.25 * l2[2] * area / dot(e[0], e[2]); - _cornerareas[EIdx][2] = -0.25 * l2[1] * area / dot(e[0], e[1]); - _cornerareas[EIdx][0] = area - _cornerareas[EIdx][1] - _cornerareas[EIdx][2]; - } - else if (ew[1] <= 0.0) - { - _cornerareas[EIdx][2] = -0.25 * l2[0] * area / dot(e[1], e[0]); - _cornerareas[EIdx][0] = -0.25 * l2[2] * area / dot(e[1], e[2]); - _cornerareas[EIdx][1] = area - _cornerareas[EIdx][2] - _cornerareas[EIdx][0]; - } - else if (ew[2] <= 0.0) - { - _cornerareas[EIdx][0] = -0.25 * l2[1] * area / dot(e[2], e[1]); - _cornerareas[EIdx][1] = -0.25 * l2[0] * area / dot(e[2], e[0]); - _cornerareas[EIdx][2] = area - _cornerareas[EIdx][0] - _cornerareas[EIdx][1]; - } - else - { - float ewscale = 0.5 * area / (ew[0] + ew[1] + ew[2]); - for (int j = 0; j < 3; j++) - _cornerareas[EIdx][j] = ewscale * (ew[(j+1)%3] + ew[(j+2)%3]); - } - - _pointareas[V0] += _cornerareas[EIdx][0]; - - _pointareas[V1] += _cornerareas[EIdx][1]; - - _pointareas[V2] += _cornerareas[EIdx][2]; - - for (int j = 0; j < 3; j++) - { - _cornerareas[EIdx][j] = factor[j]*_cornerareas[EIdx][j]; - } - - - } //End of loop over iElem - -// std::cout << "_pointareas.size = " << _pointareas.size() << std::endl; -// std::cout << "_cornerareas.size = " << _cornerareas.size() << std::endl; - - } //End of loop over _ptFinalEntityList - -} //End of the method "computePointareas" - - -//======================================================================================================== -//Rotate a coordinate system to be perpendicular to the given normal -void Curvature::rot_coord_sys(const SVector3 &old_u, const SVector3 &old_v, const SVector3 &new_norm, SVector3 &new_u, SVector3 &new_v){ - - new_u = old_u; - new_v = old_v; - SVector3 old_norm = crossprod(old_u, old_v); - double ndot = dot(old_norm, new_norm); -// if (unlikely(ndot <= -1.0f)) - if (ndot <= -1.0f) - { - new_u = -1.0*new_u; - new_v = -1.0*new_v; - return; - } - - SVector3 perp_old = new_norm - ndot*old_norm; - SVector3 dperp = 1.0f/(1 + ndot) * (old_norm + new_norm); - new_u -= dperp*dot(new_u, perp_old); - new_v -= dperp*dot(new_v, perp_old); -} - -//======================================================================================================== - -//Project a curvature tensor from the basis spanned by old_u and old_v -//(which are assumed to be unit-length and perpendicular) to the new_u -//and new_v basis - -void Curvature::proj_curv( const SVector3 &old_u, const SVector3 &old_v, - double old_ku, double old_kuv, double old_kv, - const SVector3 &new_u, const SVector3 &new_v, - double &new_ku, double &new_kuv, double &new_kv){ - SVector3 r_new_u; - SVector3 r_new_v; - rot_coord_sys(new_u, new_v, crossprod(old_u,old_v), r_new_u, r_new_v); - - const double u1 = dot(r_new_u, old_u); - const double v1 = dot(r_new_u, old_v); - const double u2 = dot(r_new_v, old_u); - const double v2 = dot(r_new_v, old_v); - - new_ku = old_ku*u1*u1 + old_kuv*(2.0f * u1*v1) + old_kv*v1*v1; - new_kuv = old_ku*u1*u2 + old_kuv*(u1*v2 * u2*v1) + old_kv*v1*v2; - new_kv = old_ku*u2*u2 + old_kuv*(2.0f * u2*v2) + old_kv*v2*v2; -} - - -//======================================================================================================== - -//Given a curvature tensor, find principal directions and curvatures -//Makes sure that pdir1 and pdir2 are perpendicular to normal - -void Curvature::diagonalize_curv(const SVector3 &old_u, const SVector3 &old_v, - double ku, double kuv, double kv, - const SVector3 &new_norm, - SVector3 &pdir1, SVector3 &pdir2, double &k1, double &k2){ - SVector3 r_old_u; - SVector3 r_old_v; - - double c = 1.0; - double s = 0.0; - double tt = 0.0; - - rot_coord_sys(old_u, old_v, new_norm, r_old_u, r_old_v); - -// if(unlikely(kuv !=0.0f)) - if(kuv !=0.0) { - //Jacobi rotation to diagonalize - double h= 0.5*(kv -ku)/ kuv; - tt = (h<0.0) ? - 1.0 / (h - std::sqrt(1.0 + h*h)): - 1.0 / (h + std::sqrt(1.0 + h*h)); - c = 1.0 / std::sqrt(1.0 + tt*tt); - s = tt*c; - } - - k1 = ku - tt *kuv; - k2 = kv + tt *kuv; - - if(std::abs(k1) >= std::abs(k2)) { - pdir1 = c*r_old_u - s*r_old_v; - } - else { - std::swap(k1,k2); - pdir1 = s*r_old_u + c*r_old_v; - } - pdir2 = crossprod(new_norm, pdir1); -} - -//======================================================================================================== -void Curvature::computeCurvature(GModel* model, typeOfCurvature typ) -{ - - _model = model; - - double t0 = Cpu(); - Msg::StatusBar(true, "(C) Computing Curvature"); - if (typ == RUSIN) - computeCurvature_Rusinkiewicz(0); - else if (typ == RBF) - computeCurvature_RBF(); - else if (typ == SIMPLE) - computeCurvature_Simple(); - - double t1 = Cpu(); - Msg::StatusBar(true, "(C) Done Computing Curvature (%g s)", t1-t0); - - //writeToMshFile("curvature.msh"); - //writeToPosFile("curvature.pos"); - //writeToVtkFile("curvature.vtk"); - -} - -//======================================================================================================== - -void Curvature::buildEdgeList() -{ - - int V[3]; - bool edgefound; - - _VertexToEdgeList.clear(); - - std::list<MeshEdgeInfo>::iterator VertToEdgeListIter; - MeshEdgeInfo TempEdge; - - _VertexToEdgeList.resize(_VertexToInt.size()); - - for (unsigned int i = 0; i< _EntityArray.size(); ++i) - { - GFace* face = _EntityArray[i]; //List of all the discrete face on which we compute the curvature - - for (unsigned int iElem = 0; iElem < face->getNumMeshElements(); iElem++) - { - MElement *e = face->getMeshElement(iElem); - - // Pointers to vertices of triangle - MVertex* A = e->getVertex(0); - MVertex* B = e->getVertex(1); - MVertex* C = e->getVertex(2); - - V[0] = _VertexToInt[A->getNum()]; //The new number of the vertex - V[1] = _VertexToInt[B->getNum()]; - V[2] = _VertexToInt[C->getNum()]; - - // Try to add edge [V0,V1] to the global list - for (int j = 0; j < 3; ++j) - { - const int StartV = std::min(V[j], V[(j+1)%3]); - const int EndV = std::max(V[j], V[(j+1)%3]); - - edgefound = false; - for (VertToEdgeListIter = _VertexToEdgeList[StartV].begin(); VertToEdgeListIter != _VertexToEdgeList[StartV].end(); - ++VertToEdgeListIter) - { - if(StartV == (*VertToEdgeListIter).StartV && EndV == (*VertToEdgeListIter).EndV) - { - (*VertToEdgeListIter).NbElemNeighbour ++; - edgefound = true; - } - - } - if (false == edgefound) - { - TempEdge.StartV = StartV; - TempEdge.EndV = EndV; - TempEdge.NbElemNeighbour = 1; - _VertexToEdgeList[StartV].push_back(TempEdge); - } - - - } // Loop over j - - - } // Loop over the elements (triangles) of the face - } - - int NbEdges = 0; - for(unsigned int i = 0; i < _VertexToEdgeList.size(); ++i) - { - NbEdges += _VertexToEdgeList[i].size(); - } - - //std::cout << "Euler formula:" << std::endl; - //std::cout << "Edges + 2 = " << NbEdges + 2 << std::endl; - //std::cout << "Elements + Nodes = " << _VertexToInt.size() + _ElementToInt.size() << std::endl; - -} - -//======================================================================================================== - - -void Curvature::smoothCurvatureField(const int NbIter) -{ - if ( _VertexToEdgeList.size() == 0 ) { buildEdgeList(); } - - std::vector<double> smoothedCurvature; - smoothedCurvature.resize( _VertexToInt.size() ); - - - // Smoothed curvature directions - std::vector<SVector3> smoothedDir1; - std::vector<SVector3> smoothedDir2; - smoothedDir1.resize(_VertexToInt.size()); - smoothedDir2.resize(_VertexToInt.size()); - - _NbNeighbour.resize(_VertexToInt.size()); - for(unsigned int i = 0; i < _VertexToInt.size(); ++i) - { - _NbNeighbour[i] = 0; - } - - - // Smoothing iterations - for(int iter = 0; iter < NbIter; ++iter) - { - - for(unsigned int i = 0; i < smoothedCurvature.size(); ++i) - { - smoothedCurvature[i] = 0.0; - smoothedDir1[i] = SVector3(); - smoothedDir2[i] = SVector3(); - } - - std::list<MeshEdgeInfo>::const_iterator edgeIterator; - - - for(unsigned int i = 0; i < _VertexToEdgeList.size(); ++i) - { - for(edgeIterator = _VertexToEdgeList[i].begin(); edgeIterator != _VertexToEdgeList[i].end(); ++edgeIterator) - { - - const int V0 = (*edgeIterator).StartV; - const int V1 = (*edgeIterator).EndV; - - smoothedCurvature[V0] += _VertexCurve[V1]; - smoothedCurvature[V1] += _VertexCurve[V0]; - - smoothedDir1[V0] += _pdir1[V1]; - smoothedDir1[V1] += _pdir1[V0]; - - smoothedDir2[V0] += _pdir2[V1]; - smoothedDir2[V1] += _pdir2[V0]; - - _NbNeighbour[V0]++; - _NbNeighbour[V1]++; - } - } - - - - const double Lambda = 0.3; - for(unsigned int i = 0; i < _VertexCurve.size(); ++i) - { - _VertexCurve[i] = Lambda*_VertexCurve[i] + (1-Lambda)*smoothedCurvature[i] / _NbNeighbour[i]; - _pdir1[i] = Lambda * _pdir1[i] + (1.-Lambda)/_NbNeighbour[i] * smoothedDir1[i]; - _pdir2[i] = Lambda * _pdir2[i] + (1.-Lambda)/_NbNeighbour[i] * smoothedDir2[i]; - } - } - -} - - -//======================================================================================================== - - - -void Curvature::computeCurvature_Rusinkiewicz(int isMax) -{ - - retrieveCompounds(); - initializeMap(); - - computeRusinkiewiczNormals(); - computePointareas(); - - SVector3 e[3]; - STensor3 w; - SVector3 t; - SVector3 n; - SVector3 b; - SVector3 m; - SVector3 dn; - - double u; - double v; - double dnu; - double dnv; - double c1; - double c2; - double c12; - double wt; - - _pdir1.resize(_VertexToInt.size()); - _pdir2.resize(_VertexToInt.size()); - - _curv1.resize(_VertexToInt.size()); - _curv2.resize(_VertexToInt.size()); - _curv12.resize(_VertexToInt.size()); - - for (unsigned int i = 0; i< _EntityArray.size(); ++i) - { - GFace* face = _EntityArray[i]; //face is a pointer to one surface of the group "FinalEntityList" - - for (unsigned int iElem = 0; iElem < face->getNumMeshElements(); iElem++) //Loop over the element all the element of the "myTag"-surface - { - MElement *E = face->getMeshElement(iElem); //Pointer to one element - - MVertex* A = E->getVertex(0); //Pointers to vertices of triangle - MVertex* B = E->getVertex(1); - MVertex* C = E->getVertex(2); - - const int V0 = _VertexToInt[A->getNum()]; //Tag of the 1st vertex of the triangle - const int V1 = _VertexToInt[B->getNum()]; - const int V2 = _VertexToInt[C->getNum()]; - - ///Set up an initial coordinate system per vertex: - _pdir1[V0] = SVector3(B->x() - A->x(), B->y() - A->y(), B->z() - A->z()); - _pdir1[V1] = SVector3(C->x() - B->x(), C->y() - B->y(), C->z() - B->z()); - _pdir1[V2] = SVector3(A->x() - C->x(), A->y() - C->y(), A->z() - C->z()); - } - } - - for (unsigned int ivertex = 0; ivertex < _VertexToInt.size(); ++ivertex) - { - _pdir1[ivertex] = crossprod(_pdir1[ivertex], _VertexNormal[ivertex]); - _pdir1[ivertex].normalize(); - _pdir2[ivertex] = crossprod(_VertexNormal[ivertex], _pdir1[ivertex]); - } - - // Compute curvature per face: - for (unsigned int i = 0; i< _EntityArray.size(); ++i) - { - //face is a pointer to one surface of the group "FinalEntityList" - GFace* face = _EntityArray[i]; - - //Loop over all elements of this face: - for (unsigned int iElem = 0; iElem < face->getNumMeshElements(); iElem++) - { - MElement *E = face->getMeshElement(iElem); //Pointer to one element - // The NEW tag of the corresponding element - const int EIdx = _ElementToInt[E->getNum()]; - - MVertex* A = E->getVertex(0); //Pointers to vertices of triangle - MVertex* B = E->getVertex(1); - MVertex* C = E->getVertex(2); - - e[0] = SVector3(C->x() - B->x(), C->y() - B->y(), C->z() - B->z()); - e[1] = SVector3(A->x() - C->x(), A->y() - C->y(), A->z() - C->z()); - e[2] = SVector3(B->x() - A->x(), B->y() - A->y(), B->z() - A->z()); - - //N-T-B coordinate system per face - t = e[0]; - t.normalize(); - n = crossprod( e[0], e[1]); - b = crossprod(n, t); - b.normalize(); - - //Estimate curvature based on variations of normals along edges: - //intialization: - m = SVector3(0.0, 0.0, 0.0); - for (int i = 0; i< 3; ++i) - for (int j = 0; j< 3; ++j) - w(i,j) = 0.0; - - //filling: - for (int j = 0; j< 3; ++j) - { - u = dot(e[j], t); - v = dot(e[j], b); - - w(0,0) += u*u; - w(0,1) += u*v; - w(2,2) += v*v; - - MVertex* U = E->getVertex(PREV(j)); - MVertex* V = E->getVertex(NEXT(j)); - - const int UIdx = _VertexToInt[U->getNum()]; - const int VIdx = _VertexToInt[V->getNum()]; - - dn = _VertexNormal[UIdx] - _VertexNormal[VIdx]; - - dnu = dot(dn, t); - dnv = dot(dn, b); - - m[0] += dnu*u; - m[1] += dnu*v + dnv*u; - m[2] += dnv*v; - } - - w(1,1) = w(0,0) + w(2,2); - w(1,2) = w(0,1); - - //Least Squares Solution - double diag[3]; - if (!ldltdc(w, diag)) - { - std::cout << "ldltdc failed" << std::endl; - continue; - } - ldltsl(w, diag, m, m); - - //Push it back out to the vertices - for (int j = 0; j< 3; ++j) - { - const int old_vj = E->getVertex(j)->getNum(); - const int vj = _VertexToInt[old_vj]; - proj_curv(t, b, m[0], m[1], m[2], _pdir1[vj], _pdir2[vj], c1, c12, c2); - wt = _cornerareas[EIdx][j]/_pointareas[vj]; - - _curv1[vj] += wt*c1; - _curv12[vj] += wt*c12; - _curv2[vj] += wt*c2; - } - - } //End of loop over the element (iElem) - - } //End of loop over "_EntityArray" - - - //Compute principal directions and curvatures at each vertex - for (unsigned int ivertex = 0; ivertex < _VertexToInt.size(); ++ivertex) { - diagonalize_curv(_pdir1[ivertex], _pdir2[ivertex], _curv1[ivertex], _curv12[ivertex], _curv2[ivertex], - _VertexNormal[ivertex], _pdir1[ivertex], _pdir2[ivertex], _curv1[ivertex], _curv2[ivertex]); - } - - - _VertexCurve.resize( _VertexToInt.size() ); - - for (unsigned int ivertex = 0; ivertex < _VertexToInt.size(); ++ivertex){ - - if (isMax){ - _VertexCurve[ivertex] = std::max(fabs(_curv1[ivertex]), fabs(_curv2[ivertex])); - } - else{ - //_VertexCurve[ivertex] = (_curv1[ivertex]+_curv2[ivertex])*0.5; //Mean curvature - //_VertexCurve[ivertex] = _curv1[ivertex]*_curv2[ivertex]; //Gaussian - _VertexCurve[ivertex] = _curv1[ivertex]; //Maximal Curvature - } - - } - -// smoothCurvatureField(1); - _alreadyComputedCurvature = true; - -// Propagate the value of curvature from nodes close the edges of the geometry onto the edges - correctOnEdges(); - // throw; - -} //End of the "computeCurvature_Rusinkiewicz" method - - //======================================================================================================== - -void Curvature::computeCurvature_RBF() -{ - retrieveCompounds(); - initializeMap(); - - //fill set of MVertex - std::set<MVertex*> allNodes; - for (unsigned int i = 0; i< _EntityArray.size(); ++i) { - GFaceCompound* face = (GFaceCompound*)_EntityArray[i]; - for (unsigned iElem = 0; iElem < face->getNumMeshElements(); iElem++) { - MElement *e = face->getMeshElement(iElem); - for(int j = 0; j < e->getNumVertices(); j++){ - allNodes.insert(e->getVertex(j)); - } - } - } - - //bounding box - SBoundingBox3d bb; - std::vector<SPoint3> vertices; - for(std::set<MVertex *>::iterator itv = allNodes.begin(); itv !=allNodes.end() ; ++itv){ - SPoint3 pt((*itv)->x(),(*itv)->y(), (*itv)->z()); - vertices.push_back(pt); - bb +=pt; - } - double sizeBox = norm(SVector3(bb.max(), bb.min())); - - //compure curvature RBF - std::map<MVertex*, SVector3> _normals; - std::vector<MVertex*> _ordered; - std::map<MVertex*, double> curvRBF; - //GLOBAL - //GRbf *_rbf = new GRbf(sizeBox, 0, 1, _normals, allNodes, _ordered); - //_rbf->computeCurvature(_rbf->getXYZ(),curvRBF); - //LOCAL FD - GRbf *_rbf = new GRbf(sizeBox, 0, 1, _normals, allNodes, _ordered, true); - _rbf->computeLocalCurvature(_rbf->getXYZ(),curvRBF); - - //fill vertex curve - _VertexCurve.resize( _VertexToInt.size() ); - for(std::set<MVertex *>::iterator itv = allNodes.begin(); itv !=allNodes.end() ; ++itv){ - MVertex *v = *itv; - std::map<int,int>::iterator vertexIterator; - int V0 = 0; - vertexIterator = _VertexToInt.find( v->getNum() ); - if ( vertexIterator != _VertexToInt.end() ) V0 = (*vertexIterator).second; - _VertexCurve[V0] = curvRBF[v]; - } - - _alreadyComputedCurvature = true; - -} //End of the "computeCurvature_RBF" method - - - //======================================================================================================== - -void Curvature::triangleNodalValues(MTriangle* triangle, double& c0, double& c1, double& c2, int isAbs) - { - MVertex* A = triangle->getVertex(0); - MVertex* B = triangle->getVertex(1); - MVertex* C = triangle->getVertex(2); - - int V0 = 0; - int V1 = 0; - int V2 = 0; - - std::map<int,int>::iterator vertexIterator; - vertexIterator = _VertexToInt.find( A->getNum() ); - if ( vertexIterator != _VertexToInt.end() ) V0 = (*vertexIterator).second; - else - std::cout << "Didn't find vertex with number " << A->getNum() << " in _VertextToInt !" << std::endl; - - vertexIterator = _VertexToInt.find( B->getNum() ); - if ( vertexIterator != _VertexToInt.end() ) V1 = (*vertexIterator).second; - else - std::cout << "Didn't find vertex with number " << B->getNum() << " in _VertextToInt !" << std::endl; - - vertexIterator = _VertexToInt.find( C->getNum() ); - if ( vertexIterator != _VertexToInt.end() ) V2 = (*vertexIterator).second; - else - std::cout << "Didn't find vertex with number " << C->getNum() << " in _VertextToInt !" << std::endl; - - if (isAbs){ - c0 = std::abs(_VertexCurve[V0]); //Mean curvature in vertex 0 - c1 = std::abs(_VertexCurve[V1]); //Mean curvature in vertex 1 - c2 = std::abs(_VertexCurve[V2]); //Mean curvature in vertex 2 - } - else{ - c0 = _VertexCurve[V0]; //Mean curvature in vertex 0 - c1 = _VertexCurve[V1]; //Mean curvature in vertex 1 - c2 = _VertexCurve[V2]; //Mean curvature in vertex 2 - } - - } - -//======================================================================================================== - -void Curvature::triangleNodalValuesAndDirections(MTriangle* triangle, SVector3* dMax, SVector3* dMin, double* cMax, double* cMin, int isAbs) -{ - MVertex* A = triangle->getVertex(0); - MVertex* B = triangle->getVertex(1); - MVertex* C = triangle->getVertex(2); - - int V0 = 0; - int V1 = 0; - int V2 = 0; - - std::map<int,int>::iterator vertexIterator; - vertexIterator = _VertexToInt.find( A->getNum() ); - if ( vertexIterator != _VertexToInt.end() ) V0 = (*vertexIterator).second; - else - std::cout << "Didn't find vertex with number " << A->getNum() << " in _VertextToInt !" << std::endl; - - vertexIterator = _VertexToInt.find( B->getNum() ); - if ( vertexIterator != _VertexToInt.end() ) V1 = (*vertexIterator).second; - else - std::cout << "Didn't find vertex with number " << B->getNum() << " in _VertextToInt !" << std::endl; - - vertexIterator = _VertexToInt.find( C->getNum() ); - if ( vertexIterator != _VertexToInt.end() ) V2 = (*vertexIterator).second; - else - std::cout << "Didn't find vertex with number " << C->getNum() << " in _VertextToInt !" << std::endl; - - if (isAbs){ - dMax[0] = _pdir1[V0]; - dMax[1] = _pdir1[V1]; - dMax[2] = _pdir1[V2]; - - dMin[0] = _pdir2[V0]; - dMin[1] = _pdir2[V1]; - dMin[2] = _pdir2[V2]; - - cMax[0] = std::abs(_curv1[V0]); - cMax[1] = std::abs(_curv1[V1]); - cMax[2] = std::abs(_curv1[V2]); - - cMin[0] = std::abs(_curv2[V0]); - cMin[1] = std::abs(_curv2[V1]); - cMin[2] = std::abs(_curv2[V2]); - - } - else{ - - dMax[0] = _pdir1[V0]; - dMax[1] = _pdir1[V1]; - dMax[2] = _pdir1[V2]; - - dMin[0] = _pdir2[V0]; - dMin[1] = _pdir2[V1]; - dMin[2] = _pdir2[V2]; - - cMax[0] = _curv1[V0]; - cMax[1] = _curv1[V1]; - cMax[2] = _curv1[V2]; - - cMin[0] = _curv2[V0]; - cMin[1] = _curv2[V1]; - cMin[2] = _curv2[V2]; - } -} - - //======================================================================================================== - -void Curvature::edgeNodalValues(MLine* edge, double& c0, double& c1, int isAbs) - { - MVertex* A = edge->getVertex(0); - MVertex* B = edge->getVertex(1); - - int V0 = 0; - int V1 = 0; - - std::map<int,int>::iterator vertexIterator; - - vertexIterator = _VertexToInt.find( A->getNum() ); - if ( vertexIterator != _VertexToInt.end() ) V0 = (*vertexIterator).second; - else std::cout << "Didn't find vertex with number " << A->getNum() << " in _VertextToInt !" << std::endl; - - vertexIterator = _VertexToInt.find( B->getNum() ); - if ( vertexIterator != _VertexToInt.end() ) V1 = (*vertexIterator).second; - else std::cout << "Didn't find vertex with number " << B->getNum() << " in _VertextToInt !" << std::endl; - - if (isAbs){ - c0 = std::abs(_VertexCurve[V0]); //Mean curvature in vertex 0 - c1 = std::abs(_VertexCurve[V1]); //Mean curvature in vertex 1 - } - else{ - c0 = _VertexCurve[V0]; //Mean curvature in vertex 0 - c1 = _VertexCurve[V1]; //Mean curvature in vertex 1 - } - - } - -//======================================================================================================== - -void Curvature::edgeNodalValuesAndDirections(MLine* edge, SVector3* dMax, SVector3* dMin, double* cMax, double* cMin, int isAbs) -{ - std::vector<MVertex*> LineVertices; - //LineVertices.resize(2); - edge->getEdgeVertices(0,LineVertices);//triangle->getVertex(0); - - int V0 = 0; - int V1 = 0; - - std::map<int,int>::iterator vertexIterator; - vertexIterator = _VertexToInt.find( LineVertices[0]->getNum() ); - if ( vertexIterator != _VertexToInt.end() ) V0 = (*vertexIterator).second; - else - std::cout << "Didn't find vertex with number " << LineVertices[0]->getNum() << " in _VertextToInt !" << std::endl; - - vertexIterator = _VertexToInt.find( LineVertices[1]->getNum() ); - if ( vertexIterator != _VertexToInt.end() ) V1 = (*vertexIterator).second; - else - std::cout << "Didn't find vertex with number " << LineVertices[1]->getNum() << " in _VertextToInt !" << std::endl; - - - if (isAbs){ - dMax[0] = _pdir1[V0]; - dMax[1] = _pdir1[V1]; - - dMin[0] = _pdir2[V0]; - dMin[1] = _pdir2[V1]; - - cMax[0] = std::abs(_curv1[V0]); - cMax[1] = std::abs(_curv1[V1]); - - cMin[0] = std::abs(_curv2[V0]); - cMin[1] = std::abs(_curv2[V1]); - - } - else{ - - dMax[0] = _pdir1[V0]; - dMax[1] = _pdir1[V1]; - - dMin[0] = _pdir2[V0]; - dMin[1] = _pdir2[V1]; - - cMax[0] = _curv1[V0]; - cMax[1] = _curv1[V1]; - - cMin[0] = _curv2[V0]; - cMin[1] = _curv2[V1]; - } -} - //======================================================================================================== - -void Curvature::vertexNodalValues(MVertex* A, double& c0, int isAbs) - { - int V0 = 0; - - std::map<int,int>::iterator vertexIterator; - - vertexIterator = _VertexToInt.find( A->getNum() ); - if ( vertexIterator != _VertexToInt.end() ) V0 = (*vertexIterator).second; - else std::cout << "Didn't find vertex with number " << A->getNum() << " in _VertextToInt !" << std::endl; - - - if (isAbs){ - c0 = std::abs(_VertexCurve[V0]); //Mean curvature in vertex 0 - } - else{ - c0 = _VertexCurve[V0]; //Mean curvature in vertex 0 - } - - } - -void Curvature::vertexNodalValuesAndDirections(MVertex *A, SVector3* dMax, SVector3* dMin, double* cMax, double* cMin, int isAbs) -{ - - int V0 = 0; - - std::map<int,int>::iterator vertexIterator; - vertexIterator = _VertexToInt.find( A->getNum() ); - if ( vertexIterator != _VertexToInt.end() ) V0 = (*vertexIterator).second; - else - std::cout << "Didn't find vertex with number " << A->getNum() << " in _VertextToInt !" << std::endl; - - if (isAbs){ - dMax[0] = _pdir1[V0]; - dMin[0] = _pdir2[V0]; - cMax[0] = std::abs(_curv1[V0]); - cMin[0] = std::abs(_curv2[V0]); - } - else{ - dMax[0] = _pdir1[V0]; - dMin[0] = _pdir2[V0]; - cMax[0] = _curv1[V0]; - cMin[0] = _curv2[V0]; - } -} - - -//======================================================================================================== - -double Curvature::getAtVertex(const MVertex *v) const { - std::map<int,int>::const_iterator it = _VertexToInt.find(v->getNum()); - if (it == _VertexToInt.end()) { - Msg::Error("curvature has not been computed for vertex %i (%i)", v->getNum(), _VertexToInt.size()); - return 1; - } - return _VertexCurve[it->second]; -} - -//======================================================================================================== - -void Curvature::writeToMshFile(const std::string &filename) -{ - std::ofstream outfile; - outfile.precision(18); - outfile.open(filename.c_str()); - - /// Write the values of curvature 1 (max) - outfile << "$MeshFormat" << std::endl; - outfile << "2.1 0 8" << std::endl; - outfile << "$EndMeshFormat" << std::endl; - outfile << "$NodeData" << std::endl; - outfile << "1" << std::endl; // One string tag - outfile << "\"Curvature 1 (max)\"" << std::endl; // The name of the view - outfile << "1" << std::endl; // One real tag - outfile << "0.0" << std::endl; // The time value - outfile << "3" << std::endl; // Three integer tags - outfile << "0" << std::endl; // The time step (time steps always start at 0) - outfile << "1" << std::endl; // 1-component (scalar) field - outfile << _VertexToInt.size() << std::endl; // How many associated nodal values - - std::map<int,int>::const_iterator vertex_iterator; - for(vertex_iterator = _VertexToInt.begin(); vertex_iterator != _VertexToInt.end(); ++vertex_iterator) - { - outfile << vertex_iterator->first << " " << _curv1[vertex_iterator->second] << std::endl; - } - - outfile << "$EndNodeData" << std::endl; - - - /// Write the values of curvature 2 (min) - outfile << "$MeshFormat" << std::endl; - outfile << "2.1 0 8" << std::endl; - outfile << "$EndMeshFormat" << std::endl; - outfile << "$NodeData" << std::endl; - outfile << "1" << std::endl; // One string tag - outfile << "\"Curvature 2 (min)\"" << std::endl; // The name of the view - outfile << "1" << std::endl; // One real tag - outfile << "0.0" << std::endl; // The time value - outfile << "3" << std::endl; // Three integer tags - outfile << "0" << std::endl; // The time step (time steps always start at 0) - outfile << "1" << std::endl; // 1-component (scalar) field - outfile << _VertexToInt.size() << std::endl; // How many associated nodal values - - - for(vertex_iterator = _VertexToInt.begin(); vertex_iterator != _VertexToInt.end(); ++vertex_iterator) - { - outfile << vertex_iterator->first << " " << _curv2[vertex_iterator->second] << std::endl; - } - - outfile << "$EndNodeData" << std::endl; - - - /// Write the values of characteristic length - - double lc; - - outfile << "$MeshFormat" << std::endl; - outfile << "2.1 0 8" << std::endl; - outfile << "$EndMeshFormat" << std::endl; - outfile << "$NodeData" << std::endl; - outfile << "1" << std::endl; // One string tag - outfile << "\"Characteristic mesh length\"" << std::endl; // The name of the view - outfile << "1" << std::endl; // One real tag - outfile << "0.0" << std::endl; // The time value - outfile << "3" << std::endl; // Three integer tags - outfile << "0" << std::endl; // The time step (time steps always start at 0) - outfile << "1" << std::endl; // 1-component (scalar) field - outfile << _VertexToInt.size() << std::endl; // How many associated nodal values - - for(vertex_iterator = _VertexToInt.begin(); vertex_iterator != _VertexToInt.end(); ++vertex_iterator) - { - lc = 2.0*M_PI/( fabs(_VertexCurve[vertex_iterator->second]) * CTX::instance()->mesh.minCircPoints ); - lc = std::max(lc, CTX::instance()->mesh.lcMin); - lc = std::min(lc, CTX::instance()->mesh.lcMax); - //outfile << vertex_iterator->first << " " << 1.0/(lc*lc) << std::endl; - outfile << vertex_iterator->first << " " << lc << std::endl; - } - - outfile << "$EndNodeData" << std::endl; - - /// Write the values of curvature direction - principal direction 1 - outfile << "$NodeData" << std::endl; - outfile << "1" << std::endl; // One string tag - outfile << "\"Principal curvature direction 1\"" << std::endl; // The name of the view - outfile << "1" << std::endl; // One real tag - outfile << "0.0" << std::endl; // The time value - outfile << "3" << std::endl; // Three integer tags - outfile << "0" << std::endl; // The time step (time steps always start at 0) - outfile << "3" << std::endl; // 3-component (vector) field - outfile << _VertexToInt.size() << std::endl; // How many associated nodal values - - for(vertex_iterator = _VertexToInt.begin(); vertex_iterator != _VertexToInt.end(); ++vertex_iterator) - { - outfile << vertex_iterator->first << " " << _pdir1[vertex_iterator->second].x() << " " - << _pdir1[vertex_iterator->second].y() << " " - << _pdir1[vertex_iterator->second].z() << std::endl; - } - - outfile << "$EndNodeData" << std::endl; - - - /// Write the values of curvature direction - principal direction 2 - outfile << "$NodeData" << std::endl; - outfile << "1" << std::endl; // One string tag - outfile << "\"Principal curvature direction 2\"" << std::endl; // The name of the view - outfile << "1" << std::endl; // One real tag - outfile << "0.0" << std::endl; // The time value - outfile << "3" << std::endl; // Three integer tags - outfile << "0" << std::endl; // The time step (time steps always start at 0) - outfile << "3" << std::endl; // 3-component (vector) field - outfile << _VertexToInt.size() << std::endl; // How many associated nodal values - - for(vertex_iterator = _VertexToInt.begin(); vertex_iterator != _VertexToInt.end(); ++vertex_iterator) - { - outfile << vertex_iterator->first << " " << _pdir2[vertex_iterator->second].x() << " " - << _pdir2[vertex_iterator->second].y() << " " - << _pdir2[vertex_iterator->second].z() << std::endl; - } - - outfile << "$EndNodeData" << std::endl; - - outfile.close(); - - -} - -//======================================================================================================== - -void Curvature::writeToPosFile( const std::string & filename) -{ - std::ofstream outfile; - outfile.precision(18); - outfile.open(filename.c_str()); - outfile << "View \"Curvature \"{" << std::endl; - - int idxelem = 0; - - for (unsigned int i = 0; i< _EntityArray.size(); ++i) { - GFace* face = _EntityArray[i]; - - for (unsigned iElem = 0; iElem < face->getNumMeshElements(); iElem++){ - MElement *e = face->getMeshElement(iElem); - //const int E = _ElementToInt[e->getNum()]; - //std::cout << "We are now looking at element Nr: " << E << std::endl; - - MVertex* A = e->getVertex(0); //Pointers to vertices of triangle - MVertex* B = e->getVertex(1); - MVertex* C = e->getVertex(2); - - const int V1 = _VertexToInt[A->getNum()]; //Tag of the 1st vertex of the triangle - const int V2 = _VertexToInt[B->getNum()]; //Tag of the 2nd vertex of the triangle - const int V3 = _VertexToInt[C->getNum()]; //Tag of the 3rd vertex of the triangle - - //Here is printing the triplet X-Y-Z of each vertex: - //************************************************* - - outfile << "ST("; //VT = vector triangles //ST = scalar triangle - outfile << A->x() << ","<< A->y() << "," << A->z()<< ","; - outfile << B->x() << ","<< B->y() << "," << B->z()<< ","; - outfile << C->x() << ","<< C->y() << "," << C->z(); - - outfile << ")"; - outfile <<"{"; - - //Here is printing the 3 components of the normal vector for each vertex: - //********************************************************************** - -// outfile << _VertexNormal[V1].x() << ","<< _VertexNormal[V1].y() << ","<< _VertexNormal[V1].z() << ","; -// outfile << _VertexNormal[V2].x() << ","<< _VertexNormal[V2].y() << ","<< _VertexNormal[V2].z() << ","; -// outfile << _VertexNormal[V3].x() << ","<< _VertexNormal[V3].y() << ","<< _VertexNormal[V3].z(); - - outfile << _VertexCurve[V1] << "," << _VertexCurve[V2] << "," << _VertexCurve[V3]; - - outfile << "};" << std::endl; - - idxelem++; - - } //Loop over elements - -} // Loop over ptFinalEntityList - -outfile << "};" << std::endl; - -outfile.close(); -} - -//======================================================================================================== - -void Curvature::writeToVtkFile( const std::string & filename) -{ - - std::ofstream outfile; - outfile.precision(18); - outfile.open(filename.c_str()); - outfile << "# vtk DataFile Version 2.0" << std::endl; - outfile << "Surface curvature computed by Gmsh" << std::endl; - outfile << "ASCII" << std::endl; - outfile << "DATASET UNSTRUCTURED_GRID" << std::endl; - - const int npoints = _VertexToInt.size(); - - outfile << "POINTS " << npoints << " double" << std::endl; - - /// Build a table of coordinates - /// Loop over all elements and look at the 'old' (not necessarily continuous) numbers of vertices - /// Get the 'new' index of each vertex through _VertexToInt and the [x,y,z] coordinates of this vertex - /// Store them in coordx,coordy and coordz - - - std::vector<VtkPoint> coord; - - coord.resize(npoints); - - for (unsigned int i = 0; i< _EntityArray.size(); ++i) - { - GFace* face = _EntityArray[i]; - - for (unsigned int iElem = 0; iElem < face->getNumMeshElements(); iElem++) - { - MElement *e = face->getMeshElement(iElem); - - MVertex* A = e->getVertex(0); //Pointers to vertices of triangle - MVertex* B = e->getVertex(1); - MVertex* C = e->getVertex(2); - - const int oldIdxA = A->getNum(); - const int oldIdxB = B->getNum(); - const int oldIdxC = C->getNum(); - - const int newIdxA = _VertexToInt[oldIdxA]; - const int newIdxB = _VertexToInt[oldIdxB]; - const int newIdxC = _VertexToInt[oldIdxC]; - - coord[newIdxA].x = A->x(); - coord[newIdxA].y = A->y(); - coord[newIdxA].z = A->z(); - - coord[newIdxB].x = B->x(); - coord[newIdxB].y = B->y(); - coord[newIdxB].z = B->z(); - - coord[newIdxC].x = C->x(); - coord[newIdxC].y = C->y(); - coord[newIdxC].z = C->z(); - } - } - - for (int v = 0; v < npoints; ++v) - { - outfile << coord[v].x << " " << coord[v].y << " " << coord[v].z << std::endl; - } - - /// Empty the array 'coord' to free the memory - /// Point coordinates will not be needed anymore - coord.clear(); - - /// Write the cell connectivity - - outfile << std::endl << "CELLS " << _ElementToInt.size() << " " << 4*_ElementToInt.size() << std::endl; - - for (unsigned int i = 0; i< _EntityArray.size(); ++i) - { - GFace* face = _EntityArray[i]; - - for (unsigned int iElem = 0; iElem < face->getNumMeshElements(); iElem++) - { - MElement *e = face->getMeshElement(iElem); - - MVertex* A = e->getVertex(0); //Pointers to vertices of triangle - MVertex* B = e->getVertex(1); - MVertex* C = e->getVertex(2); - - const int oldIdxA = A->getNum(); - const int oldIdxB = B->getNum(); - const int oldIdxC = C->getNum(); - - const int newIdxA = _VertexToInt[oldIdxA]; - const int newIdxB = _VertexToInt[oldIdxB]; - const int newIdxC = _VertexToInt[oldIdxC]; - - outfile << "3 " << newIdxA << " " << newIdxB << " " << newIdxC << std::endl; - } - } - - outfile << std::endl << "CELL_TYPES " << _ElementToInt.size() << std::endl; - for(unsigned int ie = 0; ie < _ElementToInt.size(); ++ie) - { - outfile << "5" << std::endl; //Triangle is element type 5 in vtk - - } - - /// Write the curvature values as vtk 'point data' - - outfile << std::endl << "POINT_DATA " << npoints << std::endl; - outfile << "SCALARS Curvature float 1" << std::endl; - outfile << "LOOKUP_TABLE default" << std::endl; - - for (int iv = 0; iv < npoints; ++iv) - { - outfile << _VertexCurve[iv] << std::endl; - } - - outfile << "SCALARS CharacteristicMeshLength float 1" << std::endl; - outfile << "LOOKUP_TABLE default" << std::endl; - - double lc; - - for (int iv = 0; iv < npoints; ++iv) - { - lc = 2.0*M_PI / ( fabs(_VertexCurve[iv]) * CTX::instance()->mesh.minCircPoints ); - lc = std::max(lc, CTX::instance()->mesh.lcMin); - lc = std::min(lc, CTX::instance()->mesh.lcMax); - //outfile << 1.0/(lc*lc) << std::endl; - outfile << lc << std::endl; - } - - outfile << "VECTORS CurvatureDir1 float" << std::endl; - for (int iv = 0; iv < npoints; ++iv) - { - outfile << _pdir1[iv].x() << " " << _pdir1[iv].y() << " " << _pdir1[iv].z() << std::endl; - } - - outfile << "VECTORS CurvatureDir2 float" << std::endl; - for (int iv = 0; iv < npoints; ++iv) - { - outfile << _pdir2[iv].x() << " " << _pdir2[iv].y() << " " << _pdir2[iv].z() << std::endl; - } - - outfile.close(); - -} - -//======================================================================================================== - -void Curvature::writeDirectionsToPosFile( const std::string & filename) -{ - std::ofstream outfile; - outfile.precision(18); - outfile.open(filename.c_str()); - outfile << "View \"Curvature_DirMax \"{" << std::endl; - - for (unsigned int i = 0; i< _EntityArray.size(); ++i) - { - GFace* face = _EntityArray[i]; //face is a pointer to one surface of the group "FinalEntityList" - - for (unsigned int iElem = 0; iElem < face->getNumMeshElements(); iElem++) //Loop over the element all the element of the "myTag"-surface - { - MElement *e = face->getMeshElement(iElem); //Pointer to one element - - //const int E = _ElementToInt[e->getNum()]; //The NEW tag of the corresponding element - //std::cout << "We are now looking at element Nr: " << E << std::endl; - - MVertex* A = e->getVertex(0); //Pointers to vertices of triangle - MVertex* B = e->getVertex(1); - MVertex* C = e->getVertex(2); - - const int V1 = _VertexToInt[A->getNum()]; //Tag of the 1st vertex of the triangle - const int V2 = _VertexToInt[B->getNum()]; //Tag of the 2nd vertex of the triangle - const int V3 = _VertexToInt[C->getNum()]; //Tag of the 3rd vertex of the triangle - - //Here is printing the triplet X-Y-Z of each vertex: - //************************************************* - - outfile << "VT("; //VT = vector triangles //ST = scalar triangle - outfile << A->x() << ","<< A->y() << "," << A->z()<< ","; - outfile << B->x() << ","<< B->y() << "," << B->z()<< ","; - outfile << C->x() << ","<< C->y() << "," << C->z(); - - outfile << ")"; - outfile <<"{"; - - //Here is printing the 3 components of the curvature max direction for each vertex: - //********************************************************************************* - - outfile << _pdir1[V1].x() << ","<< _pdir1[V1].y() << ","<< _pdir1[V1].z() << ","; - outfile << _pdir1[V2].x() << ","<< _pdir1[V2].y() << ","<< _pdir1[V2].z() << ","; - outfile << _pdir1[V3].x() << ","<< _pdir1[V3].y() << ","<< _pdir1[V3].z(); - - - outfile << "};" << std::endl; - - } //Loop over elements - -} // Loop over ptFinalEntityList - -outfile << "};" << std::endl; - - -//---------------------------------------------------------------------------------------------- - -outfile << "View \"Curvature_DirMin \"{" << std::endl; - -for (unsigned int i = 0; i< _EntityArray.size(); ++i) -{ - GFace* face = _EntityArray[i]; //face is a pointer to one surface of the group "FinalEntityList" - - for (unsigned int iElem = 0; iElem < face->getNumMeshElements(); iElem++) //Loop over the element all the element of the "myTag"-surface - { - MElement *e = face->getMeshElement(iElem); //Pointer to one element - - //const int E = _ElementToInt[e->getNum()]; //The NEW tag of the corresponding element - //std::cout << "We are now looking at element Nr: " << E << std::endl; - - MVertex* A = e->getVertex(0); //Pointers to vertices of triangle - MVertex* B = e->getVertex(1); - MVertex* C = e->getVertex(2); - - const int V1 = _VertexToInt[A->getNum()]; //Tag of the 1st vertex of the triangle - const int V2 = _VertexToInt[B->getNum()]; //Tag of the 2nd vertex of the triangle - const int V3 = _VertexToInt[C->getNum()]; //Tag of the 3rd vertex of the triangle - - //Here is printing the triplet X-Y-Z of each vertex: - //************************************************* - - outfile << "VT("; //VT = vector triangles //ST = scalar triangle - outfile << A->x() << ","<< A->y() << "," << A->z()<< ","; - outfile << B->x() << ","<< B->y() << "," << B->z()<< ","; - outfile << C->x() << ","<< C->y() << "," << C->z(); - - outfile << ")"; - outfile <<"{"; - - //Here is printing the 3 components of the curvature min direction for each vertex: - //********************************************************************************* - - outfile << _pdir2[V1].x() << ","<< _pdir2[V1].y() << ","<< _pdir2[V1].z() << ","; - outfile << _pdir2[V2].x() << ","<< _pdir2[V2].y() << ","<< _pdir2[V2].z() << ","; - outfile << _pdir2[V3].x() << ","<< _pdir2[V3].y() << ","<< _pdir2[V3].z(); - - - outfile << "};" << std::endl; - -} //Loop over elements - -} // Loop over ptFinalEntityList - -outfile << "};" << std::endl; - -outfile.close(); -} -//======================================================================================================== - - - diff --git a/Geo/Curvature.h b/Geo/Curvature.h deleted file mode 100644 index 133a9090f9d93ce828f37db68a1564783d350b65..0000000000000000000000000000000000000000 --- a/Geo/Curvature.h +++ /dev/null @@ -1,230 +0,0 @@ -// Gmsh - Copyright (C) 1997-2017 C. Geuzaine, J.-F. Remacle -// -// See the LICENSE.txt file for license information. Please report all -// bugs and problems to the public mailing list <gmsh@onelab.info>. - -#ifndef _CURVATURE_H_ -#define _CURVATURE_H_ - -#include "GModel.h" -#include "STensor3.h" - -#include<map> -#include<vector> -#include<list> - -class Curvature { - -private: - //---------------------------------------- - //TYPEDEFS: - - typedef std::vector<GFace*> GFaceList; - //typedef std::map<int, GEntityList >::iterator GEntityIter; - typedef std::map<int, GFaceList >::iterator GFaceIter; - - //----------------------------------------- - // HELPER TYPE FOR WRITING TO VTK FILES - struct VtkPoint - { - double x; - double y; - double z; - }; - - //----------------------------------------- - // HELPER TYPE FOR DETECTING BOUNDARY NODES - struct MeshEdgeInfo - { - int StartV; - int EndV; - int NbElemNeighbour; - }; - - //----------------------------------------- - // MEMBER VARIABLES - - //Static member variable to implement the class curvature as a Singleton - static Curvature *_instance; - static bool _destroyed; - - //Boolean to check if the curvature has already been computed - static bool _alreadyComputedCurvature; - - //Map definition - std::map<int, int> _VertexToInt; - std::map<int, int> _ElementToInt; - - bool _isMapInitialized; - - //Model and list of selected entities with give physical tag: - GModel* _model; - GFaceList _EntityArray; - - //Averaged vertex normals - std::vector<SVector3> _VertexNormal; - - // Vector of principal directions - std::vector<SVector3> _pdir1; - std::vector<SVector3> _pdir2; - - // Vector of principal curvature - std::vector<double> _curv1; - std::vector<double> _curv2; - std::vector<double> _curv12; - - // Area around point - std::vector<double> _pointareas; - std::vector<SVector3> _cornerareas; - - //Curvature Tensor per mesh vertex - std::vector<STensor3> _CurveTensor; - - //Area of a triangle element: - std::vector<double> _TriangleArea; - - //Area around a mesh vertex: - std::vector<double> _VertexArea; - std::vector<double> _VertexCurve; - - - //Number of neighbour for each vertices in the mesh: - std::vector<int> _NbNeighbour; - - //Vector of 0/1 to check which nodes are on the boundary: - std::vector<int> _isOnBoundary; - - std::vector<std::list<MeshEdgeInfo> > _VertexToEdgeList; - //----------------------------------------- - // PRIVATE METHODS - - //Constructor and destructor - Curvature(); - ~Curvature(); - - static void create(); - static void onDeadReference(); - - void initializeMap(); - void computeVertexNormals(); - void curvatureTensor(); - static void rot_coord_sys(const SVector3 &old_u, const SVector3 &old_v, - const SVector3 &new_norm, SVector3 &new_u, SVector3 &new_v); - void proj_curv( const SVector3 &old_u, const SVector3 &old_v, double old_ku, double old_kuv, - double old_kv, const SVector3 &new_u, const SVector3 &new_v, - double &new_ku, double &new_kuv, double &new_kv); - void diagonalize_curv(const SVector3 &old_u, const SVector3 &old_v, - double ku, double kuv, double kv, - const SVector3 &new_norm, - SVector3 &pdir1, SVector3 &pdir2, double &k1, double &k2); - void computePointareas(); - void computeRusinkiewiczNormals(); - - // Perform LDL^T decomposition of a symmetric positive definite matrix. - // Like Cholesky, but no square roots. Overwrites lower triangle of matrix. - static inline bool ldltdc(STensor3& A, double rdiag[3]) - { - double v[2]; - for (int i = 0; i < 3; i++) - { - for (int k = 0; k < i; k++) - v[k] = A(i,k) * rdiag[k]; - for (int j = i; j < 3; j++) - { - double sum = A(i,j); - for (int k = 0; k < i; k++) - sum -= v[k] * A(j,k); - if (i == j) - { - //if (unlikely(sum <= T(0))) - if (sum <= 0.0) - return false; - rdiag[i] = 1.0 / sum; - } - else - { - A(j,i) = sum; - } - } - } - - return true; - } - // Solve Ax=B after ldltdc - static inline void ldltsl(STensor3& A, double rdiag[3], double B[3], double x[3]) - { - int i; - for (i = 0; i < 3; i++) - { - double sum = B[i]; - for (int k = 0; k < i; k++) - sum -= A(i,k) * x[k]; - x[i] = sum * rdiag[i]; - } - for (i = 3 - 1; i >= 0; i--) - { - double sum = 0; - for (int k = i + 1; k < 3; k++) - sum += A(k,i) * x[k]; - x[i] -= sum * rdiag[i]; - } - } - - //Build the list of all edges: - void buildEdgeList(); - - //Smooth the computed curvature field via Laplacian smoothing method: - void smoothCurvatureField(const int NbIter); - -public: - - typedef enum {RUSIN=1,RBF=2, SIMPLE=3} typeOfCurvature; - static Curvature& getInstance(); - static bool valueAlreadyComputed(); - - inline void setGModel(GModel* model) - { - _model = model; - } - - void retrieveCompounds(); - void correctOnEdges(); - double getAtVertex(const MVertex *v) const; - //void retrievePhysicalSurfaces(const std::string & face_tag); - - void computeCurvature(GModel* model, typeOfCurvature typ); - - /// The following function implements algorithm from: - /// Implementation of an Algorithm for Approximating the Curvature Tensor - /// on a Triangular Surface Mesh in the Vish Environment - /// Edwin Matthews, Werner Benger, Marcel Ritter - void computeCurvature_Simple(); - - /// The following function implements algorithm from: - /// Estimating Curvatures and Their Derivatives on Triangle Meshes - /// Szymon Rusinkiewicz, Princeton University - /// Code taken from Rusinkiewicz' 'trimesh2' library - void computeCurvature_Rusinkiewicz(int isMax=0); - - void computeCurvature_RBF(); - - void triangleNodalValues(MTriangle* triangle, double& c0, double& c1, double& c2, int isAbs=0); - void triangleNodalValuesAndDirections(MTriangle* triangle, SVector3* dMax, SVector3* dMin, double* cMax, double* cMin, int isAbs=0); - - void edgeNodalValues(MLine* edge, double& c0, double& c1, int isAbs=0); - void edgeNodalValuesAndDirections(MLine* edge, SVector3* dMax, SVector3* dMin, double* cMax, double* cMin, int isAbs=0); - - void vertexNodalValues(MVertex* A, double& c0, int isAbs=0); - void vertexNodalValuesAndDirections(MVertex *A, SVector3* dMax, SVector3* dMin, double* cMax, double* cMin, int isAbs=0); - SVector3 vertexNormal (MVertex* A) ; - - void writeToMshFile( const std::string & filename); - - void writeToPosFile( const std::string & filename); - - void writeToVtkFile( const std::string & filename); - - void writeDirectionsToPosFile( const std::string & filename); -}; - -#endif diff --git a/Geo/GEdge.cpp b/Geo/GEdge.cpp index 13c8d5708b012f0b2778316db3b3028f497e83b2..66ca5b4660ae8dab3137a10e1528d52f4a1a221f 100644 --- a/Geo/GEdge.cpp +++ b/Geo/GEdge.cpp @@ -21,7 +21,7 @@ GEdge::GEdge(GModel *model, int tag, GVertex *_v0, GVertex *_v1) : GEntity(model, tag), _length(0.), _tooSmall(false), _cp(0), - v0(_v0), v1(_v1), compound(0), masterOrientation(0) + v0(_v0), v1(_v1), masterOrientation(0) { if(v0) v0->addEdge(this); if(v1 && v1 != v0) v1->addEdge(this); diff --git a/Geo/GEdge.h b/Geo/GEdge.h index 4538a95d80af0914523a647c87a428ddee9e7eec..2b415079ee0c916327b2b64f4ae4dd4e7efe8252 100644 --- a/Geo/GEdge.h +++ b/Geo/GEdge.h @@ -21,7 +21,6 @@ class MElement; class MLine; class ExtrudeParams; -class GEdgeCompound; class closestPointFinder; // A model edge. @@ -35,7 +34,6 @@ class GEdge : public GEntity { // FIXME: normals need to be mutable at the moment, because thay can // be created in const member functions mutable std::map<MVertex*, SVector3, std::less<MVertex*> > _normals; - GEdgeCompound *compound; // this model edge belongs to a compound std::list<GFace *> l_faces; // for specific solid modelers that need to re-do the internal curve // if a topological change ending points is done (glueing) @@ -191,10 +189,6 @@ class GEdge : public GEntity { virtual bool XYZToU(const double X, const double Y, const double Z, double &U, const double relax=1) const; - // compound - void setCompound(GEdgeCompound *gec) { compound = gec; } - GEdgeCompound *getCompound() const { return compound; } - // gluing void replaceEndingPoints(GVertex *, GVertex *); diff --git a/Geo/GEdgeCompound.cpp b/Geo/GEdgeCompound.cpp deleted file mode 100644 index 58f93ad36f677047b66c8088f4095767642fe74f..0000000000000000000000000000000000000000 --- a/Geo/GEdgeCompound.cpp +++ /dev/null @@ -1,359 +0,0 @@ -// Gmsh - Copyright (C) 1997-2017 C. Geuzaine, J.-F. Remacle -// -// See the LICENSE.txt file for license information. Please report all -// bugs and problems to the public mailing list <gmsh@onelab.info>. -// -// Contributor(s): -// Emilie Marchandise -// - -#include <stdlib.h> -#include "GmshConfig.h" -#include "GEdgeCompound.h" -#include "discreteEdge.h" -#include "Numeric.h" -#include "Curvature.h" - -static bool looksOk(int tag, std::vector<GEdge*> &compound) -{ - if(compound.empty()){ - Msg::Error("Empty edge compound %d", tag); - return false; - } - for(unsigned int i = 0; i < compound.size(); i++){ - if(!compound[i]->getBeginVertex() || !compound[i]->getEndVertex()){ - Msg::Error("Edge compound %d with missing begin/end vertex", tag); - return false; - } - if(compound.size() > 1 && compound[i]->getBeginVertex() == compound[i]->getEndVertex()){ - Msg::Warning("Edge compound %d with subloop", tag); - return true; - } - } - return true; -} - -GEdgeCompound::GEdgeCompound(GModel *m, int tag, std::vector<GEdge*> &compound, - std::vector<int> &orientation) - : GEdge(m, tag, 0, 0), _compound(compound), _orientation(orientation) -{ - if(!looksOk(tag, compound)) return; - - int N = _compound.size(); - if(N == (int)_orientation.size()){ - v0 = _orientation[0] ? _compound[0]->getBeginVertex() : _compound[0]->getEndVertex(); - v1 = _orientation[N-1] ? _compound[N-1]->getEndVertex() : _compound[N-1]->getBeginVertex(); - v0->addEdge(this); - v1->addEdge(this); - } - else{ - Msg::Error("Wrong input data for compound edge %d", tag); - return; - } - - for (unsigned int i = 0; i < _compound.size(); i++){ - _compound[i]->setCompound(this); - discreteEdge *de = dynamic_cast<discreteEdge*> (_compound[i]); - if(de) de->createGeometry(); - } - - for(std::vector<GEdge*>::iterator it = _compound.begin(); it != _compound.end(); ++it){ - if(!(*it)){ - Msg::Error("Incorrect edge in compound edge %d", tag); - return; - } - } - - parametrize(); -} - -GEdgeCompound::GEdgeCompound(GModel *m, int tag, std::vector<GEdge*> &compound) - : GEdge(m, tag, 0 , 0), _compound(compound) -{ - if(!looksOk(tag, compound)) return; - - orderEdges(); - int N = _compound.size(); - if(N == (int)_orientation.size()){ - v0 = _orientation[0] ? _compound[0]->getBeginVertex() : _compound[0]->getEndVertex(); - v1 = _orientation[N-1] ? _compound[N-1]->getEndVertex() : _compound[N-1]->getBeginVertex(); - v0->addEdge(this); - v1->addEdge(this); - } - else{ - Msg::Error("Wrong input data for compound edge %d", tag); - return; - } - - for (unsigned int i = 0; i < _compound.size(); i++){ - _compound[i]->setCompound(this); - discreteEdge *de = dynamic_cast<discreteEdge*> (_compound[i]); - if(de) de->createGeometry(); - } - parametrize(); -} - -void GEdgeCompound::orderEdges() -{ - std::vector<GEdge*> _c ; - std::list<GEdge*> edges ; - - for (unsigned int i = 0; i < _compound.size(); i++){ - edges.push_back(_compound[i]); - } - - // find a lonely edge - std::map<GVertex*, GEdge*> tempv; - for (std::list<GEdge*>::iterator it = edges.begin() ; it != edges.end() ; ++it){ - GVertex *v1 = (*it)->getBeginVertex(); - GVertex *v2 = (*it)->getEndVertex(); - if(!v1 || !v2){ - Msg::Error("Compounds don't support curves without two bounding vertices"); - return; - } - std::map<GVertex*, GEdge*>::iterator it1 = tempv.find(v1); - if (it1 == tempv.end()) { - tempv.insert(std::make_pair(v1, *it)); - } - else tempv.erase(it1); - std::map<GVertex*, GEdge*>::iterator it2 = tempv.find(v2); - if (it2 == tempv.end()){ - tempv.insert(std::make_pair(v2, *it)); - } - else tempv.erase(it2); - } - - // find the first GEdge and erase it from the list edges - GEdge *firstEdge; - if (tempv.size() == 2){ // non periodic - firstEdge = (tempv.begin())->second; - for (std::list<GEdge*>::iterator it = edges.begin() ; it != edges.end() ; ++it){ - if (*it == firstEdge){ - edges.erase(it); - break; - } - } - } - else if (tempv.size() == 0){ // periodic - firstEdge = *(edges.begin()); - edges.erase(edges.begin()); - } - else{ - Msg::Error("EdgeCompound %d is wrong (it has %d end points)", tag(), tempv.size()); - return; - } - - // loop over all segments to order segments and store it in the list _c - _c.push_back(firstEdge); - _orientation.push_back(1); - GVertex *first = _c[0]->getBeginVertex(); - GVertex *last = _c[0]->getEndVertex(); - - while (first != last){ - if (edges.empty())break; - bool found = false; - for (std::list<GEdge*>::iterator it = edges.begin() ; it != edges.end() ; ++it){ - GEdge *e = *it; - std::list<GEdge*>::iterator itp; - if (e->getBeginVertex() == last){ - _c.push_back(e); - itp = it; - it++; - edges.erase(itp); - _orientation.push_back(1); - last = e->getEndVertex(); - found = true; - break; - } - else if (e->getEndVertex() == last){ - _c.push_back(e); - itp = it; - it++; - edges.erase(itp); - _orientation.push_back(0); - last = e->getBeginVertex(); - found = true; - break; - } - } - if (!found){ - if (_c.size() == 1 && _orientation[0]){ - GVertex *temp = first; - first = last; - last = temp; - _orientation[0] = 0; - } - else { - Msg::Error("Compound Edge %d is wrong", tag()); - return; - } - } - } - - //edges is now a list of ordered GEdges - _compound = _c; - - // special case reverse orientation - if (_compound.size() < 2) return; - if (_orientation[0] && _compound[0]->getEndVertex() != _compound[1]->getEndVertex() - && _compound[0]->getEndVertex() != _compound[1]->getBeginVertex()){ - for (unsigned int i = 0; i < _compound.size(); i++){ - _orientation[i] = !_orientation[i] ; - } - } -} - -int GEdgeCompound::minimumMeshSegments() const -{ - // int N = 0; - // for (unsigned int i = 0; i < _compound.size(); i++) - // N += _compound[i]->minimumMeshSegments(); - return 3; -} - -int GEdgeCompound::minimumDrawSegments() const -{ - int N = 0; - for (unsigned int i = 0; i < _compound.size(); i++) - N += _compound[i]->minimumDrawSegments(); - return N; -} - -GEdgeCompound::~GEdgeCompound() -{ -} - -Range<double> GEdgeCompound::parBounds(int i) const -{ - if(_pars.empty()){ - Msg::Error("Edge compound has no parametrization"); - return Range<double>(0, 1); - } - return Range<double>(0, _pars[_compound.size()]); -} - -/* - +--------+-----------+----------- ... ----+ - 0 _pars[1] _pars[2] _pars[N-1] - -*/ - -bool GEdgeCompound::getLocalParameter(const double &t, - int &iEdge, - double &tLoc) const -{ - if(_pars.empty()){ - Msg::Error("Edge compound has no parametrization"); - return false; - } - for (iEdge = 0; iEdge < (int)_compound.size(); iEdge++){ - double tmin = _pars[iEdge]; - double tmax = _pars[iEdge+1]; - if (t >= tmin && t <= tmax){ - Range<double> b = _compound[iEdge]->parBounds(0); - tLoc = _orientation[iEdge] ? - b.low() + (t-tmin)/(tmax-tmin) * (b.high()-b.low()) : - b.high() - (t-tmin)/(tmax-tmin) * (b.high()-b.low()) ; - return true; - } - } - return false; -} - -void GEdgeCompound::parametrize() -{ - _pars.clear(); - _pars.push_back(0.0); - for (unsigned int i = 0; i < _compound.size(); i++){ - Range<double> b = _compound[i]->parBounds(0); - _pars.push_back(_pars[_pars.size()-1] + (b.high() - b.low())); - } -} - -double GEdgeCompound::curvature(double par) const -{ - double tLoc; - int iEdge; - if(!getLocalParameter(par, iEdge, tLoc)) - return 0.; - return _compound[iEdge]->curvature(tLoc); -} - -double GEdgeCompound::curvatures(const double par, SVector3 *dirMax, SVector3 *dirMin, - double *curvMax, double *curvMin) const -{ - double tLoc = -1.0; - int iEdge; - if(!getLocalParameter(par, iEdge, tLoc)) - return 0; - - if( _compound[iEdge]->geomType() == GEntity::DiscreteCurve){ - Curvature& curvature = Curvature::getInstance(); - if( !Curvature::valueAlreadyComputed() ){ - Msg::Info("Need to compute discrete curvature for anisotropic remesh (in GFace)"); - Curvature::typeOfCurvature type = Curvature::RUSIN; //RBF - curvature.computeCurvature(model(), type); - } - double tLocMLine; - int iMLine; - discreteEdge* ptrEdge = dynamic_cast<discreteEdge*>(_compound[iEdge]); - ptrEdge->getLocalParameter(tLoc, iMLine, tLocMLine); - - //vector of MLines - MLine* mline = ptrEdge->lines[iMLine]; - - double cMin[2]; - double cMax[2]; - SVector3 dMin[2]; - SVector3 dMax[2]; - curvature.edgeNodalValuesAndDirections(mline, dMax, dMin, cMax, cMin, 1); - - *dirMax = (1-tLocMLine)*dMax[0] + tLocMLine*dMax[1]; - *dirMin = (1-tLocMLine)*dMin[0] + tLocMLine*dMin[1]; - *curvMax = (1-tLocMLine)*cMax[0] + tLocMLine*cMax[1]; - *curvMin = (1-tLocMLine)*cMin[0] + tLocMLine*cMin[1]; - - return *curvMax; - } - else{ - Msg::Error("Case of CAD Geometry, don't know what to do here..."); - } - return 0.0; -} - -GPoint GEdgeCompound::point(double par) const -{ - double tLoc; - int iEdge; - if(!getLocalParameter(par, iEdge, tLoc)) - return GPoint(); - return _compound[iEdge]->point(tLoc); -} - -SVector3 GEdgeCompound::firstDer(double par) const -{ - double tLoc; - int iEdge; - if(!getLocalParameter(par, iEdge, tLoc)) - return SVector3(); - return _compound[iEdge]->firstDer(tLoc); -} - -void replaceMeshCompound(GFace *gf, std::list<GEdge*> &edges) -{ - std::list<GEdge*> e = gf->edges(); - // replace edges by their compounds - std::set<GEdge*> mySet; - std::list<GEdge*>::iterator it = e.begin(); - while(it != e.end()){ - if((*it)->getCompound()){ - mySet.insert((*it)->getCompound()); - } - else{ - mySet.insert(*it); - } - ++it; - } - edges.clear(); - edges.insert(edges.begin(), mySet.begin(), mySet.end()); -} diff --git a/Geo/GEdgeCompound.h b/Geo/GEdgeCompound.h deleted file mode 100644 index 036f021f20093233c119654ce01ef290df546714..0000000000000000000000000000000000000000 --- a/Geo/GEdgeCompound.h +++ /dev/null @@ -1,43 +0,0 @@ -// Gmsh - Copyright (C) 1997-2017 C. Geuzaine, J.-F. Remacle -// -// See the LICENSE.txt file for license information. Please report all -// bugs and problems to the public mailing list <gmsh@onelab.info>. - -#ifndef _GEDGE_COMPOUND_H_ -#define _GEDGE_COMPOUND_H_ - -#include "GFace.h" -#include "GEdge.h" - -// A GEdgeCompound is a model edge that is the compound of model edges. - -class GEdgeCompound : public GEdge { - protected: - std::vector<GEdge*> _compound; - std::vector<int> _orientation; - std::vector<double> _pars; - void orderEdges(); - public: - void parametrize(); - bool getLocalParameter(const double &t, int &iEdge, double & tLoc) const; - GEdgeCompound(GModel *m, int tag, std::vector<GEdge*> &compound); - GEdgeCompound(GModel *m, int tag, std::vector<GEdge*> &compound, - std::vector<int> &orientation); // confidence in the input - virtual ~GEdgeCompound(); - Range<double> parBounds(int i) const; - virtual GPoint point(double par) const; - virtual SVector3 firstDer(double par) const; - virtual GEntity::GeomType geomType() const { return CompoundCurve; } - ModelType getNativeType() const { return GmshModel; } - void * getNativePtr() const { return 0; } - virtual double curvature(double t) const; - virtual double curvatures(const double par, SVector3 *dirMax, SVector3 *dirMin, - double *curvMax, double *curvMin) const; - virtual int minimumMeshSegments() const; - virtual int minimumDrawSegments() const; - std::vector<GEdge*> getCompounds() const { return _compound; } -}; - -void replaceMeshCompound(GFace*, std::list<GEdge*>&); - -#endif diff --git a/Geo/GFace.cpp b/Geo/GFace.cpp index 34349160a57790910e28de77b14ab496c6e6c758..42acb346926bc9de0e71da229bf6c7c7d6af319b 100644 --- a/Geo/GFace.cpp +++ b/Geo/GFace.cpp @@ -35,7 +35,7 @@ #define SQU(a) ((a)*(a)) GFace::GFace(GModel *model, int tag) - : GEntity(model, tag), r1(0), r2(0), compound(0), va_geom_triangles(0) + : GEntity(model, tag), r1(0), r2(0), va_geom_triangles(0) { meshStatistics.status = GFace::PENDING; resetMeshAttributes(); @@ -1101,7 +1101,7 @@ GPoint GFace::closestPoint(const SPoint3 &queryPoint, const double initialGuess[ #endif } -bool GFace::containsParam(const SPoint2 &pt) +bool GFace::containsParam(const SPoint2 &pt) { Range<double> uu = parBounds(0); Range<double> vv = parBounds(1); diff --git a/Geo/GFace.h b/Geo/GFace.h index b55a4b71382452b1c63bb7ce005c25c21d69685c..5e3cd5d1a753b5e15b718d0564c5da16bb20a2a4 100644 --- a/Geo/GFace.h +++ b/Geo/GFace.h @@ -24,7 +24,6 @@ class MTriangle; class MQuadrangle; class MPolygon; class ExtrudeParams; -class GFaceCompound; class GRegion; @@ -39,7 +38,6 @@ class GFace : public GEntity { mean_plane meanPlane; std::list<GEdge *> embedded_edges; std::list<GVertex *> embedded_vertices; - GFaceCompound *compound; // this model face belongs to a compound BoundaryLayerColumns _columns; @@ -254,10 +252,6 @@ class GFace : public GEntity { void computeMeshSizeFieldAccuracy(double &avg,double &max_e, double &min_e, int &nE, int &GS); - // compound - void setCompound(GFaceCompound *gfc) { compound = gfc; } - GFaceCompound *getCompound() const { return compound; } - // add points (and optionally normals) in vectors so that two // points are at most maxDist apart bool fillPointCloud(double maxDist, diff --git a/Geo/GFaceCompound.cpp b/Geo/GFaceCompound.cpp deleted file mode 100644 index 46170ba73490387b30e98d6d97da57701dfdbae2..0000000000000000000000000000000000000000 --- a/Geo/GFaceCompound.cpp +++ /dev/null @@ -1,3083 +0,0 @@ -// Gmsh - Copyright (C) 1997-2017 C. Geuzaine, J.-F. Remacle -// -// See the LICENSE.txt file for license information. Please report all -// bugs and problems to the public mailing list <gmsh@onelab.info>. -// -// Contributor(s): -// Emilie Marchandise -// - -#include "GmshConfig.h" -#include "GmshDefines.h" -#include "GFaceCompound.h" -#include "GEdgeCompound.h" -#include "intersectCurveSurface.h" -#include "OS.h" - -#if defined(HAVE_SOLVER) && defined(HAVE_ANN) - -#include "Options.h" -#include "MLine.h" -#include "MTriangle.h" -#include "Numeric.h" -#include "Octree.h" -#include "SBoundingBox3d.h" -#include "SPoint3.h" -#include "polynomialBasis.h" -#include "robustPredicates.h" -#include "MElementCut.h" -#include "dofManager.h" -#include "laplaceTerm.h" -#include "crossConfTerm.h" -#include "convexCombinationTerm.h" -#include "diagBCTerm.h" -#include "linearSystemGMM.h" -#include "linearSystemCSR.h" -#include "linearSystemFull.h" -#include "linearSystemPETSc.h" -#include "CreateFile.h" -#include "Context.h" -#include "discreteFace.h" -#include "eigenSolver.h" -#include "multiscaleLaplace.h" -#include "GRbf.h" -#include "Curvature.h" -#include "MPoint.h" -#include "Numeric.h" -#include "meshGFace.h" -#include "ANN/ANN.h" - -static void fixEdgeToValue(GEdge *ed, double value, dofManager<double> &myAssembler) -{ - myAssembler.fixVertex(ed->getBeginVertex()->mesh_vertices[0], 0, 1, value); - myAssembler.fixVertex(ed->getEndVertex()->mesh_vertices[0], 0, 1, value); - for(unsigned int i = 0; i < ed->mesh_vertices.size(); i++){ - myAssembler.fixVertex(ed->mesh_vertices[i], 0, 1, value); - } -} - -static std::vector<MVertex*> getBlob(unsigned int minNbPt, v2t_cont::iterator it, - v2t_cont &adj) -{ - std::vector<MVertex*> vv(1,it->first), bvv = vv; - // Vector of vertices in blob and in boundary of blob - do { - std::set<MVertex*> nbvv; - // Set of vertices in new boundary - for (std::vector<MVertex*>::iterator itBV = bvv.begin(); itBV != bvv.end(); itBV++) { - // For each boundary vertex... - std::vector<MElement*> &adjBV = adj[*itBV]; - for (std::vector<MElement*>::iterator itBVEl = adjBV.begin(); itBVEl != adjBV.end(); - itBVEl++) { - for (int iV=0; iV<(*itBVEl)->getNumVertices(); iV++){ - // ... look for adjacent vertices... - MVertex *v = (*itBVEl)->getVertex(iV); - if (find(vv.begin(),vv.end(),v) == vv.end()) nbvv.insert(v); - // ... and add them in the new boundary if they are not already in the blob - } - } - } - if (nbvv.empty()) bvv.clear(); - else { - bvv.assign(nbvv.begin(),nbvv.end()); - vv.insert(vv.end(),nbvv.begin(),nbvv.end()); - } -// } while (!bvv.empty()); - } while (vv.size() < minNbPt); - // Repeat until min. number of points is reached - - return vv; -} - -static bool orderVertices(const std::list<GEdge*> &e, std::vector<MVertex*> &l, - std::vector<double> &coord) -{ - l.clear(); - coord.clear(); - - std::list<GEdge*>::const_iterator it = e.begin(); - std::list<MLine*> temp; - double tot_length = 0; - for( ; it != e.end(); ++it ){ - for(unsigned int i = 0; i < (*it)->lines.size(); i++ ){ - temp.push_back((*it)->lines[i]); - MVertex *v0 = (*it)->lines[i]->getVertex(0); - MVertex *v1 = (*it)->lines[i]->getVertex(1); - const double length = sqrt((v0->x() - v1->x()) * (v0->x() - v1->x()) + - (v0->y() - v1->y()) * (v0->y() - v1->y()) + - (v0->z() - v1->z()) * (v0->z() - v1->z())); - tot_length += length; - } - } - - MVertex *first_v = (*temp.begin())->getVertex(0); - MVertex *current_v = (*temp.begin())->getVertex(1); - - l.push_back(first_v); - coord.push_back(0.0); - temp.erase(temp.begin()); - - while(temp.size()){ - bool found = false; - for(std::list<MLine*>::iterator itl = temp.begin(); itl != temp.end(); ++itl){ - MLine *ll = *itl; - MVertex *v0 = ll->getVertex(0); - MVertex *v1 = ll->getVertex(1); - if(v0 == current_v){ - found = true; - l.push_back(current_v); - current_v = v1; - temp.erase(itl); - const double length = sqrt((v0->x() - v1->x()) * (v0->x() - v1->x()) + - (v0->y() - v1->y()) * (v0->y() - v1->y()) + - (v0->z() - v1->z()) * (v0->z() - v1->z())); - coord.push_back(coord[coord.size()-1] + length / tot_length); - break; - } - else if(v1 == current_v){ - found = true; - l.push_back(current_v); - current_v = v0; - temp.erase(itl); - const double length = sqrt((v0->x() - v1->x()) * (v0->x() - v1->x()) + - (v0->y() - v1->y()) * (v0->y() - v1->y()) + - (v0->z() - v1->z()) * (v0->z() - v1->z())); - coord.push_back(coord[coord.size()-1] + length / tot_length); - break; - } - } - if(!found) return false; - } - - return true; -} - -static bool computeCGKernelPolygon(std::map<MVertex*,SPoint3> &coordinates, - std::vector<MVertex*> &cavV, - double &ucg, double &vcg) -{ - ucg = 0.0; - vcg = 0.0; - - // place at CG KERNEL polygon - - int nbPts = cavV.size(); - fullMatrix<double> u(100,2); - int ipt = 0; - for(std::vector<MVertex*>::iterator it = cavV.begin(); it != cavV.end(); it++){ - SPoint3 vsp = coordinates[*it]; - u(ipt,0) = vsp[0]; - u(ipt,1) = vsp[1]; - ucg += u(ipt,0); - vcg += u(ipt,1); - ipt++; - } - ucg /= ipt; - vcg /= ipt; - - double eps = -5.e-7; - int N = nbPts; - - std::set<int> setP; - for(int k = 0; k < nbPts; k++) setP.insert(k); - - if(nbPts > 3){ - for(int i = 0; i < nbPts - 2; i++){ - int next = i + 1; - double x1, x2, y1, y2; - x1 = u(i, 0); y1 = u(i, 1); - x2 = u(next, 0); y2 = u(next, 1); - for(int j = i + 2; j < nbPts; j++){ - int jnext = j + 1; - if(j == nbPts - 1) jnext = 0; - double x3, x4, y3, y4, x,y; - double a, b, c, d; - x3 = u(j, 0); y3 = u(j, 1); - x4 = u(jnext, 0); y4 = u(jnext, 1); - a = (y2 - y1) / (x2 - x1); - c = (y4 - y3) / (x4 - x3); - b = y1 - a * x1; - d = y3 - c * x3; - if(fabs(a - c) > 1.e-5 && x2 !=x1 && x4 != x3 && jnext != i){ - x = (d - b) / (a - c); - y = a * x + b; - bool exist= false; - for(unsigned int k = 1; k < setP.size(); k++){ - if(x == u(k, 0) && y == u(k, 1)) exist = true; - } - if(!exist){ - u(N, 0) = x; u(N, 1) = y; - setP.insert(N); - N++; - } - } - } - } - - int nbAll = setP.size(); - for(int i = 0; i <nbPts; i++){ - int next = i + 1; - if(next == nbPts) next = 0; - double p1[2] = {u(next, 0) - u(i, 0), u(next, 1) - u(i, 1)}; - for(int k = 0; k < nbAll; k++){ - double p2[2] = {u(k, 0) - u(i, 0), u(k, 1) - u(i, 1)}; - double crossProd = p1[0] * p2[1] - p2[0] * p1[1]; - if(crossProd < eps){ - setP.erase(k); - } - } - } - } - - int nbFinal = setP.size(); - if(nbFinal > 0){ - ucg = 0.0; - vcg = 0.0; - for(std::set<int>::iterator it =setP.begin(); it != setP.end(); it++){ - ucg += u(*it,0); - vcg += u(*it,1); - } - ucg /= nbFinal; - vcg /= nbFinal; - return true; - } - else{ - return false; - } -} - -static void myPolygon(std::vector<MElement*> &vTri, std::vector<MVertex*> &vPoly) -{ - std::vector<MEdge> ePoly; - for(unsigned int i = 0; i < vTri.size() ; i++) { - MTriangle *t = (MTriangle*) vTri[i]; - for(int iEdge = 0; iEdge < 3; iEdge++) { - MEdge tmp_edge = t->getEdge(iEdge); - if(std::find(ePoly.begin(), ePoly.end(), tmp_edge) == ePoly.end()) - ePoly.push_back(tmp_edge); - else - ePoly.erase(std::find(ePoly.begin(), ePoly.end(),tmp_edge)); - } - } - - std::vector<MEdge>::iterator ite= ePoly.begin() ; - MVertex *vINIT = ite->getVertex(0); - vPoly.push_back(vINIT); - vPoly.push_back(ite->getVertex(1)); - ePoly.erase(ite); - - while(!ePoly.empty()){ - ite = ePoly.begin() ; - while(ite != ePoly.end()){ - MVertex *vB = ite->getVertex(0); - MVertex *vE = ite->getVertex(1); - if(vB == vPoly.back()){ - if(vE != vINIT) vPoly.push_back(vE); - ePoly.erase(ite); - } - else if(vE == vPoly.back()){ - if(vB != vINIT) vPoly.push_back(vB); - ePoly.erase(ite); - } - else ite++; - } - } -} - -static double normalUV(MTriangle *t, std::map<MVertex*, SPoint3> &vCoord) -{ - SPoint3 v0 = vCoord[t->getVertex(0)]; - SPoint3 v1 = vCoord[t->getVertex(1)]; - SPoint3 v2 = vCoord[t->getVertex(2)]; - double p0[2] = {v0[0], v0[1]}; - double p1[2] = {v1[0], v1[1]}; - double p2[2] = {v2[0], v2[1]}; - double normal = robustPredicates::orient2d(p0, p1, p2); - - // SVector3 P0 (v0.x(),v0.y(), 0.0); - // SVector3 P1 (v1.x(),v1.y(), 0.0); - // SVector3 P2 (v2.x(),v2.y(), 0.0); - // double normal2 = crossprod(P1-P0,P2-P1).z(); - // if (normal != 0.0) normal /= std::abs(normal); - - return normal; -} - -static bool checkCavity(std::vector<MElement*> &vTri, std::map<MVertex*, SPoint3> &vCoord) -{ - bool badCavity = false; - - unsigned int nbV = vTri.size(); - double a_old = 0.0, a_new; - for(unsigned int i = 0; i < nbV; ++i){ - a_new = normalUV((MTriangle*) vTri[i], vCoord); - if(i == 0) a_old=a_new; - if(a_new*a_old < 0.0) badCavity = true; - } - return badCavity; -} - -static bool closedCavity(MVertex *v, std::vector<MElement*> &vTri) -{ - std::set<MVertex *> vs; - for (unsigned int i = 0; i < vTri.size(); i++){ - MElement *t = vTri[i]; - for (int j = 0; j < t->getNumVertices(); j++){ - MVertex *vv = t->getVertex(j); - if (vv != v){ - if (vs.find(vv) == vs.end())vs.insert(vv); - else vs.erase(vv); - } - } - } - return vs.empty(); -} - -static MVertex* findVertexInTri(v2t_cont &adjv, MVertex *v0, MVertex *v1, - std::map<MVertex*, SPoint3> &vCoord, double nTot, - bool &inverted) -{ - MVertex *v2 = 0; - v2t_cont :: iterator it0 = adjv.find(v0); - std::vector<MElement*> vTri0 = it0->second; - MElement *myTri = 0; - for (unsigned int j = 0; j < vTri0.size(); j++){ - MVertex *vt0 = vTri0[j]->getVertex(0); - MVertex *vt1 = vTri0[j]->getVertex(1); - MVertex *vt2 = vTri0[j]->getVertex(2); - bool found0 = (vt0==v0 || vt1 ==v0 || vt2 ==v0) ? true: false; - bool found1 = (vt0==v1 || vt1 ==v1 || vt2 ==v1) ? true: false; - if (found0 && found1) { myTri = vTri0[j]; break; } - } - if(!myTri) return 0; - for (unsigned int j = 0; j < 3; j++){ - MVertex *vj = myTri->getVertex(j); - if (vj!=v0 && vj!=v1) { v2 = vj; break;} - } - double normTri = normalUV((MTriangle*)myTri, vCoord); - if (nTot*normTri < 0.0) inverted = true; - else inverted = false; - - return v2; -} - -static MTriangle* findInvertedTri(v2t_cont &adjv, MVertex*v0, MVertex*v1, MVertex*v2, - std::map<MVertex*, SPoint3> &vCoord, double nTot) -{ - v2t_cont::iterator it = adjv.find(v1); - std::vector<MElement*> vTri = it->second; - MTriangle *myTri=NULL; - for (unsigned int j = 0; j < vTri.size(); j++){ - double normTri = normalUV((MTriangle*)vTri[j], vCoord); - if (nTot * normTri < 0.0) { - MVertex *vt0 = vTri[j]->getVertex(0); - MVertex *vt1 = vTri[j]->getVertex(1); - MVertex *vt2 = vTri[j]->getVertex(2); - bool found0 = (vt0==v0 || vt1 ==v0 || vt2 ==v0) ? true: false; - bool found2 = (vt0==v2 || vt1 ==v2 || vt2 ==v2) ? true: false; - if (!found0 && !found2) { myTri = (MTriangle*)vTri[j]; break; } - } - } - - return myTri; -} - -void GFaceCompound::orientFillTris(std::list<MTriangle*> loopfillTris) const -{ - // check normal orientations of loopfillTris - bool invertTris = false; - std::map<MEdge, std::set<MTriangle*>, Less_Edge > edge2tris; - for(std::list<MTriangle*>::iterator t = loopfillTris.begin(); - t != loopfillTris.end(); t++){ - for (int j = 0; j < 3; j++){ - MEdge me = (*t)->getEdge(j); - std::map<MEdge, std::set<MTriangle*, std::less<MTriangle*> >, - Less_Edge >::iterator it = edge2tris.find(me); - if (it == edge2tris.end()) { - std::set<MTriangle*, std::less<MTriangle*> > mySet; - mySet.insert(*t); - edge2tris.insert(std::make_pair(me, mySet)); - } - else{ - std::set<MTriangle*, std::less<MTriangle*> > mySet = it->second; - mySet.insert(*t); - it->second = mySet; - } - } - } - - int iE, si, iE2, si2; - std::list<GFace*>::const_iterator itf = _compound.begin(); - for( ; itf != _compound.end(); ++itf){ - for(unsigned int i = 0; i < (*itf)->triangles.size(); ++i){ - MTriangle *t = (*itf)->triangles[i]; - for (int j = 0; j < 3; j++){ - MEdge me = t->getEdge(j); - std::map<MEdge, std::set<MTriangle*>, Less_Edge >::iterator it = - edge2tris.find(me); - if(it != edge2tris.end()){ - t->getEdgeInfo(me, iE,si); - MTriangle* t2 = *((it->second).begin()); - t2->getEdgeInfo(me,iE2,si2); - if(si == si2) { - invertTris = true; - break; - } - } - } - } - } - if (invertTris){ - for (std::list<MTriangle*>::iterator it = loopfillTris.begin(); - it != loopfillTris.end(); it++ ) - (*it)->reverse(); - } - - fillTris.insert(fillTris.begin(),loopfillTris.begin(),loopfillTris.end()); -} - -void GFaceCompound::printFillTris() const -{ - if(!CTX::instance()->mesh.saveAll) return; - - if (fillTris.size() > 0){ - char name[256]; - //std::list<GFace*>::const_iterator itf = _compound.begin(); - sprintf(name, "fillTris-%d.pos", tag()); - FILE * ftri = Fopen(name,"w"); - if(ftri){ - fprintf(ftri,"View \"\"{\n"); - for (std::list<MTriangle*>::iterator it2 = fillTris.begin(); - it2 !=fillTris.end(); it2++ ){ - MTriangle *t = (*it2); - fprintf(ftri,"ST(%g,%g,%g,%g,%g,%g,%g,%g,%g){%g,%g,%g};\n", - t->getVertex(0)->x(), t->getVertex(0)->y(), t->getVertex(0)->z(), - t->getVertex(1)->x(), t->getVertex(1)->y(), t->getVertex(1)->z(), - t->getVertex(2)->x(), t->getVertex(2)->y(), t->getVertex(2)->z(), - 1., 1., 1.); - } - fprintf(ftri,"};\n"); - fclose(ftri); - } - } -} - -void GFaceCompound::fillNeumannBCS_Plane() const -{ -#if 0 -//#if defined(HAVE_MESH) - - Msg::Debug("Meshing %d interior holes with planes ", _interior_loops.size()-1); - - fillTris.clear(); - fillNodes.clear(); - - if (_interior_loops.size()==1 && _type != SQUARE) return; - - GModel::current()->setFactory("Gmsh"); - //GModel::current()->setFactory("OpenCASCADE"); - std::vector<std::vector<GFace *> > myFaceLoops; - std::vector<GFace *> myFaces; - for(std::list<std::list<GEdge*> >::const_iterator iloop = _interior_loops.begin(); - iloop != _interior_loops.end(); iloop++){ - std::list<MTriangle*> loopfillTris; - std::list<GEdge*> loop = *iloop; - if (loop != _U0 ){ - std::vector<std::vector<GEdge *> > myEdgeLoops; - std::vector<GEdge*> myEdges; - myEdgeLoops.clear(); - myEdges.clear(); - for (std::list<GEdge*>::iterator itl = loop.begin(); itl != loop.end(); itl++){ - myEdges.push_back(*itl); - } - myEdgeLoops.push_back(myEdges); - GFace *newFace = GModel::current()->addPlanarFace(myEdgeLoops); - fillFaces.push_back(newFace); - int meshingAlgo = CTX::instance()->mesh.algo2d; - int recombine = CTX::instance()->mesh.recombineAll; - opt_mesh_algo2d(0, GMSH_SET, 1.0); //mesh adapt - opt_mesh_recombine_all(0, GMSH_SET, 0.0); //no recombination - meshGFace mgf; - mgf(newFace,false); - opt_mesh_algo2d(0, GMSH_SET, meshingAlgo); - opt_mesh_recombine_all(0, GMSH_SET, recombine); - for(unsigned int i = 0; i < newFace->triangles.size(); ++i){ - loopfillTris.push_back(newFace->triangles[i]); - fillNodes.insert(newFace->triangles[i]->getVertex(0)); - fillNodes.insert(newFace->triangles[i]->getVertex(1)); - fillNodes.insert(newFace->triangles[i]->getVertex(2)); - } - orientFillTris(loopfillTris); - } - } - - printFillTris(); -#endif -} - -void GFaceCompound::fillNeumannBCS() const -{ - fillTris.clear(); - fillNodes.clear(); - - // closed interior loops - for(std::list<std::list<GEdge*> >::const_iterator iloop = _interior_loops.begin(); - iloop != _interior_loops.end(); iloop++){ - std::list<MTriangle*> loopfillTris; - std::list<GEdge*> loop = *iloop; - if (loop != _U0 ){ - std::vector<MVertex*> orderedLoop; - std::vector<double> coordsLoop; - orderVertices(*iloop, orderedLoop, coordsLoop); - int nbLoop = orderedLoop.size(); - - //--- center of Neumann interior loop - int nb = 0; - double x=0.; - double y=0.; - double z=0.; - // EMI- TODO FIND KERNEL OF POLYGON AND PLACE AT CG KERNEL ! - // IF NO KERNEL -> DO NOT FILL TRIS - for(int i = 0; i < nbLoop; ++i){ - MVertex *v0 = orderedLoop[i]; - MVertex *v1 = (i==nbLoop-1) ? orderedLoop[0]: orderedLoop[i+1]; - x += .5*(v0->x() + v1->x()); - y += .5*(v0->y() + v1->y()); - z += .5*(v0->z() + v1->z()); - nb++; - } - x/=nb; y/=nb; z/=nb; - MVertex *c = new MVertex(x, y, z); - - //--- create new triangles - for(int i = 0; i < nbLoop; ++i){ - MVertex *v0 = orderedLoop[i]; - MVertex *v1 = (i==nbLoop-1) ? orderedLoop[0]: orderedLoop[i+1]; - - double k = 1. / 3.; double kk = 2. / 3.; - MVertex *v2 = new MVertex(kk * v0->x() + k * c->x(), - kk * v0->y() + k * c->y(), - kk * v0->z() + k * c->z()); - MVertex *v3 = new MVertex(kk * v1->x() + k * c->x(), - kk * v1->y() + k * c->y(), - kk * v1->z() + k * c->z()); - MVertex *v4 = new MVertex(k * v0->x() + kk * c->x(), - k * v0->y() + kk * c->y(), - k * v0->z() + kk * c->z()); - MVertex *v5 = new MVertex(k * v1->x() + kk * c->x(), - k * v1->y() + kk * c->y(), - k * v1->z() + kk * c->z()); - fillNodes.insert(c); fillNodes.insert(v2); fillNodes.insert(v3); - fillNodes.insert(v4); fillNodes.insert(v5); - loopfillTris.push_back(new MTriangle(v0, v2, v3)); - loopfillTris.push_back(new MTriangle(v2, v5, v3)); - loopfillTris.push_back(new MTriangle(v2, v4, v5)); - loopfillTris.push_back(new MTriangle(v4, c, v5)); - loopfillTris.push_back(new MTriangle(v0, v3, v1)); - } - } - orientFillTris(loopfillTris); - } - - printFillTris(); -} - -bool GFaceCompound::trivial() const -{ - return false; - if(_compound.size() == 1 && - (*(_compound.begin()))->getNativeType() == GEntity::OpenCascadeModel && - (*(_compound.begin()))->geomType() != GEntity::DiscreteSurface && - _mapping != CONFORMAL){ - if ((*(_compound.begin()))->periodic(0) || - (*(_compound.begin()))->periodic(1) ) return false; - return true; - } - return false; -} - -// For the conformal map the linear system cannot guarantee there is -// no overlapping of triangles -bool GFaceCompound::checkOverlap(std::vector<MVertex *> &vert) const -{ - - vert.clear(); - bool has_overlap = false; - double EPS = 1.e-2; - for(std::list<std::list<GEdge*> >::const_iterator iloop = _interior_loops.begin(); - iloop != _interior_loops.end(); iloop++){ - std::list<GEdge*> loop = *iloop; - std::vector<MVertex*> orderedLoop; - if (loop != _U0 ){ - std::vector<double> coordsLoop; - orderVertices(*iloop, orderedLoop, coordsLoop); - } - else orderedLoop = _ordered; - int nbLoop = orderedLoop.size(); - - for(int i = 0; i < nbLoop-1; ++i){ - SPoint3 p1 = coordinates[orderedLoop[i]]; - SPoint3 p2 = coordinates[orderedLoop[i+1]]; - int maxSize = (i==0) ? nbLoop-2: nbLoop-1; - for(int k = i+2; k < maxSize; ++k){ - SPoint3 q1 = coordinates[orderedLoop[k]]; - SPoint3 q2 = coordinates[orderedLoop[k+1]]; - double x[2]; - int inters = intersection_segments (p1,p2,q1,q2,x); - if (inters && x[1] > EPS && x[1] < 1.-EPS){ - has_overlap = true; - MVertex *v1 = orderedLoop[i]; - MVertex *v2 = orderedLoop[k]; - //std::set<MVertex *>::iterator it1 = ov.find(v1); - //std::set<MVertex *>::iterator it2 = ov.find(v2); - vert.push_back(v1); - vert.push_back(v2); - Msg::Info("=== Overlap"); - return has_overlap; - } - } - } - - } - - return has_overlap; -} - -// check if the discrete harmonic map is correct by checking that all -// the mapped triangles have the same normal orientation -bool GFaceCompound::checkOrientation(int iter, bool moveBoundaries) const -{ - std::list<GFace*>::const_iterator it = _compound.begin(); - double a_old = 0.0, a_new=0.0; - bool oriented = true; - int count = 0; - double nTot = 0.0; - for( ; it != _compound.end(); ++it){ - for(unsigned int i = 0; i < (*it)->triangles.size(); ++i){ - a_new = normalUV((*it)->triangles[i], coordinates); - if(count == 0) a_old=a_new; - nTot += a_new; - if(a_new*a_old < 0.0){ - oriented = false; - break; - } - count++; - } - } - - int iterMax = 15; - if(!oriented && iter < iterMax){ - if (moveBoundaries){ - if (iter ==0) Msg::Info("--- Flipping : moving boundaries."); - Msg::Debug("--- Moving Boundary - iter %d -",iter); - convexBoundary(nTot/fabs(nTot)); - printStuff(iter); - return checkOrientation(iter+1, moveBoundaries); - } - else if (!moveBoundaries){ - if (iter ==0) Msg::Info("--- Flipping : applying cavity checks."); - Msg::Debug("--- Cavity Check - iter %d -",iter); - oriented = one2OneMap(); - printStuff(iter); - iter++; - if (!oriented) return checkOrientation(iter); - } - } - - if (iter > 0 && iter < iterMax){ - Msg::Info("--- Flipping : no more flips (%d iter)", iter); - } - - return oriented; -} - -void GFaceCompound::convexBoundary(double nTot) const -{ -#if defined(HAVE_MESH) - if(adjv.size() == 0){ - std::vector<MTriangle*> allTri; - std::list<GFace*>::const_iterator it = _compound.begin(); - for( ; it != _compound.end(); ++it){ - allTri.insert(allTri.end(), (*it)->triangles.begin(), (*it)->triangles.end() ); - } - buildVertexToTriangle(allTri, adjv); - } - - for(std::list<std::list<GEdge*> >::const_iterator it = _interior_loops.begin(); - it != _interior_loops.end(); it++){ - - double s = 1.0; - std::vector<MVertex*> oVert; - std::vector<double> coords; - if (*it == _U0){ - oVert = _ordered; - } - else { - s = -1.0; - orderVertices(*it, oVert,coords); - } - - // find normal of ordered loop - MVertex *v0 = oVert[0]; - MVertex *v1 = oVert[1]; - bool inverted; - MVertex *v2 = findVertexInTri(adjv, v0,v1,coordinates, nTot, inverted); - if (inverted) s *= -1.0 ; - SPoint3 uv0 = coordinates[v0]; - SPoint3 uv1 = coordinates[v1]; - SPoint3 uv2 = coordinates[v2]; - SVector3 P0 (uv0.x(),uv0.y(), 0.0); - SVector3 P1 (uv1.x(),uv1.y(), 0.0); - SVector3 P2 (uv2.x(),uv2.y(), 0.0); - double myN = s*crossprod(P1-P0,P2-P1).z(); - SVector3 N (0,0,myN/fabs(myN)); - - // start the loop - int nbInv = 0; - int nbInvTri = 0; - for(unsigned int i = 0; i < oVert.size(); i++){ - - MVertex *v0 = oVert[i]; - MVertex *v1, *v2; - if (i == oVert.size()-2){ - v1 = oVert[i+1]; - v2 = oVert[0]; - } - else if (i == oVert.size()-1){ - v1= oVert[0]; - v2= oVert[1]; - } - else{ - v1 = oVert[i+1]; - v2 = oVert[i+2]; - } - - SPoint3 uv0 = coordinates[v0]; - SPoint3 uv1 = coordinates[v1]; - SPoint3 uv2 = coordinates[v2]; - SVector3 P0 (uv0.x(),uv0.y(), uv0.z()); - SVector3 P1 (uv1.x(),uv1.y(), uv1.z()); - SVector3 P2 (uv2.x(),uv2.y(), uv2.z()); - - SVector3 dir1 = P1-P0; - SVector3 dir2 = P2-P1; - SVector3 dir3 = crossprod(dir1,dir2); - double rot = dot(N, (1./norm(dir3))*dir3); - - bool inverted; - MVertex *v2t = findVertexInTri(adjv, v0,v1, coordinates, nTot, inverted); - - if (rot < 0.0 && inverted){ - SVector3 a = P1-P0; - SVector3 b = P2-P0; - double a_para = dot(a,b)/norm(b); - SVector3 P3,P1b; - P3= P0 + (a_para/norm(b))*b; - P1b = P1 + 1.2*(P3-P1); - SPoint3 uv1_new(P1b.x(),P1b.y(),P1b.z()); - coordinates[v1] = uv1_new; - } - else if (rot > 0.0 && inverted){ - nbInv++; - SPoint3 uv2t = coordinates[v2t]; - SVector3 P2t (uv2t.x(),uv2t.y(), uv2t.z()); - SVector3 a = P1-P0; - SVector3 b = P2t-P0; - double b_para = dot(a,b)/norm(a); - SVector3 P3,P2b; - P3= P0 + (b_para/norm(a))*a; - P2b = P2t + 1.3*(P3-P2t); - SPoint3 uv2_new(P2b.x(),P2b.y(),P2b.z()); - coordinates[v2t] = uv2_new; - } - - MTriangle *tinv = findInvertedTri(adjv, v0,v1,v2, coordinates, nTot); - if (tinv){ - nbInvTri++; - MVertex *i0 = NULL; - MVertex *i1 = NULL; - for (unsigned int j = 0; j < 3; j++){ - MVertex *vj = tinv->getVertex(j); - if (vj!=v1 && i0 == NULL) i0 = vj; - else if (vj!=v1 && i1 ==NULL ) i1 = vj; - } - MVertex *i2 = v1; - SPoint3 uv0 = coordinates[i0]; - SPoint3 uv1 = coordinates[i1]; - SPoint3 uv2 = coordinates[i2]; - SVector3 P0 (uv0.x(),uv0.y(), uv0.z()); - SVector3 P1 (uv1.x(),uv1.y(), uv1.z()); - SVector3 P2 (uv2.x(),uv2.y(), uv2.z()); - SVector3 a = P1-P0; - SVector3 b = P2-P0; - double b_para = dot(a,b)/norm(a); - SVector3 P3,P2b; - P3= P0 + (b_para/norm(a))*a; - P2b = P2 + 1.2*(P3-P2); - SPoint3 uv2_new(P2b.x(),P2b.y(),P2b.z()); - coordinates[i2] = uv2_new; - } - - } - } -#endif -} - -bool GFaceCompound::one2OneMap() const -{ -#if defined(HAVE_MESH) - if(adjv.size() == 0){ - std::vector<MTriangle*> allTri; - std::list<GFace*>::const_iterator it = _compound.begin(); - for( ; it != _compound.end(); ++it){ - allTri.insert(allTri.end(), (*it)->triangles.begin(), (*it)->triangles.end() ); - } - buildVertexToTriangle(allTri, adjv); - } - - int nbRepair = 0; - int nbCav = 0; - for(v2t_cont::iterator it = adjv.begin(); it!= adjv.end(); ++it){ - MVertex *v = it->first; - SPoint2 p = getCoordinates(v); - std::vector<MElement*> vTri = it->second; - std::map<MVertex*,SPoint3> vCoord; - for (unsigned int j = 0; j < vTri.size(); j++){ - for (int k = 0; k < vTri[j]->getNumVertices(); k++){ - MVertex *vk = vTri[j]->getVertex(k); - SPoint2 pt2 = getCoordinates(vk); - vCoord[vk] = SPoint3(pt2[0], pt2[1], 0.0); - } - } - bool badCavity = checkCavity(vTri, vCoord); - bool innerCavity = closedCavity(v,vTri); - - if( badCavity && innerCavity ){ - nbCav++; - double u_cg, v_cg; - std::vector<MVertex*> cavV; - myPolygon(vTri, cavV); - //bool success = - computeCGKernelPolygon(coordinates, cavV, u_cg, v_cg); - //if (success){ //if not succes compute with CG polygon - nbRepair++; - SPoint3 p_cg(u_cg,v_cg,0.0); - coordinates[v] = p_cg; - //} - } - } - if (nbRepair == 0) return false; - else return true; -#endif -} - -bool GFaceCompound::parametrize() const -{ - if (_compound.size() > 1) coherencePatches(); - - bool paramOK = true; - if(oct) return paramOK; - if(trivial()) return paramOK; - - if (_mapping != RBF) - coordinates.clear(); - - computeNormals(); - - if(allNodes.empty()) buildAllNodes(); - - if (_type != SQUARE){ - bool success = orderVertices(_U0, _ordered, _coords); - if(!success) { - Msg::Error("Could not order vertices on boundary"); - return false; - } - } - - //fillNeumannBCS_Plane(); - fillNeumannBCS(); - - // Convex parametrization - if (_mapping == CONVEX){ - Msg::Info("Parametrizing surface %d with 'convex map'", tag()); - parametrize(ITERU,CONVEX); - parametrize(ITERV,CONVEX); - if (_type==MEANPLANE){ - checkOrientation(0, true); - } - } - // Laplace parametrization - else if (_mapping == HARMONIC){ - Msg::Info("Parametrizing surface %d with 'harmonic map'", tag()); - parametrize(ITERU,HARMONIC); - parametrize(ITERV,HARMONIC); - if (_type == MEANPLANE) checkOrientation(0, true); - } - // Conformal map parametrization - else if (_mapping == CONFORMAL){ - std::vector<MVertex *> vert; - bool oriented, overlap; - if (_type == SPECTRAL){ - Msg::Info("Parametrizing surface %d with 'spectral conformal map'", tag()); - overlap = parametrize_conformal_spectral(); - } - else { - Msg::Info("Parametrizing surface %d with 'FE conformal map'", tag()); - overlap = parametrize_conformal(0, NULL, NULL); - } - //printStuff(55); - oriented = checkOrientation(0); - //printStuff(77); - if (_type==SPECTRAL && (!oriented || overlap) ){ - Msg::Warning("Parametrization switched to 'FE conformal' map"); - overlap = parametrize_conformal(0, NULL, NULL); - oriented = checkOrientation(0); - } - if (!oriented || overlap){ - Msg::Warning("Parametrization switched to 'convex' map"); - _type = UNITCIRCLE; - parametrize(ITERU,CONVEX); - parametrize(ITERV,CONVEX); - } - } - // Radial-Basis Function parametrization - else if (_mapping == RBF){ - Msg::Debug("Parametrizing surface %d with 'RBF' ", tag()); - int variableEps = 0; - int radFunInd = 1; // 1 MQ RBF , 0 GA - double sizeBox = getSizeH(); - /* - fullMatrix<double> Oper(3*allNodes.size(),3*allNodes.size()); - _rbf = new GRbf(sizeBox, variableEps, radFunInd, _normals, allNodes, _ordered); - _rbf->RbfLapSurface_local_CPM(false,_rbf->getXYZ(), _rbf->getN(), Oper); - _rbf->solveHarmonicMap(Oper, _ordered, _coords, coordinates); - */ - fullMatrix<double> Oper(3*allNodes.size(),3*allNodes.size()); - - _rbf = new GRbf(sizeBox, variableEps, radFunInd, _normals, allNodes, _ordered); - - linearSystemPETSc<double> sys; - - #if 1 - _rbf->RbfLapSurface_local_CPM_sparse(_ordered, false, _rbf->getXYZ(), _rbf->getN(), sys); - _rbf->solveHarmonicMap_sparse(sys, _rbf->getXYZ().size1()* 3,_ordered, _coords, coordinates); - #else - _rbf->RbfLapSurface_local_CPM(false, _rbf->getXYZ(), _rbf->getN(), Oper); - _rbf->solveHarmonicMap(Oper,_ordered, _coords, coordinates); - #endif - } - - buildOct(); - - if (_mapping != RBF){ - if (!checkOrientation(0)){ - printStuff(22); - Msg::Info("### parametrization switched to 'convex map' onto circle"); - printStuff(33); - _type = UNITCIRCLE; - coordinates.clear(); - Octree_Delete(oct); - parametrize(ITERU, CONVEX); - parametrize(ITERV, CONVEX); - checkOrientation(0); - buildOct(); - } - } - - for (unsigned int i= 0; i< fillFaces.size(); i++){ - GModel::current()->remove(fillFaces[i]); - } - - return paramOK; -} - -void GFaceCompound::getBoundingEdges() -{ - for(std::list<GFace*>::iterator it = _compound.begin(); it != _compound.end(); ++it){ - (*it)->setCompound(this); - } - - std::set<GEdge*> _unique; - getUniqueEdges(_unique); - - l_edges.clear(); - l_dirs.clear(); // added by Trevor Strickler - - - if(_U0.size()){ - // in case the bounding edges are explicitely given - std::list<GEdge*>::const_iterator it = _U0.begin(); - for( ; it != _U0.end() ; ++it){ - l_edges.push_back(*it); - (*it)->addFace(this); - } - if (_V0.size() && _U1.size() && _V1.size()){ - it = _V0.begin(); - for( ; it != _V0.end() ; ++it){ - l_edges.push_back(*it); - (*it)->addFace(this); - } - it = _U1.begin(); - for( ; it != _U1.end() ; ++it){ - l_edges.push_back(*it); - (*it)->addFace(this); - } - it = _V1.begin(); - for( ; it != _V1.end() ; ++it){ - l_edges.push_back(*it); - (*it)->addFace(this); - } - } - std::list<GEdge*> loop; - computeALoop(_unique, loop); - while(!_unique.empty()) computeALoop(_unique,loop); - } - else{ - // in case the bounding edges are NOT explicitely given - std::set<GEdge*>::iterator itf = _unique.begin(); - for( ; itf != _unique.end(); ++itf){ - l_edges.push_back(*itf); - (*itf)->addFace(this); - } - - std::list<GEdge*> loop; - computeALoop(_unique,loop); - while(!_unique.empty()) computeALoop(_unique, loop); - - // assign Derichlet BC (_U0) to boundary with largest size - double maxSize = 0.0; - for(std::list<std::list<GEdge*> >::iterator it = _interior_loops.begin(); - it != _interior_loops.end(); it++){ - double size = getSizeBB(*it); - if (size > maxSize) { - _U0 = *it; - maxSize = size; - } - } - } - - // Added by Trevor Strickler (fill in the l_dirs) - std::list<GEdge*>::iterator it_loop; - std::list<std::list<GEdge*> >::iterator it_interior; - l_edges.clear(); - - for( it_interior = _interior_loops.begin(); it_interior != _interior_loops.end(); it_interior++ ){ - for( it_loop = it_interior->begin(); it_loop != it_interior->end(); it_loop++ ){ - l_edges.push_back( (*it_loop) ); - std::list<GEdge*>::iterator it_loop_next = it_loop; - it_loop_next++; - if( it_loop_next == it_interior->end() ) - it_loop_next = it_interior->begin(); - GVertex *vB = (*it_loop)->getBeginVertex(); - GVertex *vE = (*it_loop)->getEndVertex(); - GVertex *vB_next = (*it_loop_next)->getBeginVertex(); - GVertex *vE_next = (*it_loop_next)->getEndVertex(); - if( vB == vB_next || vB == vE_next ) - l_dirs.push_back(-1); - else if( vE == vB_next || vE == vE_next ) - l_dirs.push_back(1); - else{ - l_dirs.push_back(0); - } - } - } - -} - - -double GFaceCompound::getSizeH() const -{ - SBoundingBox3d bb; - for(std::set<MVertex *>::iterator itv = allNodes.begin(); - itv != allNodes.end() ; ++itv){ - SPoint3 pt((*itv)->x(),(*itv)->y(), (*itv)->z()); - bb +=pt; - } - - double H = norm(SVector3(bb.max(), bb.min())); - - return H; -} - -double GFaceCompound::getSizeBB(const std::list<GEdge* > &elist) const -{ - SBoundingBox3d bboxD; - std::list<GEdge*>::const_iterator it = elist.begin(); - for(; it != elist.end(); it++){ - bboxD += (*it)->bounds(); - } - double D = norm(SVector3(bboxD.max(), bboxD.min())); - - return D; -} - -void GFaceCompound::getUniqueEdges(std::set<GEdge*> &_unique) -{ - _unique.clear(); - - // in case the bounding edges are not given Boundary { {} }; - std::multiset<GEdge*> _touched; - std::list<GFace*>::iterator it = _compound.begin(); - for( ; it != _compound.end(); ++it){ - std::list<GEdge*> ed = (*it)->edges(); - std::list<GEdge*>::iterator ite = ed.begin(); - for( ; ite != ed.end(); ++ite){ - _touched.insert(*ite); - } - } - it = _compound.begin(); - for( ; it != _compound.end(); ++it){ - std::list<GEdge*> ed = (*it)->edges(); - std::list<GEdge*>::iterator ite = ed.begin(); - for( ; ite != ed.end() ; ++ite){ - if(!(*ite)->degenerate(0) && _touched.count(*ite) == 1){ - _unique.insert(*ite); - } - } - } -} - -void GFaceCompound::computeALoop(std::set<GEdge*> &_unique, std::list<GEdge*> &loop) -{ - std::list<GEdge*> _loop; - - if (_unique.empty()) return; - - while(!_unique.empty()) { - std::set<GEdge*>::iterator it = _unique.begin(); - GVertex *vB = (*it)->getBeginVertex(); - GVertex *vE = (*it)->getEndVertex(); - _loop.push_back(*it); - _unique.erase(it); - - bool found = false; -/* Mod by Trevor Strickler: In the old implementation, the iterator - itx was incremented twice per loop and _loops was not set up correctly. - The While Loop below replaces the old for loop. -*/ - for(int i = 0; i < 2; i++) { - std::set<GEdge*>::iterator itx = _unique.begin(); - while (itx != _unique.end() ){ - GVertex *v1 = (*itx)->getBeginVertex(); - GVertex *v2 = (*itx)->getEndVertex(); - - std::set<GEdge*>::iterator itp = itx; - itx++; - - if(v1 == vE ){ - _loop.push_back(*itp); - vE = v2; - i = -1; - _unique.erase(itp); - } - else if(v2 == vE){ - _loop.push_back(*itp); - vE = v1; - i=-1; - _unique.erase(itp); - } - } - - if(vB == vE) { - found = true; - break; - } - - if(_unique.empty()) break; - - // Mod by Trevor Strickler: had to wrap this in an if - // or else it was executed when i == -1, which is not good. - if( i != -1 ){ - GVertex *temp = vB; - vB = vE; - vE = temp; - } - } - /* This is the old version of above nested loops before modified by Trevor Strickler - for(int i = 0; i < 2; i++) { - for(std::set<GEdge*>::iterator itx = _unique.begin(); - itx != _unique.end(); ++itx){ - GVertex *v1 = (*itx)->getBeginVertex(); - GVertex *v2 = (*itx)->getEndVertex(); - - std::set<GEdge*>::iterator itp; - if(v1 == vE){ - _loop.push_back(*itx); - itp = itx; - itx++; - _unique.erase(itp); - vE = v2; - i = -1; - } - else if(v2 == vE){ - _loop.push_back(*itx); - itp = itx; - itx++; - _unique.erase(itp); - vE = v1; - i=-1; - } - if(itx == _unique.end()) break; - } - - if(vB == vE) { - found = true; - break; - } - - if(_unique.empty()) break; - - GVertex *temp = vB; - vB = vE; - vE = temp; - }*/ - - if(found == true) break; - - it++; - } - - loop = _loop; - _interior_loops.push_back(loop); -} - -GFaceCompound::GFaceCompound(GModel *m, int tag, std::list<GFace*> &compound, - std::list<GEdge*> &U0, typeOfCompound toc, - int allowPartition) - : GFace(m, tag), _compound(compound), _U0(U0), oct(0), octNew(0), - _toc(toc), _allowPartition(allowPartition) -{ - ONE = new simpleFunction<double>(1.0); - MONE = new simpleFunction<double>(-1.0); - - for(std::list<GFace*>::iterator it = _compound.begin(); it != _compound.end(); ++it){ - if(!(*it)){ - Msg::Error("Incorrect face in compound surface %d\n", tag); - return; - } - } - - getBoundingEdges(); - - _mapping = HARMONIC; - _type = UNITCIRCLE; - if(toc == RADIAL_BASIS) _mapping = RBF; - else if (toc == HARMONIC_PLANE) _type = MEANPLANE; - else if (toc == CONVEX_CIRCLE) _mapping = CONVEX; - else if (toc == CONVEX_PLANE){ - _mapping = CONVEX; - _type = MEANPLANE; - } - else if(toc == CONFORMAL_SPECTRAL) { - _mapping = CONFORMAL; - _type = SPECTRAL; - } - else if(toc == CONFORMAL_FE) { - _mapping = CONFORMAL; - _type = FE; - } - - nbSplit = 0; - fillTris.clear(); - - kdtree = NULL; - uv_kdtree = NULL; -} - -GFaceCompound::GFaceCompound(GModel *m, int tag, std::list<GFace*> &compound, - std::list<GEdge*> &U0, std::list<GEdge*> &V0, - std::list<GEdge*> &U1, std::list<GEdge*> &V1, - typeOfCompound toc, - int allowPartition) - : GFace(m, tag), _compound(compound), _U0(U0), _V0(V0), _U1(U1), _V1(V1), - oct(0), octNew(0), _toc(toc), _allowPartition(allowPartition) -{ - ONE = new simpleFunction<double>(1.0); - MONE = new simpleFunction<double>(-1.0); - - for(std::list<GFace*>::iterator it = _compound.begin(); it != _compound.end(); ++it){ - if(!(*it)){ - Msg::Error("Incorrect face in compound surface %d\n", tag); - return; - } - } - - getBoundingEdges(); - - _mapping = HARMONIC; - _type = UNITCIRCLE; - if(toc == RADIAL_BASIS) _mapping = RBF; - else if (toc == HARMONIC_PLANE) _type = MEANPLANE; - else if (toc == CONVEX_CIRCLE) _mapping = CONVEX; - else if (toc == CONVEX_PLANE){ - _mapping = CONVEX; - _type = MEANPLANE; - } - if(toc == CONFORMAL_SPECTRAL) { - _mapping = CONFORMAL; - _type = SPECTRAL; - } - else if(toc == CONFORMAL_FE) { - _mapping = CONFORMAL; - _type = FE; - } - else if(toc == HARMONIC_SQUARE && _U0.size() && _V0.size() && _U1.size() && _V1.size()) { - _type = SQUARE; - } - - nbSplit = 0; - fillTris.clear(); - - uv_kdtree = NULL; - kdtree = NULL; -} - -GFaceCompound::~GFaceCompound() -{ - delete ONE; - delete MONE; - _deleteInternals(); -} - -void GFaceCompound::deleteInternals(){ - _deleteInternals(); -} - -void GFaceCompound::_deleteInternals() -{ - for (unsigned int i = 0; i < myParamVert.size(); i++) - delete myParamVert[i]; - myParamVert.clear(); - for (unsigned int i = 0; i < myParamElems.size(); i++) - delete myParamElems[i]; - myParamElems.clear(); - _3Dto2D.clear(); - _2Dto3D.clear(); - XYZoct.clear(); - allNodes.clear(); - adjv.clear(); - coordinates.clear(); - firstDerivatives.clear(); - xuu.clear(); - xvv.clear(); - xuv.clear(); - xu.clear(); - xv.clear(); - _coordPoints.clear(); - _normals.clear(); - fillTris.clear(); - fillNodes.clear(); - fillFaces.clear(); - _ordered.clear(); - _coords.clear(); - _mapV.clear(); - - if(oct){ - Octree_Delete(oct); - delete [] _gfct; - oct = 0; - } - if(octNew){ - delete octNew; - octNew = 0; - } - if(uv_kdtree) { - ANNpointArray uv_nodes = uv_kdtree->thePoints(); - if(uv_nodes) annDeallocPts(uv_nodes); - delete uv_kdtree; - uv_kdtree = 0; - } - if(kdtree){ - ANNpointArray nodes = kdtree->thePoints(); - if(nodes) annDeallocPts(nodes); - delete kdtree; - kdtree = 0; - } -} - - -void GFaceCompound::deleteMesh() -{ - _deleteInternals(); - GFace::deleteMesh(); -} - -SPoint2 GFaceCompound::getCoordinates(MVertex *v) const -{ - if(trivial()){ - SPoint2 param; - reparamMeshVertexOnFace(v, (*(_compound.begin())),param); - return param; - } - - std::map<MVertex*,SPoint3>::iterator it = coordinates.find(v); - - if(it != coordinates.end()){ - return SPoint2(it->second.x(),it->second.y()); - } - else{ - - //if(v->onWhat()->dim() == 1){ - double tGlob, tLoc; - double tL, tR; - int iEdge; - - // getParameter Point - v->getParameter(0, tGlob); - - //find compound Edge - GEdgeCompound *gec = dynamic_cast<GEdgeCompound*>(v->onWhat()); - - if(gec){ - // compute local parameter on Edge - gec->getLocalParameter(tGlob,iEdge,tLoc); - std::vector<GEdge*> gev = gec->getCompounds(); - GEdge *ge = gev[iEdge]; - std::map<MVertex*,SPoint3>::iterator itL; - std::map<MVertex*,SPoint3>::iterator itR; - - if(ge->geomType() == GEntity::DiscreteCurve){ - discreteEdge *de = dynamic_cast<discreteEdge*>(ge); - int i = (int)tLoc; - MLine *l = de->lines[i]; - MVertex *vL = l->getVertex(0); - MVertex *vR = l->getVertex(1); - itL = coordinates.find(vL); - if(itL == coordinates.end()){ - Msg::Error("Vertex %p (%g %g %g) not found", vL, vL->x(), vL->y(), vL->z()); - return SPoint2(0, 0); - } - itR = coordinates.find(vR); - if(itR == coordinates.end()){ - Msg::Error("Vertex %p (%g %g %g) not found", vR, vR->x(), vR->y(), vR->z()); - return SPoint2(0, 0); - } - double xi, uloc, vloc; - xi = tLoc - i; - uloc = (1 - xi) * itL->second.x() + xi * itR->second.x(); - vloc = (1 - xi) * itL->second.y() + xi * itR->second.y(); - return SPoint2(uloc,vloc); - } - else{ - // left and right vertex of the Edge - MVertex *v0 = ge->getBeginVertex()->mesh_vertices[0]; - MVertex *v1 = ge->getEndVertex()->mesh_vertices[0]; - itL = coordinates.find(v0); - itR = coordinates.find(v1); - // for the Edge, find the left and right vertices of the initial - // 1D mesh and interpolate to find (u,v) - //MVertex *vL = v0; - MVertex *vR = v1; - double tB = ge->parBounds(0).low(); - double tE = ge->parBounds(0).high(); - int j = 0; - tL=tB; - bool found = false; - while(j < (int)ge->mesh_vertices.size()){ - vR = ge->mesh_vertices[j]; - if(vR->getPolynomialOrder() > 1){ j++; continue; } - vR->getParameter(0, tR); - if(!vR->getParameter(0, tR)) { - Msg::Error("Vertex vr %p not an MEdgeVertex", vR); - return SPoint2(); - } - if(tLoc > tL && tLoc < tR){ - found = true; - itR = coordinates.find(vR); - if(itR == coordinates.end()){ - Msg::Error("Vertex %p (%g %g %g) not found", vR, vR->x(), vR->y(), vR->z()); - return SPoint2(0, 0); - } - break; - } - else{ - itL = coordinates.find(vR); - //vL = vR; - tL = tR; - } - j++; - } - if(!found) { - vR = v1; - tR = tE; - } - // linear interpolation between tL and tR - double uloc, vloc; - uloc = itL->second.x() + (tLoc-tL)/(tR-tL) * (itR->second.x()-itL->second.x()); - vloc = itL->second.y() + (tLoc-tL)/(tR-tL) * (itR->second.y()-itL->second.y()); - return SPoint2(uloc,vloc); - } - } - - } - - // never here - return SPoint2(0, 0); -} - -void GFaceCompound::parametrize(iterationStep step, typeOfMapping tom) const -{ - linearSystem<double> *lsys; - - if (tom==HARMONIC){ -#if defined(HAVE_TAUCS) - lsys = new linearSystemCSRTaucs<double>; -#elif defined(HAVE_PETSC) - lsys = new linearSystemPETSc<double>; -#elif defined(HAVE_GMM) - linearSystemGmm<double> *lsysb = new linearSystemGmm<double>; - lsysb->setGmres(1); - lsys = lsysb; -#else - lsys = new linearSystemFull<double>; -#endif - } - else{ -#if defined(HAVE_PETSC) - lsys = new linearSystemPETSc<double>; - lsys->setParameter("petscOptions", - "-pc_type ilu -ksp_rtol 1.e-12 -pc_factor_levels 10"); - - // lsys->setParameter("petscOptions", - // "-ksp_type preonly -pc_type lu -pc_factor_mat_solver_package umfpack"); -#elif defined(HAVE_GMM) - linearSystemGmm<double> *lsysb = new linearSystemGmm<double>; - lsysb->setGmres(1); - lsys = lsysb; -#else - lsys = new linearSystemFull<double>; -#endif - } - - dofManager<double> myAssembler(lsys); - - if(_type == UNITCIRCLE){ - for(unsigned int i = 0; i < _ordered.size(); i++){ - MVertex *v = _ordered[i]; - const double theta = 2 * M_PI * _coords[i]; - if(step == ITERU) myAssembler.fixVertex(v, 0, 1, cos(theta)); - else if(step == ITERV) myAssembler.fixVertex(v, 0, 1, sin(theta)); - } - } - else if(_type == SQUARE){ - if(step == ITERU){ - std::list<GEdge*>::const_iterator it = _U0.begin(); - for( ; it != _U0.end(); ++it){ - fixEdgeToValue(*it, 0.0, myAssembler); - } - it = _U1.begin(); - for( ; it != _U1.end(); ++it){ - fixEdgeToValue(*it, 1.0, myAssembler); - } - } - else if(step == ITERV){ - std::list<GEdge*>::const_iterator it = _V0.begin(); - for( ; it != _V0.end(); ++it){ - fixEdgeToValue(*it, 0.0, myAssembler); - } - it = _V1.begin(); - for( ; it != _V1.end(); ++it){ - fixEdgeToValue(*it, 1.0, myAssembler); - } - } - } - else if (_type == MEANPLANE){ - std::vector<SPoint3> points, pointsProj, pointsUV; - SPoint3 ptCG(0.0, 0.0, 0.0); - for(unsigned int i = 0; i < _ordered.size(); i++){ - MVertex *v = _ordered[i]; - points.push_back(SPoint3(v->x(), v->y(), v->z())); - ptCG[0] += v->x(); - ptCG[1] += v->y(); - ptCG[2] += v->z(); - } - - ptCG /= points.size(); - mean_plane meanPlane; - computeMeanPlaneSimple(points, meanPlane); - projectPointsToPlane(points, pointsProj, meanPlane); - transformPointsIntoOrthoBasis(pointsProj, pointsUV, ptCG, meanPlane); - - for(unsigned int i = 0; i < pointsUV.size(); i++){ - MVertex *v = _ordered[i]; - if(step == ITERU) myAssembler.fixVertex(v, 0, 1, pointsUV[i][0]); - else if(step == ITERV) myAssembler.fixVertex(v, 0, 1, pointsUV[i][1]); - } - } - else if (_type == ALREADYFIXED){ - for(unsigned int i = 0; i < _ordered.size(); i++){ - MVertex *v = _ordered[i]; - SPoint3 uv = coordinates[v]; - if(step == ITERU) myAssembler.fixVertex(v, 0, 1, uv[0]); - else if(step == ITERV) myAssembler.fixVertex(v, 0, 1, uv[1]); - } - } - else{ - Msg::Error("Unknown type of parametrization"); - return; - } - - std::list<GFace*>::const_iterator it = _compound.begin(); - for( ; it != _compound.end(); ++it){ - for(unsigned int i = 0; i < (*it)->triangles.size(); ++i){ - MTriangle *t = (*it)->triangles[i]; - myAssembler.numberVertex(t->getVertex(0), 0, 1); - myAssembler.numberVertex(t->getVertex(1), 0, 1); - myAssembler.numberVertex(t->getVertex(2), 0, 1); - } - } - - for (std::list<MTriangle*>::iterator it2 = fillTris.begin(); it2 !=fillTris.end(); it2++ ){ - MTriangle *t = (*it2); - myAssembler.numberVertex(t->getVertex(0), 0, 1); - myAssembler.numberVertex(t->getVertex(1), 0, 1); - myAssembler.numberVertex(t->getVertex(2), 0, 1); - } - - Msg::Debug("Creating term %d dofs numbered %d fixed", - myAssembler.sizeOfR(), myAssembler.sizeOfF()); - - double t1 = Cpu(); - - femTerm<double> *mapping; - if (tom == HARMONIC) - mapping = new laplaceTerm(0, 1, ONE); - else - mapping = new convexCombinationTerm(0, 1, ONE); - - it = _compound.begin(); - for( ; it != _compound.end() ; ++it){ - for(unsigned int i = 0; i < (*it)->triangles.size(); ++i){ - SElement se((*it)->triangles[i]); - mapping->addToMatrix(myAssembler, &se); - } - } - - for (std::list<MTriangle*>::iterator it2 = fillTris.begin(); it2 !=fillTris.end(); it2++ ){ - SElement se((*it2)); - mapping->addToMatrix(myAssembler, &se); - } - - double t2 = Cpu(); - Msg::Debug("Assembly done in %8.3f seconds", t2 - t1); - lsys->systemSolve(); - Msg::Debug("System solved"); - - for(std::set<MVertex *>::iterator itv = allNodes.begin(); itv !=allNodes.end() ; ++itv){ - MVertex *v = *itv; - double value; - myAssembler.getDofValue(v, 0, 1, value); - std::map<MVertex*,SPoint3>::iterator itf = coordinates.find(v); - if(itf == coordinates.end()){ - SPoint3 p(0, 0, 0); - p[step] = value; - coordinates[v] = p; - } - else{ - itf->second[step]= value; - } - } - - delete mapping; - delete lsys; -} - -bool GFaceCompound::parametrize_conformal_spectral() const -{ -#if !defined(HAVE_PETSC) && !defined(HAVE_SLEPC) - Msg::Warning("Slepc not installed: parametrization switched to 'FE conformal' map"); - return parametrize_conformal(0, NULL, NULL); -#else - - linearSystem <double> *lsysA = new linearSystemPETSc<double>; - linearSystem <double> *lsysB = new linearSystemPETSc<double>; - dofManager<double> myAssembler(lsysA, lsysB); - - myAssembler.setCurrentMatrix("A"); - for(std::set<MVertex *>::iterator itv = allNodes.begin(); itv !=allNodes.end() ; ++itv){ - MVertex *v = *itv; - myAssembler.numberVertex(v, 0, 1); - myAssembler.numberVertex(v, 0, 2); - } - - for(std::set<MVertex *>::iterator itv = fillNodes.begin(); itv !=fillNodes.end() ; ++itv){ - MVertex *v = *itv; - myAssembler.numberVertex(v, 0, 1); - myAssembler.numberVertex(v, 0, 2); - } - - laplaceTerm laplace1(model(), 1, ONE); - laplaceTerm laplace2(model(), 2, ONE); - crossConfTerm cross12(model(), 1, 2, ONE); - crossConfTerm cross21(model(), 2, 1, MONE); - std::list<GFace*>::const_iterator it = _compound.begin(); - for( ; it != _compound.end() ; ++it){ - for(unsigned int i = 0; i < (*it)->triangles.size(); ++i){ - SElement se((*it)->triangles[i]); - laplace1.addToMatrix(myAssembler, &se); - laplace2.addToMatrix(myAssembler, &se); - cross12.addToMatrix(myAssembler, &se); - cross21.addToMatrix(myAssembler, &se); - } - } - - for (std::list<MTriangle*>::iterator it2 = fillTris.begin(); it2 != fillTris.end(); it2++){ - SElement se((*it2)); - laplace1.addToMatrix(myAssembler, &se); - laplace2.addToMatrix(myAssembler, &se); - cross12.addToMatrix(myAssembler, &se); - cross21.addToMatrix(myAssembler, &se); - } - - double epsilon = 1.e-6; - for(std::set<MVertex *>::iterator itv = allNodes.begin(); itv !=allNodes.end() ; ++itv){ - MVertex *v = *itv; - if (std::find(_ordered.begin(), _ordered.end(), v) == _ordered.end() ){ - myAssembler.assemble(v, 0, 1, v, 0, 1, epsilon); - myAssembler.assemble(v, 0, 2, v, 0, 2, epsilon); - } - } - for(std::set<MVertex *>::iterator itv = fillNodes.begin(); itv !=fillNodes.end() ; ++itv){ - MVertex *v = *itv; - if (std::find(_ordered.begin(), _ordered.end(), v) == _ordered.end() ){ - myAssembler.assemble(v, 0, 1, v, 0, 1, epsilon); - myAssembler.assemble(v, 0, 2, v, 0, 2, epsilon); - } - } - - myAssembler.setCurrentMatrix("B"); - - // mettre max NC contraintes par bord - int NB = _ordered.size(); - int NC = std::min(30,NB); - int jump = (int) NB/NC; - int nbLoop = (int) NB/jump ; - for (int i = 0; i< nbLoop; i++){ - MVertex *v1 = _ordered[i*jump]; - myAssembler.assemble(v1, 0, 1, v1, 0, 1, 1.0); - myAssembler.assemble(v1, 0, 2, v1, 0, 2, 1.0); - for (int j = 0; j< nbLoop; j++){ - MVertex *v2 = _ordered[j*jump]; - myAssembler.assemble(v1, 0, 1, v2, 0, 1, -1./NC); - myAssembler.assemble(v1, 0, 2, v2, 0, 2, -1./NC); - } - } - - // FIXME: force non-hermitian. For some reason (roundoff errors?) - // on some machines and for some meshes slepc complains about bad IP - // norm otherwise - eigenSolver eig(&myAssembler, "B" , "A", false); - - bool converged = eig.solve(1, "largest"); - - if(converged) { - double Linfty = 0.0; - int k = 0; - std::vector<std::complex<double> > &ev = eig.getEigenVector(0); - for(std::set<MVertex *>::iterator itv = allNodes.begin(); itv !=allNodes.end() ; ++itv){ - double paramu = ev[k].real(); - double paramv = ev[k+1].real(); - Linfty=std::max(Linfty, sqrt(paramu*paramu+paramv*paramv)); - k = k+2; - } - k = 0; - for(std::set<MVertex *>::iterator itv = allNodes.begin(); itv !=allNodes.end() ; ++itv){ - MVertex *v = *itv; - double paramu = ev[k].real()/Linfty; - double paramv = ev[k+1].real()/Linfty; - coordinates[v] = SPoint3(paramu,paramv,0.0); - k = k+2; - } - delete lsysA; - delete lsysB; - } - else{ - Msg::Warning("Slepc not converged: parametrization switched to 'FE conformal' map"); - return parametrize_conformal(0,NULL,NULL); - } - - std::vector<MVertex *> vert; - return checkOverlap(vert); -#endif -} - -bool GFaceCompound::parametrize_conformal(int iter, MVertex *v1, MVertex *v2) const -{ - linearSystem<double> *lsys; -#if defined(HAVE_TAUCS) - lsys = new linearSystemCSRTaucs<double>; -#elif defined(HAVE_PETSC) - lsys = new linearSystemPETSc<double>; -#elif defined(HAVE_GMM) - linearSystemGmm<double> *lsysb = new linearSystemGmm<double>; - lsysb->setGmres(1); - lsys = lsysb; -#else - lsys = new linearSystemFull<double>; -#endif - - dofManager<double> myAssembler(lsys); - - if(!v1) v1 = _ordered[0]; - if(!v2) v2 = _ordered[(int)ceil((double)_ordered.size()/2.)]; - myAssembler.fixVertex(v1, 0, 1, 1.); - myAssembler.fixVertex(v1, 0, 2, 0.); - myAssembler.fixVertex(v2, 0, 1, -1.); - myAssembler.fixVertex(v2, 0, 2, 0.); - - std::list<GFace*>::const_iterator it = _compound.begin(); - for( ; it != _compound.end(); ++it){ - for(unsigned int i = 0; i < (*it)->triangles.size(); ++i){ - MTriangle *t = (*it)->triangles[i]; - myAssembler.numberVertex(t->getVertex(0), 0, 1); - myAssembler.numberVertex(t->getVertex(1), 0, 1); - myAssembler.numberVertex(t->getVertex(2), 0, 1); - myAssembler.numberVertex(t->getVertex(0), 0, 2); - myAssembler.numberVertex(t->getVertex(1), 0, 2); - myAssembler.numberVertex(t->getVertex(2), 0, 2); - } - } - for (std::list<MTriangle*>::iterator it2 = fillTris.begin(); - it2 !=fillTris.end(); it2++){ - MTriangle *t = (*it2); - myAssembler.numberVertex(t->getVertex(0), 0, 1); - myAssembler.numberVertex(t->getVertex(1), 0, 1); - myAssembler.numberVertex(t->getVertex(2), 0, 1); - myAssembler.numberVertex(t->getVertex(0), 0, 2); - myAssembler.numberVertex(t->getVertex(1), 0, 2); - myAssembler.numberVertex(t->getVertex(2), 0, 2); - } - - laplaceTerm laplace1(model(), 1, ONE); - laplaceTerm laplace2(model(), 2, ONE); - crossConfTerm cross12(model(), 1, 2, ONE); - crossConfTerm cross21(model(), 2, 1, MONE); - it = _compound.begin(); - for( ; it != _compound.end() ; ++it){ - for(unsigned int i = 0; i < (*it)->triangles.size(); ++i){ - SElement se((*it)->triangles[i]); - laplace1.addToMatrix(myAssembler, &se); - laplace2.addToMatrix(myAssembler, &se); - cross12.addToMatrix(myAssembler, &se); - cross21.addToMatrix(myAssembler, &se); - } - } - for (std::list<MTriangle*>::iterator it2 = fillTris.begin(); - it2 != fillTris.end(); it2++ ){ - SElement se((*it2)); - laplace1.addToMatrix(myAssembler, &se); - laplace2.addToMatrix(myAssembler, &se); - cross12.addToMatrix(myAssembler, &se); - cross21.addToMatrix(myAssembler, &se); - } - - Msg::Debug("Assembly done"); - lsys->systemSolve(); - Msg::Debug("System solved"); - - for(std::set<MVertex *>::iterator itv = allNodes.begin(); - itv != allNodes.end() ; ++itv){ - MVertex *v = *itv; - double value1, value2; - myAssembler.getDofValue(v, 0, 1, value1); - myAssembler.getDofValue(v, 0, 2, value2); - coordinates[v] = SPoint3(value1,value2,0.0); - } - - delete lsys; - - // check for overlap and compute new mapping with new pinned - // vertices - std::vector<MVertex *> vert; - bool hasOverlap = checkOverlap(vert); - return hasOverlap; - // if ( hasOverlap && iter < 3){ - // Msg::Info("Loop FE conformal iter (%d) v1=%d v2=%d", iter, - // vert[0]->getNum(), vert[1]->getNum()); - // printStuff(100+iter); - // return hasOverlap = parametrize_conformal(iter+1, vert[0],vert[1]); - // } - // else{ - // return hasOverlap; - // } -} - -void GFaceCompound::computeNormals(std::map<MVertex*,SVector3> &normals) const -{ - computeNormals (); - normals = _normals; -} - -void GFaceCompound::computeNormals() const -{ - _normals.clear(); - std::list<GFace*>::const_iterator it = _compound.begin(); - double J[3][3]; - for( ; it != _compound.end() ; ++it){ - for(unsigned int i = 0; i < (*it)->triangles.size(); ++i){ - MTriangle *t = (*it)->triangles[i]; - t->getJacobian(0, 0, 0, J); - SVector3 n (J[2][0], J[2][1], J[2][2]); - n.normalize(); - for(int j = 0; j < 3; j++){ - std::map<MVertex*, SVector3>::iterator itn = _normals.find(t->getVertex(j)); - if(itn == _normals.end())_normals[t->getVertex(j)] = n; - else itn->second += n; - } - } - } - std::map<MVertex*,SVector3>::iterator itn = _normals.begin(); - for( ; itn != _normals.end() ; ++itn) itn->second.normalize(); -} - -double GFaceCompound::curvatureMax(const SPoint2 ¶m) const -{ - if(!oct) parametrize(); - if(trivial()) { - return (*(_compound.begin()))->curvatureMax(param); - } - - double U, V; - GFaceCompoundTriangle *lt; - getTriangle(param.x(), param.y(), <, U,V); - - if(!lt) return 0.0; - - if(lt->gf && lt->gf->geomType() != GEntity::DiscreteSurface) { - SPoint2 pv = lt->gfp1*(1.-U-V) + lt->gfp2*U + lt->gfp3*V; - return lt->gf->curvatureMax(pv); - } - else if (lt->gf->geomType() == GEntity::DiscreteSurface) { - Curvature& curvature = Curvature::getInstance(); - if( !Curvature::valueAlreadyComputed() ) { - Msg::Info("Need to compute discrete curvature for isotropic remesh (in GFace)"); - Curvature::typeOfCurvature type = Curvature::RUSIN; - curvature.computeCurvature(model(), type); - } - double c0,c1,c2; - curvature.triangleNodalValues(lt->tri,c0, c1, c2, 1); - double cv = (1-U-V)*c0 + U*c1 + V*c2; - return cv; - } - - return 0.; -} - -double GFaceCompound::curvatures(const SPoint2 ¶m, SVector3 *dirMax, SVector3 *dirMin, - double *curvMax, double *curvMin) const -{ - if(!oct) parametrize(); - if(trivial()) { - return (*(_compound.begin()))->curvatures(param, dirMax,dirMin, curvMax, curvMin); - } - - double U, V; - GFaceCompoundTriangle *lt; - getTriangle(param.x(), param.y(), <, U,V); - - if(!lt) return 0.0; - - if(lt->gf && lt->gf->geomType() != GEntity::DiscreteSurface){ - SPoint2 pv = lt->gfp1*(1.-U-V) + lt->gfp2*U + lt->gfp3*V; - return lt->gf->curvatures(pv, dirMax,dirMin, curvMax, curvMin); - } - else if (lt->gf->geomType() == GEntity::DiscreteSurface){ - Curvature& curvature = Curvature::getInstance(); - if( !Curvature::valueAlreadyComputed() ) { - Msg::Info("Need to compute discrete curvature for anisotropic remesh (in GFace)"); - Curvature::typeOfCurvature type = Curvature::RUSIN; //RBF - curvature.computeCurvature(model(), type); - } - - double cMin[3]; - double cMax[3]; - SVector3 dMin[3]; - SVector3 dMax[3]; - curvature.triangleNodalValuesAndDirections(lt->tri, dMax, dMin, cMax, cMin, 0); - //curvature.triangleNodalValuesAndDirections(lt->tri, dMax, dMin, cMax, cMin, 1); - - *dirMax = (1-U-V)*dMax[0] + U*dMax[1] + V*dMax[2]; - *dirMin = (1-U-V)*dMin[0] + U*dMin[1] + V*dMin[2]; - *curvMax = (1-U-V)*cMax[0] + U*cMax[1] + V*cMax[2]; - *curvMin = (1-U-V)*cMin[0] + U*cMin[1] + V*cMin[2]; - - return *curvMax; - } - return 0.; -} - -double GFaceCompound::locCurvature(MTriangle *t, double u, double v) const -{ - SVector3 n1 = _normals[t->getVertex(0)]; - SVector3 n2 = _normals[t->getVertex(1)]; - SVector3 n3 = _normals[t->getVertex(2)]; - double val[9] = {n1.x(), n2.x(), n3.x(), - n1.y(), n2.y(), n3.y(), - n1.z(), n2.z(), n3.z()}; - return fabs(t->interpolateDiv(val, u, v, 3)); -} - -SPoint2 GFaceCompound::parFromVertex(MVertex *v) const -{ - double U=0.0,V=0.0; - if(v->onWhat()->dim()==2){ - v->getParameter(0, U); - v->getParameter(1, V); - } - if (v->onWhat()->dim()==1 || - (v->onWhat()->dim()==2 && - U == -1 && V==-1)){ //if MFaceVertex created on edge in bunin - SPoint2 sp = getCoordinates(v); - U = sp.x(); - V = sp.y(); - } - if (v->onWhat()->dim()==0){ - SPoint2 sp = parFromPoint(SPoint3(v->x(), v->y(), v->z())); - U = sp.x(); - V = sp.y(); - } - return SPoint2(U,V); - -} -SPoint2 GFaceCompound::parFromPoint(const SPoint3 &p, bool onSurface) const -{ - if(!oct) parametrize(); - - std::map<SPoint3,SPoint3>::const_iterator it = _coordPoints.find(p); - SPoint3 sp = it->second; - - return SPoint2(sp.x(), sp.y()); -} - -GPoint GFaceCompound::pointInRemeshedOctree(double par1, double par2) const -{ - - //create new octree with new mesh elements - if(!octNew){ - std::vector<MElement *> myElems; - for (unsigned int i = 0; i < triangles.size(); i++) myElems.push_back(triangles[i]); - for (unsigned int i = 0; i < quadrangles.size(); i++) myElems.push_back(quadrangles[i]); - - std::set<SPoint2> myBCNodes; - for (unsigned int i = 0; i < myElems.size(); i++){ - MElement *e = myElems[i]; - MVertex *news[4]; - for (int j = 0; j < e->getNumVertices(); j++){ - MVertex *v = e->getVertex(j); - std::map<MVertex*,MVertex*>::iterator it = _3Dto2D.find(v); - MVertex *newv =0; - if (it == _3Dto2D.end()){ - SPoint2 p = parFromVertex(v); - newv = new MVertex (p.x(), p.y(), 0.0); - myParamVert.push_back(newv); - _3Dto2D[v] = newv; - _2Dto3D[newv] = v; - if(v->onWhat()->dim()<2) myBCNodes.insert(p); - } - else newv = it->second; - news[j] = newv; - } - - if(e->getType() == TYPE_TRI) - myParamElems.push_back(new MTriangle(news[0],news[1],news[2],e->getNum())); - else if (e->getType() == TYPE_QUA) { - myParamElems.push_back(new MQuadrangle(news[0],news[1],news[2],news[3],e->getNum())); - } - } - - octNew = new MElementOctree(myParamElems); - - //build kdtree boundary nodes in parametric space - int nbBCNodes = myBCNodes.size(); - ANNpointArray uv_nodes = annAllocPts(nbBCNodes, 3); - std::set<SPoint2>::iterator itp = myBCNodes.begin(); - int ind = 0; - while (itp != myBCNodes.end()){ - SPoint2 pt = *itp; - uv_nodes[ind][0] = pt.x(); - uv_nodes[ind][1] = pt.y(); - uv_nodes[ind][2] = 0.0; - itp++; ind++; - } - uv_kdtree = new ANNkd_tree(uv_nodes, nbBCNodes, 3); - } - - //now use new octree to find point - double uvw[3]={par1,par2, 0.0}; - double UV[3]; - MElement *e = octNew->find(par1,par2, 0.0,-1,false); - if (e){ - e->xyz2uvw(uvw,UV); - double valX[8], valY[8], valZ[8]; - for (int i=0;i<e->getNumPrimaryVertices();i++){ - MVertex *v = _2Dto3D[e->getVertex(i)]; - valX[i] = v->x(); - valY[i] = v->y(); - valZ[i] = v->z(); - } - GPoint gp; - gp.x() = e->interpolate(valX,UV[0],UV[1],UV[2]); - gp.y() = e->interpolate(valY,UV[0],UV[1],UV[2]); - gp.z() = e->interpolate(valZ,UV[0],UV[1],UV[2]); - return gp; - } - //if element not found in new octree find closest point - else{ - GPoint gp(50,50,50); - double pt[3] = {par1,par2,0.0}; - ANNidx index[2]; - ANNdist dist[2]; - uv_kdtree->annkSearch(pt, 2, index, dist); - ANNpointArray uv_nodes = uv_kdtree->thePoints(); - SPoint3 p1(uv_nodes[index[0]][0], uv_nodes[index[0]][1], uv_nodes[index[0]][2]); - SPoint3 p2(uv_nodes[index[1]][0], uv_nodes[index[1]][1], uv_nodes[index[1]][2]); - SPoint3 pnew; double d; - signedDistancePointLine(p1,p2, SPoint3(par1,par2,0.0), d, pnew); - - double uvw[3]={pnew.x(),pnew.y(), 0.0}; - double UV[3]; - MElement *e = octNew->find(pnew.x(), pnew.y(), 0.0,-1,true); - if(!e) e = octNew->find(p1.x(), p1.y(), 0.0,-1,true); - if( e){ - e->xyz2uvw(uvw,UV); - double valX[8], valY[8], valZ[8]; - for (int i=0;i<e->getNumPrimaryVertices();i++){ - MVertex *v = _2Dto3D[e->getVertex(i)]; - valX[i] = v->x(); - valY[i] = v->y(); - valZ[i] = v->z(); - } - gp.x() = e->interpolate(valX,UV[0],UV[1],UV[2]); - gp.y() = e->interpolate(valY,UV[0],UV[1],UV[2]); - gp.z() = e->interpolate(valZ,UV[0],UV[1],UV[2]); - } - else{ - gp.setNoSuccess(); - } - - if (gp.succeeded()) return gp; - else{ - Msg::Error("NOT found point with ANN %g %g", par1, par2); - GPoint gp (30,30,30,this); - gp.setNoSuccess(); - return gp; - } - } -} - -GPoint GFaceCompound::point(double par1, double par2) const -{ - if(trivial()){ - return (*(_compound.begin()))->point(par1,par2); - } - - if(!oct) parametrize(); - - double U,V; - double par[2] = {par1,par2}; - GFaceCompoundTriangle *lt; - getTriangle(par1, par2, <, U,V); - if(!lt){ - if (meshStatistics.status == GFace::DONE && triangles.size()+quadrangles.size() != 0) { - GPoint gp = pointInRemeshedOctree(par1,par2); - gp.setNoSuccess(); - return gp; - } - else{ - double pt[3] = {par1,par2, 0.0}; - ANNidx index[2]; - ANNdist dist[2]; - kdtree->annkSearch(pt, 1, index, dist); - lt = &(_gfct[index[0]]); - - SPoint3 pnew_a, pnew_b, pnew_c; double d_a, d_b, d_c; - signedDistancePointLine(lt->p1,lt->p2, SPoint3(par1,par2,0.0), d_a, pnew_a); - signedDistancePointLine(lt->p1,lt->p3, SPoint3(par1,par2,0.0), d_b, pnew_b); - signedDistancePointLine(lt->p2,lt->p3, SPoint3(par1,par2,0.0), d_c, pnew_c); - double u,v; - if (d_a <= d_b && d_a <= d_c) { u = pnew_a.x(); v= pnew_a.y();} - else if (d_b <= d_a && d_b <= d_c) { u = pnew_b.x(); v= pnew_b.y();} - else { u = pnew_c.x(); v= pnew_c.y();} - double M[2][2],X[2],R[2]; - const SPoint3 p0 = (lt)->p1; - const SPoint3 p1 = (lt)->p2; - const SPoint3 p2 = (lt)->p3; - M[0][0] = p1.x() - p0.x(); - M[0][1] = p2.x() - p0.x(); - M[1][0] = p1.y() - p0.y(); - M[1][1] = p2.y() - p0.y(); - R[0] = (u - p0.x()); - R[1] = (v - p0.y()); - sys2x2(M, R, X); - U = X[0]; - V = X[1]; - } - } - - if (lt->gf->geomType() != GEntity::DiscreteSurface){ - SPoint2 pParam = lt->gfp1*(1.-U-V) + lt->gfp2*U + lt->gfp3*V; - GPoint pp = lt->gf->point(pParam); - return GPoint(pp.x(),pp.y(),pp.z(),this,par); - } - - const bool LINEARMESH = true; //false - if(LINEARMESH){ - // linear Lagrange mesh - SPoint3 p = lt->v1*(1.-U-V) + lt->v2*U + lt->v3*V; - return GPoint(p.x(),p.y(),p.z(),this,par); - } - else{ - // curved PN triangle - const SVector3 n1 = _normals[lt->tri->getVertex(0)]; - const SVector3 n2 = _normals[lt->tri->getVertex(1)]; - const SVector3 n3 = _normals[lt->tri->getVertex(2)]; - - SVector3 b300, b030, b003; - SVector3 b210, b120, b021, b012, b102, b201, E, VV, b111; - b300 = lt->v1; - b030 = lt->v2; - b003 = lt->v3; - - // tagged PN triangles (sigma=1) - double theta = 0.0; - SVector3 d1 = lt->v1+.33*(1-theta)*(lt->v2-lt->v1); - SVector3 d2 = lt->v2+.33*(1-theta)*(lt->v1-lt->v2); - SVector3 X1 = 1/norm(n1)*n1; - SVector3 X2 = 1/norm(n2)*n2; - b210 = d1 - dot(X1,d1-lt->v1)*X1; - b120 = d2 - dot(X2,d2-lt->v2)*X2; - SVector3 d3 = lt->v2+.33*(1-theta)*(lt->v3-lt->v2); - SVector3 d4 = lt->v3+.33*(1-theta)*(lt->v2-lt->v3); - SVector3 X3 = 1/norm(n2)*n2; - SVector3 X4 = 1/norm(n3)*n3; - b021 = d3 - dot(X3,d3-lt->v2)*X3; - b012 = d4 - dot(X4,d4-lt->v3)*X4; - SVector3 d5 = lt->v3+.33*(1-theta)*(lt->v1-lt->v3); - SVector3 d6 = lt->v1+.33*(1-theta)*(lt->v3-lt->v1); - SVector3 X5 = 1/norm(n3)*n3; - SVector3 X6 = 1/norm(n1)*n1; - b102 = d5 - dot(X5,d5-lt->v3)*X5; - b201 = d6 - dot(X6,d6-lt->v1)*X6; - - E=(b210+b120+b021+b012+b102+b201)*0.16667; - VV=(lt->v1+lt->v2+lt->v3)*0.333; - b111=E+(E-VV)*0.5; - - double W = 1-U-V; - SVector3 point = b300*W*W*W+b030*U*U*U+b003*V*V*V+ - b210*3.*W*W*U+b120*3.*W*U*U+b201*3.*W*W*V+ - b021*3.*U*U*V+b102*3.*W*V*V+b012*3.*U*V*V+ - b111*6.*W*U*V; - - SPoint3 PP(point.x(), point.y(), point.z()); - return GPoint(PP.x(),PP.y(),PP.z(),this,par); - } -} - -Pair<SVector3,SVector3> GFaceCompound::firstDer(const SPoint2 ¶m) const -{ - - if(!oct) parametrize(); - - if(trivial()) - return (*(_compound.begin()))->firstDer(param); - - double U,V; - GFaceCompoundTriangle *lt; - getTriangle(param.x(), param.y(), <, U,V); - MTriangle *tri=NULL; - if (lt) tri = lt->tri; - else { - double pt[3] = {param.x(), param.y(), 0.0}; - ANNidx index[2]; - ANNdist dist[2]; - kdtree->annkSearch(pt, 1, index, dist); - tri = (&_gfct[index[0]])->tri; - } - - SVector3 dXdu1 = firstDerivatives[tri->getVertex(0)].first(); - SVector3 dXdu2 = firstDerivatives[tri->getVertex(1)].first(); - SVector3 dXdu3 = firstDerivatives[tri->getVertex(2)].first(); - SVector3 dXdv1 = firstDerivatives[tri->getVertex(0)].second(); - SVector3 dXdv2 = firstDerivatives[tri->getVertex(1)].second(); - SVector3 dXdv3 = firstDerivatives[tri->getVertex(2)].second(); - SVector3 dXdu = dXdu1*(1.-U-V) + dXdu2*U + dXdu3*V; - SVector3 dXdv = dXdv1*(1.-U-V) + dXdv2*U + dXdv3*V; - return Pair<SVector3, SVector3>(dXdu,dXdv); -} - -void GFaceCompound::secondDer(const SPoint2 ¶m, - SVector3 *dudu, SVector3 *dvdv, SVector3 *dudv) const -{ -#if defined(HAVE_MESH) - - if(!oct) parametrize(); - - if(adjv.size() == 0){ - std::vector<MTriangle*> allTri; - std::list<GFace*>::const_iterator it = _compound.begin(); - for( ; it != _compound.end(); ++it){ - allTri.insert(allTri.end(), (*it)->triangles.begin(), (*it)->triangles.end() ); - } - buildVertexToTriangle(allTri, adjv); - } - - if (xuu.size() == 0) computeHessianMapping(); - - double U, V; - GFaceCompoundTriangle *lt; - getTriangle(param.x(), param.y(), <, U,V); - if(!lt) return; - - MVertex* v0 = lt->tri->getVertex(0); - MVertex* v1 = lt->tri->getVertex(1); - MVertex* v2 = lt->tri->getVertex(2); - - *dudu = (1-U-V)*xuu[v0] + U*xuu[v1] + V*xuu[v2]; - *dvdv = (1-U-V)*xvv[v0] + U*xvv[v1] + V*xvv[v2]; - *dudv = (1-U-V)*xuv[v0] + U*xuv[v1] + V*xuv[v2]; - -#endif - //Msg::Debug("Computation of the second derivatives is not implemented for compound faces"); -} - -void GFaceCompound::computeHessianMapping() const -{ -#if defined(HAVE_MESH) - unsigned int sysDim = 6; //for 2D - unsigned int minNbPtBlob = 3*sysDim; - for (v2t_cont::iterator it = adjv.begin(); it != adjv.end(); it++) { - MVertex *ver = it->first; - std::vector<MVertex*> vv = getBlob(minNbPtBlob, it, adjv); - fullMatrix<double> A(vv.size(),sysDim), ATAx(sysDim,sysDim); - fullMatrix<double> ATAy(sysDim,sysDim), ATAz(sysDim,sysDim); - fullVector<double> bx(vv.size()), ATbx(sysDim), coeffsx(sysDim); - fullVector<double> by(vv.size()), ATby(sysDim), coeffsy(sysDim); - fullVector<double> bz(vv.size()), ATbz(sysDim), coeffsz(sysDim); - for(unsigned int i=0; i<vv.size(); i++) { - SPoint3 uv = coordinates[vv[i]]; - A(i,0) = uv.x()*uv.x(); A(i,1) = uv.x()*uv.y(); A(i,2) = uv.y()*uv.y(); - A(i,3) = uv.x(); A(i,4) = uv.y(); A(i,5) = 1.; - bx(i) = vv[i]->x(); - by(i) = vv[i]->y(); - bz(i) = vv[i]->z(); - } - ATAx.gemm(A,A,1.,0., true, false); - ATAy = ATAx; ATAz = ATAx; - A.multWithATranspose(bx,1.,0.,ATbx); - A.multWithATranspose(by,1.,0.,ATby); - A.multWithATranspose(bz,1.,0.,ATbz); - ATAx.luSolve(ATbx,coeffsx); - ATAy.luSolve(ATby,coeffsy); - ATAz.luSolve(ATbz,coeffsz); - SPoint3 uv = coordinates[ver]; - xuu[ver] = SVector3(2.*coeffsx(0),2.*coeffsy(0),2.*coeffsz(0)) ; - xvv[ver] = SVector3(2.*coeffsx(2),2.*coeffsy(2),2.*coeffsz(2)) ; - xuv[ver] = SVector3(coeffsx(1), coeffsy(1),coeffsz(1)); - xu[ver] = SVector3(2.*coeffsx(0)*uv.x()+coeffsx(1)*uv.y()+coeffsx(3), - 2.*coeffsy(0)*uv.x()+coeffsy(1)*uv.y()+coeffsy(3), - 2.*coeffsz(0)*uv.x()+coeffsz(1)*uv.y()+coeffsz(3)); - xv[ver] = SVector3(coeffsx(1)*uv.x()+2.*coeffsx(2)*uv.y()+coeffsx(4), - coeffsy(1)*uv.x()+2.*coeffsy(2)*uv.y()+coeffsy(4), - coeffsz(1)*uv.x()+2.*coeffsz(2)*uv.y()+coeffsz(4)); - } - -#endif -} - -static void GFaceCompoundBB(void *a, double*mmin, double*mmax) -{ - GFaceCompoundTriangle *t = (GFaceCompoundTriangle *)a; - mmin[0] = std::min(std::min(t->p1.x(), t->p2.x()), t->p3.x()); - mmin[1] = std::min(std::min(t->p1.y(), t->p2.y()), t->p3.y()); - mmax[0] = std::max(std::max(t->p1.x(), t->p2.x()), t->p3.x()); - mmax[1] = std::max(std::max(t->p1.y(), t->p2.y()), t->p3.y()); - mmin[2] = -1; - mmax[2] = 1; - - const double dx = mmax[0] - mmin[0]; - const double dy = mmax[1] - mmin[1]; - const double eps = 0.0;//1.e-12; - mmin[0] -= eps*dx; - mmin[1] -= eps*dy; - mmax[0] += eps*dx; - mmax[1] += eps*dy; -} - -static void GFaceCompoundCentroid(void *a, double*c) -{ - GFaceCompoundTriangle *t = (GFaceCompoundTriangle *)a; - c[0] = (t->p1.x() + t->p2.x() + t->p3.x()) / 3.0; - c[1] = (t->p1.y() + t->p2.y() + t->p3.y()) / 3.0; - c[2] = 0.0; -} - -static int GFaceCompoundInEle(void *a, double*c) -{ - GFaceCompoundTriangle *t = (GFaceCompoundTriangle *)a; - double M[2][2], R[2], X[2]; - const double eps = 1.e-8; - const SPoint3 p0 = t->p1; - const SPoint3 p1 = t->p2; - const SPoint3 p2 = t->p3; - M[0][0] = p1.x() - p0.x(); - M[0][1] = p2.x() - p0.x(); - M[1][0] = p1.y() - p0.y(); - M[1][1] = p2.y() - p0.y(); - R[0] = (c[0] - p0.x()); - R[1] = (c[1] - p0.y()); - sys2x2(M, R, X); - if(X[0] > -eps && X[1] > -eps && 1. - X[0] - X[1] > -eps){ - return 1; - } - return 0; -} - -void GFaceCompound::getTriangle(double u, double v, - GFaceCompoundTriangle **lt, - double &_u, double &_v) const -{ - double uv[3] = {u, v, 0}; - *lt = (GFaceCompoundTriangle*)Octree_Search(uv, oct); - - if(!(*lt)){ - _u = 0.0; _v = 0.0; - return; - } - - double M[2][2],X[2],R[2]; - const SPoint3 p0 = (*lt)->p1; - const SPoint3 p1 = (*lt)->p2; - const SPoint3 p2 = (*lt)->p3; - M[0][0] = p1.x() - p0.x(); - M[0][1] = p2.x() - p0.x(); - M[1][0] = p1.y() - p0.y(); - M[1][1] = p2.y() - p0.y(); - R[0] = (u - p0.x()); - R[1] = (v - p0.y()); - sys2x2(M, R, X); - _u = X[0]; - _v = X[1]; -} - -void GFaceCompound::buildOct() const -{ -#if defined(HAVE_MESH) - SBoundingBox3d bb; - int count = 0; - std::list<GFace*>::const_iterator it = _compound.begin(); - - for( ; it != _compound.end() ; ++it){ - for(unsigned int i = 0; i < (*it)->triangles.size(); ++i){ - MTriangle *t = (*it)->triangles[i]; - //create bounding box - for(int j = 0; j < 3; j++){ - std::map<MVertex*,SPoint3>::const_iterator itj = coordinates.find(t->getVertex(j)); - _coordPoints.insert(std::make_pair(t->getVertex(j)->point(), itj->second)); - bb += SPoint3(itj->second.x(),itj->second.y(),0.0); - } - count++; - } - } - - //ANN octree - std::set<MVertex*> allVS; - ANNpointArray nodes = annAllocPts(count, 3); - - // make bounding box - SPoint3 bbmin = bb.min(), bbmax = bb.max(); - double origin[3] = {bbmin.x(), bbmin.y(), bbmin.z()}; - double ssize[3] = {bbmax.x() - bbmin.x(), - bbmax.y() - bbmin.y(), - bbmax.z() - bbmin.z()}; - - _gfct = new GFaceCompoundTriangle[count]; - const int maxElePerBucket = 15; - oct = Octree_Create(maxElePerBucket, origin, ssize, GFaceCompoundBB, - GFaceCompoundCentroid, GFaceCompoundInEle); - std::map<MElement*, Pair<SVector3,SVector3> > firstElemDerivatives; - - it = _compound.begin(); - count = 0; - - for( ; it != _compound.end() ; ++it){ - for(unsigned int i = 0; i < (*it)->triangles.size(); ++i){ - MTriangle *t = (*it)->triangles[i]; - std::map<MVertex*,SPoint3>::const_iterator it0 = - coordinates.find(t->getVertex(0)); - std::map<MVertex*,SPoint3>::const_iterator it1 = - coordinates.find(t->getVertex(1)); - std::map<MVertex*,SPoint3>::const_iterator it2 = - coordinates.find(t->getVertex(2)); - _gfct[count].p1 = it0->second; - _gfct[count].p2 = it1->second; - _gfct[count].p3 = it2->second; - if((*it)->geomType() != GEntity::DiscreteSurface){ - // take care of the seam !!!! - if (t->getVertex(0)->onWhat()->dim() == 2){ - reparamMeshEdgeOnFace(t->getVertex(0), t->getVertex(1), *it, - _gfct[count].gfp1, _gfct[count].gfp2); - reparamMeshEdgeOnFace(t->getVertex(0), t->getVertex(2), *it, - _gfct[count].gfp1, _gfct[count].gfp3); - } - else if (t->getVertex(1)->onWhat()->dim() == 2){ - reparamMeshEdgeOnFace(t->getVertex(1), t->getVertex(0), *it, - _gfct[count].gfp2, _gfct[count].gfp1); - reparamMeshEdgeOnFace(t->getVertex(1), t->getVertex(2), *it, - _gfct[count].gfp2, _gfct[count].gfp3); - } - else if (t->getVertex(2)->onWhat()->dim() == 2){ - reparamMeshEdgeOnFace(t->getVertex(2), t->getVertex(0), *it, - _gfct[count].gfp3, _gfct[count].gfp1); - reparamMeshEdgeOnFace(t->getVertex(2), t->getVertex(1), *it, - _gfct[count].gfp3, _gfct[count].gfp2); - } - else { - reparamMeshVertexOnFace(t->getVertex(0), *it, _gfct[count].gfp1); - reparamMeshVertexOnFace(t->getVertex(1), *it, _gfct[count].gfp2); - reparamMeshVertexOnFace(t->getVertex(2), *it, _gfct[count].gfp3); - } - } - _gfct[count].v1 = SPoint3(t->getVertex(0)->x(), t->getVertex(0)->y(), - t->getVertex(0)->z()); - _gfct[count].v2 = SPoint3(t->getVertex(1)->x(), t->getVertex(1)->y(), - t->getVertex(1)->z()); - _gfct[count].v3 = SPoint3(t->getVertex(2)->x(), t->getVertex(2)->y(), - t->getVertex(2)->z()); - _gfct[count].gf = *it; - _gfct[count].tri = t; - - //compute first derivatives for every triangle - double mat[2][2] = {{_gfct[count].p2.x() - _gfct[count].p1.x(), - _gfct[count].p3.x() - _gfct[count].p1.x()}, - {_gfct[count].p2.y() - _gfct[count].p1.y(), - _gfct[count].p3.y() - _gfct[count].p1.y()}}; - double inv[2][2]; - inv2x2(mat, inv); - SVector3 dXdxi (_gfct[count].v2 - _gfct[count].v1); - SVector3 dXdeta(_gfct[count].v3 - _gfct[count].v1); - SVector3 dXdu(dXdxi * inv[0][0] + dXdeta * inv[1][0]); - SVector3 dXdv(dXdxi * inv[0][1] + dXdeta * inv[1][1]); - firstElemDerivatives[(MElement*)t] = Pair<SVector3,SVector3>(dXdu,dXdv); - - // build ANN kdtree - nodes[count][0] = (it0->second.x() + it1->second.x() + it2->second.x())/3.0 ; - nodes[count][1] = (it0->second.y() + it1->second.y() + it2->second.y())/3.0 ; - nodes[count][2] = 0.0; - - Octree_Insert(&_gfct[count], oct); - count++; - } - } - nbT = count; - Octree_Arrange(oct); - - //smooth first derivatives at vertices - if(adjv.size() == 0){ - std::vector<MTriangle*> allTri; - std::list<GFace*>::const_iterator it = _compound.begin(); - for( ; it != _compound.end(); ++it){ - allTri.insert(allTri.end(), (*it)->triangles.begin(), (*it)->triangles.end() ); - } - buildVertexToTriangle(allTri, adjv); - } - for(v2t_cont::iterator it = adjv.begin(); it!= adjv.end(); ++it){ - MVertex *v = it->first; - std::vector<MElement*> vTri = it->second; - SVector3 dXdu(0.0), dXdv(0.0); - int nbTri = vTri.size(); - for (int j = 0; j < nbTri; j++){ - dXdu += firstElemDerivatives[vTri[j]].first(); - dXdv += firstElemDerivatives[vTri[j]].second(); - } - dXdu*= 1./nbTri; - dXdv*= 1./nbTri; - firstDerivatives[v] = Pair<SVector3, SVector3>(dXdu, dXdv); - } - - //build ANN kdtree - kdtree = new ANNkd_tree(nodes, count, 3); - - printStuff(); -#endif -} - -bool GFaceCompound::checkTopology() const -{ - if (_mapping == RBF) return true; - - bool correctTopo = true; - if(allNodes.empty()) buildAllNodes(); - - int Nb = _interior_loops.size(); - int G = genusGeom() ; - - double H = getSizeH(); - double D = H; - if (_interior_loops.size() > 0) D = getSizeBB(_U0); - int AR1 = (int) checkAspectRatio(); - int AR2 = (int) floor(H/D+0.5); - int AR = std::max(AR1, AR2); - - if (G != 0 || Nb < 1){ - correctTopo = false; - nbSplit = std::max(G+2, 2); - Msg::Info("Wrong topology: Genus=%d, Nb boundaries=%d, AR=%g", G, Nb, H/D); - if (_allowPartition){ - Msg::Info("-----------------------------------------------------------"); - Msg::Info("--- Split surface %d in %d parts with Multilevel Mesh partitioner", - tag(), nbSplit); - } - else{ - Msg::Fatal("For remeshing your geometry, you should enable the automatic " - "remeshing algorithm. Add 'Mesh.RemeshAlgorithm=1;' in your " - "geo file or through the Fltk window (Options > Mesh > General)"); - } - } - else if (G == 0 && AR > AR_MAX){ - correctTopo = false; - Msg::Info("Wrong topology: Aspect ratio is too high AR=%d (AR1=%d AR2=%d)", - AR, AR1, AR2); - if (_allowPartition == 1){ - nbSplit = -2; - Msg::Info("-----------------------------------------------------------"); - Msg::Info("--- Split surface %d in 2 parts with Laplacian Mesh partitioner", - tag()); - } - else if (_allowPartition == 2){ - nbSplit = 2; - Msg::Info("-----------------------------------------------------------"); - Msg::Info("--- Split surface %d in %d parts with Multilevel Mesh partitioner", - tag(), nbSplit); - } - else if (_allowPartition == 0){ - Msg::Debug("The geometrical aspect ratio of your geometry is quite high.\n " - "You should enable partitioning of the mesh by activating the\n" - "automatic remeshing algorithm. Add 'Mesh.RemeshAlgorithm=1;'\n " - "in your geo file or through the Fltk window (Options > Mesh >\n " - "General)"); - } - } - else{ - Msg::Debug("Correct topology: Genus=%d and Nb boundaries=%d, AR=%g", G, Nb, H/D); - } - - return correctTopo; -} - -double GFaceCompound::checkAspectRatio() const -{ - if(allNodes.empty()) buildAllNodes(); - - double limit = 1.e-20; - double areaMin = 1.e20; - double area3D = 0.0; - int nb = 0; - std::list<GFace*>::const_iterator it = _compound.begin(); - for( ; it != _compound.end() ; ++it){ - for(unsigned int i = 0; i < (*it)->triangles.size(); ++i){ - MTriangle *t = (*it)->triangles[i]; - std::vector<MVertex *> v(3); - for(int k = 0; k < 3; k++){ - v[k] = t->getVertex(k); - } - double p0[3] = {v[0]->x(), v[0]->y(), v[0]->z()}; - double p1[3] = {v[1]->x(), v[1]->y(), v[1]->z()}; - double p2[3] = {v[2]->x(), v[2]->y(), v[2]->z()}; - double a_3D = fabs(triangle_area(p0, p1, p2)); - area3D += a_3D; - std::map<MVertex*,SPoint3>::const_iterator it0 = coordinates.find(v[0]); - std::map<MVertex*,SPoint3>::const_iterator it1 = coordinates.find(v[1]); - std::map<MVertex*,SPoint3>::const_iterator it2 = coordinates.find(v[2]); - if(it0 != coordinates.end() && - it1 != coordinates.end() && - it2 != coordinates.end()){ - double q0[3] = {it0->second.x(), it0->second.y(), 0.0}; - double q1[3] = {it1->second.x(), it1->second.y(), 0.0}; - double q2[3] = {it2->second.x(), it2->second.y(), 0.0}; - double a_2D = fabs(triangle_area(q0, q1, q2)); - if (a_2D > limit) nb++; - areaMin = std::min(areaMin, a_2D); - } - } - } - - std::list<GEdge*>::const_iterator it0 = _U0.begin(); - double tot_length = 0.0; - for( ; it0 != _U0.end(); ++it0 ) - for(unsigned int i = 0; i < (*it0)->lines.size(); i++ ) - tot_length += (*it0)->lines[i]->getLength(); - - double AR = M_PI*area3D/(tot_length*tot_length); - - if (nb > 3 && areaMin > 0 && areaMin < limit) { - Msg::Warning("Too small triangles in mapping (a_2D=%g)", areaMin); - } - else { - Msg::Debug("Geometrical aspect ratio is OK :-)"); - } - - return AR; -} - -void GFaceCompound::coherencePatches() const -{ - if (_mapping == RBF) return; - Msg::Info("Re-orient all %d compound patches normals coherently", - _compound.size()); - - std::map<MEdge, std::set<MElement*>, Less_Edge > edge2elems; - std::vector<MElement*> allElems; - std::list<GFace*>::const_iterator it = _compound.begin(); - for( ; it != _compound.end() ; ++it){ - for(unsigned int i = 0; i < (*it)->getNumMeshElements(); ++i){ - MElement *t = (*it)->getMeshElement(i); - allElems.push_back(t); - for (int j = 0; j < t->getNumEdges(); j++){ - MEdge me = t->getEdge(j); - std::map<MEdge, std::set<MElement*, std::less<MElement*> >, - Less_Edge >::iterator it = edge2elems.find(me); - if (it == edge2elems.end()) { - std::set<MElement*, std::less<MElement*> > mySet; - mySet.insert(t); - edge2elems.insert(std::make_pair(me, mySet)); - } - else{ - std::set<MElement*, std::less<MElement*> > mySet = it->second; - mySet.insert(t); - it->second = mySet; - } - } - } - } - - std::set<MElement* , std::less<MElement*> > touched; - int iE, si, iE2, si2; - touched.insert(allElems[0]); - while(touched.size() != allElems.size()){ - for(unsigned int i = 0; i < allElems.size(); i++){ - MElement *t = allElems[i]; - std::set<MElement*, std::less<MElement*> >::iterator it2 = touched.find(t); - if(it2 != touched.end()){ - for (int j = 0; j < t->getNumEdges(); j++){ - MEdge me = t->getEdge(j); - t->getEdgeInfo(me, iE,si); - std::map<MEdge, std::set<MElement*>, Less_Edge >::iterator it = - edge2elems.find(me); - std::set<MElement*, std::less<MElement*> > mySet = it->second; - for(std::set<MElement*, std::less<MElement*> >::iterator itt = mySet.begin(); - itt != mySet.end(); itt++){ - if (*itt != t){ - (*itt)->getEdgeInfo(me,iE2,si2); - if(si == si2) { (*itt)->reverse();} - touched.insert(*itt); - } - } - } - } - } - } -} - -void GFaceCompound::coherenceNormals() -{ - if(!getNumMeshElements()) return; - Msg::Info("Re-orient all %d face normals coherently", getNumMeshElements()); - - std::map<MEdge, std::set<MElement*>, Less_Edge > edge2elems; - for(unsigned int i = 0; i < getNumMeshElements(); i++){ - MElement *t = getMeshElement(i); - for (int j = 0; j < t->getNumEdges(); j++){ - MEdge me = t->getEdge(j); - std::map<MEdge, std::set<MElement*, std::less<MElement*> >, - Less_Edge >::iterator it = edge2elems.find(me); - if (it == edge2elems.end()) { - std::set<MElement*, std::less<MElement*> > mySet; - mySet.insert(t); - edge2elems.insert(std::make_pair(me, mySet)); - } - else{ - std::set<MElement*, std::less<MElement*> > mySet = it->second; - mySet.insert(t); - it->second = mySet; - } - } - } - - std::set<MElement* , std::less<MElement*> > touched; - int iE, si, iE2, si2; - touched.insert(getMeshElement(0)); - while(touched.size() != getNumMeshElements()){ - for(unsigned int i = 0; i < getNumMeshElements(); i++){ - MElement *t = getMeshElement(i); - std::set<MElement*, std::less<MElement*> >::iterator it2 = touched.find(t); - if(it2 != touched.end()){ - for (int j = 0; j < t->getNumEdges(); j++){ - MEdge me = t->getEdge(j); - t->getEdgeInfo(me, iE,si); - std::map<MEdge, std::set<MElement*>, Less_Edge >::iterator it = - edge2elems.find(me); - std::set<MElement*, std::less<MElement*> > mySet = it->second; - for(std::set<MElement*, std::less<MElement*> >::iterator itt = mySet.begin(); - itt != mySet.end(); itt++){ - if (*itt != t){ - (*itt)->getEdgeInfo(me,iE2,si2); - if(si == si2) (*itt)->reverse(); - touched.insert(*itt); - } - } - } - } - } - } -} - -void GFaceCompound::buildAllNodes() const -{ - std::list<GFace*>::const_iterator it = _compound.begin(); - for( ; it != _compound.end() ; ++it){ - for(unsigned int i = 0; i < (*it)->triangles.size(); ++i){ - MTriangle *t = (*it)->triangles[i]; - for(int j = 0; j < 3; j++){ - allNodes.insert(t->getVertex(j)); - } - } - } -} - -int GFaceCompound::genusGeom() const -{ - std::list<GFace*>::const_iterator it = _compound.begin(); - std::set<MEdge, Less_Edge> es; - std::set<MVertex*> vs; - int N = 0; - for( ; it != _compound.end() ; ++it){ - for(unsigned int i = 0; i < (*it)->triangles.size(); ++i){ - N++; - MTriangle *e = (*it)->triangles[i]; - for(int j = 0; j < e->getNumVertices(); j++){ - vs.insert(e->getVertex(j)); - } - for(int j = 0; j < e->getNumEdges(); j++){ - es.insert(e->getEdge(j)); - } - } - } - int poincare = vs.size() - es.size() + N; - - return (int)(-poincare + 2 - _interior_loops.size())/2; -} - -void GFaceCompound::printStuff(int iNewton) const -{ - if(!CTX::instance()->mesh.saveAll) return; - - std::list<GFace*>::const_iterator it = _compound.begin(); - - char name0[256], name1[256], name2[256], name3[256]; - char name4[256], name5[256], name6[256]; - char name7[256]; - sprintf(name0, "UVAREA-%d.pos", tag()); //(*it)->tag() - sprintf(name1, "UVX-%d_%d.pos", tag(), iNewton); - sprintf(name2, "UVY-%d_%d.pos", tag(), iNewton); - sprintf(name3, "UVZ-%d_%d.pos", tag(), iNewton); - sprintf(name4, "XYZU-%d_%d.pos", tag(), iNewton); - sprintf(name5, "XYZV-%d_%d.pos", tag(), iNewton); - sprintf(name6, "XYZC-%d.pos", tag()); - - sprintf(name7, "UVM-%d.pos", (*it)->tag()); - - FILE * uvx = Fopen(name1,"w"); - if(!uvx){ - Msg::Error("Could not open file '%s'", name1); - return; - } - FILE * uvy = Fopen(name2,"w"); - if(!uvy){ - fclose(uvx); - Msg::Error("Could not open file '%s'", name2); - return; - } - FILE * uvz = Fopen(name3,"w"); - if(!uvz){ - fclose(uvx); - fclose(uvy); - Msg::Error("Could not open file '%s'", name3); - return; - } - FILE * xyzu = Fopen(name4,"w"); - if(!xyzu){ - fclose(uvx); - fclose(uvy); - fclose(uvz); - Msg::Error("Could not open file '%s'", name4); - return; - } - FILE * xyzv = Fopen(name5,"w"); - if(!xyzv){ - fclose(uvx); - fclose(uvy); - fclose(uvz); - fclose(xyzu); - Msg::Error("Could not open file '%s'", name5); - return; - } - - fprintf(uvx, "View \"\"{\n"); - fprintf(uvy, "View \"\"{\n"); - fprintf(uvz, "View \"\"{\n"); - fprintf(xyzu, "View \"\"{\n"); - fprintf(xyzv, "View \"\"{\n"); - - for( ; it != _compound.end() ; ++it){ - for(unsigned int i = 0; i < (*it)->triangles.size(); ++i){ - MTriangle *t = (*it)->triangles[i]; - std::map<MVertex*,SPoint3>::const_iterator it0 = - coordinates.find(t->getVertex(0)); - std::map<MVertex*,SPoint3>::const_iterator it1 = - coordinates.find(t->getVertex(1)); - std::map<MVertex*,SPoint3>::const_iterator it2 = - coordinates.find(t->getVertex(2)); - fprintf(xyzv, "ST(%g,%g,%g,%g,%g,%g,%g,%g,%g){%g,%g,%g};\n", - t->getVertex(0)->x(), t->getVertex(0)->y(), t->getVertex(0)->z(), - t->getVertex(1)->x(), t->getVertex(1)->y(), t->getVertex(1)->z(), - t->getVertex(2)->x(), t->getVertex(2)->y(), t->getVertex(2)->z(), - it0->second.y(),it1->second.y(),it2->second.y()); - fprintf(xyzu, "ST(%22.15E,%22.15E,%22.15E,%22.15E,%22.15E,%22.15E,%22.15E," - "%22.15E,%22.15E){%22.15E,%22.15E,%22.15E};\n", - t->getVertex(0)->x(), t->getVertex(0)->y(), t->getVertex(0)->z(), - t->getVertex(1)->x(), t->getVertex(1)->y(), t->getVertex(1)->z(), - t->getVertex(2)->x(), t->getVertex(2)->y(), t->getVertex(2)->z(), - it0->second.x(),it1->second.x(),it2->second.x()); - fprintf(uvx, "ST(%22.15E,%22.15E,%22.15E,%22.15E,%22.15E,%22.15E,%22.15E," - "%22.15E,%22.15E){%22.15E,%22.15E,%22.15E};\n", - it0->second.x(), it0->second.y(), 0.0, - it1->second.x(), it1->second.y(), 0.0, - it2->second.x(), it2->second.y(), 0.0, - t->getVertex(0)->x(), t->getVertex(1)->x(), t->getVertex(2)->x()); - fprintf(uvy, "ST(%g,%g,%g,%g,%g,%g,%g,%g,%g){%g,%g,%g};\n", - it0->second.x(), it0->second.y(), 0.0, - it1->second.x(), it1->second.y(), 0.0, - it2->second.x(), it2->second.y(), 0.0, - t->getVertex(0)->y(), t->getVertex(1)->y(), t->getVertex(2)->y()); - fprintf(uvz, "ST(%g,%g,%g,%g,%g,%g,%g,%g,%g){%g,%g,%g};\n", - it0->second.x(), it0->second.y(), 0.0, - it1->second.x(), it1->second.y(), 0.0, - it2->second.x(), it2->second.y(), 0.0, - t->getVertex(0)->z(), t->getVertex(1)->z(), t->getVertex(2)->z()); - } - } - fprintf(uvx,"};\n"); - fclose(uvx); - fprintf(uvy,"};\n"); - fclose(uvy); - fprintf(uvz,"};\n"); - fclose(uvz); - fprintf(xyzu,"};\n"); - fclose(xyzu); - fprintf(xyzv,"};\n"); - fclose(xyzv); -} - -// useful for mesh generators ---------------------------------------- -// Intersection of a circle and a plane -GPoint GFaceCompound::intersectionWithCircle(const SVector3 &n1, const SVector3 &n2, - const SVector3 &p, const double &d, - double uv[2]) const -{ - SVector3 n = crossprod(n1,n2); - n.normalize(); - for (int i=-1;i<nbT;i++){ - GFaceCompoundTriangle *ct; - double U,V; - if (i == -1) getTriangle(uv[0],uv[1], &ct, U,V); - else ct = &_gfct[i]; - if (!ct) continue; - // we have two planes, defined with n1,n2 and t1,t2 - // we have then a direction m = (n1 x n2) x (t1 x t2) - // and a point p that defines a straight line - // the point is situated in the half plane defined - // by direction n1 and point p (exclude the one on the - // other side) - - SVector3 t1 = ct->v2 - ct->v1; - SVector3 t2 = ct->v3 - ct->v1; - - // let us first compute point q to be the intersection - // of the plane of the triangle with the line L = p + t n1 - // Compute w = t1 x t2 = (a,b,c) and write a point of the plabe as - // X(x,y,z) = ax + by + cz - (v1_x a + v1_y b + v1_z * c) = 0 - // Then - // a (p_x + t n1_x) + a (p_y + t n1_y) + c (p_z + t n1_z) - - // (v1_x a + v1_y b + v1_z * c) = 0 - // gives t - - SVector3 w = crossprod(t1,t2); - double t = dot(ct->v1-p,w)/dot(n1,w); - SVector3 q = p + n1*t; - - // consider the line that intersects both planes in its - // parametric form - // X(x,y,z) = q + t m - // We have now to intersect that line with the sphere - // (x-p_x)^2 + (y-p_y)^2 + (z-p_z)^2 = d^2 - // Inserting the parametric form of the line into the sphere gives - // (t m_x + q_x - p_x)^2 + (t m_y + q_y - p_y)^2 + (t m_z + q_z - p_z)^2 = d^2 - // t^2 (m_x^2 + m_y^2 + m_z^2) + 2 t (m_x (q_x - p_x) + m_y (q_y - p_z) + - // m_z (q_z - p_z)) + ((q_x - p_x)^2 + (q_y - p_y)^2 + (q_z - p_z)^2 - d^2) = 0 - // t^2 m^2 + 2 t (m . (q-p)) + ((q-p)^2 - d^2) = 0 - // Let us call ta and tb the two roots - // they correspond to two points s_1 = q + ta m and s_2 = q + tb m - // we choose the one that corresponds to (s_i - p) . n1 > 0 - SVector3 m = crossprod(w,n); - const double a = dot(m,m); - const double b = 2*dot(m,q-p); - const double c = dot(q-p,q-p) - d*d; - const double delta = b*b-4*a*c; - - if (delta >= 0){ - const double ta = (-b + sqrt(delta)) / (2.*a); - const double tb = (-b - sqrt(delta)) / (2.*a); - SVector3 s1 = q + m * ta; - SVector3 s2 = q + m * tb; - SVector3 s; - if (dot(s1-p,n1) > 0){ - s = s1; - } - else if (dot(s2-p,n1) > 0){ - s = s2; - } - else continue; - - // we have now to look if the point is inside the triangle - // s = v1 + u t1 + v t2 - // we know the system has a solution because s is in the plane - // defined by v1 and v2 we solve then - // (s - v1) . t1 = u t1^2 + v t2 . t1 - // (s - v1) . t2 = u t1 . t2 + v t2^2 - - double mat[2][2], b[2],uv[2]; - mat[0][0] = dot(t1,t1); - mat[1][1] = dot(t2,t2); - mat[0][1] = mat[1][0] = dot(t1,t2); - b[0] = dot(s-ct->v1,t1) ; - b[1] = dot(s-ct->v1,t2) ; - sys2x2(mat,b,uv); - // check now if the point is inside the triangle - if (uv[0] >= -1.e-6 && uv[1] >= -1.e-6 && - 1.-uv[0]-uv[1] >= -1.e-6 ) { - SVector3 pp = - ct->p1 * ( 1.-uv[0]-uv[1] ) + - ct->p2 *uv[0] + - ct->p3 *uv[1] ; - return GPoint(s.x(),s.y(),s.z(),this,pp); - } - } - } - GPoint pp(0); - pp.setNoSuccess(); - Msg::Debug("ARGG no success intersection circle"); - return pp; -} - -#endif diff --git a/Geo/GFaceCompound.h b/Geo/GFaceCompound.h deleted file mode 100644 index 38f61dbd24735f660a34a61970a570b5dbeac392..0000000000000000000000000000000000000000 --- a/Geo/GFaceCompound.h +++ /dev/null @@ -1,240 +0,0 @@ -// Gmsh - Copyright (C) 1997-2017 C. Geuzaine, J.-F. Remacle -// -// See the LICENSE.txt file for license information. Please report all -// bugs and problems to the public mailing list <gmsh@onelab.info>. - -#ifndef _GFACE_COMPOUND_H_ -#define _GFACE_COMPOUND_H_ - -#include <list> -#include <map> -#include "GmshConfig.h" -#include "GmshMessage.h" -#include "GFace.h" -template <class scalar> class simpleFunction; - -#if defined(HAVE_SOLVER) && defined(HAVE_ANN) - -#include "GEdge.h" -#include "GEdgeCompound.h" -#include "meshGFaceOptimize.h" -#include "linearSystem.h" -#include "GRbf.h" -#include "MElementOctree.h" -class ANNkd_tree; - -#define AR_MAX 5 //maximal geometrical aspect ratio - -/* - A GFaceCompound is a model face that is the compound of model faces. - - It is assumed that all the faces of the compound have been meshed - first. We use this discretization to solve elliptic problems on the - compound. Those problems enable to compute the parametric - coordinates of the mesh points. The parametrization of the compound - consist in a triangulation in the (u,v) space with parameter values at - nodes. - - The compound can therefore be (re)-meshed using any surface mesh - generator of gmsh! -*/ - -class GFaceCompoundTriangle { - public: - SPoint3 p1, p2, p3; - SPoint2 gfp1, gfp2, gfp3; - SPoint3 v1, v2, v3; - GFace *gf; - MTriangle *tri; - GFaceCompoundTriangle() : gf(0), tri(0) {} -}; - -class Octree; -class GRbf; - -class GFaceCompound : public GFace { - public: - typedef enum {ITERU=0,ITERV=1,ITERD=2} iterationStep; - typedef enum {HARMONIC_CIRCLE=0, CONFORMAL_SPECTRAL=1, RADIAL_BASIS=2, HARMONIC_PLANE=3, - CONVEX_CIRCLE=4,CONVEX_PLANE=5, HARMONIC_SQUARE=6, CONFORMAL_FE=7} typeOfCompound; - typedef enum {HARMONIC=0,CONFORMAL=1, RBF=2, CONVEX=3} typeOfMapping; - typedef enum {UNITCIRCLE, MEANPLANE, SQUARE, ALREADYFIXED,SPECTRAL, FE} typeOfIsomorphism; - mutable int nbSplit; - - protected: - mutable std::set<MVertex *> ov; - mutable GRbf *_rbf; - simpleFunction<double> *ONE; - simpleFunction<double> *MONE; - std::list<GFace*> _compound; - std::list<GEdge*> _U0, _V0, _U1, _V1; - std::list<std::list<GEdge*> > _interior_loops; - mutable int nbT; - mutable GFaceCompoundTriangle *_gfct; - mutable Octree *oct; - mutable MElementOctree *octNew; - mutable std::vector<MVertex*> myParamVert; - mutable std::vector<MElement*> myParamElems; - mutable std::map<MVertex*,MVertex*> _3Dto2D; - mutable std::map<MVertex*,MVertex*> _2Dto3D; - mutable std::map<int,SPoint3> XYZoct; - mutable std::set<MVertex*> allNodes; - mutable v2t_cont adjv; - mutable std::map<MVertex*, SPoint3> coordinates; - mutable std::map<MVertex*, Pair<SVector3,SVector3> > firstDerivatives; - mutable std::map<MVertex*, SVector3> xuu; - mutable std::map<MVertex*, SVector3> xvv; - mutable std::map<MVertex*, SVector3> xuv; - mutable std::map<MVertex*, SVector3> xu; - mutable std::map<MVertex*, SVector3> xv; - mutable std::map<SPoint3,SPoint3 > _coordPoints; - mutable std::map<MVertex*, SVector3> _normals; - mutable std::list<MTriangle*> fillTris; - mutable std::set<MVertex*> fillNodes; - mutable std::vector<GFace*> fillFaces; - mutable std::vector<MVertex*> _ordered; - mutable std::vector<double> _coords; - mutable std::map<MVertex*, int> _mapV; - mutable ANNkd_tree *uv_kdtree; - mutable ANNkd_tree *kdtree; - void buildOct() const ; - void buildAllNodes() const; - - //different type of parametrizations - void parametrize(iterationStep, typeOfMapping) const; - bool parametrize_conformal(int iter, MVertex *v1, MVertex *v2) const; - bool parametrize_conformal_spectral() const; - - //check for parametrizations - bool checkOrientation(int iter, bool moveBoundaries=false) const; - bool checkOverlap(std::vector<MVertex *> &vert) const; - bool one2OneMap() const; - void convexBoundary(double nTot) const; - double checkAspectRatio() const; - - //tools for filling interior holes of surfaces - void fillNeumannBCS() const; - void fillNeumannBCS_Plane() const; - void orientFillTris(std::list<MTriangle*> loopfillTris)const; - void printFillTris()const; - - void computeNormals () const; - void getBoundingEdges(); - void getUniqueEdges(std::set<GEdge*> &_unique); - void computeALoop(std::set<GEdge*> &_unique, std::list<GEdge*> &); - - virtual double locCurvature(MTriangle *t, double u, double v) const; - - double getSizeH() const; - double getSizeBB(const std::list<GEdge* > &elist) const; - bool trivial() const; - void printStuff(int iNewton=0) const; - void computeHessianMapping() const; - - public: - GFaceCompound(GModel *m, int tag, std::list<GFace*> &compound, - std::list<GEdge*> &U0, typeOfCompound typ = HARMONIC_CIRCLE, - int allowPartition=1); - GFaceCompound(GModel *m, int tag, std::list<GFace*> &compound, - std::list<GEdge*> &U0, std::list<GEdge*> &V0, - std::list<GEdge*> &U1, std::list<GEdge*> &V1, - typeOfCompound typ = HARMONIC_CIRCLE, - int allowPartition=1); - ~GFaceCompound(); - virtual void deleteMesh(); - - Range<double> parBounds(int i) const - { return trivial() ? (*(_compound.begin()))->parBounds(i) : Range<double>(-1, 1); } - - using GFace::point; - GPoint point(double par1, double par2) const; - GPoint pointInRemeshedOctree(double par1, double par2) const; - SPoint2 parFromPoint(const SPoint3 &p, bool onSurface=true) const; - SPoint2 parFromVertex(MVertex *v) const; - virtual Pair<SVector3,SVector3> firstDer(const SPoint2 ¶m) const; - virtual void secondDer(const SPoint2 &, SVector3 *, SVector3 *, SVector3 *) const; - virtual GEntity::GeomType geomType() const { return CompoundSurface; } - ModelType getNativeType() const { return GmshModel; } - void * getNativePtr() const { return 0; } - void getTriangle(double u, double v, GFaceCompoundTriangle **lt, - double &_u, double &_v) const; - virtual SPoint2 getCoordinates(MVertex *v) const; - virtual double curvatureMax(const SPoint2 ¶m) const; - virtual double curvatures(const SPoint2 ¶m, SVector3 *dirMax, SVector3 *dirMin, - double *curvMax, double *curvMin) const; - bool parametrize() const; - void computeNormals(std::map<MVertex*, SVector3> &normals) const; - void coherenceNormals(); - void coherencePatches() const; - virtual int genusGeom () const; - virtual bool checkTopology() const; - - virtual std::list<GFace*> getCompounds() const { return _compound; } - typeOfCompound getTypeOfCompound() { return _toc;} - int getNbSplit() const { return nbSplit; } - int allowPartition() const{ return _allowPartition; } - void setType(typeOfIsomorphism type){ _type=type;} - - // useful for mesh generators - GPoint intersectionWithCircle (const SVector3 &n1, const SVector3 &n2, const SVector3 &p, - const double &d, double uv[2]) const; - - void deleteInternals(); - - private: - void _deleteInternals(); - mutable typeOfCompound _toc; - mutable typeOfMapping _mapping; - mutable typeOfIsomorphism _type; - int _allowPartition; -}; - -#else - -template<class scalar> class linearSystem; -class GFaceCompound : public GFace { - public: - typedef enum {ITERU=0,ITERV=1,ITERD=2} iterationStep; - typedef enum {HARMONIC_CIRCLE=0, CONFORMAL_SPECTRAL=1, RADIAL_BASIS=2, HARMONIC_PLANE=3, - CONVEX_CIRCLE=4,CONVEX_PLANE=5, HARMONIC_SQUARE=6, CONFORMAL_FE=7} typeOfCompound; - typedef enum {HARMONIC=0,CONFORMAL=1, RBF=2, CONVEX=3} typeOfMapping; - typedef enum {UNITCIRCLE, MEANPLANE, SQUARE, ALREADYFIXED,SPECTRAL, FE} typeOfIsomorphism; - GFaceCompound(GModel *m, int tag, std::list<GFace*> &compound, - std::list<GEdge*> &U0, typeOfCompound typ = HARMONIC_CIRCLE, - int allowPartition=1) - : GFace(m, tag) - { - Msg::Error("Gmsh has to be compiled with Solver and ANN support to use GFaceCompounds"); - } - GFaceCompound(GModel *m, int tag, std::list<GFace*> &compound, - std::list<GEdge*> &U0, std::list<GEdge*> &V0, - std::list<GEdge*> &U1, std::list<GEdge*> &V1, - typeOfCompound typ = HARMONIC_CIRCLE, - int allowPartition=1) - : GFace(m, tag) - { - Msg::Error("Gmsh has to be compiled with Solver and ANN support to use GFaceCompounds"); - } - virtual ~GFaceCompound() {} - virtual void deleteMesh() {} - using GFace::point; - GPoint point(double par1, double par2) const { return GPoint(); } - Pair<SVector3, SVector3> firstDer(const SPoint2 ¶m) const - { - return Pair<SVector3, SVector3>(SVector3(0, 0, 0), SVector3(0, 0, 0)); - } - SPoint2 parFromVertex(MVertex *v) const { return SPoint2(); } - void secondDer(const SPoint2 ¶m, - SVector3 *dudu, SVector3 *dvdv, SVector3 *dudv) const{} - virtual SPoint2 getCoordinates(MVertex *v) const { return SPoint2(); } - bool parametrize() const {return false;} - virtual std::list<GFace*> getCompounds() const { return std::list<GFace*>(); } - GPoint intersectionWithCircle (const SVector3 &n1, const SVector3 &n2, const SVector3 &p, - const double &d, double uv[2]) const { return GPoint(); } - int allowPartition() const{ return 1; } - void deleteInternals(){} -}; - -#endif - -#endif diff --git a/Geo/GModel.cpp b/Geo/GModel.cpp index eaf83e780824c6d8935ff8f99897e3fcfb398cab..cfba89f26e8be3d91a3f24c5f0c8a9ebd9e8fddb 100644 --- a/Geo/GModel.cpp +++ b/Geo/GModel.cpp @@ -12,8 +12,6 @@ #include "GModel.h" #include "GModelIO_GEO.h" #include "GModelIO_OCC.h" -#include "GFaceCompound.h" -#include "GEdgeCompound.h" #include "MPoint.h" #include "MLine.h" #include "MTriangle.h" @@ -3222,36 +3220,6 @@ int GModel::readGEO(const std::string &name) return true; } -GEdge* GModel::addCompoundEdge(std::vector<GEdge*> edges, int num) -{ - if (num < 0) num = getMaxElementaryNumber(1) + 1; - GEdgeCompound *gec = new GEdgeCompound(this, num, edges); - add(gec); - return gec; -} - -GFace* GModel::addCompoundFace(std::vector<GFace*> faces, int param, int split, int num) -{ -#if defined(HAVE_SOLVER) - if (num < 0) num = getMaxElementaryNumber(2) + 1; - std::list<GFace*> faces_comp(faces.begin(), faces.end()); - std::list<GEdge*> U0; - GFaceCompound::typeOfCompound typ = GFaceCompound::HARMONIC_CIRCLE; - if (param == 1) typ = GFaceCompound::CONFORMAL_SPECTRAL; - if (param == 2) typ = GFaceCompound::RADIAL_BASIS; - if (param == 3) typ = GFaceCompound::HARMONIC_PLANE; - if (param == 4) typ = GFaceCompound::CONVEX_CIRCLE; - if (param == 5) typ = GFaceCompound::CONVEX_PLANE; - if (param == 6) typ = GFaceCompound::HARMONIC_SQUARE; - if (param == 7) typ = GFaceCompound::CONFORMAL_FE; - GFaceCompound *gfc = new GFaceCompound(this, num, faces_comp, U0, typ, split); - add(gfc); - return gfc; -#else - return 0; -#endif -} - void GModel::setPhysicalNumToEntitiesInBox(int EntityDimension, int PhysicalNumber, SBoundingBox3d box) { @@ -3701,47 +3669,3 @@ void GModel::computeHomology() #endif } -void GModel::setCompoundVisibility() -{ - // force visibility status of compound entities - - for(eiter eit = firstEdge(); eit != lastEdge(); eit++){ - GEdge *ge = *eit; - if (ge->getCompound()){ - if(CTX::instance()->geom.hideCompounds) { - // use visibility info of compound edge if this edge belongs to it - ge->setVisibility(0, true); - bool val2 = ge->getCompound()->getVisibility(); - if(ge->getCompound()->getBeginVertex()) - ge->getCompound()->getBeginVertex()->setVisibility(val2); - if(ge->getCompound()->getEndVertex()) - ge->getCompound()->getEndVertex()->setVisibility(val2); - } - else { - ge->setVisibility(1, true); - } - } - } - - for(fiter fit = firstFace(); fit != lastFace(); fit++){ - GFace *gf = *fit; - if (gf->getCompound()){ - if(CTX::instance()->geom.hideCompounds) { - gf->setVisibility(0, true); - std::list<GEdge*> edgesComp = gf->getCompound()->edges(); - bool val2 = gf->getCompound()->getVisibility(); - // show edges of the compound surface - for (std::list<GEdge*>::iterator it = edgesComp.begin(); it != edgesComp.end(); ++it) { - if((*it)->getCompound()) - (*it)->getCompound()->setVisibility(val2, true); - else - (*it)->setVisibility(val2, true); - } - } - else { - gf->setVisibility(1, true); - } - } - } - -} diff --git a/Geo/GModel.h b/Geo/GModel.h index d14b5ea8fab51a9afd6aa67f8925bece978fc693..1d426c27a205d514711a25eb0530b7cfdeec567e 100644 --- a/Geo/GModel.h +++ b/Geo/GModel.h @@ -231,9 +231,6 @@ class GModel { char getVisibility(){ return _visible; } void setVisibility(char val){ _visible = val; } - // set the visibility of compound entities - void setCompoundVisibility(); - // get the number of entities in this model int getNumRegions() const { return regions.size(); } int getNumFaces() const { return faces.size(); } @@ -279,9 +276,6 @@ class GModel { void remove(int dim, int tag, bool recursive=false); void remove(const std::vector<std::pair<int, int> > &dimTags, bool recursive=false); - GEdge *addCompoundEdge(std::vector<GEdge*> edges, int num=-1); - GFace *addCompoundFace(std::vector<GFace*> faces, int type, int split, int num=-1); - // snap vertices on model edges by using geometry tolerance void snapVertices(); diff --git a/Geo/GModelIO_GEO.cpp b/Geo/GModelIO_GEO.cpp index 003a2ef796a4356954087a70844ab1c38935af2c..be3e5cc6a3b698c19cc978aef5e6a6e2a3317053 100644 --- a/Geo/GModelIO_GEO.cpp +++ b/Geo/GModelIO_GEO.cpp @@ -16,9 +16,6 @@ #include "ListUtils.h" #include "gmshVertex.h" #include "gmshFace.h" -#include "GFaceCompound.h" -#include "GEdgeCompound.h" -#include "GRegionCompound.h" #include "gmshEdge.h" #include "gmshRegion.h" #include "Field.h" @@ -308,22 +305,6 @@ bool GEO_Internals::addNurbs(int &tag, const std::vector<int> &vertexTags, return true; } -bool GEO_Internals::addCompoundLine(int &tag, const std::vector<int> &edgeTags) -{ - if(tag >= 0 && FindCurve(tag)){ - Msg::Error("GEO edge with tag %d already exists", tag); - return false; - } - if(tag < 0) tag = getMaxTag(1) + 1; - Curve *c = CreateCurve(tag, MSH_SEGM_COMPOUND, 1, NULL, NULL, -1, -1, 0., 1.); - c->compound = edgeTags; - EndCurve(c); - Tree_Add(Curves, &c); - CreateReversedCurve(c); - _changed = true; - return true; -} - bool GEO_Internals::addLineLoop(int &tag, const std::vector<int> &edgeTags) { if(tag >= 0 && FindEdgeLoop(tag)){ @@ -430,27 +411,6 @@ bool GEO_Internals::addSurfaceFilling(int &tag, const std::vector<int> &wireTags return true; } -bool GEO_Internals::addCompoundSurface(int &tag, const std::vector<int> &faceTags, - std::vector<int> edgeTags[4]) -{ - if(tag >= 0 && FindSurface(tag)){ - Msg::Error("GEO face with tag %d already exists", tag); - return false; - } - if(tag < 0) tag = getMaxTag(2) + 1; - - Surface *s = CreateSurface(tag, MSH_SURF_COMPOUND); - s->compound = faceTags; - if(edgeTags){ - for(int i = 0; i < 4; i++) - s->compoundBoundary[i] = edgeTags[i]; - } - SetSurfaceGeneratrices(s, 0); - Tree_Add(Surfaces, &s); - _changed = true; - return true; -} - bool GEO_Internals::addSurfaceLoop(int &tag, const std::vector<int> &faceTags) { if(tag >= 0 && FindSurfaceLoop(tag)){ @@ -492,21 +452,6 @@ bool GEO_Internals::addVolume(int &tag, const std::vector<int> &shellTags) return true; } -bool GEO_Internals::addCompoundVolume(int &tag, const std::vector<int> ®ionTags) -{ - if(tag >= 0 && FindVolume(tag)){ - Msg::Error("GEO region with tag %d already exists", tag); - return false; - } - if(tag < 0) tag = getMaxTag(3) + 1; - - Volume *v = CreateVolume(tag, MSH_VOLUME_COMPOUND); - v->compound = regionTags; - Tree_Add(Volumes, &v); - _changed = true; - return true; -} - bool GEO_Internals::_extrude(int mode, const std::vector<std::pair<int, int> > &inDimTags, double x, double y, double z, @@ -1168,11 +1113,7 @@ void GEO_Internals::synchronize(GModel *model) List_Read(curves, i, &c); if(c->Num >= 0){ GEdge *e = model->getEdgeByTag(c->Num); - if(!e && c->Typ == MSH_SEGM_COMPOUND){ - Msg::Debug("Postpone creation of compound edge %d until all others " - "have been created", c->Num); - } - else if(!e && c->beg && c->end){ + if(!e && c->beg && c->end){ e = new gmshEdge(model, c, model->getVertexByTag(c->beg->Num), model->getVertexByTag(c->end->Num)); model->add(e); @@ -1182,8 +1123,7 @@ void GEO_Internals::synchronize(GModel *model) model->add(e); } else{ - if(e->getNativeType() == GEntity::GmshModel && - c->Typ != MSH_SEGM_COMPOUND){ + if(e->getNativeType() == GEntity::GmshModel){ if(c->beg && c->end) ((gmshEdge*)e)->resetNativePtr(c, model->getVertexByTag(c->beg->Num), model->getVertexByTag(c->end->Num)); @@ -1195,30 +1135,6 @@ void GEO_Internals::synchronize(GModel *model) if(c->degenerated) e->setTooSmall(true); } } - // now generate the compound curves - for(int i = 0; i < List_Nbr(curves); i++){ - Curve *c; - List_Read(curves, i, &c); - if(c->Num >= 0){ - GEdge *e = model->getEdgeByTag(c->Num); - if(!e && c->Typ == MSH_SEGM_COMPOUND){ - std::vector<GEdge*> comp; - for(unsigned int j = 0; j < c->compound.size(); j++){ - GEdge *ge = model->getEdgeByTag(c->compound[j]); - if(ge) comp.push_back(ge); - } - e = new GEdgeCompound(model, c->Num, comp); - e->meshAttributes.method = c->Method; - e->meshAttributes.nbPointsTransfinite = c->nbPointsTransfinite; - e->meshAttributes.typeTransfinite = c->typeTransfinite; - e->meshAttributes.coeffTransfinite = c->coeffTransfinite; - e->meshAttributes.extrude = c->Extrude; - e->meshAttributes.reverseMesh = c->ReverseMesh; - model->add(e); - if(c->degenerated) e->setTooSmall(true); - } - } - } List_Delete(curves); } @@ -1228,55 +1144,12 @@ void GEO_Internals::synchronize(GModel *model) Surface *s; List_Read(surfaces, i, &s); GFace *f = model->getFaceByTag(s->Num); - if(!f && s->Typ == MSH_SURF_COMPOUND){ - std::list<GFace*> comp; - for(unsigned int j = 0; j < s->compound.size(); j++){ - GFace *gf = model->getFaceByTag(s->compound[j]); - if(gf) - comp.push_back(gf); - } - std::list<GEdge*> b[4]; - for(int j = 0; j < 4; j++){ - for(unsigned int k = 0; k < s->compoundBoundary[j].size(); k++){ - GEdge *ge = model->getEdgeByTag(s->compoundBoundary[j][k]); - if(ge) b[j].push_back(ge); - } - } - int param = CTX::instance()->mesh.remeshParam; - GFaceCompound::typeOfCompound typ = GFaceCompound::HARMONIC_CIRCLE; - if (param == 1) typ = GFaceCompound::CONFORMAL_SPECTRAL; - if (param == 2) typ = GFaceCompound::RADIAL_BASIS; - if (param == 3) typ = GFaceCompound::HARMONIC_PLANE; - if (param == 4) typ = GFaceCompound::CONVEX_CIRCLE; - if (param == 5) typ = GFaceCompound::CONVEX_PLANE; - if (param == 6) typ = GFaceCompound::HARMONIC_SQUARE; - if (param == 7) typ = GFaceCompound::CONFORMAL_FE; - int algo = CTX::instance()->mesh.remeshAlgo; - f = new GFaceCompound(model, s->Num, comp, b[0], b[1], b[2], b[3], typ, algo); - f->meshAttributes.recombine = s->Recombine; - f->meshAttributes.recombineAngle = s->RecombineAngle; - f->meshAttributes.method = s->Method; - f->meshAttributes.extrude = s->Extrude; - f->meshAttributes.transfiniteArrangement = s->Recombine_Dir; - f->meshAttributes.corners.clear(); - for(int j = 0; j < List_Nbr(s->TrsfPoints); j++){ - Vertex *corn; - List_Read(s->TrsfPoints, j, &corn); - GVertex *gv = f->model()->getVertexByTag(corn->Num); - if(gv) - f->meshAttributes.corners.push_back(gv); - else - Msg::Error("Unknown vertex %d in transfinite attributes", corn->Num); - } - model->add(f); - } - else if(!f){ + if(!f){ f = new gmshFace(model, s); model->add(f); } else{ - if(f->getNativeType() == GEntity::GmshModel && - s->Typ != MSH_SURF_COMPOUND) + if(f->getNativeType() == GEntity::GmshModel) ((gmshFace*)f)->resetNativePtr(s); f->resetMeshAttributes(); } @@ -1290,22 +1163,12 @@ void GEO_Internals::synchronize(GModel *model) Volume *v; List_Read(volumes, i, &v); GRegion *r = model->getRegionByTag(v->Num); - if(!r && v->Typ == MSH_VOLUME_COMPOUND){ - std::vector<GRegion*> comp; - for(unsigned int j = 0; j < v->compound.size(); j++){ - GRegion *gr = model->getRegionByTag(v->compound[j]); - if(gr) comp.push_back(gr); - } - r = new GRegionCompound(model, v->Num, comp); - model->add(r); - } - else if(!r){ + if(!r){ r = new gmshRegion(model, v); model->add(r); } else{ - if(r->getNativeType() == GEntity::GmshModel && - v->Typ != MSH_VOLUME_COMPOUND) + if(r->getNativeType() == GEntity::GmshModel) ((gmshRegion*)r)->resetNativePtr(v); r->resetMeshAttributes(); } diff --git a/Geo/GRegion.cpp b/Geo/GRegion.cpp index bca79da37c3d5c455e800b8e7f92b6af8d15784b..e6cd748a64e74e6ca419e7e6dc2b9b8be0420bfb 100644 --- a/Geo/GRegion.cpp +++ b/Geo/GRegion.cpp @@ -19,7 +19,7 @@ #include "GmshDefines.h" GRegion::GRegion(GModel *model, int tag) - : GEntity (model, tag), compound(0) + : GEntity (model, tag) { resetMeshAttributes(); } @@ -309,13 +309,6 @@ std::list<GEdge*> GRegion::edges() const std::list<GEdge*>::const_iterator it2 = e2.begin(); while (it2 != e2.end()){ GEdge *edge = *it2; - - // FIXME: we need to fix the compound design and decide what to do; same - // thing for faces() (either store or compute the entities, either use - // original or compound entities, etc.) - if(edge->getCompound()) - edge = (GEdge*)edge->getCompound(); - if(std::find(e.begin(), e.end(), edge) == e.end()) e.push_back(edge); ++it2; diff --git a/Geo/GRegion.h b/Geo/GRegion.h index b9810d558720652f4476d80fc1a2e6894f505cf3..4679ab1b521e92d7f632c8375bf1e0603c350c97 100644 --- a/Geo/GRegion.h +++ b/Geo/GRegion.h @@ -21,7 +21,6 @@ class MPyramid; class MPolyhedron; class MTrihedron; class ExtrudeParams; -class GRegionCompound; class BoundaryLayerColumns; // A model region. @@ -32,7 +31,6 @@ class GRegion : public GEntity { std::list<GFace *> embedded_faces; std::list<GEdge *> embedded_edges; std::list<int> l_dirs; - GRegionCompound *compound; // this model ede belongs to a compound // replace faces (for gluing) for specific modelers, we have to // re-create internal data ... @@ -118,10 +116,6 @@ class GRegion : public GEntity { // reset the mesh attributes to default values virtual void resetMeshAttributes(); - // compound - void setCompound(GRegionCompound *grc) { compound = grc; } - GRegionCompound *getCompound() const { return compound; } - struct { // do we recombine the tetrahedra of the mesh into hex? int recombine3D; diff --git a/Geo/GRegionCompound.cpp b/Geo/GRegionCompound.cpp deleted file mode 100644 index 0a7d8dcd46578ad756d4719380b6a68410fd12f6..0000000000000000000000000000000000000000 --- a/Geo/GRegionCompound.cpp +++ /dev/null @@ -1,88 +0,0 @@ -// Gmsh - Copyright (C) 1997-2017 C. Geuzaine, J.-F. Remacle -// -// See the LICENSE.txt file for license information. Please report all -// bugs and problems to the public mailing list <gmsh@onelab.info>. -// -// Contributor(s): -// Emilie Marchandise -// - -#include <stdlib.h> -#include "GmshConfig.h" -#include "GRegionCompound.h" -#include "Numeric.h" - -GRegionCompound::GRegionCompound(GModel *m, int tag, std::vector<GRegion*> &compound) - : GRegion(m, tag), _compound(compound) -{ - - for (unsigned int i = 0; i < _compound.size(); i++){ - if(!_compound[i]){ - Msg::Error("Incorrect region in compound region %d", tag); - return; - } - } - for (unsigned int i = 0; i < _compound.size(); i++) - _compound[i]->setCompound(this); - getBoundingFaces(); -} - -GRegionCompound::~GRegionCompound() -{ -} - -void GRegionCompound::getBoundingFaces() -{ - std::set<GFace*> _unique; - std::multiset<GFace*> _touched; - std::vector<GRegion*>::iterator it = _compound.begin(); - for ( ; it != _compound.end(); ++it){ - std::list<GFace*> ed = (*it)->faces(); - std::list<GFace*> :: iterator ite = ed.begin(); - for ( ; ite != ed.end(); ++ite){ - _touched.insert(*ite); - } - } - it = _compound.begin(); - for ( ; it != _compound.end(); ++it){ - std::list<GFace*> ed = (*it)->faces(); - std::list<GFace*> :: iterator ite = ed.begin(); - for ( ; ite != ed.end() ; ++ite){ - if (!(*ite)->degenerate(0) && _touched.count(*ite) == 1) { - _unique.insert(*ite); - } - } - } - - std::set<GFace*>::iterator itf = _unique.begin(); - for ( ; itf != _unique.end(); ++itf){ - printf("Compound Volume %d face %d \n", tag(), (*itf)->tag()); - l_faces.push_back(*itf); - (*itf)->addRegion(this); - } -} - -SBoundingBox3d GRegionCompound::bounds() const -{ - Msg::Error("Cannot evaluate bounds on GRegion Compound"); - return SBoundingBox3d(SPoint3()); -} - -double GRegionCompound::curvature(double par) const -{ - double k = 0.0; - Msg::Error("Cannot evaluate curvature on GRegionCompound"); - return k; -} - -GPoint GRegionCompound::point(double par) const -{ - Msg::Error("Cannot evaluate point on GRegionCompound"); - return GPoint(); -} - -SVector3 GRegionCompound::firstDer(double par) const -{ - Msg::Error("Cannot evaluate firstDeriv on GRegionCompound"); - return SVector3(); -} diff --git a/Geo/GRegionCompound.h b/Geo/GRegionCompound.h deleted file mode 100644 index bd7578c9f28e9367a159759431b89e6f69074db4..0000000000000000000000000000000000000000 --- a/Geo/GRegionCompound.h +++ /dev/null @@ -1,43 +0,0 @@ -// Gmsh - Copyright (C) 1997-2017 C. Geuzaine, J.-F. Remacle -// -// See the LICENSE.txt file for license information. Please report all -// bugs and problems to the public mailing list <gmsh@onelab.info>. - -#ifndef _GREGION_COMPOUND_H_ -#define _GREGION_COMPOUND_H_ - -#include <list> -#include <map> -#include "GRegion.h" -#include "GFace.h" -#include "GFaceCompound.h" - -/* -A GRegionCompound is a model region that is the compound of model regions. - -It is assumed that all the regions of the compound have been meshed -first and that all the faces of the compound region are compound surfaces. - -The compound can therefore be re-meshed using any volume mesh -generator of gmsh! -*/ - -class GRegionCompound : public GRegion { - public: - GRegionCompound(GModel *m, int tag, std::vector<GRegion*> &compound); - virtual ~GRegionCompound(); - virtual SBoundingBox3d bounds() const; - virtual double curvature(double t) const; - virtual GPoint point(double par) const; - virtual SVector3 firstDer(double par) const; - virtual GEntity::GeomType geomType() const { return CompoundVolume; } - ModelType getNativeType() const { return GmshModel; } - void * getNativePtr() const { return 0; } - - protected: - std::vector<GRegion*> _compound; - void getBoundingFaces(); -}; - -#endif - diff --git a/Geo/MVertex.cpp b/Geo/MVertex.cpp index cd1535f1d86152f204593e1963c6472f9c11bcb9..b7588f2bb0375d1aa0d3f53f279ffe12e88bd430 100644 --- a/Geo/MVertex.cpp +++ b/Geo/MVertex.cpp @@ -10,7 +10,6 @@ #include "GVertex.h" #include "GEdge.h" #include "GFace.h" -#include "GFaceCompound.h" #include "discreteDiskFace.h" #include "GmshMessage.h" #include "StringUtils.h" @@ -399,12 +398,6 @@ static void getAllParameters(MVertex *v, GFace *gf, std::vector<SPoint2> ¶ms { params.clear(); - if (gf->geomType() == GEntity::CompoundSurface ){ - GFaceCompound *gfc = (GFaceCompound*) gf; - params.push_back(gfc->parFromVertex(v)); - return; - } - #if defined(HAVE_ANN) && defined(HAVE_SOLVER) if (gf->geomType() == GEntity::DiscreteDiskSurface ){ discreteDiskFace *gfc = (discreteDiskFace*) gf; @@ -510,12 +503,6 @@ bool reparamMeshEdgeOnFace(MVertex *v1, MVertex *v2, GFace *gf, bool reparamMeshVertexOnFace(MVertex *v, const GFace *gf, SPoint2 ¶m, bool onSurface) { - if(gf->geomType() == GEntity::CompoundSurface){ - GFaceCompound *gfc = (GFaceCompound*) gf; - param = gfc->parFromVertex(v); - return true; - } - #if defined(HAVE_ANN) && defined(HAVE_SOLVER) if (gf->geomType() == GEntity::DiscreteDiskSurface ){ discreteDiskFace *gfc = (discreteDiskFace*) gf; diff --git a/Geo/discreteEdge.cpp b/Geo/discreteEdge.cpp index 29b53f1bab4ae0226e7bf5b6a91fb6b825f2ae90..81863528f0332d95650c443069aab2fc4c962e4b 100644 --- a/Geo/discreteEdge.cpp +++ b/Geo/discreteEdge.cpp @@ -20,8 +20,6 @@ #include "GModelIO_GEO.h" #include "Geo.h" #include "OS.h" -#include "Curvature.h" -#include "GEdgeCompound.h" #if defined(HAVE_MESH) #include "meshGEdge.h" @@ -489,34 +487,15 @@ SVector3 discreteEdge::firstDer(double par) const double discreteEdge::curvature(double par) const { - double tLoc; - int iEdge; - if(!getLocalParameter(par, iEdge, tLoc)) return MAX_LC; - - double c0, c1; - Curvature& curvature = Curvature::getInstance(); - if( !Curvature::valueAlreadyComputed() ) { - Msg::Warning("Need to compute discrete curvature (in discreteEdge)"); - Curvature::typeOfCurvature type = Curvature::RUSIN; //RUSIN; //RBF - curvature.computeCurvature(model(), type); - } - - curvature.edgeNodalValues(lines[iEdge],c0, c1, 1); - double cv = (1-tLoc)*c0 + tLoc*c1; - - return cv; + Msg::Error("Curvature for discrete edge not implemented yet"); + return 0.; } double discreteEdge::curvatures(const double par, SVector3 *dirMax, SVector3 *dirMin, double *curvMax, double *curvMin) const { - if (getCompound()){ - return getCompound()->curvatures(par, dirMax, dirMin, curvMax, curvMin); - } - else{ - Msg::Error("Cannot evaluate curvatures and curvature directions on discrete edge"); - return false; - } + Msg::Error("Cannot evaluate curvatures and curvature directions on discrete edge"); + return false; } Range<double> discreteEdge::parBounds(int i) const diff --git a/Geo/discreteFace.cpp b/Geo/discreteFace.cpp index dc82256177f5b1b1f8c4536945d5b7004176c0d3..6fea94e66918250135288565bf84ca4c176f6f1c 100644 --- a/Geo/discreteFace.cpp +++ b/Geo/discreteFace.cpp @@ -13,7 +13,6 @@ #include "discreteDiskFace.h" #include "GModelIO_GEO.h" #include "Geo.h" -#include "GFaceCompound.h" #include "Context.h" #include "OS.h" #include "meshPartitionObjects.h" diff --git a/Geo/discreteFace.h b/Geo/discreteFace.h index 71a83fec6a15b8317e9f07325f230065fa2e8039..5ba5eb554fb5ee93532aa69bf51bd66cc9e48b3e 100644 --- a/Geo/discreteFace.h +++ b/Geo/discreteFace.h @@ -40,7 +40,6 @@ class discreteFace : public GFace { double curvatureMax(const SPoint2 ¶m) const; double curvatures(const SPoint2 ¶m, SVector3 *dirMax, SVector3 *dirMin, double *curvMax, double *curvMin) const; - virtual bool haveParametrization() { return getCompound(); } GEntity::GeomType geomType() const { return DiscreteSurface; } virtual Pair<SVector3, SVector3> firstDer(const SPoint2 ¶m) const; virtual void secondDer(const SPoint2 ¶m, diff --git a/Geo/gmshEdge.cpp b/Geo/gmshEdge.cpp index 1283ce10c341a60cc4f96354103fe22d3722e265..0065e954a4bedcd0cccfe299ec070d844f348a51 100644 --- a/Geo/gmshEdge.cpp +++ b/Geo/gmshEdge.cpp @@ -6,7 +6,6 @@ #include <sstream> #include "GModel.h" #include "GFace.h" -#include "GFaceCompound.h" #include "gmshEdge.h" #include "Geo.h" #include "GeoInterpolation.h" diff --git a/Graphics/drawGeom.cpp b/Graphics/drawGeom.cpp index 67cf4f25f125e2a3497678e4a77c0637c466e453..59b1eef9c0ee4f8814ce4cbc0f28779ef3772d38 100644 --- a/Graphics/drawGeom.cpp +++ b/Graphics/drawGeom.cpp @@ -11,8 +11,6 @@ #include "GModel.h" #include "SBoundingBox3d.h" #include "GmshMessage.h" -#include "GEdgeCompound.h" -#include "GFaceCompound.h" static void drawEntityLabel(drawContext *ctx, GEntity *e, double x, double y, double z, double offset) @@ -124,7 +122,6 @@ class drawGEdge { if(e->geomType() == GEntity::DiscreteCurve) return; if(e->geomType() == GEntity::PartitionCurve) return; if(e->geomType() == GEntity::BoundaryLayerCurve) return; - // if(e->geomType() == GEntity::CompoundCurve) return; bool select = (_ctx->render_mode == drawContext::GMSH_SELECT && e->model() == GModel::current()); @@ -286,7 +283,7 @@ class drawGFace { if(CTX::instance()->geom.surfaces){ if(CTX::instance()->geom.surfaceType > 0 && f->va_geom_triangles){ bool selected = false; - if (f->getSelection() || (f->getCompound() && f->getCompound()->getSelection())) + if (f->getSelection()) selected = true; _drawVertexArray (f->va_geom_triangles, CTX::instance()->geom.light, @@ -365,8 +362,6 @@ class drawGFace { if(CTX::instance()->geom.surfaces) { //bool selected = false; - //if (f->getSelection() || (f->getCompound() && f->getCompound()->getSelection())) - //selected = true; if(CTX::instance()->geom.surfaceType > 0 && f->va_geom_triangles){ _drawVertexArray(f->va_geom_triangles, CTX::instance()->geom.light, f->getSelection(), CTX::instance()->color.geom.selection); @@ -415,24 +410,6 @@ class drawGFace { } } - void _drawCompoundGFace(GFace *f, bool visible = false, bool selected = false) - { - GFaceCompound *fc = (GFaceCompound*) f; - std::list<GFace*> faces = fc->getCompounds(); - for (std::list<GFace*>::iterator it = faces.begin(); it!=faces.end(); it++) { - if ((*it)->geomType() == GEntity::DiscreteSurface) continue; - if ((*it)->geomType() == GEntity::PartitionSurface) continue; - if ((*it)->geomType() == GEntity::BoundaryLayerSurface) continue; - - if((*it)->geomType() == GEntity::CompoundSurface) - _drawCompoundGFace((*it)); - else if ((*it)->geomType() == GEntity::Plane) - _drawPlaneGFace((*it)); - else - _drawParametricGFace((*it)); - } - } - public : drawGFace(drawContext *ctx) : _ctx(ctx) {} void operator () (GFace *f) @@ -467,9 +444,7 @@ class drawGFace { else glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); - if(f->geomType() == GEntity::CompoundSurface) - _drawCompoundGFace(f); - else if(f->geomType() == GEntity::Plane) + if(f->geomType() == GEntity::Plane) _drawPlaneGFace(f); else _drawParametricGFace(f); diff --git a/Graphics/drawMesh.cpp b/Graphics/drawMesh.cpp index 1240f3117024343a61d6782aa4d4b91833ca0369..41d34f3dd3a2263e9c3c70936c1a61277d63ae58 100644 --- a/Graphics/drawMesh.cpp +++ b/Graphics/drawMesh.cpp @@ -8,8 +8,6 @@ #include "GmshMessage.h" #include "GmshDefines.h" #include "GModel.h" -#include "GFaceCompound.h" -#include "GEdgeCompound.h" #include "MLine.h" #include "MTriangle.h" #include "MQuadrangle.h" @@ -147,12 +145,6 @@ static void drawVertexLabel(drawContext *ctx, GEntity *e, MVertex *v, static void drawVerticesPerEntity(drawContext *ctx, GEntity *e) { - //if(e->dim() == 2) { - // if(e->cast2Edge()->getCompound()) { - // if(e->cast2Edge()->getCompound() - // - // } - //} if(CTX::instance()->mesh.points) { if(CTX::instance()->mesh.pointType) { for(unsigned int i = 0; i < e->mesh_vertices.size(); i++){ @@ -442,11 +434,7 @@ class drawMeshGEdge { void operator () (GEdge *e) { if(!e->getVisibility()) { - if(e->getCompound()) { - if(!e->getCompound()->getVisibility()) return; - } - else - return; + return; } bool select = (_ctx->render_mode == drawContext::GMSH_SELECT && @@ -491,11 +479,7 @@ class drawMeshGFace { void operator () (GFace *f) { if(!f->getVisibility()) { - if(f->getCompound()) { - if(!f->getCompound()->getVisibility()) return; - } - else - return; + return; } bool select = (_ctx->render_mode == drawContext::GMSH_SELECT && diff --git a/Mesh/BackgroundMesh.cpp b/Mesh/BackgroundMesh.cpp index b2cc9aa681a2e7274d63093523278bcac37e0d06..381b9d7f32ec589d0390162f77c9846226218efb 100644 --- a/Mesh/BackgroundMesh.cpp +++ b/Mesh/BackgroundMesh.cpp @@ -9,9 +9,7 @@ #include "Context.h" #include "GVertex.h" #include "GEdge.h" -#include "GEdgeCompound.h" #include "GFace.h" -#include "GFaceCompound.h" #include "GModel.h" #include "OS.h" #include "Field.h" @@ -227,7 +225,6 @@ static void propagateValuesOnFace(GFace *_gf, void backgroundMesh::propagate1dMesh(GFace *_gf) { std::list<GEdge*> e;// = _gf->edges(); - replaceMeshCompound(_gf, e); std::list<GEdge*>::const_iterator it = e.begin(); std::map<MVertex*,double> sizes; @@ -282,7 +279,6 @@ crossField2d::crossField2d(MVertex* v, GEdge* ge) void backgroundMesh::propagateCrossFieldByDistance(GFace *_gf) { std::list<GEdge*> e; - replaceMeshCompound(_gf, e); std::list<GEdge*>::const_iterator it = e.begin(); std::map<MVertex*,double> _cosines4,_sines4; @@ -443,7 +439,6 @@ void backgroundMesh::propagateCrossField(GFace *_gf, simpleFunction<double> *ONE std::map<MVertex*,double> _cosines4,_sines4; std::list<GEdge*> e; - replaceMeshCompound(_gf, e); std::list<GEdge*>::const_iterator it = e.begin(); @@ -486,7 +481,7 @@ void backgroundMesh::propagateCrossField(GFace *_gf, simpleFunction<double> *ONE // print("cos4.pos",0,_cosines4,0); // print("sin4.pos",0,_sines4,0); - + std::map<MVertex*,MVertex*>::iterator itv2 = _2Dto3D.begin(); for ( ; itv2 != _2Dto3D.end(); ++itv2){ MVertex *v_2D = itv2->first; diff --git a/Mesh/BackgroundMesh2D.cpp b/Mesh/BackgroundMesh2D.cpp index f3ff9e3c775fe0baeb79dc4ddd89564c4a8a57d2..f45c6707d1bfc32dddaaafad2fee00b44276993f 100644 --- a/Mesh/BackgroundMesh2D.cpp +++ b/Mesh/BackgroundMesh2D.cpp @@ -10,9 +10,7 @@ #include "GModel.h" #include "GVertex.h" #include "GEdge.h" -#include "GEdgeCompound.h" #include "GFace.h" -#include "GFaceCompound.h" #include "MElement.h" #include "MElementOctree.h" #include "MTriangle.h" @@ -291,7 +289,6 @@ void backgroundMesh2D::computeSizeField() } list<GEdge*> e; - replaceMeshCompound(face, e); list<GEdge*>::const_iterator it = e.begin(); DoubleStorageType sizes; @@ -483,8 +480,6 @@ void frameFieldBackgroundMesh2D::computeCrossField(simpleFunction<double> &eval_ return; } - replaceMeshCompound(face, e); - list<GEdge*>::const_iterator it = e.begin(); for( ; it != e.end(); ++it ){ diff --git a/Mesh/BackgroundMeshTools.cpp b/Mesh/BackgroundMeshTools.cpp index 85dc609596df67087f840ec513a90996e3c39a46..e882aa3fd9933e766c7cd86f6818147b8eb9e24a 100644 --- a/Mesh/BackgroundMeshTools.cpp +++ b/Mesh/BackgroundMeshTools.cpp @@ -7,7 +7,6 @@ #include "GFace.h" #include "GVertex.h" #include "GEdge.h" -#include "GEdgeCompound.h" #include "GEntity.h" #include "Context.h" #include "Field.h" @@ -19,12 +18,9 @@ static double max_surf_curvature(const GEdge *ge, double u) std::list<GFace *> faces = ge->faces(); std::list<GFace *>::iterator it = faces.begin(); while(it != faces.end()){ - if ((*it)->geomType() != GEntity::CompoundSurface && - (*it)->geomType() != GEntity::DiscreteSurface){ - SPoint2 par = ge->reparamOnFace((*it), u, 1); - double cc = (*it)->curvature(par); - val = std::max(cc, val); - } + SPoint2 par = ge->reparamOnFace((*it), u, 1); + double cc = (*it)->curvature(par); + val = std::max(cc, val); ++it; } return val; @@ -93,71 +89,24 @@ SMetric3 max_edge_curvature_metric(const GEdge *ge, double u) static SMetric3 metric_based_on_surface_curvature(const GEdge *ge, double u, bool iso_surf) { - const GEdgeCompound* ptrCompoundEdge = dynamic_cast<const GEdgeCompound*>(ge); - if (ptrCompoundEdge){ - double cmax, cmin; - SVector3 dirMax,dirMin; - cmax = ptrCompoundEdge->curvatures(u,&dirMax, &dirMin, &cmax,&cmin); - if (cmin == 0)cmin =1.e-12; - if (cmax == 0)cmax =1.e-12; - double lambda2 = ((2 * M_PI) /( fabs(cmax) * CTX::instance()->mesh.minCircPoints ) ); - double lambda1 = ((2 * M_PI) /( fabs(cmin) * CTX::instance()->mesh.minCircPoints ) ); - SVector3 Z = crossprod(dirMax,dirMin); - - lambda1 = std::max(lambda1, CTX::instance()->mesh.lcMin); - lambda2 = std::max(lambda2, CTX::instance()->mesh.lcMin); - lambda1 = std::min(lambda1, CTX::instance()->mesh.lcMax); - lambda2 = std::min(lambda2, CTX::instance()->mesh.lcMax); - - SMetric3 curvMetric (1. / (lambda1 * lambda1), 1. / (lambda2 * lambda2), - 1.e-12, dirMin, dirMax, Z); - return curvMetric; - } - else{ - SMetric3 mesh_size(1.e-12); - std::list<GFace *> faces = ge->faces(); - std::list<GFace *>::iterator it = faces.begin(); - // we choose the metric eigenvectors to be the ones - // related to the edge ... - SMetric3 curvMetric = max_edge_curvature_metric(ge, u); - while(it != faces.end()){ - if (((*it)->geomType() != GEntity::CompoundSurface) && - ((*it)->geomType() != GEntity::DiscreteSurface)){ - SPoint2 par = ge->reparamOnFace((*it), u, 1); - SMetric3 m = metric_based_on_surface_curvature (*it, par.x(), par.y(), iso_surf); - curvMetric = intersection_conserveM1(curvMetric,m); - } - ++it; - } - - return curvMetric; + SMetric3 mesh_size(1.e-12); + std::list<GFace *> faces = ge->faces(); + std::list<GFace *>::iterator it = faces.begin(); + // we choose the metric eigenvectors to be the ones + // related to the edge ... + SMetric3 curvMetric = max_edge_curvature_metric(ge, u); + while(it != faces.end()){ + SPoint2 par = ge->reparamOnFace((*it), u, 1); + SMetric3 m = metric_based_on_surface_curvature (*it, par.x(), par.y(), iso_surf); + curvMetric = intersection_conserveM1(curvMetric,m); + ++it; } + return curvMetric; } static SMetric3 metric_based_on_surface_curvature(const GVertex *gv, bool iso_surf) { SMetric3 mesh_size(1.e-15); - std::list<GEdge*> l_edges = gv->edges(); - for (std::list<GEdge*>::const_iterator ite = l_edges.begin(); - ite != l_edges.end(); ++ite){ - GEdge *_myGEdge = *ite; - Range<double> bounds = _myGEdge->parBounds(0); - - // ES: Added extra if condition to use the code below only with compund curves - // This is because we want to call the function - // metric_based_on_surface_curvature(const GEdge *ge, double u) for the case when - // ge is a compound edge - if (_myGEdge->geomType() == GEntity::CompoundCurve){ - if (gv == _myGEdge->getBeginVertex()) - mesh_size = intersection - (mesh_size, - metric_based_on_surface_curvature(_myGEdge, bounds.low(), iso_surf)); - else - mesh_size = intersection - (mesh_size, - metric_based_on_surface_curvature(_myGEdge, bounds.high(), iso_surf)); - } - } return mesh_size; } diff --git a/Mesh/BoundaryLayers.cpp b/Mesh/BoundaryLayers.cpp index 41dc3860770106faafc73698b461743b27fed968..635e367440628e7a068413c8935503f892e5fef2 100644 --- a/Mesh/BoundaryLayers.cpp +++ b/Mesh/BoundaryLayers.cpp @@ -13,7 +13,6 @@ #include "meshGFace.h" #include "GmshMessage.h" #include "Field.h" -#include "GFaceCompound.h" #if defined(HAVE_POST) #include "PView.h" @@ -250,20 +249,6 @@ static void checkDepends(GModel *m, GFace *f, std::set<GFace*> &dep) dep.insert(from); checkDepends(m, from, dep); } - - if(f->geomType() == GEntity::CompoundSurface){ - std::list<GFace*> compounds = ((GFaceCompound*)(f))->getCompounds(); - std::list<GFace*>::iterator itgf = compounds.begin(); - for( ; itgf != compounds.end(); itgf++ ){ - if(!(*itgf)){ - Msg::Error("Unknown compound face in boundary layer source face %d", - f->tag()); - return; - } - dep.insert(*itgf); - checkDepends(m, *itgf, dep); - } - } } static unsigned int FixErasedExtrScaleFlags(GModel *m, diff --git a/Mesh/CMakeLists.txt b/Mesh/CMakeLists.txt index a25131ee307a5c4e87540b3a8831a75180fddf36..2f5d07785a59ab0046a06ba1d994b2b8ff2576c8 100644 --- a/Mesh/CMakeLists.txt +++ b/Mesh/CMakeLists.txt @@ -35,7 +35,6 @@ set(SRC HighOrder.cpp meshPartition.cpp meshRefine.cpp - multiscalePartition.cpp QuadTriUtils.cpp QuadTriExtruded2D.cpp QuadTriExtruded3D.cpp QuadTriTransfinite3D.cpp simple3D.cpp ThinLayer.cpp diff --git a/Mesh/DivideAndConquer.cpp b/Mesh/DivideAndConquer.cpp index 81c9d2874133e3ecf472413a5fdae4b421d0eb3a..274e643e436271affbf3233b00ad6c575d320f6a 100644 --- a/Mesh/DivideAndConquer.cpp +++ b/Mesh/DivideAndConquer.cpp @@ -23,7 +23,6 @@ #include "OS.h" #include "GPoint.h" #include "GFace.h" -#include "GEdgeCompound.h" #include "MLine.h" #define Pred(x) ((x)->prev) @@ -1008,7 +1007,7 @@ void DocRecord::concave(double x,double y,GFace* gf) std::set<int>::iterator it2; list = gf->edges(); - replaceMeshCompound(gf,list); + for(it1 = list.begin(); it1 != list.end(); it1++){ edge = *it1; for(unsigned int i = 0; i < edge->getNumMeshElements(); i++){ @@ -1142,7 +1141,7 @@ void DocRecord::clear_edges() bool DocRecord::delaunay_conformity(GFace* gf) { std::list<GEdge*> list = gf->edges(); - replaceMeshCompound(gf,list); + for(std::list<GEdge*>::iterator it = list.begin(); it!= list.end(); it++){ GEdge *edge = *it; for(unsigned int i = 0; i < edge->getNumMeshElements(); i++){ diff --git a/Mesh/Generator.cpp b/Mesh/Generator.cpp index 5a774d171d72cba44dbb6ffb2574838688296492..3a939ad9f5459a002ae13f4723736ccf908d8c84 100644 --- a/Mesh/Generator.cpp +++ b/Mesh/Generator.cpp @@ -29,7 +29,6 @@ #include "HighOrder.h" #include "Generator.h" #include "meshGFaceLloyd.h" -#include "GFaceCompound.h" #include "Field.h" #include "Options.h" #include "simple3D.h" @@ -449,10 +448,7 @@ static void Mesh2D(GModel *m) if(!Mesh2DWithBoundaryLayers(m)){ std::set<GFace*, GEntityLessThan> cf, f; for(GModel::fiter it = m->firstFace(); it != m->lastFace(); ++it) - if ((*it)->geomType() == GEntity::CompoundSurface) - cf.insert(*it); - else - f.insert(*it); + f.insert(*it); Msg::ResetProgressMeter(); @@ -471,8 +467,7 @@ static void Mesh2D(GModel *m) temp[K]->mesh(true); #if defined(HAVE_BFGS) if(CTX::instance()->mesh.optimizeLloyd){ - if (temp[K]->geomType()==GEntity::CompoundSurface || - temp[K]->geomType()==GEntity::Plane || + if (temp[K]->geomType()==GEntity::Plane || temp[K]->geomType()==GEntity::RuledSurface) { if (temp[K]->meshAttributes.method != MESH_TRANSFINITE && !temp[K]->meshAttributes.extrude) { @@ -509,8 +504,7 @@ static void Mesh2D(GModel *m) (*it)->mesh(true); #if defined(HAVE_BFGS) if(CTX::instance()->mesh.optimizeLloyd){ - if ((*it)->geomType()==GEntity::CompoundSurface || - (*it)->geomType()==GEntity::Plane || + if ((*it)->geomType()==GEntity::Plane || (*it)->geomType()==GEntity::RuledSurface) { if ((*it)->meshAttributes.method != MESH_TRANSFINITE && !(*it)->meshAttributes.extrude) { diff --git a/Mesh/directions3D.cpp b/Mesh/directions3D.cpp index 7145f30e509971b5a7a4f78162f06eca2f1fef2d..ea27ca3179b8e6227f8a0e41006cd43ca9322082 100644 --- a/Mesh/directions3D.cpp +++ b/Mesh/directions3D.cpp @@ -13,7 +13,6 @@ #include "MTetrahedron.h" #include "directions3D.h" #include "OS.h" -#include "GFaceCompound.h" #include "cross3D.h" #if defined(HAVE_SOLVER) @@ -509,21 +508,14 @@ void Frame_field::initFace(GFace* gf) // compute cumulative cross-data "vertices x elements" for the whole contour of gf std::list<GEdge*> edges = gf->edges(); vertex_to_elements.clear(); - //Replace edges by their compounds - std::set<GEdge*> mySet; - std::list<GEdge*>::iterator it = edges.begin(); - while(it != edges.end()){ - if((*it)->getCompound()){ - GEdge *gec = (GEdge*)(*it)->getCompound(); - mySet.insert(gec); - } - else{ - mySet.insert(*it); - } + std::set<GEdge*> mySet; + std::list<GEdge*>::iterator it = edges.begin(); + while(it != edges.end()){ + mySet.insert(*it); ++it; - } - edges.clear(); - edges.insert(edges.begin(), mySet.begin(), mySet.end()); + } + edges.clear(); + edges.insert(edges.begin(), mySet.begin(), mySet.end()); for( std::list<GEdge*>::const_iterator it=edges.begin(); it!=edges.end(); it++){ build_vertex_to_elements(*it,false); } diff --git a/Mesh/meshGFace.cpp b/Mesh/meshGFace.cpp index 6508a69dea59f6bc99ff8e86ddc14ca47b230a0f..e1ea164d64f394e3d207d14c937aea30c77751d5 100644 --- a/Mesh/meshGFace.cpp +++ b/Mesh/meshGFace.cpp @@ -16,7 +16,6 @@ #include "BackgroundMesh.h" #include "GVertex.h" #include "GEdge.h" -#include "GEdgeCompound.h" #include "robustPredicates.h" #include "discreteFace.h" #include "GFace.h" @@ -41,7 +40,6 @@ #include "meshPartition.h" #include "CreateFile.h" #include "Context.h" -#include "multiscalePartition.h" #include "meshGFaceLloyd.h" #include "boundaryLayersData.h" #include "filterElements.h" @@ -958,16 +956,7 @@ static void directions_storage(GFace* gf) gf->storage4.clear(); for(it=vertices.begin();it!=vertices.end();it++){ - ok = 0; - - if(!gf->getCompound()){ - if(gf->geomType()==GEntity::CompoundSurface){ - ok = translate(gf,octree,*it,SPoint2(0.0,0.0),v1,v2); - } - else{ - ok = improved_translate(gf,*it,v1,v2); - } - } + ok = improved_translate(gf,*it,v1,v2); if(ok){ gf->storage1.push_back(SPoint3((*it)->x(),(*it)->y(),(*it)->z())); @@ -998,16 +987,6 @@ bool meshGenerator(GFace *gf, int RECUR_ITER, std::list<int> dir = gf->edgeOrientations(); std::vector<MEdge> medgesToRecover; - // replace edges by their compounds - // if necessary split compound and remesh parts - bool isMeshed = false; - if(gf->geomType() == GEntity::CompoundSurface && !onlyInitialMesh){ - isMeshed = checkMeshCompound((GFaceCompound*) gf, edges); - if (isMeshed) return true; - } - - // if (gf->degenerate(0))return 0; - // build a set with all points of the boundaries std::set<MVertex*, MVertexLessThanNum> all_vertices, boundary; std::list<GEdge*>::iterator ite = edges.begin(); @@ -1507,9 +1486,7 @@ bool meshGenerator(GFace *gf, int RECUR_ITER, //gf->triangles.clear(); //gf->quadrangles.clear(); - // only delete the mesh data stored in the base GFace class (calling - // gf->deleteMesh() would also destroy e.g. the data in a compound face, which - // we should not do) + // only delete the mesh data stored in the base GFace class gf->GFace::deleteMesh(); Msg::Debug("Starting to add internal points"); @@ -2523,247 +2500,6 @@ void meshGFace::operator() (GFace *gf, bool print) } } -bool checkMeshCompound(GFaceCompound *gf, std::list<GEdge*> &edges) -{ - bool isMeshed = false; -#if defined(HAVE_SOLVER) - bool correctTopo = gf->checkTopology(); - if (!correctTopo && gf->allowPartition()){ - partitionAndRemesh((GFaceCompound*) gf); - isMeshed = true; - return isMeshed; - } - - bool correctParam = gf->parametrize(); - - if (!correctParam && gf->allowPartition()){ - partitionAndRemesh((GFaceCompound*) gf); - isMeshed = true; - return isMeshed; - } - - //Replace edges by their compounds - std::set<GEdge*> mySet; - std::list<GEdge*>::iterator it = edges.begin(); - while(it != edges.end()){ - if((*it)->getCompound()){ - mySet.insert((*it)->getCompound()); - } - else{ - mySet.insert(*it); - } - ++it; - } - edges.clear(); - edges.insert(edges.begin(), mySet.begin(), mySet.end()); -#endif - return isMeshed; -} - -void partitionAndRemesh(GFaceCompound *gf) -{ -#if defined(HAVE_SOLVER) && defined(HAVE_ANN) && (defined(HAVE_CHACO) || defined(HAVE_METIS)) - - // Partition the mesh and createTopology for new faces - double tbegin = Cpu(); - std::list<GFace*> cFaces = gf->getCompounds(); - std::vector<MElement *> elements; - for (std::list<GFace*>::iterator it = cFaces.begin(); it != cFaces.end(); it++) - for(unsigned int j = 0; j < (*it)->getNumMeshElements(); j++) - elements.push_back((*it)->getMeshElement(j)); - - typeOfPartition method; - if(gf->nbSplit > 0) method = MULTILEVEL; - else method = LAPLACIAN; - - int allowType = gf->allowPartition(); - multiscalePartition *msp = new multiscalePartition(elements, abs(gf->nbSplit), - method, allowType); - - int NF = msp->getNumberOfParts(); - int numv = gf->model()->getMaxElementaryNumber(0) + 1; - int nume = gf->model()->getMaxElementaryNumber(1) + 1; - int numf = gf->model()->getMaxElementaryNumber(2) + 1; - std::vector<discreteFace*> pFaces; - createPartitionFaces(gf->model(), elements, NF, pFaces); - - gf->model()->createTopologyFromFaces(pFaces); - - double tmult = Cpu(); - Msg::Info("Multiscale Partition SUCCESSFULLY PERFORMED : %d parts (%g s)", - NF, tmult - tbegin); - gf->model()->writeMSH("multiscalePARTS.msh", 2.2, false, true); - - // Remesh new faces (Compound Lines and Compound Surfaces) - Msg::Info("*** Starting parametrize compounds:"); - double t0 = Cpu(); - - //Parametrize Compound Lines - int NE = gf->model()->getMaxElementaryNumber(1) - nume + 1; - for (int i=0; i < NE; i++){ - std::vector<GEdge*>e_compound; - GEdge *pe = gf->model()->getEdgeByTag(nume+i);//partition edge - e_compound.push_back(pe); - int num_gec = nume + NE + i ; - Msg::Info("Parametrize Compound Line (%d) = %d discrete edge", - num_gec, pe->tag()); - GEdgeCompound *gec = new GEdgeCompound(gf->model(), num_gec, e_compound); - gf->model()->add(gec); - } - - // Parametrize Compound surfaces - std::set<MVertex*> allNod; - std::list<GEdge*> U0; - for (int i=0; i < NF; i++){ - std::list<GFace*> f_compound; - GFace *pf = gf->model()->getFaceByTag(numf+i);//partition face - int num_gfc = numf + NF + i ; - f_compound.push_back(pf); - Msg::Info("Parametrize Compound Surface (%d) = %d discrete face", - num_gfc, pf->tag()); - - GFaceCompound *gfc = new GFaceCompound(gf->model(), num_gfc, f_compound, U0, - gf->getTypeOfCompound()); - - gfc->meshAttributes.recombine = gf->meshAttributes.recombine; - gf->model()->add(gfc); - - gfc->parametrize(); - } - - double t1 = Cpu(); - Msg::Info("*** Parametrize compounds done (%g s)", t1-t0); - Msg::Info("*** Starting meshing 1D edges ...:"); - for (int i = 0; i < NE; i++){ - GEdge *gec = gf->model()->getEdgeByTag(nume + NE + i); - meshGEdge mge; - mge(gec); - } - double t2 = Cpu(); - Msg::Info("*** Meshing 1D edges done (%gs)", t2-t1); - - Msg::Info("*** Starting Mesh of surface %d ...", gf->tag()); - - for (int i=0; i < NF; i++){ - GFace *gfc = gf->model()->getFaceByTag(numf + NF + i ); - meshGFace mgf; - mgf(gfc); - - for(unsigned int j = 0; j < gfc->triangles.size(); ++j){ - MTriangle *t = gfc->triangles[j]; - std::vector<MVertex *> v(3); - for(int k = 0; k < 3; k++){ - v[k] = t->getVertex(k); - allNod.insert(v[k]); - } - gf->triangles.push_back(new MTriangle(v[0], v[1], v[2])); - } - for(unsigned int j = 0; j < gfc->quadrangles.size(); ++j){ - MQuadrangle *q = gfc->quadrangles[j]; - std::vector<MVertex *> v(4); - for(int k = 0; k < 4; k++){ - v[k] = q->getVertex(k); - allNod.insert(v[k]); - } - gf->quadrangles.push_back(new MQuadrangle(v[0], v[1], v[2], v[3])); - } - - //update mesh statistics - gf->meshStatistics.efficiency_index += gfc->meshStatistics.efficiency_index; - gf->meshStatistics.longest_edge_length = std::max(gf->meshStatistics.longest_edge_length, - gfc->meshStatistics.longest_edge_length); - gf->meshStatistics.smallest_edge_length= std::min(gf->meshStatistics.smallest_edge_length, - gfc->meshStatistics.smallest_edge_length); - gf->meshStatistics.nbGoodLength += gfc->meshStatistics.nbGoodLength; - gf->meshStatistics.nbGoodQuality += gfc->meshStatistics.nbGoodQuality; - gf->meshStatistics.nbEdge += gfc->meshStatistics.nbEdge; - - } - - // Removing discrete Vertices - Edges - Faces - int NV = gf->model()->getMaxElementaryNumber(0) - numv + 1; - for (int i=0; i < NV; i++){ - GVertex *pv = gf->model()->getVertexByTag(numv+i); - gf->model()->remove(pv); - } - for (int i=0; i < NE; i++){ - GEdge *gec = gf->model()->getEdgeByTag(nume+NE+i); - GEdge *pe = gf->model()->getEdgeByTag(nume+i); - gf->model()->remove(pe); - gf->model()->remove(gec); - } - for (int i=0; i < NF; i++){ - GFace *gfc = gf->model()->getFaceByTag(numf+NF+i); - GFace *pf = gf->model()->getFaceByTag(numf+i); - gf->model()->remove(pf); - gf->model()->remove(gfc); - } - - // Put new mesh in a new discreteFace - for(std::set<MVertex*>::iterator it = allNod.begin(); it != allNod.end(); ++it){ - gf->mesh_vertices.push_back(*it); - } - - // FIXME: This horrible hack is necessary to remove vertices that might belong - // to a GVertex. The true fix is rewrite this part of the code: it's far too - // complex and error prone. - for(GModel::viter it = gf->model()->firstVertex(); it != gf->model()->lastVertex(); it++){ - std::vector<MVertex*>::iterator itve = std::find - (gf->mesh_vertices.begin(), gf->mesh_vertices.end(), (*it)->mesh_vertices[0]); - if(itve != gf->mesh_vertices.end()) - gf->mesh_vertices.erase(itve); - } - - // Remove mesh_vertices that belong to l_edges - std::list<GEdge*> l_edges = gf->edges(); - for(std::list<GEdge*>::iterator it = l_edges.begin(); it != l_edges.end(); it++){ - std::vector<MVertex*> edge_vertices = (*it)->mesh_vertices; - std::vector<MVertex*>::const_iterator itv = edge_vertices.begin(); - for(; itv != edge_vertices.end(); itv++){ - std::vector<MVertex*>::iterator itve = std::find - (gf->mesh_vertices.begin(), gf->mesh_vertices.end(), *itv); - if (itve != gf->mesh_vertices.end()) gf->mesh_vertices.erase(itve); - } - MVertex *vB = (*it)->getBeginVertex()->mesh_vertices[0]; - std::vector<MVertex*>::iterator itvB = std::find - (gf->mesh_vertices.begin(), gf->mesh_vertices.end(), vB); - if (itvB != gf->mesh_vertices.end()) gf->mesh_vertices.erase(itvB); - MVertex *vE = (*it)->getEndVertex()->mesh_vertices[0]; - std::vector<MVertex*>::iterator itvE = std::find - (gf->mesh_vertices.begin(), gf->mesh_vertices.end(), vE); - if (itvE != gf->mesh_vertices.end()) gf->mesh_vertices.erase(itvE); - - //if l_edge is a compond - if((*it)->getCompound()){ - GEdgeCompound *gec = (*it)->getCompound(); - std::vector<MVertex*> edge_vertices = gec->mesh_vertices; - std::vector<MVertex*>::const_iterator itv = edge_vertices.begin(); - for(; itv != edge_vertices.end(); itv++){ - std::vector<MVertex*>::iterator itve = std::find - (gf->mesh_vertices.begin(), gf->mesh_vertices.end(), *itv); - if (itve != gf->mesh_vertices.end()) gf->mesh_vertices.erase(itve); - } - MVertex *vB = (*it)->getBeginVertex()->mesh_vertices[0]; - std::vector<MVertex*>::iterator itvB = std::find - (gf->mesh_vertices.begin(), gf->mesh_vertices.end(), vB); - if (itvB != gf->mesh_vertices.end()) gf->mesh_vertices.erase(itvB); - MVertex *vE = (*it)->getEndVertex()->mesh_vertices[0]; - std::vector<MVertex*>::iterator itvE = std::find - (gf->mesh_vertices.begin(), gf->mesh_vertices.end(), vE); - if (itvE != gf->mesh_vertices.end()) gf->mesh_vertices.erase(itvE); - } - } - - double t3 = Cpu(); - Msg::Info("*** Mesh of surface %d done by assembly %d remeshed faces (%g s)", - gf->tag(), NF, t3-t2); - Msg::Info("-----------------------------------------------------------"); - - gf->coherenceNormals(); - gf->meshStatistics.status = GFace::DONE; -#endif -} - static bool getGFaceNormalFromVert(GFace *gf, MElement *el, SVector3 &nf) { bool found = false; @@ -2832,8 +2568,7 @@ void orientMeshGFace::operator()(GFace *gf) gf->model()->setCurrentMeshEntity(gf); if(gf->geomType() == GEntity::DiscreteSurface || - gf->geomType() == GEntity::BoundaryLayerSurface || - gf->geomType() == GEntity::CompoundSurface){ + gf->geomType() == GEntity::BoundaryLayerSurface){ // don't do anything } else { diff --git a/Mesh/meshGFaceBamg.cpp b/Mesh/meshGFaceBamg.cpp index 7cf9ae6b0778ca3f3696f5b5ff086f2182aacf03..250a0a53e08c528bd659dd396a080c93e29b2b11 100644 --- a/Mesh/meshGFaceBamg.cpp +++ b/Mesh/meshGFaceBamg.cpp @@ -20,7 +20,6 @@ #include "meshGFaceDelaunayInsertion.h" #include "Options.h" #include "meshGFace.h" -#include "GFaceCompound.h" #include "MElementOctree.h" #if defined(HAVE_BAMG) @@ -74,21 +73,13 @@ static void computeMeshMetricsForBamg(GFace *gf, int numV, void meshGFaceBamg(GFace *gf){ std::list<GEdge*> edges = gf->edges(); - bool hasCompounds = false; //Replace edges by their compounds std::set<GEdge*> mySet; std::list<GEdge*>::iterator it = edges.begin(); while(it != edges.end()){ - if((*it)->getCompound()){ - hasCompounds = true; - GEdge *gec = (GEdge*)(*it)->getCompound(); - mySet.insert(gec); - } - else{ - mySet.insert(*it); - } - ++it; + mySet.insert(*it); + ++it; } edges.clear(); edges.insert(edges.begin(), mySet.begin(), mySet.end()); @@ -149,16 +140,6 @@ void meshGFaceBamg(GFace *gf){ double v1(bamgVertices[nodes[0]][1]); double v2(bamgVertices[nodes[1]][1]); double v3(bamgVertices[nodes[2]][1]); - if (hasCompounds){ - MVertex *vv1 = new MVertex(u1,v1,0.0); - MVertex *vv2 = new MVertex(u2,v2,0.0); - MVertex *vv3 = new MVertex(u3,v3,0.0); - newVert.push_back(vv1); - newVert.push_back(vv2); - newVert.push_back(vv3); - MTriangle *tri = new MTriangle(vv1,vv2,vv3, i); - myParamElems.push_back(tri); - } double sign = (u2-u1)*(v3-v1) - (u3-u1)*(v2-v1); if (sign < 0){ int temp = nodes[0]; @@ -189,9 +170,6 @@ void meshGFaceBamg(GFace *gf){ bamgVertices, bamgTriangles, bamgBoundary); MElementOctree *_octree = NULL; - if (hasCompounds){ - _octree = new MElementOctree(myParamElems); - } Mesh2 *refinedBamgMesh = 0; int iterMax = 41; @@ -239,27 +217,6 @@ void meshGFaceBamg(GFace *gf){ // } //If point not found because compound edges have been remeshed and boundary triangles have changed //then we call our new octree - if ( !gp.succeeded() && hasCompounds){ - double uvw[3] = {v[0],v[1], 0.0}; - double UV[3]; - double initialTol = MElement::getTolerance(); - MElement::setTolerance(1.e-2); - MElement *e = _octree->find(v[0],v[1], 0.0, -1); - MElement::setTolerance(initialTol); - if (e){ - e->xyz2uvw(uvw,UV); - double valX[8], valY[8], valZ[8]; - for (int i=0;i<e->getNumPrimaryVertices();i++){ - int numTri = e->getNum(); - valX[i] = gf->triangles[numTri]->getVertex(i)->x(); - valY[i] = gf->triangles[numTri]->getVertex(i)->y(); - valZ[i] = gf->triangles[numTri]->getVertex(i)->z(); - } - gp.x() = e->interpolate(valX,UV[0],UV[1],UV[2]); - gp.y() = e->interpolate(valY,UV[0],UV[1],UV[2]); - gp.z() = e->interpolate(valZ,UV[0],UV[1],UV[2]); - } - } MFaceVertex *x = new MFaceVertex(gp.x(), gp.y(), gp.z(), gf, v[0], v[1]); yetAnother[i] = x; gf->mesh_vertices.push_back(x); diff --git a/Mesh/meshGFaceDelaunayInsertion.cpp b/Mesh/meshGFaceDelaunayInsertion.cpp index 37b7e568916088dadc7dd90b9ee8ef052cac24ec..5e5afb43d6993079fa072ae18313ba19718333ac 100644 --- a/Mesh/meshGFaceDelaunayInsertion.cpp +++ b/Mesh/meshGFaceDelaunayInsertion.cpp @@ -23,7 +23,6 @@ #include "MQuadrangle.h" #include "Field.h" #include "GModel.h" -#include "GFaceCompound.h" #include "discreteDiskFace.h" #include "intersectCurveSurface.h" #include "HilbertCurve.h" @@ -1327,18 +1326,6 @@ bool optimalPointFrontalB (GFace *gf, } #endif - if (gf->geomType() == GEntity::CompoundSurface){ - GFaceCompound *gfc = dynamic_cast<GFaceCompound*> (gf); - if (gfc){ - GPoint gp = gfc->intersectionWithCircle(n2,n1,middle,d,newPoint); - if (gp.succeeded()){ - newPoint[0] = gp.u(); - newPoint[1] = gp.v(); - return true; - } - } - } - double uvt[3] = {newPoint[0],newPoint[1],0.0}; curveFunctorCircle cc (n2,n1,middle,d); surfaceFunctorGFace ss (gf); diff --git a/Mesh/meshGFaceLloyd.cpp b/Mesh/meshGFaceLloyd.cpp index eb265729fddc3a2ad3844996c922ea3c9c4d4fef..a29c83aa6f293993537d6696e0af0087778273f0 100644 --- a/Mesh/meshGFaceLloyd.cpp +++ b/Mesh/meshGFaceLloyd.cpp @@ -413,8 +413,9 @@ smoothing::smoothing(int param1,int param2){ NORM = param2; } -void smoothing::optimize_face(GFace* gf){ - if(gf->getNumMeshElements()==0 || gf->getCompound()) return; +void smoothing::optimize_face(GFace* gf) +{ + if(gf->getNumMeshElements()==0) return; std::set<MVertex*> all; @@ -600,10 +601,10 @@ void smoothing::optimize_model(){ for(it=model->firstFace();it!=model->lastFace();it++) { gf = *it; - if(gf->getNumMeshElements()>0 && !gf->getCompound() /*&& gf->geomType()==GEntity::CompoundSurface*/){ - optimize_face(gf); - //recombineIntoQuads(gf,1,1); - } + if(gf->getNumMeshElements()>0){ + optimize_face(gf); + //recombineIntoQuads(gf,1,1); + } } } diff --git a/Mesh/meshGFaceOptimize.cpp b/Mesh/meshGFaceOptimize.cpp index bb9715703edcb45713c594e240fdb8a681d588ea..5a9b0dadc032c65e731fdac442a9d74be33f2a0c 100644 --- a/Mesh/meshGFaceOptimize.cpp +++ b/Mesh/meshGFaceOptimize.cpp @@ -1173,7 +1173,6 @@ int edgeSwapPass2(GFace *gf, std::set<MTri3*, compareTri3Ptr> &allTris, static int _recombineIntoQuads(GFace *gf, double minqual, bool cubicGraph = 1) { // never recombine a face that is part of a compound! - if(gf->getCompound()) return 0; if(gf->triangles.size() == 0) return 1; int success = 1; @@ -1444,7 +1443,7 @@ void recombineIntoQuads(GFace *gf, bool haveParam = true; bool saveAll = CTX::instance()->mesh.saveAll; - if(gf->geomType() == GEntity::DiscreteSurface && !gf->getCompound()) + if(gf->geomType() == GEntity::DiscreteSurface) haveParam = false; if (saveAll) gf->model()->writeMSH("before.msh"); diff --git a/Mesh/meshGRegion.cpp b/Mesh/meshGRegion.cpp index 7f2864c378d9de09b329a61794d50846f6b8acb1..c30c609351679ac0443ff173b00ed9deeb6a6dae 100644 --- a/Mesh/meshGRegion.cpp +++ b/Mesh/meshGRegion.cpp @@ -30,7 +30,6 @@ #include "BDS.h" #include "OS.h" #include "Context.h" -#include "GFaceCompound.h" #include "meshGRegionMMG3D.h" #include "simple3D.h" #include "directions3D.h" @@ -1076,22 +1075,6 @@ void meshGRegion::operator() (GRegion *gr) } } - // replace discreteFaces by their compounds - { - std::set<GFace*, GEntityLessThan> mySet; - std::list<GFace*>::iterator it = faces.begin(); - while(it != faces.end()){ - if((*it)->getCompound()) - mySet.insert((*it)->getCompound()); - else - mySet.insert(*it); - ++it; - } - faces.clear(); - faces.insert(faces.begin(), mySet.begin(), mySet.end()); - gr->set(faces); - } - if(CTX::instance()->mesh.algo3d != ALGO_3D_FRONTAL){ delaunay.push_back(gr); } diff --git a/Mesh/meshPartition.cpp b/Mesh/meshPartition.cpp index 62ed7f260bdf6e6b53d37bc1ef0acca251f6e7bf..951852d94496783527285c90cc3897043d05878e 100644 --- a/Mesh/meshPartition.cpp +++ b/Mesh/meshPartition.cpp @@ -28,7 +28,6 @@ #include "discreteEdge.h" #include "discreteFace.h" #include "discreteRegion.h" -#include "GFaceCompound.h" //--Prototype for Chaco interface diff --git a/Mesh/meshPartition.h b/Mesh/meshPartition.h index fcc593b492b16e4c7a991fd9211dfce8aa89f25e..6da2a9a9b1ee567e452719e7b303b0bb4333c4df 100644 --- a/Mesh/meshPartition.h +++ b/Mesh/meshPartition.h @@ -8,7 +8,6 @@ #include <vector> #include "partitionEdge.h" -#include "GFaceCompound.h" #include "GFace.h" class GModel; @@ -27,7 +26,7 @@ int RenumberGraph(Graph &graph, meshPartitionOptions &options); int PartitionMesh(GModel *const model, meshPartitionOptions &options); int RenumberMesh(GModel *const model, meshPartitionOptions &options); int PartitionMeshFace(std::list<GFace*> &cFaces, meshPartitionOptions &options); -int PartitionMeshElements(std::vector<MElement*> &elements, +int PartitionMeshElements(std::vector<MElement*> &elements, meshPartitionOptions &options); int CreatePartitionBoundaries(GModel *model, bool createGhostCells, bool createAllDims = false); diff --git a/Mesh/multiscalePartition.cpp b/Mesh/multiscalePartition.cpp deleted file mode 100644 index 0bd30710b28ccda54ecf74fe47defb4ba4202be6..0000000000000000000000000000000000000000 --- a/Mesh/multiscalePartition.cpp +++ /dev/null @@ -1,428 +0,0 @@ -// Gmsh - Copyright (C) 1997-2017 C. Geuzaine, J.-F. Remacle -// -// See the LICENSE.txt file for license information. Please report all -// bugs and problems to the public mailing list <gmsh@onelab.info>. -// -// Contributor(s): -// Emilie Marchandise - -#include "multiscalePartition.h" -#include "GmshConfig.h" -#include "GmshDefines.h" -#include "meshPartition.h" -#include "MEdge.h" -#include "MElement.h" -#include "multiscaleLaplace.h" -#include "GFaceCompound.h" -#include "Numeric.h" -#include "Context.h" -#include "OS.h" - -static void recur_connect(MVertex *v, - std::multimap<MVertex*,MEdge> &v2e, - std::set<MEdge,Less_Edge> &group, - std::set<MVertex*> &touched) -{ - if (touched.find(v) != touched.end())return; - - touched.insert(v); - for (std::multimap <MVertex*,MEdge>::iterator it = v2e.lower_bound(v); - it != v2e.upper_bound(v) ; ++it){ - group.insert(it->second); - for (int i=0;i<it->second.getNumVertices();++i){ - recur_connect (it->second.getVertex(i),v2e,group,touched); - } - } - -} - - -// starting form a list of elements, returns -// lists of lists that are all simply connected -static void recur_connect_e (const MEdge &e, - std::multimap<MEdge,MElement*,Less_Edge> &e2e, - std::set<MElement*> &group, - std::set<MEdge,Less_Edge> &touched){ - if (touched.find(e) != touched.end())return; - touched.insert(e); - for (std::multimap <MEdge,MElement*,Less_Edge>::iterator it = e2e.lower_bound(e); - it != e2e.upper_bound(e) ; ++it){ - group.insert(it->second); - for (int i=0;i<it->second->getNumEdges();++i){ - recur_connect_e (it->second->getEdge(i),e2e,group,touched); - } - } -} - - -static int connected_bounds (std::vector<MEdge> &edges, std::vector<std::vector<MEdge> > &boundaries) -{ - std::multimap<MVertex*,MEdge> v2e; - for (unsigned i = 0; i < edges.size(); ++i){ - for (int j=0;j<edges[i].getNumVertices();j++){ - v2e.insert(std::make_pair(edges[i].getVertex(j),edges[i])); - } - } - while (!v2e.empty()){ - std::set<MEdge, Less_Edge> group; - std::set<MVertex*> touched; - recur_connect (v2e.begin()->first,v2e,group,touched); - std::vector<MEdge> temp; - temp.insert(temp.begin(), group.begin(), group.end()); - boundaries.push_back(temp); - for (std::set<MVertex*>::iterator it = touched.begin() ; it != touched.end();++it) - v2e.erase(*it); - } - - return boundaries.size(); -} - -//-------------------------------------------------------------- -static void connectedRegions (std::vector<MElement*> &elements, - std::vector<std::vector<MElement*> > ®ions) -{ - std::multimap<MEdge,MElement*,Less_Edge> e2e; - for (unsigned int i = 0; i < elements.size(); ++i){ - for (int j = 0; j < elements[i]->getNumEdges(); j++){ - e2e.insert(std::make_pair(elements[i]->getEdge(j),elements[i])); - } - } - while (!e2e.empty()){ - std::set<MElement*> group; - std::set<MEdge,Less_Edge> touched; - recur_connect_e (e2e.begin()->first,e2e,group,touched); - std::vector<MElement*> temp; - temp.insert(temp.begin(), group.begin(), group.end()); - regions.push_back(temp); - for ( std::set<MEdge,Less_Edge>::iterator it = touched.begin() ; it != touched.end();++it) - e2e.erase(*it); - } -} - -static int getGenus (std::vector<MElement *> &elements, - std::vector<std::vector<MEdge> > &boundaries) -{ - - //We suppose MElements are simply connected - - std::set<MEdge, Less_Edge> es; - std::set<MVertex*> vs; - int N = 0; - for(unsigned int i = 0; i < elements.size(); i++){ - N++; - MElement *e = elements[i]; - for(int j = 0; j < e->getNumVertices(); j++){ - vs.insert(e->getVertex(j)); - } - for(int j = 0; j < e->getNumEdges(); j++){ - es.insert(e->getEdge(j)); - } - } - - int poincare = vs.size() - es.size() + N; - - //compute connected boundaries - int nbBounds = 0; - std::vector<MEdge> bEdges; - for(unsigned int i = 0; i < elements.size(); i++){ - for(int j = 0; j < elements[i]->getNumEdges(); j++){ - MEdge me = elements[i]->getEdge(j); - if(std::find(bEdges.begin(), bEdges.end(), me) == bEdges.end()) - bEdges.push_back(me); - else - bEdges.erase(std::find(bEdges.begin(), bEdges.end(),me)); - } - } - nbBounds = connected_bounds(bEdges, boundaries); - int genus = (int)(-poincare + 2 - nbBounds)/2; - - //printf("************** partition has %d boundaries and genus =%d \n", nbBounds, genus); - - return genus; - -} - -static int getAspectRatio(std::vector<MElement *> &elements, - std::vector<std::vector<MEdge> > &boundaries) -{ - - double area3D = 0.0; - for(unsigned int i = 0; i <elements.size(); ++i){ - MElement *t = elements[i]; - std::vector<MVertex *> v(3); - for(int k = 0; k < 3; k++) v[k] = t->getVertex(k); - double p0[3] = {v[0]->x(), v[0]->y(), v[0]->z()}; - double p1[3] = {v[1]->x(), v[1]->y(), v[1]->z()}; - double p2[3] = {v[2]->x(), v[2]->y(), v[2]->z()}; - double a_3D = fabs(triangle_area(p0, p1, p2)); - area3D += a_3D; - } - - double tot_length = 0.0; - for(unsigned int i = 0; i <boundaries.size(); ++i){ - std::vector<MEdge> iBound = boundaries[i]; - double iLength = 0.0; - for( unsigned int j = 0; j <iBound.size(); ++j){ - MVertex *v0 = iBound[j].getVertex(0); - MVertex *v1 = iBound[j].getVertex(1); - const double length = sqrt((v0->x() - v1->x()) * (v0->x() - v1->x()) + - (v0->y() - v1->y()) * (v0->y() - v1->y()) + - (v0->z() - v1->z()) * (v0->z() - v1->z())); - iLength += length; - } - tot_length += iLength; - } - int AR = 1; - if (boundaries.size() > 0){ - tot_length /= boundaries.size(); - AR = (int) ceil(2*3.14*area3D/(tot_length*tot_length)); - } - - //compute AR also with Bounding box - std::set<MVertex*> vs; - for(unsigned int i = 0; i < elements.size(); i++){ - MElement *e = elements[i]; - for(int j = 0; j < e->getNumVertices(); j++){ - vs.insert(e->getVertex(j)); - } - } - SBoundingBox3d bb; - std::vector<SPoint3> vertices; - for (std::set<MVertex* >::iterator it = vs.begin(); it != vs.end(); it++){ - SPoint3 pt((*it)->x(),(*it)->y(), (*it)->z()); - vertices.push_back(pt); - bb += pt; - } - double H = norm(SVector3(bb.max(), bb.min())); - - //SOrientedBoundingBox obbox = SOrientedBoundingBox::buildOBB(vertices); - //double H = obbox.getMaxSize(); - - double D = H; - if (boundaries.size() > 0 ) D = 10e4; - for (unsigned int i = 0; i < boundaries.size(); i++){ - std::set<MVertex*> vb; - std::vector<MEdge> iBound = boundaries[i]; - for (unsigned int j = 0; j < iBound.size(); j++){ - MEdge e = iBound[j]; - vb.insert(e.getVertex(0)); - vb.insert(e.getVertex(1)); - } - std::vector<SPoint3> vBounds; - SBoundingBox3d bb; - for (std::set<MVertex* >::iterator it = vb.begin(); it != vb.end(); it++){ - SPoint3 pt((*it)->x(),(*it)->y(), (*it)->z()); - vBounds.push_back(pt); - bb +=pt; - } - double iD = norm(SVector3(bb.max(), bb.min())); - D = std::min(D, iD); - - //SOrientedBoundingBox obboxD = SOrientedBoundingBox::buildOBB(vBounds); - //D = std::max(D, obboxD.getMaxSize()); - } - int AR2 = (int)ceil(H/D); - - return std::max(AR, AR2); -} - -static void getGenusAndRatio(std::vector<MElement *> &elements, int & genus, int &AR, int &NB) -{ - std::vector<std::vector<MEdge> > boundaries; - boundaries.clear(); - genus = getGenus(elements, boundaries); - NB = boundaries.size(); - AR = getAspectRatio(elements, boundaries); - -} -static void partitionRegions(std::vector<MElement*> &elements, - std::vector<std::vector<MElement*> > ®ions) -{ - - for (unsigned int i = 0; i < elements.size(); ++i){ - MElement *e = elements[i]; - int part = e->getPartition(); - regions[part-1].push_back(e); - } - - std::vector<std::vector<MElement*> > allRegions; - for (unsigned int k = 0; k < regions.size(); ++k){ - std::vector<std::vector<MElement*> > conRegions; - conRegions.clear(); - connectedRegions (regions[k], conRegions); - for (unsigned int j = 0; j < conRegions.size(); j++) - allRegions.push_back(conRegions[j]); - } - regions.clear(); - regions.resize(allRegions.size()); - regions = allRegions; - -} - -/* -static void printLevel(std::vector<MElement *> &elements, int recur, int region) -{ - char fn[256]; - sprintf(fn, "part_%d_%d.msh", recur, region); - double version = 2.2; - - std::set<MVertex*> vs; - for (unsigned int i = 0; i < elements.size(); i++){ - for (int j = 0; j < elements[i]->getNumVertices(); j++){ - vs.insert(elements[i]->getVertex(j)); - } - } - - bool binary = false; - FILE *fp = Fopen (fn, "w"); - if(fp){ - fprintf(fp, "$MeshFormat\n"); - fprintf(fp, "%g %d %d\n", version, binary ? 1 : 0, (int)sizeof(double)); - fprintf(fp, "$EndMeshFormat\n"); - - fprintf(fp,"$Nodes\n%d\n", (int)vs.size()); - std::set<MVertex*> :: iterator it = vs.begin(); - int index = 1; - for (; it != vs.end() ; ++it){ - (*it)->setIndex(index++); - fprintf(fp,"%d %g %g %g\n",(*it)->getIndex(), - (*it)->x(),(*it)->y(),(*it)->z()); - } - fprintf(fp,"$EndNodes\n"); - - fprintf(fp,"$Elements\n%d\n", (int)elements.size()); - for (unsigned int i = 0; i < elements.size(); i++){ - elements[i]->writeMSH(fp, version); - } - fprintf(fp,"$EndElements\n%d\n", (int)elements.size()); - - fclose(fp); - } -} -*/ - -multiscalePartition::multiscalePartition(std::vector<MElement *> &elements, - int nbParts, typeOfPartition method, - int allowPartition) -{ - options = CTX::instance()->partitionOptions; - options.num_partitions = nbParts; - options.partitioner = 1; //1 CHACO, 2 METIS - if (options.partitioner == 1){ - options.global_method = 1;// 1 Multilevel-KL, 2 Spectral - options.mesh_dims[0] = nbParts; - } - else if (options.partitioner == 2){ - options.algorithm = 2;//1 recursive, 2=kway, 3=nodal weights - options.refine_algorithm=2; - options.edge_matching = 3; - } - - partitionLevel *level = new partitionLevel; - level->elements.insert(level->elements.begin(),elements.begin(),elements.end()); - level->recur = 0; - level->region = 0; - - levels.push_back(level); - onlyMultilevel = false; - if (allowPartition == 2) onlyMultilevel = true; - - partition(*level, nbParts, method); - - totalParts = assembleAllPartitions(elements); - -} - -void multiscalePartition::setNumberOfPartitions(int &nbParts) -{ - options.num_partitions = nbParts; - if (options.partitioner == 1){ - options.mesh_dims[0] = nbParts; - } -} - -void multiscalePartition::partition(partitionLevel & level, int nbParts, - typeOfPartition method) -{ -#if defined(HAVE_SOLVER) && defined(HAVE_ANN) && (defined(HAVE_METIS) || defined(HAVE_CHACO)) - - if (method == LAPLACIAN){ - std::map<MVertex*, SPoint3> coordinates; - multiscaleLaplace multiLaplace(level.elements, coordinates); - } - else if (method == MULTILEVEL){ - setNumberOfPartitions(nbParts); - PartitionMeshElements(level.elements, options); - } - - std::vector<std::vector<MElement*> > regions(nbParts); - partitionRegions(level.elements, regions); - level.elements.clear(); - - for (unsigned i=0;i< regions.size() ; i++){ - - partitionLevel *nextLevel = new partitionLevel; - nextLevel->elements = regions[i]; - nextLevel->recur = level.recur+1; - nextLevel->region = i; - - levels.push_back(nextLevel); - int genus, AR, NB; - getGenusAndRatio(regions[i], genus, AR, NB); - - if (genus < 0) { - Msg::Error("Genus partition is negative G=%d!", genus); - return; - } - - if (genus != 0 ){ - int nbParts = std::max(genus+2,2); - Msg::Info("Mesh partition: level (%d-%d) is %d-GENUS (AR=%d) " - "---> MULTILEVEL partition %d parts", - nextLevel->recur,nextLevel->region, genus, AR, nbParts); - partition(*nextLevel, nbParts, MULTILEVEL); - } - else if ((genus == 0 && AR > AR_MAX) || (genus == 0 && NB > 1)){ - int nbParts = 2; - if(!onlyMultilevel){ - Msg::Info("Mesh partition: level (%d-%d) is ZERO-GENUS (AR=%d NB=%d) " - "---> LAPLACIAN partition %d parts", - nextLevel->recur,nextLevel->region, AR, NB, nbParts); - partition(*nextLevel, nbParts, LAPLACIAN); - } - else { - Msg::Info("Mesh partition: level (%d-%d) is ZERO-GENUS (AR=%d NB=%d) " - "---> MULTILEVEL partition %d parts", - nextLevel->recur,nextLevel->region, AR, NB, nbParts); - partition(*nextLevel, nbParts, MULTILEVEL); - } - } - else { - Msg::Info("*** Mesh partition: level (%d-%d) is ZERO-GENUS (AR=%d, NB=%d)", - nextLevel->recur,nextLevel->region, AR, NB); - } - - } - -#endif -} - -int multiscalePartition::assembleAllPartitions(std::vector<MElement*> & elements) -{ - int iPart = 1; - - elements.clear(); - for (unsigned i = 0; i< levels.size(); i++){ - partitionLevel *iLevel = levels[i]; - if(iLevel->elements.size() > 0){ - for (unsigned j = 0; j < iLevel->elements.size(); j++){ - MElement *e = iLevel->elements[j]; - elements.push_back(e); - e->setPartition(iPart); - } - iPart++; - } - } - - return iPart - 1; -} diff --git a/Mesh/multiscalePartition.h b/Mesh/multiscalePartition.h deleted file mode 100644 index 3f44ad525db693e8a6ea3e7b0d35c03f5f7f54cb..0000000000000000000000000000000000000000 --- a/Mesh/multiscalePartition.h +++ /dev/null @@ -1,46 +0,0 @@ -// Gmsh - Copyright (C) 1997-2017 C. Geuzaine, J.-F. Remacle -// -// See the LICENSE.txt file for license information. Please report all -// bugs and problems to the public mailing list <gmsh@onelab.info>. -// -// Contributor(s): -// Emilie Marchandise - -#ifndef _MULTI_PARTITION_H_ -#define _MULTI_PARTITION_H_ - -#include <vector> -#include <map> -#include "linearSystemGMM.h" -#include "meshPartitionOptions.h" -#include "meshPartition.h" - -class MElement; -class meshPartitionOptions; - -struct partitionLevel { - int recur; - int region; - std::vector<MElement *> elements; -}; - -typedef enum {LAPLACIAN= 0, MULTILEVEL=1} typeOfPartition; - -class multiscalePartition{ - - private: - std::vector<partitionLevel*> levels; - void partition(partitionLevel &level, int nbParts, typeOfPartition method); - int totalParts; - bool onlyMultilevel; - meshPartitionOptions options; - - public: - multiscalePartition(std::vector<MElement *> &elements, int nbParts, - typeOfPartition method, int allowPartition); - int assembleAllPartitions(std::vector<MElement*> & elements); - void setNumberOfPartitions(int &nbParts); - int getNumberOfParts(){return totalParts;} -}; - -#endif diff --git a/Parser/Gmsh.tab.cpp b/Parser/Gmsh.tab.cpp index 833158f6e5a05d59d49f6bafe7b32ef60515875a..c6ae1b0ffeb1adde9f5c9833eea4cb0e2372ee9a 100644 --- a/Parser/Gmsh.tab.cpp +++ b/Parser/Gmsh.tab.cpp @@ -1440,48 +1440,48 @@ static const yytype_uint16 yyrline[] = 1540, 1549, 1552, 1559, 1562, 1569, 1593, 1609, 1625, 1662, 1702, 1718, 1734, 1756, 1772, 1791, 1807, 1828, 1839, 1845, 1851, 1858, 1889, 1904, 1926, 1949, 1972, 1995, 2019, 2043, - 2067, 2093, 2110, 2126, 2144, 2162, 2192, 2222, 2221, 2251, - 2253, 2255, 2257, 2259, 2267, 2269, 2271, 2273, 2281, 2283, - 2285, 2293, 2295, 2297, 2299, 2309, 2325, 2341, 2357, 2373, - 2389, 2426, 2448, 2472, 2473, 2478, 2481, 2485, 2501, 2519, - 2537, 2562, 2581, 2602, 2617, 2633, 2651, 2702, 2723, 2745, - 2768, 2873, 2889, 2924, 2946, 2968, 2974, 2989, 3017, 3029, - 3038, 3045, 3057, 3076, 3080, 3085, 3089, 3094, 3101, 3108, - 3115, 3127, 3200, 3218, 3235, 3250, 3283, 3295, 3319, 3323, - 3328, 3335, 3340, 3350, 3355, 3361, 3369, 3373, 3377, 3386, - 3450, 3466, 3483, 3500, 3522, 3544, 3579, 3587, 3595, 3601, - 3608, 3615, 3635, 3661, 3673, 3684, 3702, 3720, 3739, 3738, - 3763, 3762, 3789, 3788, 3813, 3812, 3835, 3851, 3868, 3885, - 3908, 3911, 3917, 3929, 3949, 3953, 3957, 3961, 3965, 3969, - 3973, 3977, 3986, 3999, 4000, 4001, 4002, 4003, 4007, 4008, - 4009, 4010, 4011, 4014, 4038, 4057, 4080, 4083, 4099, 4102, - 4119, 4122, 4128, 4131, 4138, 4141, 4148, 4170, 4211, 4255, - 4294, 4319, 4328, 4358, 4384, 4410, 4442, 4469, 4495, 4521, - 4547, 4573, 4595, 4606, 4654, 4703, 4715, 4726, 4733, 4748, - 4762, 4763, 4764, 4768, 4774, 4786, 4804, 4832, 4833, 4834, - 4835, 4836, 4837, 4838, 4839, 4840, 4847, 4848, 4849, 4850, - 4851, 4852, 4853, 4854, 4855, 4856, 4857, 4858, 4859, 4860, - 4861, 4862, 4863, 4864, 4865, 4866, 4867, 4868, 4869, 4870, - 4871, 4872, 4873, 4874, 4875, 4876, 4877, 4878, 4879, 4880, - 4881, 4882, 4883, 4884, 4893, 4894, 4895, 4896, 4897, 4898, - 4899, 4900, 4901, 4902, 4903, 4908, 4907, 4915, 4917, 4922, - 4927, 4931, 4936, 4941, 4945, 4949, 4953, 4957, 4961, 4965, - 4971, 4987, 4992, 4998, 5004, 5023, 5044, 5077, 5081, 5086, - 5090, 5094, 5098, 5103, 5108, 5118, 5128, 5133, 5144, 5153, - 5158, 5163, 5191, 5192, 5198, 5199, 5205, 5204, 5227, 5229, - 5234, 5243, 5245, 5251, 5252, 5257, 5261, 5265, 5269, 5273, - 5280, 5284, 5288, 5292, 5299, 5304, 5311, 5316, 5320, 5325, - 5329, 5337, 5348, 5352, 5356, 5370, 5378, 5386, 5393, 5403, - 5426, 5431, 5437, 5442, 5448, 5459, 5465, 5470, 5480, 5490, - 5500, 5512, 5516, 5521, 5533, 5537, 5541, 5545, 5563, 5571, - 5579, 5608, 5618, 5634, 5645, 5650, 5654, 5658, 5670, 5674, - 5686, 5703, 5713, 5717, 5732, 5737, 5744, 5748, 5753, 5767, - 5783, 5787, 5791, 5795, 5799, 5807, 5813, 5819, 5825, 5834, - 5838, 5842, 5850, 5856, 5862, 5866, 5874, 5882, 5889, 5898, - 5902, 5906, 5921, 5935, 5949, 5961, 5977, 5986, 5995, 6005, - 6016, 6024, 6032, 6036, 6055, 6062, 6068, 6075, 6083, 6082, - 6092, 6116, 6118, 6124, 6129, 6131, 6136, 6141, 6146, 6148, - 6152, 6164, 6178, 6182, 6189, 6197, 6205, 6216, 6218, 6221 + 2067, 2093, 2110, 2126, 2144, 2162, 2168, 2176, 2175, 2205, + 2207, 2209, 2211, 2213, 2221, 2223, 2225, 2227, 2235, 2237, + 2239, 2247, 2249, 2251, 2253, 2263, 2279, 2295, 2311, 2327, + 2343, 2380, 2402, 2426, 2427, 2432, 2435, 2439, 2455, 2473, + 2491, 2516, 2535, 2556, 2571, 2587, 2605, 2656, 2677, 2699, + 2722, 2827, 2843, 2878, 2900, 2922, 2928, 2943, 2971, 2983, + 2992, 2999, 3011, 3030, 3034, 3039, 3043, 3048, 3055, 3062, + 3069, 3081, 3154, 3172, 3189, 3204, 3237, 3249, 3273, 3277, + 3282, 3289, 3294, 3304, 3309, 3315, 3323, 3327, 3331, 3340, + 3404, 3420, 3437, 3454, 3476, 3498, 3533, 3541, 3549, 3555, + 3562, 3569, 3589, 3615, 3627, 3638, 3656, 3674, 3693, 3692, + 3717, 3716, 3743, 3742, 3767, 3766, 3789, 3805, 3822, 3839, + 3862, 3865, 3871, 3883, 3903, 3907, 3911, 3915, 3919, 3923, + 3927, 3931, 3940, 3953, 3954, 3955, 3956, 3957, 3961, 3962, + 3963, 3964, 3965, 3968, 3992, 4011, 4034, 4037, 4053, 4056, + 4073, 4076, 4082, 4085, 4092, 4095, 4102, 4124, 4165, 4209, + 4248, 4273, 4282, 4312, 4338, 4364, 4396, 4423, 4449, 4475, + 4501, 4527, 4549, 4560, 4608, 4657, 4669, 4680, 4687, 4702, + 4716, 4717, 4718, 4722, 4728, 4740, 4758, 4786, 4787, 4788, + 4789, 4790, 4791, 4792, 4793, 4794, 4801, 4802, 4803, 4804, + 4805, 4806, 4807, 4808, 4809, 4810, 4811, 4812, 4813, 4814, + 4815, 4816, 4817, 4818, 4819, 4820, 4821, 4822, 4823, 4824, + 4825, 4826, 4827, 4828, 4829, 4830, 4831, 4832, 4833, 4834, + 4835, 4836, 4837, 4838, 4847, 4848, 4849, 4850, 4851, 4852, + 4853, 4854, 4855, 4856, 4857, 4862, 4861, 4869, 4871, 4876, + 4881, 4885, 4890, 4895, 4899, 4903, 4907, 4911, 4915, 4919, + 4925, 4941, 4946, 4952, 4958, 4977, 4998, 5031, 5035, 5040, + 5044, 5048, 5052, 5057, 5062, 5072, 5082, 5087, 5098, 5107, + 5112, 5117, 5145, 5146, 5152, 5153, 5159, 5158, 5181, 5183, + 5188, 5197, 5199, 5205, 5206, 5211, 5215, 5219, 5223, 5227, + 5234, 5238, 5242, 5246, 5253, 5258, 5265, 5270, 5274, 5279, + 5283, 5291, 5302, 5306, 5310, 5324, 5332, 5340, 5347, 5357, + 5380, 5385, 5391, 5396, 5402, 5413, 5419, 5424, 5434, 5444, + 5454, 5466, 5470, 5475, 5487, 5491, 5495, 5499, 5517, 5525, + 5533, 5562, 5572, 5588, 5599, 5604, 5608, 5612, 5624, 5628, + 5640, 5657, 5667, 5671, 5686, 5691, 5698, 5702, 5707, 5721, + 5737, 5741, 5745, 5749, 5753, 5761, 5767, 5773, 5779, 5788, + 5792, 5796, 5804, 5810, 5816, 5820, 5828, 5836, 5843, 5852, + 5856, 5860, 5875, 5889, 5903, 5915, 5931, 5940, 5949, 5959, + 5970, 5978, 5986, 5990, 6009, 6016, 6022, 6029, 6037, 6036, + 6046, 6070, 6072, 6078, 6083, 6085, 6090, 6095, 6100, 6102, + 6106, 6118, 6132, 6136, 6143, 6151, 6159, 6170, 6172, 6175 }; #endif @@ -8615,76 +8615,30 @@ yyreduce: case 185: #line 2163 "Gmsh.y" { - int num = (int)(yyvsp[(4) - (8)].d); - std::vector<int> tags; ListOfDouble2Vector((yyvsp[(7) - (8)].l), tags); - switch ((yyvsp[(2) - (8)].i)) { - case 1: - { - bool r = GModel::current()->getGEOInternals()->addCompoundLine(num, tags); - if(!r) yymsg(0, "Could not add compound line"); - } - (yyval.s).Type = MSH_SEGM_COMPOUND; - break; - case 2: - { - bool r = GModel::current()->getGEOInternals()->addCompoundSurface(num, tags); - if(!r) yymsg(0, "Could not add compound surface"); - } - (yyval.s).Type = MSH_SURF_COMPOUND; - break; - case 3: - { - bool r = GModel::current()->getGEOInternals()->addCompoundVolume(num, tags); - if(!r) yymsg(0, "Could not add compound volume"); - } - (yyval.s).Type = MSH_VOLUME_COMPOUND; - break; - } - List_Delete((yyvsp[(7) - (8)].l)); - (yyval.s).Num = num; + yymsg(0, "Compounds entities are deprecated: use Compound meshing constraints instead"); + (yyval.s).Type = 0; + (yyval.s).Num = 0; ;} break; case 186: -#line 2194 "Gmsh.y" - { - // Particular case only for dim 2 (Surface) - if ((yyvsp[(2) - (12)].i) == 2) { - int num = (int)(yyvsp[(4) - (12)].d); - std::vector<int> tags; ListOfDouble2Vector((yyvsp[(7) - (12)].l), tags); - std::vector<int> bndTags[4]; - for(int i = 0; i < List_Nbr((yyvsp[(10) - (12)].l)); i++){ - if(i < 4) - ListOfDouble2Vector(*(List_T**)List_Pointer((yyvsp[(10) - (12)].l), i), bndTags[i]); - else - break; - } - bool r = GModel::current()->getGEOInternals()->addCompoundSurface - (num, tags, bndTags); - if(!r) yymsg(0, "Could not add compound surface"); - List_Delete((yyvsp[(7) - (12)].l)); - Free((yyvsp[(8) - (12)].c)); - for (int i = 0; i < List_Nbr((yyvsp[(10) - (12)].l)); i++) - List_Delete(*(List_T**)List_Pointer((yyvsp[(10) - (12)].l), i)); - List_Delete((yyvsp[(10) - (12)].l)); - (yyval.s).Type = MSH_SURF_COMPOUND; - (yyval.s).Num = num; - } - else { - yymsg(0, "GeoEntity dim out of range [2,2]"); - } +#line 2170 "Gmsh.y" + { + yymsg(0, "Compounds entities are deprecated: use Compound meshing constraints instead"); + (yyval.s).Type = 0; + (yyval.s).Num = 0; ;} break; case 187: -#line 2222 "Gmsh.y" +#line 2176 "Gmsh.y" { dim_entity = (yyvsp[(2) - (2)].i); ;} break; case 188: -#line 2226 "Gmsh.y" +#line 2180 "Gmsh.y" { int num = (int)(yyvsp[(5) - (9)].i); int op = (yyvsp[(7) - (9)].i); @@ -8710,27 +8664,27 @@ yyreduce: break; case 189: -#line 2252 "Gmsh.y" +#line 2206 "Gmsh.y" { (yyval.i) = 0; ;} break; case 190: -#line 2254 "Gmsh.y" +#line 2208 "Gmsh.y" { (yyval.i) = 1; ;} break; case 191: -#line 2256 "Gmsh.y" +#line 2210 "Gmsh.y" { (yyval.i) = 2; ;} break; case 192: -#line 2258 "Gmsh.y" +#line 2212 "Gmsh.y" { (yyval.i) = 3; ;} break; case 193: -#line 2260 "Gmsh.y" +#line 2214 "Gmsh.y" { (yyval.i) = (int)(yyvsp[(3) - (4)].d); if ((yyval.i)<0 || (yyval.i)>3) yymsg(0, "GeoEntity dim out of range [0,3]"); @@ -8738,22 +8692,22 @@ yyreduce: break; case 194: -#line 2268 "Gmsh.y" +#line 2222 "Gmsh.y" { (yyval.i) = 1; ;} break; case 195: -#line 2270 "Gmsh.y" +#line 2224 "Gmsh.y" { (yyval.i) = 2; ;} break; case 196: -#line 2272 "Gmsh.y" +#line 2226 "Gmsh.y" { (yyval.i) = 3; ;} break; case 197: -#line 2274 "Gmsh.y" +#line 2228 "Gmsh.y" { (yyval.i) = (int)(yyvsp[(3) - (4)].d); if ((yyval.i)<1 || (yyval.i)>3) yymsg(0, "GeoEntity dim out of range [1,3]"); @@ -8761,17 +8715,17 @@ yyreduce: break; case 198: -#line 2282 "Gmsh.y" +#line 2236 "Gmsh.y" { (yyval.i) = 1; ;} break; case 199: -#line 2284 "Gmsh.y" +#line 2238 "Gmsh.y" { (yyval.i) = 2; ;} break; case 200: -#line 2286 "Gmsh.y" +#line 2240 "Gmsh.y" { (yyval.i) = (int)(yyvsp[(3) - (4)].d); if ((yyval.i)<1 || (yyval.i)>2) yymsg(0, "GeoEntity dim out of range [1,2]"); @@ -8779,22 +8733,22 @@ yyreduce: break; case 201: -#line 2294 "Gmsh.y" +#line 2248 "Gmsh.y" { (yyval.i) = 0; ;} break; case 202: -#line 2296 "Gmsh.y" +#line 2250 "Gmsh.y" { (yyval.i) = 1; ;} break; case 203: -#line 2298 "Gmsh.y" +#line 2252 "Gmsh.y" { (yyval.i) = 2; ;} break; case 204: -#line 2300 "Gmsh.y" +#line 2254 "Gmsh.y" { (yyval.i) = (int)(yyvsp[(3) - (4)].d); if ((yyval.i)<0 || (yyval.i)>2) yymsg(0, "GeoEntity dim out of range [0,2]"); @@ -8802,7 +8756,7 @@ yyreduce: break; case 205: -#line 2310 "Gmsh.y" +#line 2264 "Gmsh.y" { std::vector<std::pair<int, int> > dimTags; ListOfShapes2VectorOfPairs((yyvsp[(4) - (5)].l), dimTags); @@ -8821,7 +8775,7 @@ yyreduce: break; case 206: -#line 2326 "Gmsh.y" +#line 2280 "Gmsh.y" { std::vector<std::pair<int, int> > dimTags; ListOfShapes2VectorOfPairs((yyvsp[(10) - (11)].l), dimTags); @@ -8840,7 +8794,7 @@ yyreduce: break; case 207: -#line 2342 "Gmsh.y" +#line 2296 "Gmsh.y" { std::vector<std::pair<int, int> > dimTags; ListOfShapes2VectorOfPairs((yyvsp[(4) - (5)].l), dimTags); @@ -8859,7 +8813,7 @@ yyreduce: break; case 208: -#line 2358 "Gmsh.y" +#line 2312 "Gmsh.y" { std::vector<std::pair<int, int> > dimTags; ListOfShapes2VectorOfPairs((yyvsp[(8) - (9)].l), dimTags); @@ -8878,7 +8832,7 @@ yyreduce: break; case 209: -#line 2374 "Gmsh.y" +#line 2328 "Gmsh.y" { std::vector<std::pair<int, int> > dimTags; ListOfShapes2VectorOfPairs((yyvsp[(8) - (9)].l), dimTags); @@ -8897,7 +8851,7 @@ yyreduce: break; case 210: -#line 2390 "Gmsh.y" +#line 2344 "Gmsh.y" { std::vector<std::pair<int, int> > inDimTags, outDimTags; ListOfShapes2VectorOfPairs((yyvsp[(3) - (4)].l), inDimTags); @@ -8937,7 +8891,7 @@ yyreduce: break; case 211: -#line 2427 "Gmsh.y" +#line 2381 "Gmsh.y" { (yyval.l) = List_Create(2, 1, sizeof(Shape)); bool r = true; @@ -8961,7 +8915,7 @@ yyreduce: break; case 212: -#line 2449 "Gmsh.y" +#line 2403 "Gmsh.y" { (yyval.l) = List_Create(2, 1, sizeof(Shape)); bool r = true; @@ -8985,31 +8939,31 @@ yyreduce: break; case 213: -#line 2472 "Gmsh.y" +#line 2426 "Gmsh.y" { (yyval.l) = (yyvsp[(1) - (1)].l); ;} break; case 214: -#line 2473 "Gmsh.y" +#line 2427 "Gmsh.y" { (yyval.l) = (yyvsp[(1) - (1)].l); ;} break; case 215: -#line 2478 "Gmsh.y" +#line 2432 "Gmsh.y" { (yyval.l) = List_Create(3, 3, sizeof(Shape)); ;} break; case 216: -#line 2482 "Gmsh.y" +#line 2436 "Gmsh.y" { List_Add((yyval.l), &(yyvsp[(2) - (2)].s)); ;} break; case 217: -#line 2486 "Gmsh.y" +#line 2440 "Gmsh.y" { for(int i = 0; i < List_Nbr((yyvsp[(4) - (6)].l)); i++){ double d; @@ -9028,7 +8982,7 @@ yyreduce: break; case 218: -#line 2502 "Gmsh.y" +#line 2456 "Gmsh.y" { List_T *tmp = List_Create(10, 10, sizeof(double)); getElementaryTagsForPhysicalGroups((yyvsp[(3) - (7)].i), (yyvsp[(5) - (7)].l), tmp); @@ -9049,7 +9003,7 @@ yyreduce: break; case 219: -#line 2520 "Gmsh.y" +#line 2474 "Gmsh.y" { List_T *tmp = List_Create(10, 10, sizeof(double)); getAllElementaryTags((yyvsp[(2) - (6)].i), tmp); @@ -9070,7 +9024,7 @@ yyreduce: break; case 220: -#line 2538 "Gmsh.y" +#line 2492 "Gmsh.y" { List_T *tmp = List_Create(10, 10, sizeof(double)); List_T *tmp2 = List_Create(10, 10, sizeof(double)); @@ -9093,7 +9047,7 @@ yyreduce: break; case 221: -#line 2563 "Gmsh.y" +#line 2517 "Gmsh.y" { if(List_Nbr((yyvsp[(7) - (8)].l)) == 4){ int t = (int)(yyvsp[(4) - (8)].d); @@ -9115,7 +9069,7 @@ yyreduce: break; case 222: -#line 2582 "Gmsh.y" +#line 2536 "Gmsh.y" { int t = (int)(yyvsp[(4) - (10)].d); if(gLevelset::find(t)){ @@ -9139,7 +9093,7 @@ yyreduce: break; case 223: -#line 2604 "Gmsh.y" +#line 2558 "Gmsh.y" { int t = (int)(yyvsp[(4) - (14)].d); if(gLevelset::find(t)){ @@ -9156,7 +9110,7 @@ yyreduce: break; case 224: -#line 2619 "Gmsh.y" +#line 2573 "Gmsh.y" { int t = (int)(yyvsp[(4) - (16)].d); if(gLevelset::find(t)){ @@ -9174,7 +9128,7 @@ yyreduce: break; case 225: -#line 2634 "Gmsh.y" +#line 2588 "Gmsh.y" { if(List_Nbr((yyvsp[(10) - (12)].l)) == 1){ int t = (int)(yyvsp[(4) - (12)].d); @@ -9195,7 +9149,7 @@ yyreduce: break; case 226: -#line 2653 "Gmsh.y" +#line 2607 "Gmsh.y" { if(List_Nbr((yyvsp[(12) - (14)].l)) == 1){ int t = (int)(yyvsp[(4) - (14)].d); @@ -9248,7 +9202,7 @@ yyreduce: break; case 227: -#line 2704 "Gmsh.y" +#line 2658 "Gmsh.y" { if(List_Nbr((yyvsp[(12) - (14)].l)) == 1){ int t = (int)(yyvsp[(4) - (14)].d); @@ -9271,7 +9225,7 @@ yyreduce: break; case 228: -#line 2725 "Gmsh.y" +#line 2679 "Gmsh.y" { if(List_Nbr((yyvsp[(12) - (14)].l)) == 3){ int t = (int)(yyvsp[(4) - (14)].d); @@ -9295,7 +9249,7 @@ yyreduce: break; case 229: -#line 2747 "Gmsh.y" +#line 2701 "Gmsh.y" { if(List_Nbr((yyvsp[(12) - (14)].l)) == 5){ int t = (int)(yyvsp[(4) - (14)].d); @@ -9320,7 +9274,7 @@ yyreduce: break; case 230: -#line 2769 "Gmsh.y" +#line 2723 "Gmsh.y" { if(!strcmp((yyvsp[(2) - (8)].c), "Union")){ int t = (int)(yyvsp[(4) - (8)].d); @@ -9428,7 +9382,7 @@ yyreduce: break; case 231: -#line 2874 "Gmsh.y" +#line 2828 "Gmsh.y" { if(!strcmp((yyvsp[(2) - (8)].c), "MathEval")){ int t = (int)(yyvsp[(4) - (8)].d); @@ -9447,7 +9401,7 @@ yyreduce: break; case 232: -#line 2890 "Gmsh.y" +#line 2844 "Gmsh.y" { if(!strcmp((yyvsp[(2) - (6)].c), "CutMesh")){ int t = (int)(yyvsp[(4) - (6)].d); @@ -9480,7 +9434,7 @@ yyreduce: break; case 233: -#line 2925 "Gmsh.y" +#line 2879 "Gmsh.y" { std::vector<std::pair<int, int> > dimTags; ListOfShapes2VectorOfPairs((yyvsp[(3) - (4)].l), dimTags); @@ -9505,7 +9459,7 @@ yyreduce: break; case 234: -#line 2947 "Gmsh.y" +#line 2901 "Gmsh.y" { std::vector<std::pair<int, int> > dimTags; ListOfShapes2VectorOfPairs((yyvsp[(4) - (5)].l), dimTags); @@ -9530,7 +9484,7 @@ yyreduce: break; case 235: -#line 2969 "Gmsh.y" +#line 2923 "Gmsh.y" { #if defined(HAVE_MESH) GModel::current()->getFields()->deleteField((int)(yyvsp[(4) - (6)].d)); @@ -9539,7 +9493,7 @@ yyreduce: break; case 236: -#line 2975 "Gmsh.y" +#line 2929 "Gmsh.y" { #if defined(HAVE_POST) if(!strcmp((yyvsp[(2) - (6)].c), "View")){ @@ -9557,7 +9511,7 @@ yyreduce: break; case 237: -#line 2990 "Gmsh.y" +#line 2944 "Gmsh.y" { if(!strcmp((yyvsp[(2) - (3)].c), "Meshes") || !strcmp((yyvsp[(2) - (3)].c), "All")){ ClearProject(); @@ -9588,7 +9542,7 @@ yyreduce: break; case 238: -#line 3018 "Gmsh.y" +#line 2972 "Gmsh.y" { #if defined(HAVE_POST) if(!strcmp((yyvsp[(2) - (4)].c), "Empty") && !strcmp((yyvsp[(3) - (4)].c), "Views")){ @@ -9603,14 +9557,14 @@ yyreduce: break; case 239: -#line 3030 "Gmsh.y" +#line 2984 "Gmsh.y" { gmsh_yynamespaces.clear(); ;} break; case 240: -#line 3039 "Gmsh.y" +#line 2993 "Gmsh.y" { std::vector<std::pair<int, int> > dimTags; ListOfShapes2VectorOfPairs((yyvsp[(4) - (5)].l), dimTags); @@ -9620,7 +9574,7 @@ yyreduce: break; case 241: -#line 3046 "Gmsh.y" +#line 3000 "Gmsh.y" { std::vector<std::pair<int, int> > dimTags; ListOfShapes2VectorOfPairs((yyvsp[(5) - (6)].l), dimTags); @@ -9630,7 +9584,7 @@ yyreduce: break; case 242: -#line 3058 "Gmsh.y" +#line 3012 "Gmsh.y" { std::vector<std::pair<int, int> > dimTags; ListOfShapes2VectorOfPairs((yyvsp[(4) - (5)].l), dimTags); @@ -9647,14 +9601,14 @@ yyreduce: break; case 243: -#line 3077 "Gmsh.y" +#line 3031 "Gmsh.y" { setVisibility(-1, 1, false); ;} break; case 244: -#line 3081 "Gmsh.y" +#line 3035 "Gmsh.y" { setVisibility(-1, 1, false); Free((yyvsp[(2) - (3)].c)); @@ -9662,14 +9616,14 @@ yyreduce: break; case 245: -#line 3086 "Gmsh.y" +#line 3040 "Gmsh.y" { setVisibility(-1, 0, false); ;} break; case 246: -#line 3090 "Gmsh.y" +#line 3044 "Gmsh.y" { setVisibility(-1, 0, false); Free((yyvsp[(2) - (3)].c)); @@ -9677,7 +9631,7 @@ yyreduce: break; case 247: -#line 3095 "Gmsh.y" +#line 3049 "Gmsh.y" { std::vector<std::pair<int, int> > dimTags; ListOfShapes2VectorOfPairs((yyvsp[(3) - (4)].l), dimTags); @@ -9687,7 +9641,7 @@ yyreduce: break; case 248: -#line 3102 "Gmsh.y" +#line 3056 "Gmsh.y" { std::vector<std::pair<int, int> > dimTags; ListOfShapes2VectorOfPairs((yyvsp[(4) - (5)].l), dimTags); @@ -9697,7 +9651,7 @@ yyreduce: break; case 249: -#line 3109 "Gmsh.y" +#line 3063 "Gmsh.y" { std::vector<std::pair<int, int> > dimTags; ListOfShapes2VectorOfPairs((yyvsp[(3) - (4)].l), dimTags); @@ -9707,7 +9661,7 @@ yyreduce: break; case 250: -#line 3116 "Gmsh.y" +#line 3070 "Gmsh.y" { std::vector<std::pair<int, int> > dimTags; ListOfShapes2VectorOfPairs((yyvsp[(4) - (5)].l), dimTags); @@ -9717,7 +9671,7 @@ yyreduce: break; case 251: -#line 3128 "Gmsh.y" +#line 3082 "Gmsh.y" { if(!strcmp((yyvsp[(1) - (3)].c), "Include")){ std::string tmp = FixRelativePath(gmsh_yyname, (yyvsp[(2) - (3)].c)); @@ -9793,7 +9747,7 @@ yyreduce: break; case 252: -#line 3201 "Gmsh.y" +#line 3155 "Gmsh.y" { int n = List_Nbr((yyvsp[(3) - (5)].l)); if(n == 1){ @@ -9814,7 +9768,7 @@ yyreduce: break; case 253: -#line 3219 "Gmsh.y" +#line 3173 "Gmsh.y" { #if defined(HAVE_POST) if(!strcmp((yyvsp[(1) - (7)].c), "Save") && !strcmp((yyvsp[(2) - (7)].c), "View")){ @@ -9834,7 +9788,7 @@ yyreduce: break; case 254: -#line 3236 "Gmsh.y" +#line 3190 "Gmsh.y" { #if defined(HAVE_POST) && defined(HAVE_MESH) if(!strcmp((yyvsp[(1) - (7)].c), "Background") && !strcmp((yyvsp[(2) - (7)].c), "Mesh") && !strcmp((yyvsp[(3) - (7)].c), "View")){ @@ -9852,7 +9806,7 @@ yyreduce: break; case 255: -#line 3251 "Gmsh.y" +#line 3205 "Gmsh.y" { if(!strcmp((yyvsp[(1) - (3)].c), "Sleep")){ SleepInSeconds((yyvsp[(2) - (3)].d)); @@ -9888,7 +9842,7 @@ yyreduce: break; case 256: -#line 3284 "Gmsh.y" +#line 3238 "Gmsh.y" { #if defined(HAVE_PLUGINS) try { @@ -9903,7 +9857,7 @@ yyreduce: break; case 257: -#line 3296 "Gmsh.y" +#line 3250 "Gmsh.y" { #if defined(HAVE_POST) if(!strcmp((yyvsp[(2) - (3)].c), "ElementsFromAllViews")) @@ -9930,14 +9884,14 @@ yyreduce: break; case 258: -#line 3320 "Gmsh.y" +#line 3274 "Gmsh.y" { Msg::Exit(0); ;} break; case 259: -#line 3324 "Gmsh.y" +#line 3278 "Gmsh.y" { gmsh_yyerrorstate = 999; // this will be checked when yyparse returns YYABORT; @@ -9945,7 +9899,7 @@ yyreduce: break; case 260: -#line 3329 "Gmsh.y" +#line 3283 "Gmsh.y" { // force sync if(GModel::current()->getOCCInternals()) @@ -9955,7 +9909,7 @@ yyreduce: break; case 261: -#line 3336 "Gmsh.y" +#line 3290 "Gmsh.y" { new GModel(); GModel::current(GModel::list.size() - 1); @@ -9963,7 +9917,7 @@ yyreduce: break; case 262: -#line 3341 "Gmsh.y" +#line 3295 "Gmsh.y" { CTX::instance()->forcedBBox = 0; if(GModel::current()->getOCCInternals() && @@ -9976,7 +9930,7 @@ yyreduce: break; case 263: -#line 3351 "Gmsh.y" +#line 3305 "Gmsh.y" { CTX::instance()->forcedBBox = 1; SetBoundingBox((yyvsp[(3) - (15)].d), (yyvsp[(5) - (15)].d), (yyvsp[(7) - (15)].d), (yyvsp[(9) - (15)].d), (yyvsp[(11) - (15)].d), (yyvsp[(13) - (15)].d)); @@ -9984,7 +9938,7 @@ yyreduce: break; case 264: -#line 3356 "Gmsh.y" +#line 3310 "Gmsh.y" { #if defined(HAVE_OPENGL) drawContext::global()->draw(); @@ -9993,7 +9947,7 @@ yyreduce: break; case 265: -#line 3362 "Gmsh.y" +#line 3316 "Gmsh.y" { #if defined(HAVE_OPENGL) CTX::instance()->mesh.changed = ENT_ALL; @@ -10004,21 +9958,21 @@ yyreduce: break; case 266: -#line 3370 "Gmsh.y" +#line 3324 "Gmsh.y" { GModel::current()->createTopologyFromMesh(); ;} break; case 267: -#line 3374 "Gmsh.y" +#line 3328 "Gmsh.y" { GModel::current()->createTopologyFromMesh(1); ;} break; case 268: -#line 3378 "Gmsh.y" +#line 3332 "Gmsh.y" { if(GModel::current()->getOCCInternals() && GModel::current()->getOCCInternals()->getChanged()) @@ -10030,7 +9984,7 @@ yyreduce: break; case 269: -#line 3388 "Gmsh.y" +#line 3342 "Gmsh.y" { int lock = CTX::instance()->lock; CTX::instance()->lock = 0; @@ -10091,7 +10045,7 @@ yyreduce: break; case 270: -#line 3451 "Gmsh.y" +#line 3405 "Gmsh.y" { #if defined(HAVE_POPPLER) std::vector<int> is; @@ -10106,7 +10060,7 @@ yyreduce: break; case 271: -#line 3467 "Gmsh.y" +#line 3421 "Gmsh.y" { LoopControlVariablesTab[ImbricatedLoop][0] = (yyvsp[(3) - (6)].d); LoopControlVariablesTab[ImbricatedLoop][1] = (yyvsp[(5) - (6)].d); @@ -10126,7 +10080,7 @@ yyreduce: break; case 272: -#line 3484 "Gmsh.y" +#line 3438 "Gmsh.y" { LoopControlVariablesTab[ImbricatedLoop][0] = (yyvsp[(3) - (8)].d); LoopControlVariablesTab[ImbricatedLoop][1] = (yyvsp[(5) - (8)].d); @@ -10146,7 +10100,7 @@ yyreduce: break; case 273: -#line 3501 "Gmsh.y" +#line 3455 "Gmsh.y" { LoopControlVariablesTab[ImbricatedLoop][0] = (yyvsp[(5) - (8)].d); LoopControlVariablesTab[ImbricatedLoop][1] = (yyvsp[(7) - (8)].d); @@ -10171,7 +10125,7 @@ yyreduce: break; case 274: -#line 3523 "Gmsh.y" +#line 3477 "Gmsh.y" { LoopControlVariablesTab[ImbricatedLoop][0] = (yyvsp[(5) - (10)].d); LoopControlVariablesTab[ImbricatedLoop][1] = (yyvsp[(7) - (10)].d); @@ -10196,7 +10150,7 @@ yyreduce: break; case 275: -#line 3545 "Gmsh.y" +#line 3499 "Gmsh.y" { if(ImbricatedLoop <= 0){ yymsg(0, "Invalid For/EndFor loop"); @@ -10234,7 +10188,7 @@ yyreduce: break; case 276: -#line 3580 "Gmsh.y" +#line 3534 "Gmsh.y" { if(!FunctionManager::Instance()->createFunction (std::string((yyvsp[(2) - (2)].c)), gmsh_yyin, gmsh_yyname, gmsh_yylineno)) @@ -10245,7 +10199,7 @@ yyreduce: break; case 277: -#line 3588 "Gmsh.y" +#line 3542 "Gmsh.y" { if(!FunctionManager::Instance()->createFunction (std::string((yyvsp[(2) - (2)].c)), gmsh_yyin, gmsh_yyname, gmsh_yylineno)) @@ -10256,7 +10210,7 @@ yyreduce: break; case 278: -#line 3596 "Gmsh.y" +#line 3550 "Gmsh.y" { if(!FunctionManager::Instance()->leaveFunction (&gmsh_yyin, gmsh_yyname, gmsh_yylineno)) @@ -10265,7 +10219,7 @@ yyreduce: break; case 279: -#line 3602 "Gmsh.y" +#line 3556 "Gmsh.y" { if(!FunctionManager::Instance()->enterFunction (std::string((yyvsp[(2) - (3)].c)), &gmsh_yyin, gmsh_yyname, gmsh_yylineno)) @@ -10275,7 +10229,7 @@ yyreduce: break; case 280: -#line 3609 "Gmsh.y" +#line 3563 "Gmsh.y" { if(!FunctionManager::Instance()->enterFunction (std::string((yyvsp[(2) - (3)].c)), &gmsh_yyin, gmsh_yyname, gmsh_yylineno)) @@ -10285,7 +10239,7 @@ yyreduce: break; case 281: -#line 3616 "Gmsh.y" +#line 3570 "Gmsh.y" { ImbricatedTest++; if(ImbricatedTest > MAX_RECUR_TESTS-1){ @@ -10308,7 +10262,7 @@ yyreduce: break; case 282: -#line 3636 "Gmsh.y" +#line 3590 "Gmsh.y" { if(ImbricatedTest > 0){ if (statusImbricatedTests[ImbricatedTest]){ @@ -10337,7 +10291,7 @@ yyreduce: break; case 283: -#line 3662 "Gmsh.y" +#line 3616 "Gmsh.y" { if(ImbricatedTest > 0){ if(statusImbricatedTests[ImbricatedTest]){ @@ -10352,7 +10306,7 @@ yyreduce: break; case 284: -#line 3674 "Gmsh.y" +#line 3628 "Gmsh.y" { ImbricatedTest--; if(ImbricatedTest < 0) @@ -10361,7 +10315,7 @@ yyreduce: break; case 285: -#line 3685 "Gmsh.y" +#line 3639 "Gmsh.y" { std::vector<std::pair<int, int> > inDimTags, outDimTags; ListOfShapes2VectorOfPairs((yyvsp[(4) - (5)].l), inDimTags); @@ -10382,7 +10336,7 @@ yyreduce: break; case 286: -#line 3703 "Gmsh.y" +#line 3657 "Gmsh.y" { std::vector<std::pair<int, int> > inDimTags, outDimTags; ListOfShapes2VectorOfPairs((yyvsp[(10) - (11)].l), inDimTags); @@ -10403,7 +10357,7 @@ yyreduce: break; case 287: -#line 3721 "Gmsh.y" +#line 3675 "Gmsh.y" { std::vector<std::pair<int, int> > inDimTags, outDimTags; ListOfShapes2VectorOfPairs((yyvsp[(12) - (13)].l), inDimTags); @@ -10424,7 +10378,7 @@ yyreduce: break; case 288: -#line 3739 "Gmsh.y" +#line 3693 "Gmsh.y" { extr.mesh.ExtrudeMesh = extr.mesh.Recombine = false; extr.mesh.QuadToTri = NO_QUADTRI; @@ -10433,7 +10387,7 @@ yyreduce: break; case 289: -#line 3745 "Gmsh.y" +#line 3699 "Gmsh.y" { std::vector<std::pair<int, int> > inDimTags, outDimTags; ListOfShapes2VectorOfPairs((yyvsp[(4) - (7)].l), inDimTags); @@ -10454,7 +10408,7 @@ yyreduce: break; case 290: -#line 3763 "Gmsh.y" +#line 3717 "Gmsh.y" { extr.mesh.ExtrudeMesh = extr.mesh.Recombine = false; extr.mesh.QuadToTri = NO_QUADTRI; @@ -10463,7 +10417,7 @@ yyreduce: break; case 291: -#line 3769 "Gmsh.y" +#line 3723 "Gmsh.y" { std::vector<std::pair<int, int> > inDimTags, outDimTags; ListOfShapes2VectorOfPairs((yyvsp[(10) - (13)].l), inDimTags); @@ -10486,7 +10440,7 @@ yyreduce: break; case 292: -#line 3789 "Gmsh.y" +#line 3743 "Gmsh.y" { extr.mesh.ExtrudeMesh = extr.mesh.Recombine = false; extr.mesh.QuadToTri = NO_QUADTRI; @@ -10495,7 +10449,7 @@ yyreduce: break; case 293: -#line 3795 "Gmsh.y" +#line 3749 "Gmsh.y" { std::vector<std::pair<int, int> > inDimTags, outDimTags; ListOfShapes2VectorOfPairs((yyvsp[(12) - (15)].l), inDimTags); @@ -10516,7 +10470,7 @@ yyreduce: break; case 294: -#line 3813 "Gmsh.y" +#line 3767 "Gmsh.y" { extr.mesh.ExtrudeMesh = extr.mesh.Recombine = false; extr.mesh.QuadToTri = NO_QUADTRI; @@ -10525,7 +10479,7 @@ yyreduce: break; case 295: -#line 3819 "Gmsh.y" +#line 3773 "Gmsh.y" { std::vector<std::pair<int, int> > inDimTags, outDimTags; ListOfShapes2VectorOfPairs((yyvsp[(3) - (6)].l), inDimTags); @@ -10545,7 +10499,7 @@ yyreduce: break; case 296: -#line 3836 "Gmsh.y" +#line 3790 "Gmsh.y" { std::vector<std::pair<int, int> > inDimTags, outDimTags; ListOfShapes2VectorOfPairs((yyvsp[(3) - (9)].l), inDimTags); @@ -10564,7 +10518,7 @@ yyreduce: break; case 297: -#line 3852 "Gmsh.y" +#line 3806 "Gmsh.y" { (yyval.l) = List_Create(2, 1, sizeof(Shape)); bool r = true; @@ -10584,7 +10538,7 @@ yyreduce: break; case 298: -#line 3869 "Gmsh.y" +#line 3823 "Gmsh.y" { (yyval.l) = List_Create(2, 1, sizeof(Shape)); bool r = true; @@ -10604,7 +10558,7 @@ yyreduce: break; case 299: -#line 3886 "Gmsh.y" +#line 3840 "Gmsh.y" { (yyval.l) = List_Create(2, 1, sizeof(Shape)); bool r = true; @@ -10627,19 +10581,19 @@ yyreduce: break; case 300: -#line 3909 "Gmsh.y" +#line 3863 "Gmsh.y" { ;} break; case 301: -#line 3912 "Gmsh.y" +#line 3866 "Gmsh.y" { ;} break; case 302: -#line 3918 "Gmsh.y" +#line 3872 "Gmsh.y" { int n = (int)fabs((yyvsp[(3) - (5)].d)); if(n){ // we accept n==0 to easily disable layers @@ -10654,7 +10608,7 @@ yyreduce: break; case 303: -#line 3930 "Gmsh.y" +#line 3884 "Gmsh.y" { extr.mesh.ExtrudeMesh = true; extr.mesh.NbLayer = List_Nbr((yyvsp[(3) - (7)].l)); @@ -10677,56 +10631,56 @@ yyreduce: break; case 304: -#line 3950 "Gmsh.y" +#line 3904 "Gmsh.y" { extr.mesh.ScaleLast = true; ;} break; case 305: -#line 3954 "Gmsh.y" +#line 3908 "Gmsh.y" { extr.mesh.Recombine = true; ;} break; case 306: -#line 3958 "Gmsh.y" +#line 3912 "Gmsh.y" { extr.mesh.Recombine = (yyvsp[(2) - (3)].d) ? true : false; ;} break; case 307: -#line 3962 "Gmsh.y" +#line 3916 "Gmsh.y" { extr.mesh.QuadToTri = QUADTRI_ADDVERTS_1; ;} break; case 308: -#line 3966 "Gmsh.y" +#line 3920 "Gmsh.y" { extr.mesh.QuadToTri = QUADTRI_ADDVERTS_1_RECOMB; ;} break; case 309: -#line 3970 "Gmsh.y" +#line 3924 "Gmsh.y" { extr.mesh.QuadToTri = QUADTRI_NOVERTS_1; ;} break; case 310: -#line 3974 "Gmsh.y" +#line 3928 "Gmsh.y" { extr.mesh.QuadToTri = QUADTRI_NOVERTS_1_RECOMB; ;} break; case 311: -#line 3978 "Gmsh.y" +#line 3932 "Gmsh.y" { std::vector<int> tags; ListOfDouble2Vector((yyvsp[(6) - (9)].l), tags); int num = (int)(yyvsp[(3) - (9)].d); @@ -10738,7 +10692,7 @@ yyreduce: break; case 312: -#line 3987 "Gmsh.y" +#line 3941 "Gmsh.y" { if(!strcmp((yyvsp[(2) - (6)].c), "Index")) extr.mesh.BoundaryLayerIndex = (yyvsp[(4) - (6)].d); @@ -10749,57 +10703,57 @@ yyreduce: break; case 313: -#line 3999 "Gmsh.y" +#line 3953 "Gmsh.y" { (yyval.i) = OCC_Internals::Union; ;} break; case 314: -#line 4000 "Gmsh.y" +#line 3954 "Gmsh.y" { (yyval.i) = OCC_Internals::Intersection; ;} break; case 315: -#line 4001 "Gmsh.y" +#line 3955 "Gmsh.y" { (yyval.i) = OCC_Internals::Difference; ;} break; case 316: -#line 4002 "Gmsh.y" +#line 3956 "Gmsh.y" { (yyval.i) = OCC_Internals::Section; ;} break; case 317: -#line 4003 "Gmsh.y" +#line 3957 "Gmsh.y" { (yyval.i) = OCC_Internals::Fragments; ;} break; case 318: -#line 4007 "Gmsh.y" +#line 3961 "Gmsh.y" { (yyval.i) = 0; ;} break; case 319: -#line 4008 "Gmsh.y" +#line 3962 "Gmsh.y" { (yyval.i) = 1; ;} break; case 320: -#line 4009 "Gmsh.y" +#line 3963 "Gmsh.y" { (yyval.i) = 2; ;} break; case 321: -#line 4010 "Gmsh.y" +#line 3964 "Gmsh.y" { (yyval.i) = (yyvsp[(2) - (3)].d) ? 1 : 0; ;} break; case 322: -#line 4011 "Gmsh.y" +#line 3965 "Gmsh.y" { (yyval.i) = (yyvsp[(3) - (4)].d) ? 2 : 0; ;} break; case 323: -#line 4016 "Gmsh.y" +#line 3970 "Gmsh.y" { (yyval.l) = List_Create(2, 1, sizeof(Shape)); bool r = true; @@ -10825,7 +10779,7 @@ yyreduce: break; case 324: -#line 4039 "Gmsh.y" +#line 3993 "Gmsh.y" { (yyval.l) = List_Create(2, 1, sizeof(Shape)); bool r = true; @@ -10844,7 +10798,7 @@ yyreduce: break; case 325: -#line 4059 "Gmsh.y" +#line 4013 "Gmsh.y" { bool r = true; if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){ @@ -10865,14 +10819,14 @@ yyreduce: break; case 326: -#line 4080 "Gmsh.y" +#line 4034 "Gmsh.y" { (yyval.v)[0] = (yyval.v)[1] = 1.; ;} break; case 327: -#line 4084 "Gmsh.y" +#line 4038 "Gmsh.y" { if(!strcmp((yyvsp[(2) - (3)].c), "Progression") || !strcmp((yyvsp[(2) - (3)].c), "Power")) (yyval.v)[0] = 1.; @@ -10888,14 +10842,14 @@ yyreduce: break; case 328: -#line 4099 "Gmsh.y" +#line 4053 "Gmsh.y" { (yyval.i) = -1; // left ;} break; case 329: -#line 4103 "Gmsh.y" +#line 4057 "Gmsh.y" { if(!strcmp((yyvsp[(1) - (1)].c), "Right")) (yyval.i) = 1; @@ -10912,49 +10866,49 @@ yyreduce: break; case 330: -#line 4119 "Gmsh.y" +#line 4073 "Gmsh.y" { (yyval.l) = List_Create(1, 1, sizeof(double)); ;} break; case 331: -#line 4123 "Gmsh.y" +#line 4077 "Gmsh.y" { (yyval.l) = (yyvsp[(2) - (2)].l); ;} break; case 332: -#line 4128 "Gmsh.y" +#line 4082 "Gmsh.y" { (yyval.i) = 45; ;} break; case 333: -#line 4132 "Gmsh.y" +#line 4086 "Gmsh.y" { (yyval.i) = (int)(yyvsp[(2) - (2)].d); ;} break; case 334: -#line 4138 "Gmsh.y" +#line 4092 "Gmsh.y" { (yyval.l) = List_Create(1, 1, sizeof(double)); ;} break; case 335: -#line 4142 "Gmsh.y" +#line 4096 "Gmsh.y" { (yyval.l) = (yyvsp[(2) - (2)].l); ;} break; case 336: -#line 4149 "Gmsh.y" +#line 4103 "Gmsh.y" { // mesh sizes at vertices are stored in internal CAD data, as they can be // specified during vertex creation and copied around during CAD @@ -10979,7 +10933,7 @@ yyreduce: break; case 337: -#line 4171 "Gmsh.y" +#line 4125 "Gmsh.y" { // transfinite constraints are stored in GEO internals in addition to // GModel, as they can be copied around during GEO operations @@ -11023,7 +10977,7 @@ yyreduce: break; case 338: -#line 4212 "Gmsh.y" +#line 4166 "Gmsh.y" { // transfinite constraints are stored in GEO internals in addition to // GModel, as they can be copied around during GEO operations @@ -11070,7 +11024,7 @@ yyreduce: break; case 339: -#line 4256 "Gmsh.y" +#line 4210 "Gmsh.y" { // transfinite constraints are stored in GEO internals in addition to // GModel, as they can be copied around during GEO operations @@ -11112,7 +11066,7 @@ yyreduce: break; case 340: -#line 4295 "Gmsh.y" +#line 4249 "Gmsh.y" { // transfinite constraints are stored in GEO internals in addition to // GModel, as they can be copied around during GEO operations @@ -11140,7 +11094,7 @@ yyreduce: break; case 341: -#line 4320 "Gmsh.y" +#line 4274 "Gmsh.y" { for(int i = 0; i < List_Nbr((yyvsp[(4) - (8)].l)); i++){ double d; @@ -11152,7 +11106,7 @@ yyreduce: break; case 342: -#line 4329 "Gmsh.y" +#line 4283 "Gmsh.y" { // recombine constraints are stored in GEO internals in addition to // GModel, as they can be copied around during GEO operations @@ -11185,7 +11139,7 @@ yyreduce: break; case 343: -#line 4359 "Gmsh.y" +#line 4313 "Gmsh.y" { // recombine constraints are stored in GEO internals in addition to // GModel, as they can be copied around during GEO operations @@ -11214,7 +11168,7 @@ yyreduce: break; case 344: -#line 4385 "Gmsh.y" +#line 4339 "Gmsh.y" { // smoothing constraints are stored in GEO internals in addition to // GModel, as they can be copied around during GEO operations @@ -11243,7 +11197,7 @@ yyreduce: break; case 345: -#line 4412 "Gmsh.y" +#line 4366 "Gmsh.y" { if (List_Nbr((yyvsp[(4) - (11)].l)) != List_Nbr((yyvsp[(8) - (11)].l))){ yymsg(0, "Number of master lines (%d) different from number of " @@ -11277,7 +11231,7 @@ yyreduce: break; case 346: -#line 4444 "Gmsh.y" +#line 4398 "Gmsh.y" { if (List_Nbr((yyvsp[(4) - (11)].l)) != List_Nbr((yyvsp[(8) - (11)].l))){ yymsg(0, "Number of master faces (%d) different from number of " @@ -11306,7 +11260,7 @@ yyreduce: break; case 347: -#line 4471 "Gmsh.y" +#line 4425 "Gmsh.y" { if (List_Nbr((yyvsp[(4) - (18)].l)) != List_Nbr((yyvsp[(8) - (18)].l))){ yymsg(0, "Number of master edges (%d) different from number of " @@ -11334,7 +11288,7 @@ yyreduce: break; case 348: -#line 4497 "Gmsh.y" +#line 4451 "Gmsh.y" { if (List_Nbr((yyvsp[(4) - (18)].l)) != List_Nbr((yyvsp[(8) - (18)].l))){ yymsg(0, "Number of master faces (%d) different from number of " @@ -11362,7 +11316,7 @@ yyreduce: break; case 349: -#line 4523 "Gmsh.y" +#line 4477 "Gmsh.y" { if (List_Nbr((yyvsp[(4) - (12)].l)) != List_Nbr((yyvsp[(8) - (12)].l))){ yymsg(0, "Number of master edges (%d) different from number of " @@ -11390,7 +11344,7 @@ yyreduce: break; case 350: -#line 4549 "Gmsh.y" +#line 4503 "Gmsh.y" { if (List_Nbr((yyvsp[(4) - (12)].l)) != List_Nbr((yyvsp[(8) - (12)].l))){ yymsg(0, "Number of master faces (%d) different from number of " @@ -11418,7 +11372,7 @@ yyreduce: break; case 351: -#line 4575 "Gmsh.y" +#line 4529 "Gmsh.y" { if (List_Nbr((yyvsp[(5) - (12)].l)) != List_Nbr((yyvsp[(10) - (12)].l))){ yymsg(0, "Number of master surface edges (%d) different from number of " @@ -11442,7 +11396,7 @@ yyreduce: break; case 352: -#line 4596 "Gmsh.y" +#line 4550 "Gmsh.y" { if (((yyvsp[(6) - (10)].i)==2 || (yyvsp[(6) - (10)].i)==3) && (yyvsp[(1) - (10)].i)<(yyvsp[(6) - (10)].i) ) { std::vector<int> tags; ListOfDouble2Vector((yyvsp[(3) - (10)].l), tags); @@ -11456,7 +11410,7 @@ yyreduce: break; case 353: -#line 4607 "Gmsh.y" +#line 4561 "Gmsh.y" { // reverse mesh constraints are stored in GEO internals in addition to // GModel, as they can be copied around during GEO operations @@ -11507,7 +11461,7 @@ yyreduce: break; case 354: -#line 4655 "Gmsh.y" +#line 4609 "Gmsh.y" { if(!(yyvsp[(3) - (4)].l)){ switch ((yyvsp[(2) - (4)].i)) { @@ -11559,7 +11513,7 @@ yyreduce: break; case 355: -#line 4704 "Gmsh.y" +#line 4658 "Gmsh.y" { for(int i = 0; i < List_Nbr((yyvsp[(3) - (4)].l)); i++){ double dnum; @@ -11574,7 +11528,7 @@ yyreduce: break; case 356: -#line 4716 "Gmsh.y" +#line 4670 "Gmsh.y" { std::vector<int> tags; ListOfDouble2Vector((yyvsp[(3) - (4)].l), tags); GModel::current()->getGEOInternals()->setCompoundMesh((yyvsp[(2) - (4)].i), tags); @@ -11583,7 +11537,7 @@ yyreduce: break; case 357: -#line 4727 "Gmsh.y" +#line 4681 "Gmsh.y" { if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()) GModel::current()->getOCCInternals()->removeAllDuplicates(); @@ -11593,7 +11547,7 @@ yyreduce: break; case 358: -#line 4734 "Gmsh.y" +#line 4688 "Gmsh.y" { if(!strcmp((yyvsp[(2) - (3)].c), "Geometry")){ if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()) @@ -11611,7 +11565,7 @@ yyreduce: break; case 359: -#line 4749 "Gmsh.y" +#line 4703 "Gmsh.y" { std::vector<int> tags; ListOfDouble2Vector((yyvsp[(4) - (6)].l), tags); if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()) @@ -11623,22 +11577,22 @@ yyreduce: break; case 360: -#line 4762 "Gmsh.y" +#line 4716 "Gmsh.y" { (yyval.c) = (char*)"Homology"; ;} break; case 361: -#line 4763 "Gmsh.y" +#line 4717 "Gmsh.y" { (yyval.c) = (char*)"Cohomology"; ;} break; case 362: -#line 4764 "Gmsh.y" +#line 4718 "Gmsh.y" { (yyval.c) = (char*)"Betti"; ;} break; case 363: -#line 4769 "Gmsh.y" +#line 4723 "Gmsh.y" { std::vector<int> domain, subdomain, dim; for(int i = 0; i < 4; i++) dim.push_back(i); @@ -11647,7 +11601,7 @@ yyreduce: break; case 364: -#line 4775 "Gmsh.y" +#line 4729 "Gmsh.y" { std::vector<int> domain, subdomain, dim; for(int i = 0; i < List_Nbr((yyvsp[(3) - (5)].l)); i++){ @@ -11662,7 +11616,7 @@ yyreduce: break; case 365: -#line 4787 "Gmsh.y" +#line 4741 "Gmsh.y" { std::vector<int> domain, subdomain, dim; for(int i = 0; i < List_Nbr((yyvsp[(3) - (7)].l)); i++){ @@ -11683,7 +11637,7 @@ yyreduce: break; case 366: -#line 4805 "Gmsh.y" +#line 4759 "Gmsh.y" { std::vector<int> domain, subdomain, dim; for(int i = 0; i < List_Nbr((yyvsp[(6) - (10)].l)); i++){ @@ -11709,47 +11663,47 @@ yyreduce: break; case 367: -#line 4832 "Gmsh.y" +#line 4786 "Gmsh.y" { (yyval.d) = (yyvsp[(1) - (1)].d); ;} break; case 368: -#line 4833 "Gmsh.y" +#line 4787 "Gmsh.y" { (yyval.d) = (yyvsp[(2) - (3)].d); ;} break; case 369: -#line 4834 "Gmsh.y" +#line 4788 "Gmsh.y" { (yyval.d) = -(yyvsp[(2) - (2)].d); ;} break; case 370: -#line 4835 "Gmsh.y" +#line 4789 "Gmsh.y" { (yyval.d) = (yyvsp[(2) - (2)].d); ;} break; case 371: -#line 4836 "Gmsh.y" +#line 4790 "Gmsh.y" { (yyval.d) = !(yyvsp[(2) - (2)].d); ;} break; case 372: -#line 4837 "Gmsh.y" +#line 4791 "Gmsh.y" { (yyval.d) = (yyvsp[(1) - (3)].d) - (yyvsp[(3) - (3)].d); ;} break; case 373: -#line 4838 "Gmsh.y" +#line 4792 "Gmsh.y" { (yyval.d) = (yyvsp[(1) - (3)].d) + (yyvsp[(3) - (3)].d); ;} break; case 374: -#line 4839 "Gmsh.y" +#line 4793 "Gmsh.y" { (yyval.d) = (yyvsp[(1) - (3)].d) * (yyvsp[(3) - (3)].d); ;} break; case 375: -#line 4841 "Gmsh.y" +#line 4795 "Gmsh.y" { if(!(yyvsp[(3) - (3)].d)) yymsg(0, "Division by zero in '%g / %g'", (yyvsp[(1) - (3)].d), (yyvsp[(3) - (3)].d)); @@ -11759,257 +11713,257 @@ yyreduce: break; case 376: -#line 4847 "Gmsh.y" +#line 4801 "Gmsh.y" { (yyval.d) = (int)(yyvsp[(1) - (3)].d) | (int)(yyvsp[(3) - (3)].d); ;} break; case 377: -#line 4848 "Gmsh.y" +#line 4802 "Gmsh.y" { (yyval.d) = (int)(yyvsp[(1) - (3)].d) & (int)(yyvsp[(3) - (3)].d); ;} break; case 378: -#line 4849 "Gmsh.y" +#line 4803 "Gmsh.y" { (yyval.d) = (int)(yyvsp[(1) - (3)].d) % (int)(yyvsp[(3) - (3)].d); ;} break; case 379: -#line 4850 "Gmsh.y" +#line 4804 "Gmsh.y" { (yyval.d) = pow((yyvsp[(1) - (3)].d), (yyvsp[(3) - (3)].d)); ;} break; case 380: -#line 4851 "Gmsh.y" +#line 4805 "Gmsh.y" { (yyval.d) = (yyvsp[(1) - (3)].d) < (yyvsp[(3) - (3)].d); ;} break; case 381: -#line 4852 "Gmsh.y" +#line 4806 "Gmsh.y" { (yyval.d) = (yyvsp[(1) - (3)].d) > (yyvsp[(3) - (3)].d); ;} break; case 382: -#line 4853 "Gmsh.y" +#line 4807 "Gmsh.y" { (yyval.d) = (yyvsp[(1) - (3)].d) <= (yyvsp[(3) - (3)].d); ;} break; case 383: -#line 4854 "Gmsh.y" +#line 4808 "Gmsh.y" { (yyval.d) = (yyvsp[(1) - (3)].d) >= (yyvsp[(3) - (3)].d); ;} break; case 384: -#line 4855 "Gmsh.y" +#line 4809 "Gmsh.y" { (yyval.d) = (yyvsp[(1) - (3)].d) == (yyvsp[(3) - (3)].d); ;} break; case 385: -#line 4856 "Gmsh.y" +#line 4810 "Gmsh.y" { (yyval.d) = (yyvsp[(1) - (3)].d) != (yyvsp[(3) - (3)].d); ;} break; case 386: -#line 4857 "Gmsh.y" +#line 4811 "Gmsh.y" { (yyval.d) = (yyvsp[(1) - (3)].d) && (yyvsp[(3) - (3)].d); ;} break; case 387: -#line 4858 "Gmsh.y" +#line 4812 "Gmsh.y" { (yyval.d) = (yyvsp[(1) - (3)].d) || (yyvsp[(3) - (3)].d); ;} break; case 388: -#line 4859 "Gmsh.y" +#line 4813 "Gmsh.y" { (yyval.d) = ((int)(yyvsp[(1) - (3)].d) >> (int)(yyvsp[(3) - (3)].d)); ;} break; case 389: -#line 4860 "Gmsh.y" +#line 4814 "Gmsh.y" { (yyval.d) = ((int)(yyvsp[(1) - (3)].d) << (int)(yyvsp[(3) - (3)].d)); ;} break; case 390: -#line 4861 "Gmsh.y" +#line 4815 "Gmsh.y" { (yyval.d) = (yyvsp[(1) - (5)].d) ? (yyvsp[(3) - (5)].d) : (yyvsp[(5) - (5)].d); ;} break; case 391: -#line 4862 "Gmsh.y" +#line 4816 "Gmsh.y" { (yyval.d) = exp((yyvsp[(3) - (4)].d)); ;} break; case 392: -#line 4863 "Gmsh.y" +#line 4817 "Gmsh.y" { (yyval.d) = log((yyvsp[(3) - (4)].d)); ;} break; case 393: -#line 4864 "Gmsh.y" +#line 4818 "Gmsh.y" { (yyval.d) = log10((yyvsp[(3) - (4)].d)); ;} break; case 394: -#line 4865 "Gmsh.y" +#line 4819 "Gmsh.y" { (yyval.d) = sqrt((yyvsp[(3) - (4)].d)); ;} break; case 395: -#line 4866 "Gmsh.y" +#line 4820 "Gmsh.y" { (yyval.d) = sin((yyvsp[(3) - (4)].d)); ;} break; case 396: -#line 4867 "Gmsh.y" +#line 4821 "Gmsh.y" { (yyval.d) = asin((yyvsp[(3) - (4)].d)); ;} break; case 397: -#line 4868 "Gmsh.y" +#line 4822 "Gmsh.y" { (yyval.d) = cos((yyvsp[(3) - (4)].d)); ;} break; case 398: -#line 4869 "Gmsh.y" +#line 4823 "Gmsh.y" { (yyval.d) = acos((yyvsp[(3) - (4)].d)); ;} break; case 399: -#line 4870 "Gmsh.y" +#line 4824 "Gmsh.y" { (yyval.d) = tan((yyvsp[(3) - (4)].d)); ;} break; case 400: -#line 4871 "Gmsh.y" +#line 4825 "Gmsh.y" { (yyval.d) = atan((yyvsp[(3) - (4)].d)); ;} break; case 401: -#line 4872 "Gmsh.y" +#line 4826 "Gmsh.y" { (yyval.d) = atan2((yyvsp[(3) - (6)].d), (yyvsp[(5) - (6)].d));;} break; case 402: -#line 4873 "Gmsh.y" +#line 4827 "Gmsh.y" { (yyval.d) = sinh((yyvsp[(3) - (4)].d)); ;} break; case 403: -#line 4874 "Gmsh.y" +#line 4828 "Gmsh.y" { (yyval.d) = cosh((yyvsp[(3) - (4)].d)); ;} break; case 404: -#line 4875 "Gmsh.y" +#line 4829 "Gmsh.y" { (yyval.d) = tanh((yyvsp[(3) - (4)].d)); ;} break; case 405: -#line 4876 "Gmsh.y" +#line 4830 "Gmsh.y" { (yyval.d) = fabs((yyvsp[(3) - (4)].d)); ;} break; case 406: -#line 4877 "Gmsh.y" +#line 4831 "Gmsh.y" { (yyval.d) = std::abs((yyvsp[(3) - (4)].d)); ;} break; case 407: -#line 4878 "Gmsh.y" +#line 4832 "Gmsh.y" { (yyval.d) = floor((yyvsp[(3) - (4)].d)); ;} break; case 408: -#line 4879 "Gmsh.y" +#line 4833 "Gmsh.y" { (yyval.d) = ceil((yyvsp[(3) - (4)].d)); ;} break; case 409: -#line 4880 "Gmsh.y" +#line 4834 "Gmsh.y" { (yyval.d) = floor((yyvsp[(3) - (4)].d) + 0.5); ;} break; case 410: -#line 4881 "Gmsh.y" +#line 4835 "Gmsh.y" { (yyval.d) = fmod((yyvsp[(3) - (6)].d), (yyvsp[(5) - (6)].d)); ;} break; case 411: -#line 4882 "Gmsh.y" +#line 4836 "Gmsh.y" { (yyval.d) = fmod((yyvsp[(3) - (6)].d), (yyvsp[(5) - (6)].d)); ;} break; case 412: -#line 4883 "Gmsh.y" +#line 4837 "Gmsh.y" { (yyval.d) = sqrt((yyvsp[(3) - (6)].d) * (yyvsp[(3) - (6)].d) + (yyvsp[(5) - (6)].d) * (yyvsp[(5) - (6)].d)); ;} break; case 413: -#line 4884 "Gmsh.y" +#line 4838 "Gmsh.y" { (yyval.d) = (yyvsp[(3) - (4)].d) * (double)rand() / (double)RAND_MAX; ;} break; case 414: -#line 4893 "Gmsh.y" +#line 4847 "Gmsh.y" { (yyval.d) = (yyvsp[(1) - (1)].d); ;} break; case 415: -#line 4894 "Gmsh.y" +#line 4848 "Gmsh.y" { (yyval.d) = 3.141592653589793; ;} break; case 416: -#line 4895 "Gmsh.y" +#line 4849 "Gmsh.y" { (yyval.d) = (double)ImbricatedTest; ;} break; case 417: -#line 4896 "Gmsh.y" +#line 4850 "Gmsh.y" { (yyval.d) = Msg::GetCommRank(); ;} break; case 418: -#line 4897 "Gmsh.y" +#line 4851 "Gmsh.y" { (yyval.d) = Msg::GetCommSize(); ;} break; case 419: -#line 4898 "Gmsh.y" +#line 4852 "Gmsh.y" { (yyval.d) = GetGmshMajorVersion(); ;} break; case 420: -#line 4899 "Gmsh.y" +#line 4853 "Gmsh.y" { (yyval.d) = GetGmshMinorVersion(); ;} break; case 421: -#line 4900 "Gmsh.y" +#line 4854 "Gmsh.y" { (yyval.d) = GetGmshPatchVersion(); ;} break; case 422: -#line 4901 "Gmsh.y" +#line 4855 "Gmsh.y" { (yyval.d) = Cpu(); ;} break; case 423: -#line 4902 "Gmsh.y" +#line 4856 "Gmsh.y" { (yyval.d) = GetMemoryUsage()/1024./1024.; ;} break; case 424: -#line 4903 "Gmsh.y" +#line 4857 "Gmsh.y" { (yyval.d) = TotalRam(); ;} break; case 425: -#line 4908 "Gmsh.y" +#line 4862 "Gmsh.y" { init_options(); ;} break; case 426: -#line 4910 "Gmsh.y" +#line 4864 "Gmsh.y" { std::vector<double> val(1, (yyvsp[(3) - (6)].d)); Msg::ExchangeOnelabParameter("", val, floatOptions, charOptions); @@ -12018,12 +11972,12 @@ yyreduce: break; case 427: -#line 4916 "Gmsh.y" +#line 4870 "Gmsh.y" { (yyval.d) = (yyvsp[(1) - (1)].d); ;} break; case 428: -#line 4918 "Gmsh.y" +#line 4872 "Gmsh.y" { (yyval.d) = Msg::GetOnelabNumber((yyvsp[(3) - (4)].c)); Free((yyvsp[(3) - (4)].c)); @@ -12031,7 +11985,7 @@ yyreduce: break; case 429: -#line 4923 "Gmsh.y" +#line 4877 "Gmsh.y" { (yyval.d) = Msg::GetOnelabNumber((yyvsp[(3) - (6)].c), (yyvsp[(5) - (6)].d)); Free((yyvsp[(3) - (6)].c)); @@ -12039,70 +11993,70 @@ yyreduce: break; case 430: -#line 4928 "Gmsh.y" +#line 4882 "Gmsh.y" { (yyval.d) = treat_Struct_FullName_Float((yyvsp[(1) - (1)].c2).char1, (yyvsp[(1) - (1)].c2).char2); ;} break; case 431: -#line 4933 "Gmsh.y" +#line 4887 "Gmsh.y" { (yyval.d) = treat_Struct_FullName_Float(NULL, (yyvsp[(1) - (4)].c), 2, (int)(yyvsp[(3) - (4)].d)); ;} break; case 432: -#line 4938 "Gmsh.y" +#line 4892 "Gmsh.y" { (yyval.d) = treat_Struct_FullName_Float(NULL, (yyvsp[(1) - (4)].c), 2, (int)(yyvsp[(3) - (4)].d)); ;} break; case 433: -#line 4942 "Gmsh.y" +#line 4896 "Gmsh.y" { (yyval.d) = treat_Struct_FullName_Float((yyvsp[(3) - (4)].c2).char1, (yyvsp[(3) - (4)].c2).char2, 1, 0, 0., 1); ;} break; case 434: -#line 4946 "Gmsh.y" +#line 4900 "Gmsh.y" { (yyval.d) = treat_Struct_FullName_dot_tSTRING_Float((yyvsp[(3) - (6)].c2).char1, (yyvsp[(3) - (6)].c2).char2, (yyvsp[(5) - (6)].c), 0, 0., 1); ;} break; case 435: -#line 4950 "Gmsh.y" +#line 4904 "Gmsh.y" { (yyval.d) = treat_Struct_FullName_Float((yyvsp[(3) - (5)].c2).char1, (yyvsp[(3) - (5)].c2).char2, 1, 0, (yyvsp[(4) - (5)].d), 2); ;} break; case 436: -#line 4954 "Gmsh.y" +#line 4908 "Gmsh.y" { (yyval.d) = treat_Struct_FullName_dot_tSTRING_Float((yyvsp[(3) - (7)].c2).char1, (yyvsp[(3) - (7)].c2).char2, (yyvsp[(5) - (7)].c), 0, (yyvsp[(6) - (7)].d), 2); ;} break; case 437: -#line 4958 "Gmsh.y" +#line 4912 "Gmsh.y" { (yyval.d) = treat_Struct_FullName_Float((yyvsp[(3) - (8)].c2).char1, (yyvsp[(3) - (8)].c2).char2, 2, (int)(yyvsp[(5) - (8)].d), (yyvsp[(7) - (8)].d), 2); ;} break; case 438: -#line 4962 "Gmsh.y" +#line 4916 "Gmsh.y" { (yyval.d) = treat_Struct_FullName_dot_tSTRING_Float((yyvsp[(3) - (10)].c2).char1, (yyvsp[(3) - (10)].c2).char2, (yyvsp[(5) - (10)].c), (int)(yyvsp[(7) - (10)].d), (yyvsp[(9) - (10)].d), 2); ;} break; case 439: -#line 4966 "Gmsh.y" +#line 4920 "Gmsh.y" { std::string tmp = FixRelativePath(gmsh_yyname, (yyvsp[(3) - (4)].c)); (yyval.d) = !StatFile(tmp); @@ -12111,7 +12065,7 @@ yyreduce: break; case 440: -#line 4972 "Gmsh.y" +#line 4926 "Gmsh.y" { if(gmsh_yysymbols.count((yyvsp[(2) - (4)].c))){ gmsh_yysymbol &s(gmsh_yysymbols[(yyvsp[(2) - (4)].c)]); @@ -12129,14 +12083,14 @@ yyreduce: break; case 441: -#line 4988 "Gmsh.y" +#line 4942 "Gmsh.y" { (yyval.d) = treat_Struct_FullName_dot_tSTRING_Float_getDim((yyvsp[(2) - (6)].c2).char1, (yyvsp[(2) - (6)].c2).char2, (yyvsp[(4) - (6)].c)); ;} break; case 442: -#line 4993 "Gmsh.y" +#line 4947 "Gmsh.y" { std::string struct_namespace((yyvsp[(3) - (4)].c)); (yyval.d) = (double)gmsh_yynamespaces[struct_namespace].size(); @@ -12145,7 +12099,7 @@ yyreduce: break; case 443: -#line 4999 "Gmsh.y" +#line 4953 "Gmsh.y" { std::string struct_namespace(std::string("")); (yyval.d) = (double)gmsh_yynamespaces[struct_namespace].size(); @@ -12153,7 +12107,7 @@ yyreduce: break; case 444: -#line 5005 "Gmsh.y" +#line 4959 "Gmsh.y" { if(!gmsh_yysymbols.count((yyvsp[(1) - (2)].c))){ yymsg(0, "Unknown variable '%s'", (yyvsp[(1) - (2)].c)); @@ -12175,7 +12129,7 @@ yyreduce: break; case 445: -#line 5024 "Gmsh.y" +#line 4978 "Gmsh.y" { int index = (int)(yyvsp[(3) - (5)].d); if(!gmsh_yysymbols.count((yyvsp[(1) - (5)].c))){ @@ -12198,7 +12152,7 @@ yyreduce: break; case 446: -#line 5045 "Gmsh.y" +#line 4999 "Gmsh.y" { int index = (int)(yyvsp[(3) - (5)].d); if(!gmsh_yysymbols.count((yyvsp[(1) - (5)].c))){ @@ -12221,49 +12175,49 @@ yyreduce: break; case 447: -#line 5078 "Gmsh.y" +#line 5032 "Gmsh.y" { (yyval.d) = treat_Struct_FullName_dot_tSTRING_Float(NULL, (yyvsp[(1) - (3)].c), (yyvsp[(3) - (3)].c)); ;} break; case 448: -#line 5082 "Gmsh.y" +#line 5036 "Gmsh.y" { (yyval.d) = treat_Struct_FullName_dot_tSTRING_Float((yyvsp[(1) - (5)].c), (yyvsp[(3) - (5)].c), (yyvsp[(5) - (5)].c)); ;} break; case 449: -#line 5087 "Gmsh.y" +#line 5041 "Gmsh.y" { (yyval.d) = treat_Struct_FullName_dot_tSTRING_Float(NULL, (yyvsp[(1) - (6)].c), (yyvsp[(3) - (6)].c), (int)(yyvsp[(5) - (6)].d)); ;} break; case 450: -#line 5091 "Gmsh.y" +#line 5045 "Gmsh.y" { (yyval.d) = treat_Struct_FullName_dot_tSTRING_Float((yyvsp[(1) - (8)].c), (yyvsp[(3) - (8)].c), (yyvsp[(5) - (8)].c), (int)(yyvsp[(7) - (8)].d)); ;} break; case 451: -#line 5095 "Gmsh.y" +#line 5049 "Gmsh.y" { (yyval.d) = treat_Struct_FullName_dot_tSTRING_Float(NULL, (yyvsp[(1) - (6)].c), (yyvsp[(3) - (6)].c), (int)(yyvsp[(5) - (6)].d)); ;} break; case 452: -#line 5099 "Gmsh.y" +#line 5053 "Gmsh.y" { (yyval.d) = treat_Struct_FullName_dot_tSTRING_Float((yyvsp[(1) - (8)].c), (yyvsp[(3) - (8)].c), (yyvsp[(5) - (8)].c), (int)(yyvsp[(7) - (8)].d)); ;} break; case 453: -#line 5104 "Gmsh.y" +#line 5058 "Gmsh.y" { NumberOption(GMSH_GET, (yyvsp[(1) - (6)].c), (int)(yyvsp[(3) - (6)].d), (yyvsp[(6) - (6)].c), (yyval.d)); Free((yyvsp[(1) - (6)].c)); Free((yyvsp[(6) - (6)].c)); @@ -12271,7 +12225,7 @@ yyreduce: break; case 454: -#line 5109 "Gmsh.y" +#line 5063 "Gmsh.y" { double d = 0.; if(NumberOption(GMSH_GET, (yyvsp[(1) - (4)].c), 0, (yyvsp[(3) - (4)].c), d)){ @@ -12284,7 +12238,7 @@ yyreduce: break; case 455: -#line 5119 "Gmsh.y" +#line 5073 "Gmsh.y" { double d = 0.; if(NumberOption(GMSH_GET, (yyvsp[(1) - (7)].c), (int)(yyvsp[(3) - (7)].d), (yyvsp[(6) - (7)].c), d)){ @@ -12297,7 +12251,7 @@ yyreduce: break; case 456: -#line 5129 "Gmsh.y" +#line 5083 "Gmsh.y" { (yyval.d) = Msg::GetValue((yyvsp[(3) - (6)].c), (yyvsp[(5) - (6)].d)); Free((yyvsp[(3) - (6)].c)); @@ -12305,7 +12259,7 @@ yyreduce: break; case 457: -#line 5134 "Gmsh.y" +#line 5088 "Gmsh.y" { int matches = 0; for(int i = 0; i < List_Nbr((yyvsp[(3) - (6)].l)); i++){ @@ -12319,7 +12273,7 @@ yyreduce: break; case 458: -#line 5145 "Gmsh.y" +#line 5099 "Gmsh.y" { std::string s((yyvsp[(3) - (6)].c)), substr((yyvsp[(5) - (6)].c)); if(s.find(substr) != std::string::npos) @@ -12331,7 +12285,7 @@ yyreduce: break; case 459: -#line 5154 "Gmsh.y" +#line 5108 "Gmsh.y" { (yyval.d) = strlen((yyvsp[(3) - (4)].c)); Free((yyvsp[(3) - (4)].c)); @@ -12339,7 +12293,7 @@ yyreduce: break; case 460: -#line 5159 "Gmsh.y" +#line 5113 "Gmsh.y" { (yyval.d) = strcmp((yyvsp[(3) - (6)].c), (yyvsp[(5) - (6)].c)); Free((yyvsp[(3) - (6)].c)); Free((yyvsp[(5) - (6)].c)); @@ -12347,7 +12301,7 @@ yyreduce: break; case 461: -#line 5164 "Gmsh.y" +#line 5118 "Gmsh.y" { int align = 0, font = 0, fontsize = CTX::instance()->glFontSize; if(List_Nbr((yyvsp[(3) - (4)].l)) % 2){ @@ -12374,27 +12328,27 @@ yyreduce: break; case 462: -#line 5191 "Gmsh.y" +#line 5145 "Gmsh.y" { (yyval.d) = 0.; ;} break; case 463: -#line 5193 "Gmsh.y" +#line 5147 "Gmsh.y" { (yyval.d) = (yyvsp[(2) - (2)].d);;} break; case 464: -#line 5198 "Gmsh.y" +#line 5152 "Gmsh.y" { (yyval.c) = NULL; ;} break; case 465: -#line 5200 "Gmsh.y" +#line 5154 "Gmsh.y" { (yyval.c) = (yyvsp[(2) - (2)].c);;} break; case 466: -#line 5205 "Gmsh.y" +#line 5159 "Gmsh.y" { std::string struct_namespace((yyvsp[(2) - (3)].c2).char1? (yyvsp[(2) - (3)].c2).char1 : std::string("")), struct_name((yyvsp[(2) - (3)].c2).char2); @@ -12404,7 +12358,7 @@ yyreduce: break; case 467: -#line 5212 "Gmsh.y" +#line 5166 "Gmsh.y" { std::string struct_namespace((yyvsp[(2) - (7)].c2).char1? (yyvsp[(2) - (7)].c2).char1 : std::string("")), struct_name((yyvsp[(2) - (7)].c2).char2); @@ -12420,105 +12374,105 @@ yyreduce: break; case 468: -#line 5228 "Gmsh.y" +#line 5182 "Gmsh.y" { (yyval.c2).char1 = NULL; (yyval.c2).char2 = (yyvsp[(1) - (1)].c); ;} break; case 469: -#line 5230 "Gmsh.y" +#line 5184 "Gmsh.y" { (yyval.c2).char1 = (yyvsp[(1) - (3)].c); (yyval.c2).char2 = (yyvsp[(3) - (3)].c); ;} break; case 470: -#line 5235 "Gmsh.y" +#line 5189 "Gmsh.y" { (yyval.c) = (yyvsp[(1) - (1)].c); flag_tSTRING_alloc = 1; ;} break; case 471: -#line 5244 "Gmsh.y" +#line 5198 "Gmsh.y" { (yyval.i) = 99; ;} break; case 472: -#line 5246 "Gmsh.y" +#line 5200 "Gmsh.y" { (yyval.i) = (int)(yyvsp[(2) - (2)].d); ;} break; case 473: -#line 5251 "Gmsh.y" +#line 5205 "Gmsh.y" { (yyval.i) = 0; ;} break; case 474: -#line 5253 "Gmsh.y" +#line 5207 "Gmsh.y" { (yyval.i) = (yyvsp[(2) - (3)].i); ;} break; case 475: -#line 5258 "Gmsh.y" +#line 5212 "Gmsh.y" { memcpy((yyval.v), (yyvsp[(1) - (1)].v), 5*sizeof(double)); ;} break; case 476: -#line 5262 "Gmsh.y" +#line 5216 "Gmsh.y" { for(int i = 0; i < 5; i++) (yyval.v)[i] = -(yyvsp[(2) - (2)].v)[i]; ;} break; case 477: -#line 5266 "Gmsh.y" +#line 5220 "Gmsh.y" { for(int i = 0; i < 5; i++) (yyval.v)[i] = (yyvsp[(2) - (2)].v)[i]; ;} break; case 478: -#line 5270 "Gmsh.y" +#line 5224 "Gmsh.y" { for(int i = 0; i < 5; i++) (yyval.v)[i] = (yyvsp[(1) - (3)].v)[i] - (yyvsp[(3) - (3)].v)[i]; ;} break; case 479: -#line 5274 "Gmsh.y" +#line 5228 "Gmsh.y" { for(int i = 0; i < 5; i++) (yyval.v)[i] = (yyvsp[(1) - (3)].v)[i] + (yyvsp[(3) - (3)].v)[i]; ;} break; case 480: -#line 5281 "Gmsh.y" +#line 5235 "Gmsh.y" { (yyval.v)[0] = (yyvsp[(2) - (11)].d); (yyval.v)[1] = (yyvsp[(4) - (11)].d); (yyval.v)[2] = (yyvsp[(6) - (11)].d); (yyval.v)[3] = (yyvsp[(8) - (11)].d); (yyval.v)[4] = (yyvsp[(10) - (11)].d); ;} break; case 481: -#line 5285 "Gmsh.y" +#line 5239 "Gmsh.y" { (yyval.v)[0] = (yyvsp[(2) - (9)].d); (yyval.v)[1] = (yyvsp[(4) - (9)].d); (yyval.v)[2] = (yyvsp[(6) - (9)].d); (yyval.v)[3] = (yyvsp[(8) - (9)].d); (yyval.v)[4] = 1.0; ;} break; case 482: -#line 5289 "Gmsh.y" +#line 5243 "Gmsh.y" { (yyval.v)[0] = (yyvsp[(2) - (7)].d); (yyval.v)[1] = (yyvsp[(4) - (7)].d); (yyval.v)[2] = (yyvsp[(6) - (7)].d); (yyval.v)[3] = 0.0; (yyval.v)[4] = 1.0; ;} break; case 483: -#line 5293 "Gmsh.y" +#line 5247 "Gmsh.y" { (yyval.v)[0] = (yyvsp[(2) - (7)].d); (yyval.v)[1] = (yyvsp[(4) - (7)].d); (yyval.v)[2] = (yyvsp[(6) - (7)].d); (yyval.v)[3] = 0.0; (yyval.v)[4] = 1.0; ;} break; case 484: -#line 5300 "Gmsh.y" +#line 5254 "Gmsh.y" { (yyval.l) = List_Create(2, 1, sizeof(List_T*)); List_Add((yyval.l), &((yyvsp[(1) - (1)].l))); @@ -12526,14 +12480,14 @@ yyreduce: break; case 485: -#line 5305 "Gmsh.y" +#line 5259 "Gmsh.y" { List_Add((yyval.l), &((yyvsp[(3) - (3)].l))); ;} break; case 486: -#line 5312 "Gmsh.y" +#line 5266 "Gmsh.y" { (yyval.l) = List_Create(2, 1, sizeof(double)); List_Add((yyval.l), &((yyvsp[(1) - (1)].d))); @@ -12541,14 +12495,14 @@ yyreduce: break; case 487: -#line 5317 "Gmsh.y" +#line 5271 "Gmsh.y" { (yyval.l) = (yyvsp[(1) - (1)].l); ;} break; case 488: -#line 5321 "Gmsh.y" +#line 5275 "Gmsh.y" { // creates an empty list (yyval.l) = List_Create(2, 1, sizeof(double)); @@ -12556,14 +12510,14 @@ yyreduce: break; case 489: -#line 5326 "Gmsh.y" +#line 5280 "Gmsh.y" { (yyval.l) = (yyvsp[(2) - (3)].l); ;} break; case 490: -#line 5330 "Gmsh.y" +#line 5284 "Gmsh.y" { (yyval.l) = (yyvsp[(3) - (4)].l); for(int i = 0; i < List_Nbr((yyval.l)); i++){ @@ -12574,7 +12528,7 @@ yyreduce: break; case 491: -#line 5338 "Gmsh.y" +#line 5292 "Gmsh.y" { (yyval.l) = (yyvsp[(4) - (5)].l); for(int i = 0; i < List_Nbr((yyval.l)); i++){ @@ -12585,21 +12539,21 @@ yyreduce: break; case 492: -#line 5349 "Gmsh.y" +#line 5303 "Gmsh.y" { (yyval.l) = (yyvsp[(1) - (1)].l); ;} break; case 493: -#line 5353 "Gmsh.y" +#line 5307 "Gmsh.y" { (yyval.l) = 0; ;} break; case 494: -#line 5357 "Gmsh.y" +#line 5311 "Gmsh.y" { if(!strcmp((yyvsp[(1) - (1)].c), "*") || !strcmp((yyvsp[(1) - (1)].c), "all")){ (yyval.l) = 0; @@ -12613,7 +12567,7 @@ yyreduce: break; case 495: -#line 5371 "Gmsh.y" +#line 5325 "Gmsh.y" { (yyval.l) = (yyvsp[(2) - (2)].l); for(int i = 0; i < List_Nbr((yyval.l)); i++){ @@ -12624,7 +12578,7 @@ yyreduce: break; case 496: -#line 5379 "Gmsh.y" +#line 5333 "Gmsh.y" { (yyval.l) = (yyvsp[(3) - (3)].l); for(int i = 0; i < List_Nbr((yyval.l)); i++){ @@ -12635,7 +12589,7 @@ yyreduce: break; case 497: -#line 5387 "Gmsh.y" +#line 5341 "Gmsh.y" { (yyval.l) = List_Create(2, 1, sizeof(double)); for(double d = (yyvsp[(1) - (3)].d); ((yyvsp[(1) - (3)].d) < (yyvsp[(3) - (3)].d)) ? (d <= (yyvsp[(3) - (3)].d)) : (d >= (yyvsp[(3) - (3)].d)); @@ -12645,7 +12599,7 @@ yyreduce: break; case 498: -#line 5394 "Gmsh.y" +#line 5348 "Gmsh.y" { (yyval.l) = List_Create(2, 1, sizeof(double)); if(!(yyvsp[(5) - (5)].d)){ //|| ($1 < $3 && $5 < 0) || ($1 > $3 && $5 > 0) @@ -12658,7 +12612,7 @@ yyreduce: break; case 499: -#line 5404 "Gmsh.y" +#line 5358 "Gmsh.y" { (yyval.l) = List_Create(3, 1, sizeof(double)); int tag = (int)(yyvsp[(3) - (4)].d); @@ -12684,7 +12638,7 @@ yyreduce: break; case 500: -#line 5427 "Gmsh.y" +#line 5381 "Gmsh.y" { (yyval.l) = List_Create(10, 10, sizeof(double)); getAllElementaryTags(0, (yyval.l)); @@ -12692,7 +12646,7 @@ yyreduce: break; case 501: -#line 5432 "Gmsh.y" +#line 5386 "Gmsh.y" { (yyval.l) = List_Create(10, 10, sizeof(double)); getAllElementaryTags(0, (yyval.l)); @@ -12701,7 +12655,7 @@ yyreduce: break; case 502: -#line 5438 "Gmsh.y" +#line 5392 "Gmsh.y" { (yyval.l) = List_Create(10, 10, sizeof(double)); getAllElementaryTags((yyvsp[(1) - (4)].i), (yyval.l)); @@ -12709,7 +12663,7 @@ yyreduce: break; case 503: -#line 5443 "Gmsh.y" +#line 5397 "Gmsh.y" { (yyval.l) = List_Create(10, 10, sizeof(double)); getAllElementaryTags((yyvsp[(1) - (2)].i), (yyval.l)); @@ -12718,7 +12672,7 @@ yyreduce: break; case 504: -#line 5449 "Gmsh.y" +#line 5403 "Gmsh.y" { (yyval.l) = List_Create(10, 10, sizeof(double)); if(!(yyvsp[(3) - (3)].l)){ @@ -12732,7 +12686,7 @@ yyreduce: break; case 505: -#line 5461 "Gmsh.y" +#line 5415 "Gmsh.y" { (yyval.l) = List_Create(10, 10, sizeof(double)); getElementaryTagsInBoundingBox((yyvsp[(1) - (16)].i), (yyvsp[(5) - (16)].d), (yyvsp[(7) - (16)].d), (yyvsp[(9) - (16)].d), (yyvsp[(11) - (16)].d), (yyvsp[(13) - (16)].d), (yyvsp[(15) - (16)].d), (yyval.l)); @@ -12740,7 +12694,7 @@ yyreduce: break; case 506: -#line 5466 "Gmsh.y" +#line 5420 "Gmsh.y" { (yyval.l) = List_Create(10, 10, sizeof(double)); getBoundingBox((yyvsp[(2) - (5)].i), (int)(yyvsp[(4) - (5)].d), (yyval.l)); @@ -12748,7 +12702,7 @@ yyreduce: break; case 507: -#line 5471 "Gmsh.y" +#line 5425 "Gmsh.y" { (yyval.l) = List_Create(List_Nbr((yyvsp[(1) - (1)].l)), 1, sizeof(double)); for(int i = 0; i < List_Nbr((yyvsp[(1) - (1)].l)); i++){ @@ -12761,7 +12715,7 @@ yyreduce: break; case 508: -#line 5481 "Gmsh.y" +#line 5435 "Gmsh.y" { (yyval.l) = List_Create(List_Nbr((yyvsp[(1) - (1)].l)), 1, sizeof(double)); for(int i = 0; i < List_Nbr((yyvsp[(1) - (1)].l)); i++){ @@ -12774,7 +12728,7 @@ yyreduce: break; case 509: -#line 5491 "Gmsh.y" +#line 5445 "Gmsh.y" { (yyval.l) = List_Create(List_Nbr((yyvsp[(1) - (1)].l)), 1, sizeof(double)); for(int i = 0; i < List_Nbr((yyvsp[(1) - (1)].l)); i++){ @@ -12787,7 +12741,7 @@ yyreduce: break; case 510: -#line 5501 "Gmsh.y" +#line 5455 "Gmsh.y" { (yyval.l) = List_Create(20, 20, sizeof(double)); if(!gmsh_yysymbols.count((yyvsp[(1) - (3)].c))) @@ -12802,21 +12756,21 @@ yyreduce: break; case 511: -#line 5513 "Gmsh.y" +#line 5467 "Gmsh.y" { (yyval.l) = treat_Struct_FullName_dot_tSTRING_ListOfFloat(NULL, (yyvsp[(1) - (5)].c), (yyvsp[(3) - (5)].c)); ;} break; case 512: -#line 5517 "Gmsh.y" +#line 5471 "Gmsh.y" { (yyval.l) = treat_Struct_FullName_dot_tSTRING_ListOfFloat((yyvsp[(1) - (7)].c), (yyvsp[(3) - (7)].c), (yyvsp[(5) - (7)].c)); ;} break; case 513: -#line 5522 "Gmsh.y" +#line 5476 "Gmsh.y" { (yyval.l) = List_Create(2, 1, sizeof(double)); if(!gmsh_yysymbols.count((yyvsp[(3) - (4)].c))) @@ -12831,28 +12785,28 @@ yyreduce: break; case 514: -#line 5534 "Gmsh.y" +#line 5488 "Gmsh.y" { (yyval.l) = (yyvsp[(3) - (4)].l); ;} break; case 515: -#line 5538 "Gmsh.y" +#line 5492 "Gmsh.y" { (yyval.l) = (yyvsp[(3) - (4)].l); ;} break; case 516: -#line 5542 "Gmsh.y" +#line 5496 "Gmsh.y" { (yyval.l) = (yyvsp[(4) - (6)].l); ;} break; case 517: -#line 5546 "Gmsh.y" +#line 5500 "Gmsh.y" { (yyval.l) = List_Create(2, 1, sizeof(double)); if(!gmsh_yysymbols.count((yyvsp[(1) - (6)].c))) @@ -12873,7 +12827,7 @@ yyreduce: break; case 518: -#line 5564 "Gmsh.y" +#line 5518 "Gmsh.y" { (yyval.l) = List_Create(20,20,sizeof(double)); for(int i = 0; i < (int)(yyvsp[(7) - (8)].d); i++) { @@ -12884,7 +12838,7 @@ yyreduce: break; case 519: -#line 5572 "Gmsh.y" +#line 5526 "Gmsh.y" { (yyval.l) = List_Create(20,20,sizeof(double)); for(int i = 0; i < (int)(yyvsp[(7) - (8)].d); i++) { @@ -12895,7 +12849,7 @@ yyreduce: break; case 520: -#line 5580 "Gmsh.y" +#line 5534 "Gmsh.y" { Msg::Barrier(); FILE *File; @@ -12927,7 +12881,7 @@ yyreduce: break; case 521: -#line 5609 "Gmsh.y" +#line 5563 "Gmsh.y" { double x0 = (yyvsp[(3) - (14)].d), x1 = (yyvsp[(5) - (14)].d), y0 = (yyvsp[(7) - (14)].d), y1 = (yyvsp[(9) - (14)].d), ys = (yyvsp[(11) - (14)].d); int N = (int)(yyvsp[(13) - (14)].d); @@ -12940,7 +12894,7 @@ yyreduce: break; case 522: -#line 5619 "Gmsh.y" +#line 5573 "Gmsh.y" { std::vector<double> tmp; for(int i = 0; i < List_Nbr((yyvsp[(3) - (4)].l)); i++){ @@ -12959,7 +12913,7 @@ yyreduce: break; case 523: -#line 5635 "Gmsh.y" +#line 5589 "Gmsh.y" { for(int i = 0; i < List_Nbr((yyvsp[(3) - (4)].l)); i++){ double *d = (double*)List_Pointer((yyvsp[(3) - (4)].l), i); @@ -12970,7 +12924,7 @@ yyreduce: break; case 524: -#line 5646 "Gmsh.y" +#line 5600 "Gmsh.y" { (yyval.l) = List_Create(2, 1, sizeof(double)); List_Add((yyval.l), &((yyvsp[(1) - (1)].d))); @@ -12978,21 +12932,21 @@ yyreduce: break; case 525: -#line 5651 "Gmsh.y" +#line 5605 "Gmsh.y" { (yyval.l) = (yyvsp[(1) - (1)].l); ;} break; case 526: -#line 5655 "Gmsh.y" +#line 5609 "Gmsh.y" { List_Add((yyval.l), &((yyvsp[(3) - (3)].d))); ;} break; case 527: -#line 5659 "Gmsh.y" +#line 5613 "Gmsh.y" { for(int i = 0; i < List_Nbr((yyvsp[(3) - (3)].l)); i++){ double d; @@ -13004,21 +12958,21 @@ yyreduce: break; case 528: -#line 5671 "Gmsh.y" +#line 5625 "Gmsh.y" { (yyval.u) = CTX::instance()->packColor((int)(yyvsp[(2) - (9)].d), (int)(yyvsp[(4) - (9)].d), (int)(yyvsp[(6) - (9)].d), (int)(yyvsp[(8) - (9)].d)); ;} break; case 529: -#line 5675 "Gmsh.y" +#line 5629 "Gmsh.y" { (yyval.u) = CTX::instance()->packColor((int)(yyvsp[(2) - (7)].d), (int)(yyvsp[(4) - (7)].d), (int)(yyvsp[(6) - (7)].d), 255); ;} break; case 530: -#line 5687 "Gmsh.y" +#line 5641 "Gmsh.y" { int flag = 0; if(gmsh_yystringsymbols.count((yyvsp[(1) - (1)].c))){ @@ -13038,7 +12992,7 @@ yyreduce: break; case 531: -#line 5704 "Gmsh.y" +#line 5658 "Gmsh.y" { unsigned int val = 0; ColorOption(GMSH_GET, (yyvsp[(1) - (5)].c), 0, (yyvsp[(5) - (5)].c), val); @@ -13048,14 +13002,14 @@ yyreduce: break; case 532: -#line 5714 "Gmsh.y" +#line 5668 "Gmsh.y" { (yyval.l) = (yyvsp[(2) - (3)].l); ;} break; case 533: -#line 5718 "Gmsh.y" +#line 5672 "Gmsh.y" { (yyval.l) = List_Create(256, 10, sizeof(unsigned int)); GmshColorTable *ct = GetColorTable((int)(yyvsp[(3) - (6)].d)); @@ -13070,7 +13024,7 @@ yyreduce: break; case 534: -#line 5733 "Gmsh.y" +#line 5687 "Gmsh.y" { (yyval.l) = List_Create(256, 10, sizeof(unsigned int)); List_Add((yyval.l), &((yyvsp[(1) - (1)].u))); @@ -13078,21 +13032,21 @@ yyreduce: break; case 535: -#line 5738 "Gmsh.y" +#line 5692 "Gmsh.y" { List_Add((yyval.l), &((yyvsp[(3) - (3)].u))); ;} break; case 536: -#line 5745 "Gmsh.y" +#line 5699 "Gmsh.y" { (yyval.c) = (yyvsp[(1) - (1)].c); ;} break; case 537: -#line 5749 "Gmsh.y" +#line 5703 "Gmsh.y" { // No need to extend to Struct_FullName (a Tag is not a String) (yyval.c) = treat_Struct_FullName_String(NULL, (yyvsp[(1) - (1)].c)); @@ -13100,7 +13054,7 @@ yyreduce: break; case 538: -#line 5754 "Gmsh.y" +#line 5708 "Gmsh.y" { std::string val; int j = (int)(yyvsp[(3) - (4)].d); @@ -13117,7 +13071,7 @@ yyreduce: break; case 539: -#line 5768 "Gmsh.y" +#line 5722 "Gmsh.y" { std::string val; int j = (int)(yyvsp[(3) - (4)].d); @@ -13134,35 +13088,35 @@ yyreduce: break; case 540: -#line 5784 "Gmsh.y" +#line 5738 "Gmsh.y" { (yyval.c) = treat_Struct_FullName_dot_tSTRING_String(NULL, (yyvsp[(1) - (3)].c), (yyvsp[(3) - (3)].c)); ;} break; case 541: -#line 5788 "Gmsh.y" +#line 5742 "Gmsh.y" { (yyval.c) = treat_Struct_FullName_dot_tSTRING_String((yyvsp[(1) - (5)].c), (yyvsp[(3) - (5)].c), (yyvsp[(5) - (5)].c)); ;} break; case 542: -#line 5792 "Gmsh.y" +#line 5746 "Gmsh.y" { (yyval.c) = treat_Struct_FullName_dot_tSTRING_String(NULL, (yyvsp[(1) - (6)].c), (yyvsp[(3) - (6)].c), (int)(yyvsp[(5) - (6)].d)); ;} break; case 543: -#line 5796 "Gmsh.y" +#line 5750 "Gmsh.y" { (yyval.c) = treat_Struct_FullName_dot_tSTRING_String((yyvsp[(1) - (8)].c), (yyvsp[(3) - (8)].c), (yyvsp[(5) - (8)].c), (int)(yyvsp[(7) - (8)].d)); ;} break; case 544: -#line 5800 "Gmsh.y" +#line 5754 "Gmsh.y" { std::string out; StringOption(GMSH_GET, (yyvsp[(1) - (6)].c), (int)(yyvsp[(3) - (6)].d), (yyvsp[(6) - (6)].c), out); @@ -13173,7 +13127,7 @@ yyreduce: break; case 545: -#line 5808 "Gmsh.y" +#line 5762 "Gmsh.y" { std::string name = GModel::current()->getPhysicalName(0, (int)(yyvsp[(4) - (5)].d)); (yyval.c) = (char*)Malloc((name.size() + 1) * sizeof(char)); @@ -13182,7 +13136,7 @@ yyreduce: break; case 546: -#line 5814 "Gmsh.y" +#line 5768 "Gmsh.y" { std::string name = GModel::current()->getPhysicalName(1, (int)(yyvsp[(4) - (5)].d)); (yyval.c) = (char*)Malloc((name.size() + 1) * sizeof(char)); @@ -13191,7 +13145,7 @@ yyreduce: break; case 547: -#line 5820 "Gmsh.y" +#line 5774 "Gmsh.y" { std::string name = GModel::current()->getPhysicalName(2, (int)(yyvsp[(4) - (5)].d)); (yyval.c) = (char*)Malloc((name.size() + 1) * sizeof(char)); @@ -13200,7 +13154,7 @@ yyreduce: break; case 548: -#line 5826 "Gmsh.y" +#line 5780 "Gmsh.y" { std::string name = GModel::current()->getPhysicalName(3, (int)(yyvsp[(4) - (5)].d)); (yyval.c) = (char*)Malloc((name.size() + 1) * sizeof(char)); @@ -13209,21 +13163,21 @@ yyreduce: break; case 549: -#line 5835 "Gmsh.y" +#line 5789 "Gmsh.y" { (yyval.c) = (yyvsp[(1) - (1)].c); ;} break; case 550: -#line 5839 "Gmsh.y" +#line 5793 "Gmsh.y" { (yyval.c) = (yyvsp[(3) - (4)].c); ;} break; case 551: -#line 5843 "Gmsh.y" +#line 5797 "Gmsh.y" { (yyval.c) = (char *)Malloc(32 * sizeof(char)); time_t now; @@ -13234,7 +13188,7 @@ yyreduce: break; case 552: -#line 5851 "Gmsh.y" +#line 5805 "Gmsh.y" { std::string exe = Msg::GetExecutableName(); (yyval.c) = (char *)Malloc(exe.size() + 1); @@ -13243,7 +13197,7 @@ yyreduce: break; case 553: -#line 5857 "Gmsh.y" +#line 5811 "Gmsh.y" { std::string action = Msg::GetOnelabAction(); (yyval.c) = (char *)Malloc(action.size() + 1); @@ -13252,14 +13206,14 @@ yyreduce: break; case 554: -#line 5863 "Gmsh.y" +#line 5817 "Gmsh.y" { (yyval.c) = strsave((char*)"Gmsh"); ;} break; case 555: -#line 5867 "Gmsh.y" +#line 5821 "Gmsh.y" { const char *env = GetEnvironmentVar((yyvsp[(3) - (4)].c)); if(!env) env = ""; @@ -13270,7 +13224,7 @@ yyreduce: break; case 556: -#line 5875 "Gmsh.y" +#line 5829 "Gmsh.y" { std::string s = Msg::GetString((yyvsp[(3) - (6)].c), (yyvsp[(5) - (6)].c)); (yyval.c) = (char *)Malloc((s.size() + 1) * sizeof(char)); @@ -13281,7 +13235,7 @@ yyreduce: break; case 557: -#line 5883 "Gmsh.y" +#line 5837 "Gmsh.y" { std::string s = Msg::GetOnelabString((yyvsp[(3) - (4)].c)); (yyval.c) = (char *)Malloc((s.size() + 1) * sizeof(char)); @@ -13291,7 +13245,7 @@ yyreduce: break; case 558: -#line 5890 "Gmsh.y" +#line 5844 "Gmsh.y" { std::string s = Msg::GetOnelabString((yyvsp[(3) - (6)].c), (yyvsp[(5) - (6)].c)); (yyval.c) = (char *)Malloc((s.size() + 1) * sizeof(char)); @@ -13302,21 +13256,21 @@ yyreduce: break; case 559: -#line 5899 "Gmsh.y" +#line 5853 "Gmsh.y" { (yyval.c) = treat_Struct_FullName_String(NULL, (yyvsp[(3) - (5)].c2).char2, 1, 0, (yyvsp[(4) - (5)].c), 2); ;} break; case 560: -#line 5903 "Gmsh.y" +#line 5857 "Gmsh.y" { (yyval.c) = treat_Struct_FullName_dot_tSTRING_String((yyvsp[(3) - (7)].c2).char1, (yyvsp[(3) - (7)].c2).char2, (yyvsp[(5) - (7)].c), 0, (yyvsp[(6) - (7)].c), 2); ;} break; case 561: -#line 5907 "Gmsh.y" +#line 5861 "Gmsh.y" { int size = 1; for(int i = 0; i < List_Nbr((yyvsp[(3) - (4)].l)); i++) @@ -13334,7 +13288,7 @@ yyreduce: break; case 562: -#line 5922 "Gmsh.y" +#line 5876 "Gmsh.y" { (yyval.c) = (char *)Malloc((strlen((yyvsp[(3) - (4)].c)) + 1) * sizeof(char)); int i; @@ -13351,7 +13305,7 @@ yyreduce: break; case 563: -#line 5936 "Gmsh.y" +#line 5890 "Gmsh.y" { (yyval.c) = (char *)Malloc((strlen((yyvsp[(3) - (4)].c)) + 1) * sizeof(char)); int i; @@ -13368,7 +13322,7 @@ yyreduce: break; case 564: -#line 5950 "Gmsh.y" +#line 5904 "Gmsh.y" { std::string input = (yyvsp[(3) - (8)].c); std::string substr_old = (yyvsp[(5) - (8)].c); @@ -13383,7 +13337,7 @@ yyreduce: break; case 565: -#line 5962 "Gmsh.y" +#line 5916 "Gmsh.y" { int size = 1; for(int i = 0; i < List_Nbr((yyvsp[(3) - (4)].l)); i++) @@ -13402,7 +13356,7 @@ yyreduce: break; case 566: -#line 5978 "Gmsh.y" +#line 5932 "Gmsh.y" { int i = 0; while ((yyvsp[(3) - (4)].c)[i]) { @@ -13414,7 +13368,7 @@ yyreduce: break; case 567: -#line 5987 "Gmsh.y" +#line 5941 "Gmsh.y" { int i = 0; while ((yyvsp[(3) - (4)].c)[i]) { @@ -13426,7 +13380,7 @@ yyreduce: break; case 568: -#line 5996 "Gmsh.y" +#line 5950 "Gmsh.y" { int i = 0; while ((yyvsp[(3) - (4)].c)[i]) { @@ -13439,7 +13393,7 @@ yyreduce: break; case 569: -#line 6006 "Gmsh.y" +#line 5960 "Gmsh.y" { if((yyvsp[(3) - (8)].d)){ (yyval.c) = (yyvsp[(5) - (8)].c); @@ -13453,7 +13407,7 @@ yyreduce: break; case 570: -#line 6017 "Gmsh.y" +#line 5971 "Gmsh.y" { std::string in = (yyvsp[(3) - (8)].c); std::string out = in.substr((int)(yyvsp[(5) - (8)].d), (int)(yyvsp[(7) - (8)].d)); @@ -13464,7 +13418,7 @@ yyreduce: break; case 571: -#line 6025 "Gmsh.y" +#line 5979 "Gmsh.y" { std::string in = (yyvsp[(3) - (6)].c); std::string out = in.substr((int)(yyvsp[(5) - (6)].d), std::string::npos); @@ -13475,14 +13429,14 @@ yyreduce: break; case 572: -#line 6033 "Gmsh.y" +#line 5987 "Gmsh.y" { (yyval.c) = (yyvsp[(3) - (4)].c); ;} break; case 573: -#line 6037 "Gmsh.y" +#line 5991 "Gmsh.y" { char tmpstring[5000]; int i = printListOfDouble((yyvsp[(3) - (6)].c), (yyvsp[(5) - (6)].l), tmpstring); @@ -13504,7 +13458,7 @@ yyreduce: break; case 574: -#line 6056 "Gmsh.y" +#line 6010 "Gmsh.y" { std::string tmp = FixRelativePath(gmsh_yyname, (yyvsp[(3) - (4)].c)); (yyval.c) = (char*)Malloc((tmp.size() + 1) * sizeof(char)); @@ -13514,7 +13468,7 @@ yyreduce: break; case 575: -#line 6063 "Gmsh.y" +#line 6017 "Gmsh.y" { std::string tmp = SplitFileName(GetAbsolutePath(gmsh_yyname))[0]; (yyval.c) = (char*)Malloc((tmp.size() + 1) * sizeof(char)); @@ -13523,7 +13477,7 @@ yyreduce: break; case 576: -#line 6069 "Gmsh.y" +#line 6023 "Gmsh.y" { std::string tmp = SplitFileName((yyvsp[(3) - (4)].c))[0]; (yyval.c) = (char*)Malloc((tmp.size() + 1) * sizeof(char)); @@ -13533,7 +13487,7 @@ yyreduce: break; case 577: -#line 6076 "Gmsh.y" +#line 6030 "Gmsh.y" { std::string tmp = GetAbsolutePath((yyvsp[(3) - (4)].c)); (yyval.c) = (char*)Malloc((tmp.size() + 1) * sizeof(char)); @@ -13543,12 +13497,12 @@ yyreduce: break; case 578: -#line 6083 "Gmsh.y" +#line 6037 "Gmsh.y" { init_options(); ;} break; case 579: -#line 6085 "Gmsh.y" +#line 6039 "Gmsh.y" { std::string val((yyvsp[(3) - (6)].c)); Msg::ExchangeOnelabParameter("", val, floatOptions, charOptions); @@ -13559,7 +13513,7 @@ yyreduce: break; case 580: -#line 6093 "Gmsh.y" +#line 6047 "Gmsh.y" { std::string out; const std::string * key_struct = NULL; @@ -13583,37 +13537,37 @@ yyreduce: break; case 581: -#line 6117 "Gmsh.y" +#line 6071 "Gmsh.y" { struct_namespace = std::string(""); (yyval.d) = (yyvsp[(2) - (2)].d); ;} break; case 582: -#line 6119 "Gmsh.y" +#line 6073 "Gmsh.y" { struct_namespace = (yyvsp[(1) - (4)].c); Free((yyvsp[(1) - (4)].c)); (yyval.d) = (yyvsp[(4) - (4)].d); ;} break; case 583: -#line 6125 "Gmsh.y" +#line 6079 "Gmsh.y" { (yyval.l) = (yyvsp[(3) - (4)].l); ;} break; case 584: -#line 6130 "Gmsh.y" +#line 6084 "Gmsh.y" { (yyval.l) = (yyvsp[(1) - (1)].l); ;} break; case 585: -#line 6132 "Gmsh.y" +#line 6086 "Gmsh.y" { (yyval.l) = (yyvsp[(1) - (1)].l); ;} break; case 586: -#line 6137 "Gmsh.y" +#line 6091 "Gmsh.y" { (yyval.l) = (yyvsp[(2) - (3)].l); ;} break; case 587: -#line 6142 "Gmsh.y" +#line 6096 "Gmsh.y" { (yyval.l) = List_Create(20,20,sizeof(char*)); List_Add((yyval.l), &((yyvsp[(1) - (1)].c))); @@ -13621,19 +13575,19 @@ yyreduce: break; case 588: -#line 6147 "Gmsh.y" +#line 6101 "Gmsh.y" { (yyval.l) = (yyvsp[(1) - (1)].l); ;} break; case 589: -#line 6149 "Gmsh.y" +#line 6103 "Gmsh.y" { List_Add((yyval.l), &((yyvsp[(3) - (3)].c))); ;} break; case 590: -#line 6153 "Gmsh.y" +#line 6107 "Gmsh.y" { for(int i = 0; i < List_Nbr((yyvsp[(3) - (3)].l)); i++){ char* c; @@ -13645,7 +13599,7 @@ yyreduce: break; case 591: -#line 6165 "Gmsh.y" +#line 6119 "Gmsh.y" { (yyval.l) = List_Create(20, 20, sizeof(char *)); if(!gmsh_yystringsymbols.count((yyvsp[(1) - (3)].c))) @@ -13662,21 +13616,21 @@ yyreduce: break; case 592: -#line 6179 "Gmsh.y" +#line 6133 "Gmsh.y" { (yyval.l) = treat_Struct_FullName_dot_tSTRING_ListOfString(NULL, (yyvsp[(1) - (5)].c), (yyvsp[(3) - (5)].c)); ;} break; case 593: -#line 6183 "Gmsh.y" +#line 6137 "Gmsh.y" { (yyval.l) = treat_Struct_FullName_dot_tSTRING_ListOfString((yyvsp[(1) - (7)].c), (yyvsp[(3) - (7)].c), (yyvsp[(5) - (7)].c)); ;} break; case 594: -#line 6190 "Gmsh.y" +#line 6144 "Gmsh.y" { char tmpstr[256]; sprintf(tmpstr, "_%d", (int)(yyvsp[(4) - (5)].d)); @@ -13687,7 +13641,7 @@ yyreduce: break; case 595: -#line 6198 "Gmsh.y" +#line 6152 "Gmsh.y" { char tmpstr[256]; sprintf(tmpstr, "_%d", (int)(yyvsp[(4) - (5)].d)); @@ -13698,7 +13652,7 @@ yyreduce: break; case 596: -#line 6206 "Gmsh.y" +#line 6160 "Gmsh.y" { char tmpstr[256]; sprintf(tmpstr, "_%d", (int)(yyvsp[(7) - (8)].d)); @@ -13709,23 +13663,23 @@ yyreduce: break; case 597: -#line 6217 "Gmsh.y" +#line 6171 "Gmsh.y" { (yyval.c) = (yyvsp[(1) - (1)].c); ;} break; case 598: -#line 6219 "Gmsh.y" +#line 6173 "Gmsh.y" { (yyval.c) = (yyvsp[(1) - (1)].c); ;} break; case 599: -#line 6222 "Gmsh.y" +#line 6176 "Gmsh.y" { (yyval.c) = (yyvsp[(3) - (4)].c); ;} break; /* Line 1267 of yacc.c. */ -#line 13729 "Gmsh.tab.cpp" +#line 13683 "Gmsh.tab.cpp" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); @@ -13939,7 +13893,7 @@ yyreturn: } -#line 6225 "Gmsh.y" +#line 6179 "Gmsh.y" void assignVariable(const std::string &name, int index, int assignType, diff --git a/Parser/Gmsh.y b/Parser/Gmsh.y index 4200917b0193120c90fcc9c1764e3eadd99c437d..5667f813e79058d973b5a62655c78571171f8c51 100644 --- a/Parser/Gmsh.y +++ b/Parser/Gmsh.y @@ -2161,62 +2161,16 @@ Shape : } | tCompound GeoEntity123 '(' FExpr ')' tAFFECT ListOfDouble tEND { - int num = (int)$4; - std::vector<int> tags; ListOfDouble2Vector($7, tags); - switch ($2) { - case 1: - { - bool r = GModel::current()->getGEOInternals()->addCompoundLine(num, tags); - if(!r) yymsg(0, "Could not add compound line"); - } - $$.Type = MSH_SEGM_COMPOUND; - break; - case 2: - { - bool r = GModel::current()->getGEOInternals()->addCompoundSurface(num, tags); - if(!r) yymsg(0, "Could not add compound surface"); - } - $$.Type = MSH_SURF_COMPOUND; - break; - case 3: - { - bool r = GModel::current()->getGEOInternals()->addCompoundVolume(num, tags); - if(!r) yymsg(0, "Could not add compound volume"); - } - $$.Type = MSH_VOLUME_COMPOUND; - break; - } - List_Delete($7); - $$.Num = num; + yymsg(0, "Compounds entities are deprecated: use Compound meshing constraints instead"); + $$.Type = 0; + $$.Num = 0; } | tCompound GeoEntity123 '(' FExpr ')' tAFFECT ListOfDouble tSTRING '{' RecursiveListOfListOfDouble '}' tEND { - // Particular case only for dim 2 (Surface) - if ($2 == 2) { - int num = (int)$4; - std::vector<int> tags; ListOfDouble2Vector($7, tags); - std::vector<int> bndTags[4]; - for(int i = 0; i < List_Nbr($10); i++){ - if(i < 4) - ListOfDouble2Vector(*(List_T**)List_Pointer($10, i), bndTags[i]); - else - break; - } - bool r = GModel::current()->getGEOInternals()->addCompoundSurface - (num, tags, bndTags); - if(!r) yymsg(0, "Could not add compound surface"); - List_Delete($7); - Free($8); - for (int i = 0; i < List_Nbr($10); i++) - List_Delete(*(List_T**)List_Pointer($10, i)); - List_Delete($10); - $$.Type = MSH_SURF_COMPOUND; - $$.Num = num; - } - else { - yymsg(0, "GeoEntity dim out of range [2,2]"); - } + yymsg(0, "Compounds entities are deprecated: use Compound meshing constraints instead"); + $$.Type = 0; + $$.Num = 0; } | tPhysical GeoEntity { diff --git a/Solver/CMakeLists.txt b/Solver/CMakeLists.txt index d9f5de36614eb4848556ccdc3dad4f09925f3a74..9254e2aa6d368096dcbb97c0dd5d80da9332ea8f 100644 --- a/Solver/CMakeLists.txt +++ b/Solver/CMakeLists.txt @@ -15,7 +15,6 @@ elasticitySolver.cpp thermicSolver.cpp SElement.cpp eigenSolver.cpp - multiscaleLaplace.cpp functionSpace.cpp filters.cpp frameSolver.cpp diff --git a/Solver/multiscaleLaplace.cpp b/Solver/multiscaleLaplace.cpp deleted file mode 100644 index ca2d11eaae226ec908d1dd3350f94e0498aeeb0d..0000000000000000000000000000000000000000 --- a/Solver/multiscaleLaplace.cpp +++ /dev/null @@ -1,1138 +0,0 @@ -// Gmsh - Copyright (C) 1997-2017 C. Geuzaine, J.-F. Remacle -// -// See the LICENSE.txt file for license information. Please report all -// bugs and problems to the public mailing list <gmsh@onelab.info>. -// -// Contributor(s): -// Emilie Marchandise -// - -#include "Context.h" -#include "multiscaleLaplace.h" -#include "GmshConfig.h" -#include "GmshDefines.h" -#include "Numeric.h" -#include "OS.h" -#include "SBoundingBox3d.h" -#include "SPoint3.h" -#include "dofManager.h" -#include "laplaceTerm.h" -#include "convexCombinationTerm.h" -#include "linearSystemCSR.h" -#include "linearSystemPETSc.h" -#include "robustPredicates.h" -#include "meshGFaceOptimize.h" -#include "GFaceCompound.h" - -#ifdef HAVE_GMM -#include "linearSystemGMM.h" -#endif - -#include "linearSystemFull.h" -#include "MTriangle.h" -#include "robustPredicates.h" - -struct compareRotatedPoints { - double angle; - const SPoint2 &left; - compareRotatedPoints (const SPoint2& l,const SPoint2& r) : left(l){ - angle = atan2(r.y()-l.y(),r.x()-l.x()); - } - bool operator ( ) (const SPoint2 &p1, const SPoint2 &p2) const { - //sort from left (x=-1) to right (sin=0), cos(=1) - double x1 = (p1.x()-left.x())*cos(angle) + (p1.y()-left.y())*sin(angle); - double x2 = (p2.x()-left.x())*cos(angle) + (p2.y()-left.y())*sin(angle); - if (x1<x2)return true; - if (x1>x2)return false; - double y1 =-(p1.x()-left.x())*sin(angle) + (p1.y()-left.y())*cos(angle); - double y2 =-(p2.x()-left.x())*sin(angle) + (p2.y()-left.y())*cos(angle); - if (y1<y2)return true; - return false; - } -}; - -struct sort_pred { - compareRotatedPoints comparator; - sort_pred (const SPoint2 &left, const SPoint2 &right) - : comparator(left,right) {} - bool operator()(const std::pair<SPoint2,multiscaleLaplaceLevel*> &left, - const std::pair<SPoint2,multiscaleLaplaceLevel*> &right) - { - return comparator(left.first,right.first); - } -}; - -static void recur_connect (MVertex *v, - std::multimap<MVertex*,MEdge> &v2e, - std::set<MEdge,Less_Edge> &group, - std::set<MVertex*> &touched) -{ - if (touched.find(v) != touched.end()) return; - - touched.insert(v); - for (std::multimap <MVertex*,MEdge>::iterator it = v2e.lower_bound(v); - it != v2e.upper_bound(v) ; ++it){ - group.insert(it->second); - for (int i=0;i<it->second.getNumVertices();++i){ - recur_connect (it->second.getVertex(i),v2e,group,touched); - } - } - -} - -static void connected_bounds (std::vector<MElement*> &elements, - std::vector<std::vector<MEdge> > &boundaries) -{ - std::vector<MEdge> bEdges; - for(unsigned int i = 0; i < elements.size(); i++){ - for(int j = 0; j < elements[i]->getNumEdges(); j++){ - MEdge me = elements[i]->getEdge(j); - if(std::find(bEdges.begin(), bEdges.end(), me) == bEdges.end()) - bEdges.push_back(me); - else - bEdges.erase(std::find(bEdges.begin(), bEdges.end(),me)); - } - } - - std::multimap<MVertex*,MEdge> v2e; - for (unsigned int i = 0; i < bEdges.size(); ++i){ - for (int j=0;j<bEdges[i].getNumVertices();j++){ - v2e.insert(std::make_pair(bEdges[i].getVertex(j),bEdges[i])); - } - } - while (!v2e.empty()){ - std::set<MEdge, Less_Edge> group; - std::set<MVertex*> touched; - recur_connect (v2e.begin()->first,v2e,group,touched); - std::vector<MEdge> temp; - temp.insert(temp.begin(), group.begin(), group.end()); - boundaries.push_back(temp); - for ( std::set<MVertex*>::iterator it = touched.begin() ; it != touched.end();++it) - v2e.erase(*it); - } - - return; -} - -static double getSizeBB(std::vector<MEdge> &me) -{ - SBoundingBox3d bb ; - SOrientedBoundingBox obbox ; - - std::vector<SPoint3> vertices; - for (unsigned int i=0; i< me.size(); i++){ - MVertex *v0 = me[i].getVertex(0); - MVertex *v1 = me[i].getVertex(1); - SPoint3 pt1(v0->x(),v0->y(), v0->z()); - vertices.push_back(pt1); - SPoint3 pt2(v1->x(),v1->y(), v1->z()); - vertices.push_back(pt2); - bb+=pt1; - bb+=pt2; - } - - //double H = norm(SVector3(bb.max(), bb.min())); - //printf("H=%g \n", H); - - obbox = SOrientedBoundingBox::buildOBB(vertices); - double H = obbox.getMaxSize(); - - return H; -} - -static void ordering_dirichlet(std::vector<MElement*> &elements, - std::vector<std::pair<MVertex*,double> > &dirichletNodes) -{ - //finding all boundaries - std::vector<std::vector<MEdge> > boundaries; - connected_bounds(elements,boundaries); - - //largest boundary is dirichlet boundary - std::vector<MEdge> dirichletEdges; - double maxSize = 0.0; - for(unsigned int i = 0; i < boundaries.size(); i++){ - std::vector<MEdge> iBound = boundaries[i]; - double size = getSizeBB(iBound); - if (size > maxSize) { - dirichletEdges = iBound; - maxSize = size; - } - } - - //ordering dirichletNodes - dirichletNodes.clear(); - std::list<MEdge> temp; - double tot_length = 0.0; - for(unsigned int i = 0; i < dirichletEdges.size(); i++ ){ - MVertex *v0 = dirichletEdges[i].getVertex(0); - MVertex *v1 = dirichletEdges[i].getVertex(1); - double len = sqrt((v0->x() - v1->x()) * (v0->x() - v1->x()) + - (v0->y() - v1->y()) * (v0->y() - v1->y()) + - (v0->z() - v1->z()) * (v0->z() - v1->z())) ; - tot_length += len; - temp.push_back(dirichletEdges[i]); - } - - dirichletNodes.push_back(std::make_pair(dirichletEdges[0].getVertex(0),0.0)); - MVertex *current_v = dirichletEdges[0].getVertex(1); - temp.erase(temp.begin()); - - while(temp.size()){ - bool found = false; - for(std::list<MEdge>::iterator itl = temp.begin(); itl != temp.end(); ++itl){ - MVertex *v0 = itl->getVertex(0); - MVertex *v1 = itl->getVertex(1); - if(v0 == current_v){ - found = true; - current_v = v1; - temp.erase(itl); - double length = sqrt((v0->x() - v1->x()) * (v0->x() - v1->x()) + - (v0->y() - v1->y()) * (v0->y() - v1->y()) + - (v0->z() - v1->z()) * (v0->z() - v1->z())); - double iLength = dirichletNodes[dirichletNodes.size()-1].second + - (length / tot_length); - dirichletNodes.push_back(std::make_pair(v0,iLength)); - break; - } - else if(v1 == current_v){ - found = true; - current_v = v0; - temp.erase(itl); - double length = sqrt((v0->x() - v1->x()) * (v0->x() - v1->x()) + - (v0->y() - v1->y()) * (v0->y() - v1->y()) + - (v0->z() - v1->z()) * (v0->z() - v1->z())); - double iLength = dirichletNodes[dirichletNodes.size()-1].second + - (length / tot_length); - dirichletNodes.push_back(std::make_pair(v1,iLength)); - break; - } - } - if(!found) return ; - } - - return; -} - -static int intersection_segments (SPoint2 &p1, SPoint2 &p2, - SPoint2 &q1, SPoint2 &q2, - double x[2]) -{ - double A[2][2]; - A[0][0] = p2.x()-p1.x(); - A[0][1] = q1.x()-q2.x(); - A[1][0] = p2.y()-p1.y(); - A[1][1] = q1.y()-q2.y(); - double b[2] = {q1.x()-p1.x(),q1.y()-p1.y()}; - sys2x2(A,b,x); - - return (x[0] >= 0.0 && x[0] <= 1. && - x[1] >= 0.0 && x[1] <= 1.); - -} - -static void recur_compute_centers_ (double R, double a1, double a2, - multiscaleLaplaceLevel * root, int &nbElems) -{ - nbElems += root->elements.size(); - - root->radius = R; - std::vector<std::pair<SPoint2,multiscaleLaplaceLevel*> > ¢ers = root->cut; - centers.clear(); - multiscaleLaplaceLevel* zero = 0; - - double fact = 2.5; - SPoint2 PL (fact*R*cos(a1),fact*R*sin(a1)); - SPoint2 PR (fact*R*cos(a2),fact*R*sin(a2)); - - std::vector<SPoint2> centersChild; - centersChild.clear(); - for (unsigned int i=0;i<root->children.size();i++){ - multiscaleLaplaceLevel* m = root->children[i]; - centers.push_back(std::make_pair(m->center,m)); - m->radius = 0.0; - for (std::map<MVertex*,SPoint2>::iterator it = m->coordinates.begin(); - it != m->coordinates.end() ; ++it){ - SPoint2 p = it->second; - m->radius = std::max(m->radius,sqrt ((m->center.x() - p.x())*(m->center.x() - p.x())+ - (m->center.y() - p.y())*(m->center.y() - p.y()))); - } - centersChild.push_back(m->center); - } - - //add the center of real holes ... - std::vector<std::vector<MEdge> > boundaries; - connected_bounds(root->elements, boundaries); - int added = 0; - int toadd = boundaries.size()-1 - root->children.size(); - if (root->children.size()==0 || (root->children.size()> 0 && toadd > 0) ){ - for (unsigned int i = 0; i < boundaries.size(); i++){ - std::vector<MEdge> me = boundaries[i]; - SPoint2 c(0.0,0.0); - double rad = 0.0; - for(unsigned int j= 0; j< me.size(); j++){ - MVertex *v = me[j].getVertex(0); - std::map<MVertex *, SPoint2>::iterator it0 = root->coordinates.find(v); - c += it0->second; - } - c *= 1./((double)me.size()); - for(unsigned int j= 0; j< me.size(); j++){ - SPoint2 p = root->coordinates[me[j].getVertex(0)]; - rad = std::max(rad,sqrt ((c.x() - p.x())*(c.x() - p.x())+ - (c.y() - p.y())*(c.y() - p.y()))); - } - - //check if the center has not been added - bool newCenter = true; - for (std::vector<SPoint2>::iterator it2 = centersChild.begin(); - it2 != centersChild.end(); it2++){ - SPoint2 p = *it2; - double dist = sqrt ((c.x() - p.x())*(c.x() - p.x())+ - (c.y() - p.y())*(c.y() - p.y())); - if (dist < 0.5*rad) newCenter = false;//0.6 - } - - if (std::abs(rad/root->radius) < 0.65 && std::abs(rad) < 0.95 && newCenter){//0.6 - added++; - centers.push_back(std::make_pair(c,zero)); - } - } - } - if (added != toadd && root->children.size()> 0) { - printf("!!!!!!!! ARG added = %d != %d (bounds=%d, child=%d)\n", added, - (int)(boundaries.size() - 1 - root->children.size()), (int)boundaries.size(), - (int)root->children.size()); - } - - //sort centers from left to right - std::sort(centers.begin(),centers.end(), sort_pred(PL,PR)); - - //sort from distances - //sort_centers_dist(centers, PL); - - centers.insert(centers.begin(), std::make_pair(PL,zero)); - centers.push_back(std::make_pair(PR,zero)); - - for (unsigned int i = 1; i < centers.size() - 1; i++){ - multiscaleLaplaceLevel* m2 = centers[i].second; - if (m2){ - a1 = myatan2 (centers[i-1].first.y()- m2->center.y(), - centers[i-1].first.x()-m2->center.x()); - a2 = myatan2 (centers[i+1].first.y()- m2->center.y(), - centers[i+1].first.x()-m2->center.x()); - recur_compute_centers_ (m2->radius, a1, a2, m2, nbElems); - } - } - -} - -static void recur_cut_edges_ (multiscaleLaplaceLevel *root, - std::map<MEdge,MVertex*,Less_Edge> &cutEdges, - std::set<MVertex*> &cutVertices) -{ - const double EPS = 0.001; - - std::multimap<MEdge,MElement*,Less_Edge> e2e; - std::set<MEdge,Less_Edge> allEdges; - for (unsigned int i = 0; i < root->elements.size(); ++i){ - for (int j = 0; j < root->elements[i]->getNumEdges(); j++){ - e2e.insert(std::make_pair(root->elements[i]->getEdge(j),root->elements[i])); - allEdges.insert(root->elements[i]->getEdge(j)); - } - } - - std::vector<std::pair<SPoint2,multiscaleLaplaceLevel*> > ¢ers = root->cut; - for (unsigned int i = 0; i < centers.size() - 1; i++){ - SPoint2 p1 = centers[i].first; - SPoint2 p2 = centers[i+1].first; - //printf("*************** line p1p2 (%g %g) -- (%g %g) \n",p1.x(),p1.y(),p2.x(),p2.y()); - for (std::set <MEdge,Less_Edge>::iterator it = allEdges.begin(); - it != allEdges.end() ; ++it){ - if(cutEdges.find(*it) == cutEdges.end()){//e2e.count(*it) == 2 && - std::map<MVertex *, SPoint2>::iterator it0 = root->coordinates.find(it->getVertex(0)); - std::map<MVertex *, SPoint2>::iterator it1 = root->coordinates.find(it->getVertex(1)); - if (it0 != root->coordinates.end() && it1 != root->coordinates.end()){ - SPoint2 q1 = root->coordinates[it->getVertex(0)]; - SPoint2 q2 = root->coordinates[it->getVertex(1)]; - double x[2]; - int inters = intersection_segments (p1,p2,q1,q2,x); - if (inters && x[1] > EPS && x[1] < 1.-EPS){ - MVertex *newv = new MVertex - ((1.-x[1])*it->getVertex(0)->x() + x[1]*it->getVertex(1)->x(), - (1.-x[1])*it->getVertex(0)->y() + x[1]*it->getVertex(1)->y(), - (1.-x[1])*it->getVertex(0)->z() + x[1]*it->getVertex(1)->z()); - cutEdges[*it] = newv; - root->coordinates[newv] = q1*(1.-x[1]) + q2*x[1] ; - } - else if (inters && x[1] <= EPS) cutVertices.insert(it->getVertex(0)); - else if (inters && x[1] >= 1.-EPS) cutVertices.insert(it->getVertex(1)); - } - } - } - } - for (unsigned int i = 0; i < centers.size(); i++){ - multiscaleLaplaceLevel* m2 = centers[i].second; - if (m2){ - recur_cut_edges_ (m2,cutEdges,cutVertices); - } - } -} - -static void recur_cut_elements_ (multiscaleLaplaceLevel * root, - std::map<MEdge,MVertex*,Less_Edge> &cutEdges, - std::set<MVertex*> &cutVertices, - std::set<MEdge,Less_Edge> &theCut, - std::vector<MElement*> &_all) -{ - std::vector<std::pair<SPoint2,multiscaleLaplaceLevel*> > ¢ers = root->cut; - std::vector<MElement*> newElements; - for (unsigned int i = 0; i < root->elements.size(); i++){ - MVertex *c[3] = {0,0,0}; - for (int j=0;j<3;j++){ - MEdge ed = root->elements[i]->getEdge(j); - std::map<MEdge,MVertex*,Less_Edge> :: iterator it = cutEdges.find(ed); - if (it != cutEdges.end()){ - c[j] = it->second; - } - } - if (c[0] && c[1]){ - newElements.push_back(new MTriangle (c[0],root->elements[i]->getVertex(1),c[1])); - newElements.push_back(new MTriangle (root->elements[i]->getVertex(0),c[0], - root->elements[i]->getVertex(2))); - newElements.push_back(new MTriangle (root->elements[i]->getVertex(2),c[0],c[1])); - theCut.insert(MEdge(c[0],c[1])); - } - else if (c[0] && c[2]){ - newElements.push_back(new MTriangle (root->elements[i]->getVertex(0),c[0],c[2])); - newElements.push_back(new MTriangle (c[0],root->elements[i]->getVertex(1), - root->elements[i]->getVertex(2))); - newElements.push_back(new MTriangle (root->elements[i]->getVertex(2),c[2],c[0])); - theCut.insert(MEdge(c[0],c[2])); - } - else if (c[1] && c[2]){ - newElements.push_back(new MTriangle (root->elements[i]->getVertex(2),c[2],c[1])); - newElements.push_back(new MTriangle (root->elements[i]->getVertex(0), - root->elements[i]->getVertex(1),c[2])); - newElements.push_back(new MTriangle (c[2],root->elements[i]->getVertex(1),c[1])); - theCut.insert(MEdge(c[1],c[2])); - } - else if (c[0]){ - newElements.push_back(new MTriangle (root->elements[i]->getVertex(0),c[0], - root->elements[i]->getVertex(2))); - newElements.push_back(new MTriangle (root->elements[i]->getVertex(2),c[0], - root->elements[i]->getVertex(1))); - if (cutVertices.find (root->elements[i]->getVertex(0)) != cutVertices.end()){ - theCut.insert(MEdge(c[0],root->elements[i]->getVertex(0))); - } - else if (cutVertices.find (root->elements[i]->getVertex(1)) != cutVertices.end()) { - theCut.insert(MEdge(c[0],root->elements[i]->getVertex(1))); - } - else{ - theCut.insert(MEdge(c[0],root->elements[i]->getVertex(2))); - } - } - else if (c[1]){ - newElements.push_back(new MTriangle (root->elements[i]->getVertex(1),c[1], - root->elements[i]->getVertex(0))); - newElements.push_back(new MTriangle (root->elements[i]->getVertex(0),c[1], - root->elements[i]->getVertex(2))); - if (cutVertices.find (root->elements[i]->getVertex(0)) != cutVertices.end()){ - theCut.insert(MEdge(c[1],root->elements[i]->getVertex(0))); - } - else if (cutVertices.find (root->elements[i]->getVertex(1)) != cutVertices.end()) { - theCut.insert(MEdge(c[1],root->elements[i]->getVertex(1))); - } - else{ - theCut.insert(MEdge(c[1],root->elements[i]->getVertex(2))); - } - } - else if (c[2]){ - newElements.push_back(new MTriangle (root->elements[i]->getVertex(0), - root->elements[i]->getVertex(1), c[2])); - newElements.push_back(new MTriangle (root->elements[i]->getVertex(1), - root->elements[i]->getVertex(2), c[2])); - if (cutVertices.find (root->elements[i]->getVertex(0)) != cutVertices.end()){ - theCut.insert(MEdge(c[2],root->elements[i]->getVertex(0))); - } - else if (cutVertices.find (root->elements[i]->getVertex(1)) != cutVertices.end()) { - theCut.insert(MEdge(c[2],root->elements[i]->getVertex(1))); - } - else{ - theCut.insert(MEdge(c[2],root->elements[i]->getVertex(2))); - } - } - else { - newElements.push_back(root->elements[i]); - if (cutVertices.find (root->elements[i]->getVertex(0)) != cutVertices.end() && - cutVertices.find (root->elements[i]->getVertex(1)) != cutVertices.end()) - theCut.insert(MEdge(root->elements[i]->getVertex(0),root->elements[i]->getVertex(1))); - if (cutVertices.find (root->elements[i]->getVertex(0)) != cutVertices.end() && - cutVertices.find (root->elements[i]->getVertex(2)) != cutVertices.end()) - theCut.insert(MEdge(root->elements[i]->getVertex(0),root->elements[i]->getVertex(2))); - if (cutVertices.find (root->elements[i]->getVertex(2)) != cutVertices.end() && - cutVertices.find (root->elements[i]->getVertex(1)) != cutVertices.end()) - theCut.insert(MEdge(root->elements[i]->getVertex(2),root->elements[i]->getVertex(1))); - } - } - - root->elements.clear(); - root->elements = newElements; - _all.insert(_all.end(),newElements.begin(),newElements.end()); - for (unsigned int i = 0; i < centers.size(); i++){ - multiscaleLaplaceLevel* m2 = centers[i].second; - if (m2){ - recur_cut_elements_ (m2,cutEdges,cutVertices,theCut,_all); - } - } -} - -static void recur_leftCut_ (MElement *e, - std::multimap<MEdge,MElement*,Less_Edge> &e2e, - std::set<MEdge,Less_Edge> &theCut, - std::set<MElement*> &leftSet) -{ - if (leftSet.find(e) != leftSet.end())return; - leftSet.insert(e); - //printf("insert in left %d \n", e->getNum()); - for (int i=0;i<e->getNumEdges();i++){ - MEdge ed = e->getEdge(i); - if (theCut.find(ed) == theCut.end()){ - for (std::multimap <MEdge,MElement*,Less_Edge>::iterator it = e2e.lower_bound(ed); - it != e2e.upper_bound(ed) ; ++it){ - if (it->second != e) recur_leftCut_ (it->second,e2e,theCut, leftSet); - } - } - } - -} - -// starting form a list of elements, returns -// lists of lists that are all simply connected -static void recur_connect (const MEdge &e, - std::multimap<MEdge,MElement*,Less_Edge> &e2e, - std::set<MElement*> &group, - std::set<MEdge,Less_Edge> &touched) -{ - if (touched.find(e) != touched.end())return; - touched.insert(e); - for (std::multimap <MEdge,MElement*,Less_Edge>::iterator it = e2e.lower_bound(e); - it != e2e.upper_bound(e) ; ++it){ - group.insert(it->second); - for (int i=0;i<it->second->getNumEdges();++i){ - recur_connect (it->second->getEdge(i),e2e,group,touched); - } - } -} - -static void connectedRegions (const std::vector<MElement*> &elements, - std::vector<std::vector<MElement*> > ®ions) -{ - std::multimap<MEdge,MElement*,Less_Edge> e2e; - for (unsigned int i = 0; i < elements.size(); ++i){ - for (int j = 0; j < elements[i]->getNumEdges(); j++){ - e2e.insert(std::make_pair(elements[i]->getEdge(j),elements[i])); - } - } - while (!e2e.empty()){ - std::set<MElement*> group; - std::set<MEdge,Less_Edge> touched; - recur_connect (e2e.begin()->first,e2e,group,touched); - std::vector<MElement*> temp; - temp.insert(temp.begin(), group.begin(), group.end()); - regions.push_back(temp); - for ( std::set<MEdge,Less_Edge>::iterator it = touched.begin() ; it != touched.end();++it) - e2e.erase(*it); - } -} - -static void keepConnected(std::vector<MElement*> &goodSize, std::vector<MElement*> &tooSmall) -{ - std::vector<std::vector<MElement*> > regGoodSize; - connectedRegions (goodSize,regGoodSize); - if (regGoodSize.size() > 0){ - int index=0; - int maxSize= regGoodSize[0].size(); - for (unsigned int i=1;i< regGoodSize.size() ; i++){ - int size = regGoodSize[i].size(); - if(size > maxSize){ - index = i; - maxSize = size; - } - } - goodSize.clear(); - for (unsigned int i = 0; i < regGoodSize.size(); i++){ - if ((int)i == index) - goodSize.insert(goodSize.begin(), regGoodSize[i].begin(), - regGoodSize[i].end()); - else - tooSmall.insert(tooSmall.begin(), regGoodSize[i].begin(), - regGoodSize[i].end()); - } - } -} - -static void recur_cut_ (double R, double a1, double a2, - multiscaleLaplaceLevel * root, - std::vector<MElement *> &left, - std::vector<MElement *> &right) -{ - SPoint2 PL (R*cos(a1),R*sin(a1)); - SPoint2 PR (R*cos(a2),R*sin(a2)); - std::vector<std::pair<SPoint2,multiscaleLaplaceLevel*> > centers = root->cut; - - double d = sqrt((PL.x()-PR.x())*(PL.x()-PR.x())+ - (PL.y()-PR.y())*(PL.y()-PR.y())); - SPoint2 farLeft (0.5*(PL.x()+PR.x()) - (PR.y()-PL.y())/d , - 0.5*(PL.y()+PR.y()) + (PR.x()-PL.x())/d ); - - for (unsigned int i = 0; i < root->elements.size(); i++){ - SPoint2 pp (0,0); - for (int j=0; j<root->elements[i]->getNumVertices(); j++){ - pp += root->coordinates[root->elements[i]->getVertex(j)]; - } - pp *= 1./(double)root->elements[i]->getNumVertices(); - int nbIntersect = 0; - for (unsigned int j = 0; j < centers.size() - 1; j++){ - double x[2]; - nbIntersect += intersection_segments (centers[j].first,centers[j+1].first,pp,farLeft,x); - } - if (nbIntersect %2 != 0) - left.push_back(root->elements[i]); - else - right.push_back(root->elements[i]); - } - - for (unsigned int i = 1; i < centers.size() - 1; i++){ - multiscaleLaplaceLevel* m2 = centers[i].second; - if (m2){ - a1 = myatan2 (centers[i-1].first.y() - m2->center.y(), - centers[i-1].first.x() - m2->center.x()); - a2 = myatan2 (centers[i+1].first.y() - m2->center.y(), - centers[i+1].first.x() - m2->center.x()); - recur_cut_ (m2->radius, a1, a2, m2, left, right); - } - } -} - -static void connected_left_right (std::vector<MElement *> &left, - std::vector<MElement *> &right) -{ - //connected left - keepConnected(left, right); - - //assign partitions - for (unsigned int i= 0; i< left.size(); i++) - left[i]->setPartition(1); - for (unsigned int i= 0; i< right.size(); i++) - right[i]->setPartition(2); -} - -static void printCut(std::map<MEdge,MVertex*,Less_Edge> &cutEdges, - std::set<MEdge,Less_Edge> &theCut, std::set<MVertex*> cutVertices) -{ - printf("Writing points.pos \n"); - std::map<MEdge,MVertex*,Less_Edge>::iterator ite = cutEdges.begin(); - FILE *f1 = Fopen("points.pos","w"); - if(f1){ - fprintf(f1,"View\"\"{\n"); - for ( ; ite != cutEdges.end();++ite){ - fprintf(f1,"SP(%g,%g,%g){1.0};\n",ite->second->x(),ite->second->y(),ite->second->z()); - } - std::set<MVertex*>::iterator itv = cutVertices.begin(); - for ( ; itv != cutVertices.end();++itv){ - fprintf(f1,"SP(%g,%g,%g){3.0};\n",(*itv)->x(),(*itv)->y(),(*itv)->z()); - } - fprintf(f1,"};\n"); - fclose(f1); - } - - printf("Writing edges.pos \n"); - std::set<MEdge,Less_Edge>::iterator itc = theCut.begin(); - FILE *f2 = Fopen("edges.pos","w"); - if(f2){ - fprintf(f2,"View\"\"{\n"); - for ( ; itc != theCut.end();++itc){ - fprintf(f2,"SL(%g,%g,%g,%g,%g,%g){1.0,1.0};\n",itc->getVertex(0)->x(), - itc->getVertex(0)->y(),itc->getVertex(0)->z(), - itc->getVertex(1)->x(),itc->getVertex(1)->y(),itc->getVertex(1)->z()); - } - fprintf(f2,"};\n"); - fclose(f2); - } -} - -static void printLevel(const char* fn, - std::vector<MElement *> &elements, - std::map<MVertex*,SPoint2> *coordinates, - double version, - double *dx = 0) -{ - if(!CTX::instance()->mesh.saveAll) return; - - std::set<MVertex*> vs; - for (unsigned int i = 0; i < elements.size(); i++) - for (int j = 0; j < elements[i]->getNumVertices(); j++) - vs.insert(elements[i]->getVertex(j)); - - bool binary = false; - FILE *fp = Fopen (fn, "w"); - if(!fp){ - Msg::Error("Could not open file '%s'", fn); - return; - } - fprintf(fp, "$MeshFormat\n"); - fprintf(fp, "%g %d %d\n", version, binary ? 1 : 0, (int)sizeof(double)); - fprintf(fp, "$EndMeshFormat\n"); - - fprintf(fp, "$Nodes\n%d\n", (int)vs.size()); - std::set<MVertex*> :: iterator it = vs.begin(); - int index = 1; - for (; it != vs.end() ; ++it){ - (*it)->setIndex(index++); - SPoint2 p = (coordinates) ? (*coordinates)[*it] : SPoint2(0,0); - if (coordinates) { - if (dx)fprintf(fp, "%d %22.15E %22.15E 0\n", (*it)->getIndex(), - dx[2]*(p.x()-dx[0]), dx[2]*(p.y()-dx[1])); - else fprintf(fp, "%d %22.15E %22.15E 0\n", (*it)->getIndex(), p.x(), p.y()); - } - else fprintf(fp, "%d %g %g %g\n", (*it)->getIndex(),(*it)->x(), (*it)->y(), (*it)->z()); - } - fprintf(fp, "$EndNodes\n"); - - fprintf(fp, "$Elements\n%d\n", (int)elements.size()); - for (unsigned int i = 0; i < elements.size(); i++){ - elements[i]->writeMSH(fp, version); - } - fprintf(fp, "$EndElements\n"); - - fclose(fp); -} - -static double localSize(MElement *e, std::map<MVertex*,SPoint2> &solution) -{ - SBoundingBox3d local; - for(int j = 0; j<e->getNumVertices(); ++j){ - SPoint2 p = solution[e->getVertex(j)]; - local += SPoint3(p.x(),p.y(),0.0); - } - return local.max().distance(local.min()); - -// MVertex* v0 = e->getVertex(0); -// MVertex* v1 = e->getVertex(1); -// MVertex* v2 = e->getVertex(2); -// double p0[3] = {v0->x(), v0->y(), v0->z()}; -// double p1[3] = {v1->x(), v1->y(), v1->z()}; -// double p2[3] = {v2->x(), v2->y(), v2->z()}; -// double a_3D = fabs(triangle_area(p0, p1, p2)); -// SPoint2 s1 = solution[v0]; -// SPoint2 s2 = solution[v1]; -// SPoint2 s3 = solution[v2]; -// double q0[3] = {s1.x(), s1.y(), 0.0}; -// double q1[3] = {s2.x(), s2.y(), 0.0}; -// double q2[3] = {s3.x(), s3.y(), 0.0}; -// double a_2D = fabs(triangle_area(q0, q1, q2)); - -// return a_2D; //a_2D / a_3D; -} - -static void printLevel_onlysmall(const char* fn, - std::vector<MElement *> &elements, - std::map<MVertex*,SPoint2> *coordinates, - double version, - double tolerance) -{ - std::vector<MElement *> small; - double dx[3] = {0,0,0}; - int COUNT = 0; - for (unsigned i=0;i<elements.size();i++){ - double local_size = localSize(elements[i],*coordinates); - if (local_size < tolerance){ - small.push_back(elements[i]); - for (int j=0;j<3;j++){ - SPoint2 p = (*coordinates)[elements[i]->getVertex(j)]; - dx[0] += p.x(); - dx[1] += p.y(); - COUNT++; - } - } - } - dx[0] /= COUNT; - dx[1] /= COUNT; - dx[2] = 1./tolerance; - printLevel(fn,small,coordinates,version,dx); -} - -multiscaleLaplace::multiscaleLaplace (std::vector<MElement *> &elements, - std::map<MVertex*, SPoint3> &allCoordinates) -{ - //Find the boundary loops - //The loop with the largest equivalent radius is the Dirichlet boundary - std::vector<std::pair<MVertex*,double> > boundaryNodes; - ordering_dirichlet(elements,boundaryNodes); - - //Assign Dirichlet BCs - // FIXME: this is never deleted - root = new multiscaleLaplaceLevel; - root->elements = elements; - for(unsigned int i = 0; i < boundaryNodes.size(); i++){ - MVertex *v = boundaryNodes[i].first; - const double theta = 2 * M_PI * boundaryNodes[i].second; - root->coordinates[v] = SPoint2(cos(theta),sin(theta)); - } - - //Recursively parametrize - root->recur = 0; - root->region = 0; - root->scale = 1.0; - root->_name = "Root"; - - parametrize(*root); - - //fill the coordinates - std::vector<double> iScale; - std::vector<SPoint2> iCenter; - fillCoordinates(*root, allCoordinates, iScale, iCenter); - - //Compute centers for the cut - int nbElems = 0; - recur_compute_centers_ (1.0, M_PI, 0.0, root, nbElems); - - //Split the mesh in left and right - //or Cut the mesh in left and right (of bamg) - if ( CTX::instance()->mesh.algo2d == ALGO_2D_BAMG){ - printf("-------------> EXACT CUTTING \n"); - cutElems(elements); - } - else { - splitElems(elements); - } - -} - -void multiscaleLaplace::fillCoordinates (multiscaleLaplaceLevel & level, - std::map<MVertex*, SPoint3> &allCoordinates, - std::vector<double> &iScale, - std::vector<SPoint2> &iCenter) -{ - iScale.push_back(level.scale); - iCenter.push_back(level.center); - - for(unsigned int i = 0; i < level.elements.size(); ++i){ - MElement *e = level.elements[i]; - for(int j = 0; j<e->getNumVertices(); ++j){ - MVertex *v = e->getVertex(j); - SPoint2 coord = level.coordinates[v]; - for (int k= iScale.size()-1; k > 0; k--){ - coord = coord*iScale[k] + iCenter[k]; - } - allCoordinates[v] = SPoint3(coord.x(), coord.y(), 0.0); - } - } - - for (unsigned int i=0;i<level.children.size();i++){ - multiscaleLaplaceLevel* m = level.children[i]; - fillCoordinates(*m, allCoordinates, iScale, iCenter); - } -} - -void multiscaleLaplace::parametrize(multiscaleLaplaceLevel & level) -{ - //Compute all nodes for the level - std::set<MVertex*> allNodes; - for(unsigned int i = 0; i < level.elements.size(); ++i){ - MElement *e = level.elements[i]; - for(int j = 0; j<e->getNumVertices(); ++j){ - allNodes.insert(e->getVertex(j)); - } - } - - //Parametrize level - std::map<MVertex*,SPoint2> solution; - parametrize_method(level, allNodes, solution); - - //Compute the bbox of the parametric space - SBoundingBox3d bbox; - for(std::set<MVertex *>::iterator itv = allNodes.begin(); itv !=allNodes.end() ; ++itv){ - MVertex *v = *itv; - SPoint2 p = solution[v]; - bbox += SPoint3(p.x(),p.y(),0.0); - } - double global_size = bbox.max().distance(bbox.min()); - - //Check elements that are too small - std::vector<MElement*> tooSmall, goodSize; - for(unsigned int i = 0; i < level.elements.size(); ++i){ - MElement *e = level.elements[i]; - std::vector<SPoint2> localCoord; - double local_size = localSize(e,solution); - if (local_size < 1.e-6*global_size) - tooSmall.push_back(e); - else goodSize.push_back(e); - } - - //Only keep the connected elements vectors goodSize (the rest goes into tooSmall) - keepConnected(goodSize, tooSmall); - - //Add the not too small regions to the level.elements - std::vector<std::vector<MElement*> > regions_, regions ; - regions.clear(); regions_.clear(); - connectedRegions (tooSmall,regions_); - for (unsigned int i=0;i< regions_.size() ; i++){ - bool really_small_elements = false; - for (unsigned int k=0; k<regions_[i].size() ; k++){ - MElement *e = regions_[i][k]; - double local_size = localSize(e,solution); - if (local_size < 1.e-8*global_size) //1.e-7 - really_small_elements = true; - } - if(really_small_elements ){ - regions.push_back(regions_[i]); - } - else - goodSize.insert(goodSize.begin(), regions_[i].begin(), regions_[i].end() ); - } - - //check for convex small regions patches - for (unsigned int i = 0; i < regions.size(); i++){ - std::vector<MElement*> &elemR = regions[i]; - v2t_cont adj; - buildVertexToElement (elemR,adj); - for (std::vector<MElement*>::iterator it = elemR.begin(); it != elemR.end(); ++it){ - int nbNeigh = 0; - MElement *e = *it; - v2t_cont::iterator it0 = adj.find(e->getVertex(0)); - if(it0 != adj.end()) nbNeigh += it0->second.size(); - v2t_cont::iterator it1 = adj.find(e->getVertex(1)); - if(it1 != adj.end()) nbNeigh += it1->second.size(); - v2t_cont::iterator it2 = adj.find(e->getVertex(2)); - if(it2 != adj.end()) nbNeigh += it2->second.size(); - std::vector<MElement*>::iterator itp; - if (nbNeigh < 12) { - goodSize.push_back(e); - itp = it; - it++; - elemR.erase(itp); - } - } - keepConnected(elemR, goodSize); - } - tooSmall.clear(); - for (unsigned int i = 0; i < regions.size(); i++) - tooSmall.insert(tooSmall.begin(), regions[i].begin(), regions[i].end()); - - keepConnected(goodSize, tooSmall); - regions.clear(); - connectedRegions (tooSmall,regions); - - level.elements.clear(); - level.elements = goodSize; - - //Fill level.coordinates - std::set<MVertex*> goodSizev; - for(unsigned int i = 0; i < level.elements.size(); ++i){ - MElement *e = level.elements[i]; - for(int j = 0; j<e->getNumVertices(); ++j){ - MVertex *v = e->getVertex(j); - goodSizev.insert(v); - level.coordinates[v] = solution[v]; - } - } - - //Save multiscale meshes - std::string name1(level._name+"real.msh"); - std::string name2(level._name+"param.msh"); - std::string name3(level._name+"param_small.msh"); - printLevel (name1.c_str(),level.elements,0,2.2); - printLevel (name2.c_str(),level.elements,&level.coordinates,2.2); - printLevel_onlysmall (name3.c_str(),level.elements,&level.coordinates,2.2,1.e-15); - - //For every small region compute a new parametrization - Msg::Info("Level (%d-%d): %d connected small regions", - level.recur, level.region, regions.size()); - for (unsigned int i = 0; i < regions.size(); i++){ - std::set<MVertex*> tooSmallv; - tooSmallv.clear(); - for (unsigned int k=0; k<regions[i].size() ; k++){ - MElement *e = regions[i][k]; - for(int j = 0; j<e->getNumVertices(); ++j){ - tooSmallv.insert(e->getVertex(j)); - } - } - - // FIXME: this is never deleted - multiscaleLaplaceLevel *nextLevel = new multiscaleLaplaceLevel; - nextLevel->elements = regions[i]; - nextLevel->recur = level.recur+1; - nextLevel->region = i; - std::stringstream s1 ; s1 << nextLevel->recur; - std::stringstream s2 ; s2 << nextLevel->region; - nextLevel->_name = level._name+"-"+s1.str()+"-"+s2.str(); - SBoundingBox3d smallB; - for(std::set<MVertex *>::iterator itv = tooSmallv.begin(); - itv !=tooSmallv.end(); ++itv){ - SPoint2 p = solution[*itv]; - nextLevel->center += p; - smallB += SPoint3(p.x(),p.y(),0.0); - } - nextLevel->center *= (1./(double)tooSmallv.size()); - nextLevel->scale = smallB.max().distance(smallB.min()); - - for(std::set<MVertex *>::iterator itv = tooSmallv.begin(); - itv !=tooSmallv.end() ; ++itv){ - MVertex *v = *itv; - if (goodSizev.find(v) != goodSizev.end()){ - nextLevel->coordinates[v] = (solution[v]-nextLevel->center) * - (1./nextLevel->scale); - } - } - // recursively continue if tooSmall is not empty - if (!tooSmallv.empty()){ - Msg::Info("Level (%d-%d) Multiscale Laplace (reg[%d] = %d too small)", - level.recur,level.region, i, tooSmallv.size()); - level.children.push_back(nextLevel); - parametrize(*nextLevel); - } - } -} - -void multiscaleLaplace::parametrize_method (multiscaleLaplaceLevel & level, - std::set<MVertex*> &allNodes, - std::map<MVertex*,SPoint2> &solution) -{ - linearSystem<double> *_lsys; -#if defined(HAVE_PETSC) - _lsys = new linearSystemPETSc<double>; -#elif defined(HAVE_GMM) - linearSystemGmm<double> *_lsysb = new linearSystemGmm<double>; - _lsysb->setGmres(1); - _lsys = _lsysb; -#else - _lsys = new linearSystemFull<double>; -#endif - - solution.clear(); - simpleFunction<double> ONE(1.0); - - for (int step =0 ; step<2 ; step++){ - - dofManager<double> myAssembler(_lsys); - for(std::map<MVertex*,SPoint2>::iterator it = level.coordinates.begin(); - it != level.coordinates.end(); ++it){ - MVertex *v = it->first; - myAssembler.fixVertex(v, 0, 1, it->second[step]); - } - - // do the numbering - for(std::set<MVertex *>::iterator itv = allNodes.begin(); - itv != allNodes.end(); ++itv){ - MVertex *v = *itv; - myAssembler.numberVertex(v, 0, 1); - } - - // assemble - femTerm<double> *mapping; - mapping = new convexCombinationTerm(0, 1, &ONE); - - for(unsigned int i = 0; i < level.elements.size(); ++i){ - MElement *e = level.elements[i]; - SElement se(e); - mapping->addToMatrix(myAssembler, &se); - } - - delete mapping; - - // solve - if (myAssembler.sizeOfR() != 0) _lsys->systemSolve(); - - // get the values - for(std::set<MVertex *>::iterator itv = allNodes.begin(); - itv != allNodes.end(); ++itv){ - MVertex *v = *itv; - double value; - myAssembler.getDofValue(v, 0, 1, value); - if (step == 0)solution[v] = SPoint2(value,0); - else solution[v] = SPoint2(solution[v][0],value); - } - _lsys->clear(); - - } - - delete _lsys; -} - -void multiscaleLaplace::cutElems(std::vector<MElement *> &elements) -{ - std::map<MEdge,MVertex*,Less_Edge> cutEdges; - std::set<MEdge,Less_Edge> theCut; - std::set<MVertex*> cutVertices; - elements.clear(); - - recur_cut_edges_ (root, cutEdges,cutVertices); - recur_cut_elements_ (root,cutEdges,cutVertices,theCut, elements); - printCut(cutEdges, theCut, cutVertices); - - std::multimap<MEdge,MElement*,Less_Edge> e2e; - for (unsigned int i = 0; i < elements.size(); ++i){ - for (int j = 0; j < elements[i]->getNumEdges(); j++){ - e2e.insert(std::make_pair(elements[i]->getEdge(j),elements[i])); - } - } - std::set<MElement*> leftS; - leftS.clear(); - std::vector<MElement*> left,right; - recur_leftCut_ (elements[0], e2e, theCut, leftS); - - for (unsigned int i = 0; i < elements.size(); i++){ - MElement *e = elements[i]; - if (leftS.find(e) != leftS.end()) left.push_back(e); - else right.push_back(e); - } - - connected_left_right(left, right); - if (left.size() == 0 || right.size() == 0) { - Msg::Error("KO size left=%d, right=%d not good (zero elems)", - (int) left.size(), (int) right.size() ); - return; - } - - elements.clear(); - elements.insert(elements.end(),left.begin(),left.end()); - elements.insert(elements.end(),right.begin(),right.end()); - - printLevel ("Rootcut-left.msh",left,0,2.2); - printLevel ("Rootcut-right.msh",right,0,2.2); - printLevel ("Rootcut-all.msh",elements, 0,2.2); -} - -void multiscaleLaplace::splitElems(std::vector<MElement *> &elements) -{ - std::vector<MElement*> left,right; - recur_cut_ (1.0, M_PI, 0.0, root,left,right); - connected_left_right(left, right); - - printLevel ("Rootsplit-left.msh",left,0,2.2); - printLevel ("Rootsplit-right.msh",right,0,2.2); - printLevel ("Rootsplit-all.msh",elements, 0,2.2); - - printLevel ("Rootsplit-left-param.msh",left,&root->coordinates,2.2); - // printLevel_onlysmall ("Rootsplit-left-param10.msh",left,&root->coordinates,2.2,1.e-10); - // printLevel_onlysmall ("Rootsplit-left-param12.msh",left,&root->coordinates,2.2,1.e-12); - // printLevel_onlysmall ("Rootsplit-left-param15.msh",left,&root->coordinates,2.2,1.e-15); - - printLevel ("Rootsplit-right-param.msh",right,&root->coordinates,2.2); - // printLevel_onlysmall ("Rootsplit-right-param10.msh",right,&root->coordinates,2.2,1.e-10); - // printLevel_onlysmall ("Rootsplit-right-param12.msh",right,&root->coordinates,2.2,1.e-12); - // printLevel_onlysmall ("Rootsplit-right-param15.msh",right,&root->coordinates,2.2,1.e-15); - - // printLevel_onlysmall ("Rootsplit-all-param12.msh",elements,&root->coordinates,2.2,1.e-12); - // printLevel_onlysmall ("Rootsplit-all-param15.msh",elements,&root->coordinates,2.2,1.e-15); - - if ( elements.size() != left.size()+right.size()) { - Msg::Error("Cutting laplace wrong nb elements (%d) != left + right (%d)", - elements.size(), left.size()+right.size()); - return; - } - - elements.clear(); - elements.insert(elements.end(),left.begin(),left.end()); - elements.insert(elements.end(),right.begin(),right.end()); -} diff --git a/Solver/multiscaleLaplace.h b/Solver/multiscaleLaplace.h deleted file mode 100644 index b5411284fb98a7168387c44d0f2575d72ee8f853..0000000000000000000000000000000000000000 --- a/Solver/multiscaleLaplace.h +++ /dev/null @@ -1,50 +0,0 @@ -// Gmsh - Copyright (C) 1997-2017 C. Geuzaine, J.-F. Remacle -// -// See the LICENSE.txt file for license information. Please report all -// bugs and problems to the public mailing list <gmsh@onelab.info>. - -#ifndef _MULTISCALE_LAPLACE_H_ -#define _MULTISCALE_LAPLACE_H_ - -#include <vector> -#include <map> -#include <set> -#include "SPoint2.h" -#include "SPoint3.h" -#include "linearSystem.h" - -class MElement; -class MVertex; - -struct multiscaleLaplaceLevel { - SPoint2 center; - double scale; - double radius; - int recur,region; - std::vector<multiscaleLaplaceLevel*> children; - std::vector<MElement *> elements; - std::map<MVertex*,SPoint2> coordinates; - std::vector<std::pair<SPoint2,multiscaleLaplaceLevel*> > cut; - std::string _name; -}; - -class multiscaleLaplace{ -public: - multiscaleLaplace (std::vector<MElement *> &elements, - std::map<MVertex*, SPoint3> &allCoordinates); - void cutElems (std::vector<MElement *> &elements); - void splitElems (std::vector<MElement *> &elements); - - multiscaleLaplaceLevel* root; - void fillCoordinates (multiscaleLaplaceLevel & level, - std::map<MVertex*, SPoint3> &allCoordinates, - std::vector<double> &iScale, - std::vector<SPoint2> &iCenter); - void parametrize (multiscaleLaplaceLevel &); - void parametrize_method (multiscaleLaplaceLevel & level, - std::set<MVertex*> &allNodes, - std::map<MVertex*,SPoint2> &solution); - - -}; -#endif diff --git a/doc/texinfo/gmsh.texi b/doc/texinfo/gmsh.texi index 2378519e840ace89e832c4c59fbb6065ad6d4f8c..f645649b3bb3455828860c32ce8e6df91e2fa633 100644 --- a/doc/texinfo/gmsh.texi +++ b/doc/texinfo/gmsh.texi @@ -1963,16 +1963,6 @@ Creates a path made of lines. Wires are only available with the OpenCASCADE kernel. They are used to create @code{ThruSections} and extrusions along paths. -@item Compound Line ( @var{expression} ) = @{ @var{expression-list} @}; -Creates a compound line from several elementary lines. When meshed, a -compound line will be reparametrized as a single line, whose mesh can -thus cross internal boundaries. The @var{expression} inside the -parentheses is the compound line's identification number; the -@var{expression-list} on the right hand side contains the identification -number of the elementary lines that should be reparametrized as a single -line. See @code{Compound Surface} for additional information on compound -entities. - @item Physical Line ( @var{expression} | @var{char-expression} <, @var{expression}> ) <+|->= @{ @var{expression-list} @}; Creates a physical line. The @var{expression} inside the parentheses is the physical line's identification number; the @var{expression-list} on @@ -2043,19 +2033,6 @@ elementary surfaces should be oriented consistently (using negative identification numbers to specify reverse orientation). (Surface loops are used to create volumes: see @ref{Volumes}.) -@item Compound Surface ( @var{expression} ) = @{ @var{expression-list} @} < Boundary @{ @{ @var{expression-list} @}, @{ @var{expression-list} @}, @{ @var{expression-list} @}, @{ @var{expression-list} @} @} > ; -Creates a compound surface from several elementary surfaces. When -meshed, a compound surface will be reparametrized as a single surface, -whose mesh can thus cross internal boundaries. Compound surfaces are -mostly useful for remeshing discrete models; see ``J.-F. Remacle, -C. Geuzaine, G. Compere and E. Marchandise, @emph{High Quality Surface -Remeshing Using Harmonic Maps}, International Journal for Numerical -Methods in Engineering, 2009'' for details as well as the wiki for more -examples. The @var{expression} inside the parentheses is the compound -surface's identification number; the mandatory @var{expression-list} on -the right hand side contains the identification number of the elementary -surfaces that should be reparametrized as a single surface. - @item Physical Surface ( @var{expression} | @var{char-expression} <, @var{expression}> ) <+|->= @{ @var{expression-list} @}; Creates a physical surface. The @var{expression} inside the parentheses is the physical surface's identification number; the @@ -2143,16 +2120,6 @@ the OpenCASCADE kernel. @c @item ThickSolid ( @var{expression} ) = @{ @var{expression-list} @}; @c todo: @code{ThickSolid} is only available with the OpenCASCADE kernel. -@item Compound Volume ( @var{expression} ) = @{ @var{expression-list} @}; -Creates a compound volume from several elementary volumes. When meshed, -a compound volume will be reparametrized as a single volume, whose mesh -can thus cross internal boundaries. The @var{expression} inside the -parentheses is the compound volume's identification number; the -@var{expression-list} on the right hand side contains the identification -number of the elementary volumes that should be reparametrized as a -single volume. See @code{Compound Surface} for additional information on -compound entities. - @item Physical Volume ( @var{expression} | @var{char-expression} <, @var{expression}> ) <+|->= @{ @var{expression-list} @}; Creates a physical volume. The @var{expression} inside the parentheses is the physical volume's identification number; the