diff --git a/doc/salome/gui/SMESH/input/over_constrained_faces.doc b/doc/salome/gui/SMESH/input/over_constrained_faces.doc index 6c026f84a..d4c563030 100644 --- a/doc/salome/gui/SMESH/input/over_constrained_faces.doc +++ b/doc/salome/gui/SMESH/input/over_constrained_faces.doc @@ -4,10 +4,11 @@ \n This mesh quality control highlights faces sharing only one border with other faces. In other words, the faces having all thier nodes on -the external border of the mesh are highlighted. +the free border of the 2D mesh are highlighted. -\note The highlighted faces are actually over-constrained only if, at the computation time, -the boundary conditions on the borders where the nodes are located are all Dirichlet boundary conditions. +\note The highlighted faces are actually over-constrained only if, at +the computation time, the boundary conditions on the borders where the +nodes are located are all Dirichlet boundary conditions. \image html over_constrained_faces.png diff --git a/resources/SalomeApp.xml.in b/resources/SalomeApp.xml.in index c1f99f6a4..4020eecc7 100644 --- a/resources/SalomeApp.xml.in +++ b/resources/SalomeApp.xml.in @@ -122,7 +122,7 @@ - +
diff --git a/src/Controls/SMESH_Controls.cxx b/src/Controls/SMESH_Controls.cxx index 4ac7baab5..e4efffe41 100644 --- a/src/Controls/SMESH_Controls.cxx +++ b/src/Controls/SMESH_Controls.cxx @@ -1832,10 +1832,10 @@ void Length2D::GetValues(TValues& theValues) dynamic_cast(anElem); // use special nodes iterator SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator(); - long aNodeId[4]; + long aNodeId[4] = { 0,0,0,0 }; gp_Pnt P[4]; - double aLength; + double aLength = 0; const SMDS_MeshElement* aNode; if(anIter->more()){ aNode = anIter->next(); @@ -1957,7 +1957,7 @@ double MultiConnection2D::GetValue( long theElementId ) SMDS_ElemIteratorPtr anIter = aFaceElem->nodesIterator(); if (!anIter) break; - const SMDS_MeshNode *aNode, *aNode0; + const SMDS_MeshNode *aNode, *aNode0 = 0; TColStd_MapOfInteger aMap, aMapPrev; for (i = 0; i <= len; i++) { @@ -2038,7 +2038,7 @@ void MultiConnection2D::GetValues(MValues& theValues) (anElem)->interlacedNodesElemIterator(); else aNodesIter = anElem->nodesIterator(); - long aNodeId[3]; + long aNodeId[3] = {0,0,0}; //int aNbConnects=0; const SMDS_MeshNode* aNode0; @@ -2511,7 +2511,7 @@ void FreeEdges::GetBoreders(TBorders& theBorders) interlacedNodesElemIterator(); else aNodesIter = anElem->nodesIterator(); - long aNodeId[2]; + long aNodeId[2] = {0,0}; const SMDS_MeshElement* aNode; if(aNodesIter->more()){ aNode = aNodesIter->next(); diff --git a/src/DriverMED/DriverMED_R_SMESHDS_Mesh.cxx b/src/DriverMED/DriverMED_R_SMESHDS_Mesh.cxx index 4e922c872..3164ae065 100644 --- a/src/DriverMED/DriverMED_R_SMESHDS_Mesh.cxx +++ b/src/DriverMED/DriverMED_R_SMESHDS_Mesh.cxx @@ -42,7 +42,7 @@ //#include #ifdef _DEBUG_ -static int MYDEBUG = 1; +static int MYDEBUG = 0; //#define _DEXCEPT_ #else static int MYDEBUG = 0; diff --git a/src/MEDWrapper/Base/MED_Wrapper.cxx b/src/MEDWrapper/Base/MED_Wrapper.cxx index ad1a4fd52..745872228 100644 --- a/src/MEDWrapper/Base/MED_Wrapper.cxx +++ b/src/MEDWrapper/Base/MED_Wrapper.cxx @@ -644,7 +644,7 @@ namespace MED TIntVector aVec; aVec.resize(theMeshInfo->GetDim()); for(int aAxe=0;aAxeGetDim();aAxe++){ - ETable aATable; + ETable aATable = eCOOR_IND1; switch(aAxe){ case 0: aATable = eCOOR_IND1; diff --git a/src/MEDWrapper/V2_2/MED_V2_2_Wrapper.cxx b/src/MEDWrapper/V2_2/MED_V2_2_Wrapper.cxx index 0bbfb2148..934839742 100644 --- a/src/MEDWrapper/V2_2/MED_V2_2_Wrapper.cxx +++ b/src/MEDWrapper/V2_2/MED_V2_2_Wrapper.cxx @@ -2739,7 +2739,7 @@ namespace MED } if(aMaillageType == eSTRUCTURE && aGrilleType != eGRILLE_STANDARD){ - ETable aTable; + ETable aTable = eCOOR_IND1; for(med_int anAxis = 1; anAxis <= aMeshInfo.myDim; anAxis++){ switch(anAxis){ case 1 : diff --git a/src/OBJECT/SMESH_Actor.cxx b/src/OBJECT/SMESH_Actor.cxx index 0ec723103..b0136d8e4 100644 --- a/src/OBJECT/SMESH_Actor.cxx +++ b/src/OBJECT/SMESH_Actor.cxx @@ -82,9 +82,9 @@ #include "utilities.h" #ifdef _DEBUG_ -static int MYDEBUG = 1; +static int MYDEBUG = 0; #else -static int MYDEBUG = 1; +static int MYDEBUG = 0; #endif static int aLineWidthInc = 2; @@ -799,8 +799,7 @@ SetControlMode(eControl theMode) void SMESH_ActorDef:: -SetControlMode(eControl theMode, - bool theCheckEntityMode) +SetControlMode( eControl theMode, bool theCheckEntityMode ) { vtkLookupTable* lookupTable = static_cast(myScalarBarActor->GetLookupTable()); bool isLogarithmic = lookupTable->GetScale() == VTK_SCALE_LOG10; diff --git a/src/OBJECT/SMESH_DeviceActor.cxx b/src/OBJECT/SMESH_DeviceActor.cxx index 5dcaf64f8..4520d9327 100644 --- a/src/OBJECT/SMESH_DeviceActor.cxx +++ b/src/OBJECT/SMESH_DeviceActor.cxx @@ -311,7 +311,7 @@ SMESH_DeviceActor vtkIdType aNbCells = aGrid->GetNumberOfCells(); aScalars->SetNumberOfComponents(1); aScalars->SetNumberOfTuples(aNbCells); - double* range;// = aScalars->GetRange(); + double* range = 0;// = aScalars->GetRange(); myVisualObj->UpdateFunctor(theFunctor); diff --git a/src/OBJECT/SMESH_Object.cxx b/src/OBJECT/SMESH_Object.cxx index 2997063e5..61b36a78c 100644 --- a/src/OBJECT/SMESH_Object.cxx +++ b/src/OBJECT/SMESH_Object.cxx @@ -67,7 +67,7 @@ using namespace std; #endif #ifdef _DEBUG_ -static int MYDEBUG = 1; +static int MYDEBUG = 0; static int MYDEBUGWITHFILES = 0;//1; #else static int MYDEBUG = 0; @@ -133,7 +133,7 @@ static int MYDEBUGWITHFILES = 0; //================================================================================= SMESH_VisualObjDef::SMESH_VisualObjDef() { - MESSAGE("---------------------------------------------SMESH_VisualObjDef::SMESH_VisualObjDef"); + if ( MYDEBUG ) MESSAGE("-------------------------------SMESH_VisualObjDef::SMESH_VisualObjDef"); myGrid = vtkUnstructuredGrid::New(); myLocalGrid = false; ClearEntitiesFlags(); @@ -141,9 +141,8 @@ SMESH_VisualObjDef::SMESH_VisualObjDef() } SMESH_VisualObjDef::~SMESH_VisualObjDef() { - MESSAGE("---------------------------------------------SMESH_VisualObjDef::~SMESH_VisualObjDef"); - //if ( MYDEBUG ) - MESSAGE( "~SMESH_MeshObj - myGrid->GetReferenceCount() = " << myGrid->GetReferenceCount() ); + if ( MYDEBUG ) MESSAGE("--------------------------------SMESH_VisualObjDef::~SMESH_VisualObjDef"); + if ( MYDEBUG ) MESSAGE( "myGrid->GetReferenceCount() = " << myGrid->GetReferenceCount() ); myGrid->Delete(); } @@ -248,7 +247,7 @@ void SMESH_VisualObjDef::createPoints( vtkPoints* thePoints ) //================================================================================= void SMESH_VisualObjDef::buildPrs(bool buildGrid) { - MESSAGE("----------------------------------------------------------SMESH_VisualObjDef::buildPrs " << buildGrid); + if ( MYDEBUG ) MESSAGE("---------------------------SMESH_VisualObjDef::buildPrs " << buildGrid); if (buildGrid) { myLocalGrid = true; @@ -281,7 +280,7 @@ void SMESH_VisualObjDef::buildPrs(bool buildGrid) myLocalGrid = false; if (!GetMesh()->isCompacted()) { - MESSAGE("*** buildPrs ==> compactMesh!"); + if ( MYDEBUG ) MESSAGE("*** buildPrs ==> compactMesh!"); GetMesh()->compactMesh(); } vtkUnstructuredGrid *theGrid = GetMesh()->getGrid(); @@ -697,9 +696,9 @@ SMESH_MeshObj::~SMESH_MeshObj() bool SMESH_MeshObj::Update( int theIsClear ) { // Update SMDS_Mesh on client part - MESSAGE("SMESH_MeshObj::Update " << this); + if ( MYDEBUG ) MESSAGE("SMESH_MeshObj::Update " << this); if ( myClient.Update(theIsClear) || GetUnstructuredGrid()->GetNumberOfPoints()==0) { - MESSAGE("buildPrs"); + if ( MYDEBUG ) MESSAGE("buildPrs"); buildPrs(); // Fill unstructured grid return true; } @@ -708,7 +707,7 @@ bool SMESH_MeshObj::Update( int theIsClear ) bool SMESH_MeshObj::NulData() { - MESSAGE ("SMESH_MeshObj::NulData() =================================================================================="); + if ( MYDEBUG ) MESSAGE ("SMESH_MeshObj::NulData() ============================================="); if (!myEmptyGrid) { myEmptyGrid = SMDS_UnstructuredGrid::New(); @@ -901,7 +900,7 @@ void SMESH_SubMeshObj::UpdateFunctor( const SMESH::Controls::FunctorPtr& theFunc //================================================================================= bool SMESH_SubMeshObj::Update( int theIsClear ) { - MESSAGE("SMESH_SubMeshObj::Update " << this) + if ( MYDEBUG ) MESSAGE("SMESH_SubMeshObj::Update " << this) bool changed = myMeshObj->Update( theIsClear ); buildPrs(true); return changed; diff --git a/src/OBJECT/SMESH_ScalarBarActor.cxx b/src/OBJECT/SMESH_ScalarBarActor.cxx index 7b5eb231e..92a8a94b4 100644 --- a/src/OBJECT/SMESH_ScalarBarActor.cxx +++ b/src/OBJECT/SMESH_ScalarBarActor.cxx @@ -321,8 +321,8 @@ int SMESH_ScalarBarActor::RenderOpaqueGeometry(vtkViewport *viewport) // rnv begin // Customization of the vtkScalarBarActor to show distribution histogram. bool distrVisibility = (numColors == (int)this->myNbValues.size()); - vtkPoints *distrPts; - vtkCellArray *distrPolys; + vtkPoints *distrPts = 0; + vtkCellArray *distrPolys = 0; vtkUnsignedCharArray *distColors = 0; int numDistrPts = 0, numPositiveVal=0, maxValue=0; if(!distrVisibility) diff --git a/src/SMDS/SMDS_Mesh.cxx b/src/SMDS/SMDS_Mesh.cxx index 578782ae0..6582e23f1 100644 --- a/src/SMDS/SMDS_Mesh.cxx +++ b/src/SMDS/SMDS_Mesh.cxx @@ -525,7 +525,6 @@ SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshEdge * e1, if ( !e1 || !e2 || !e3 ) return 0; if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory(); - MESSAGE("AddFaceWithID" << ID); SMDS_MeshFace * face = new SMDS_FaceOfEdges(e1,e2,e3); adjustmyCellsCapacity(ID); @@ -552,7 +551,6 @@ SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshEdge * e1, { if (!hasConstructionEdges()) return NULL; - //MESSAGE("AddFaceWithID" ); return AddFaceWithID(e1,e2,e3,e4, myElementIDFactory->GetFreeID()); } @@ -568,7 +566,6 @@ SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshEdge * e1, { if (!hasConstructionEdges()) return NULL; - MESSAGE("AddFaceWithID" << ID); if ( !e1 || !e2 || !e3 || !e4 ) return 0; if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory(); SMDS_MeshFace * face = new SMDS_FaceOfEdges(e1,e2,e3,e4); @@ -596,7 +593,6 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1, const SMDS_MeshNode * n4) { int ID = myElementIDFactory->GetFreeID(); - //MESSAGE("AddVolumeWithID " << ID); SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, ID); if(v==NULL) myElementIDFactory->ReleaseID(ID); return v; @@ -615,7 +611,6 @@ SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1, int idnode4, int ID) { - //MESSAGE("AddVolumeWithID" << ID); SMDS_MeshNode *node1, *node2, *node3, *node4; node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1); node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2); @@ -637,7 +632,6 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1, const SMDS_MeshNode * n4, int ID) { - //MESSAGE("AddVolumeWithID " << ID); SMDS_MeshVolume* volume = 0; if ( !n1 || !n2 || !n3 || !n4) return volume; if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory(); @@ -652,7 +646,6 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1, myInfo.myNbTetras++; } else if(hasConstructionEdges()) { - MESSAGE("Error : Not implemented"); return NULL; } else { @@ -697,7 +690,6 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1, const SMDS_MeshNode * n5) { int ID = myElementIDFactory->GetFreeID(); - //MESSAGE("AddVolumeWithID " << ID); SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, ID); if(v==NULL) myElementIDFactory->ReleaseID(ID); return v; @@ -718,7 +710,6 @@ SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1, int idnode5, int ID) { - //MESSAGE("AddVolumeWithID " << ID); SMDS_MeshNode *node1, *node2, *node3, *node4, *node5; node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1); node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2); @@ -743,7 +734,6 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1, const SMDS_MeshNode * n5, int ID) { - //MESSAGE("AddVolumeWithID " << ID); SMDS_MeshVolume* volume = 0; if ( !n1 || !n2 || !n3 || !n4 || !n5) return volume; if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory(); @@ -758,7 +748,6 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1, myInfo.myNbPyramids++; } else if(hasConstructionEdges()) { - MESSAGE("Error : Not implemented"); return NULL; } else { @@ -805,7 +794,6 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1, const SMDS_MeshNode * n6) { int ID = myElementIDFactory->GetFreeID(); - //MESSAGE("AddVolumeWithID " << ID); SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, ID); if(v==NULL) myElementIDFactory->ReleaseID(ID); return v; @@ -827,7 +815,6 @@ SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1, int idnode6, int ID) { - //MESSAGE("AddVolumeWithID " << ID); SMDS_MeshNode *node1, *node2, *node3, *node4, *node5, *node6; node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1); node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2); @@ -854,7 +841,6 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1, const SMDS_MeshNode * n6, int ID) { - //MESSAGE("AddVolumeWithID " << ID); SMDS_MeshVolume* volume = 0; if ( !n1 || !n2 || !n3 || !n4 || !n5 || !n6) return volume; if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory(); @@ -870,7 +856,6 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1, myInfo.myNbPrisms++; } else if(hasConstructionEdges()) { - MESSAGE("Error : Not implemented"); return NULL; } else { @@ -994,11 +979,9 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1, return volume; if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory(); if(hasConstructionFaces()) { - MESSAGE("Error : Not implemented"); return NULL; } else if(hasConstructionEdges()) { - MESSAGE("Error : Not implemented"); return NULL; } else { @@ -1074,7 +1057,6 @@ SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1, int idnode8, int ID) { - //MESSAGE("AddVolumeWithID " << ID); SMDS_MeshNode *node1, *node2, *node3, *node4, *node5, *node6, *node7, *node8; node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1); node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2); @@ -1108,7 +1090,6 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1, const SMDS_MeshNode * n8, int ID) { - //MESSAGE("AddVolumeWithID " << ID); SMDS_MeshVolume* volume = 0; if ( !n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8) return volume; if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory(); @@ -1125,7 +1106,6 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1, myInfo.myNbHexas++; } else if(hasConstructionEdges()) { - MESSAGE("Error : Not implemented"); return NULL; } else { @@ -1171,7 +1151,6 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshFace * f1, const SMDS_MeshFace * f3, const SMDS_MeshFace * f4) { - //MESSAGE("AddVolumeWithID"); if (!hasConstructionFaces()) return NULL; return AddVolumeWithID(f1,f2,f3,f4, myElementIDFactory->GetFreeID()); @@ -1189,7 +1168,6 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshFace * f1, const SMDS_MeshFace * f4, int ID) { - MESSAGE("AddVolumeWithID" << ID); if (!hasConstructionFaces()) return NULL; if ( !f1 || !f2 || !f3 || !f4) return 0; @@ -1218,7 +1196,6 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshFace * f1, const SMDS_MeshFace * f4, const SMDS_MeshFace * f5) { - //MESSAGE("AddVolumeWithID"); if (!hasConstructionFaces()) return NULL; return AddVolumeWithID(f1,f2,f3,f4,f5, myElementIDFactory->GetFreeID()); @@ -1237,7 +1214,6 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshFace * f1, const SMDS_MeshFace * f5, int ID) { - MESSAGE("AddVolumeWithID" << ID); if (!hasConstructionFaces()) return NULL; if ( !f1 || !f2 || !f3 || !f4 || !f5) return 0; @@ -1267,7 +1243,6 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshFace * f1, const SMDS_MeshFace * f5, const SMDS_MeshFace * f6) { - //MESSAGE("AddVolumeWithID" ); if (!hasConstructionFaces()) return NULL; return AddVolumeWithID(f1,f2,f3,f4,f5,f6, myElementIDFactory->GetFreeID()); @@ -1287,7 +1262,6 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshFace * f1, const SMDS_MeshFace * f6, int ID) { - MESSAGE("AddVolumeWithID" << ID); if (!hasConstructionFaces()) return NULL; if ( !f1 || !f2 || !f3 || !f4 || !f5 || !f6) return 0; @@ -1334,7 +1308,6 @@ SMDS_Mesh::AddPolygonalFaceWithID (const vector & nodes, if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory(); if (hasConstructionEdges()) { - MESSAGE("Error : Not implemented"); return NULL; } else @@ -1399,7 +1372,6 @@ SMDS_Mesh::AddQuadPolygonalFaceWithID (const vector & node if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory(); if (hasConstructionEdges()) { - MESSAGE("Error : Not implemented"); return NULL; } else @@ -1472,18 +1444,15 @@ SMDS_Mesh::AddPolyhedralVolumeWithID (const vector& nodes, if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory(); if (hasConstructionFaces()) { - MESSAGE("Error : Not implemented"); return NULL; } else if (hasConstructionEdges()) { - MESSAGE("Error : Not implemented"); return NULL; } else { //#ifdef VTK_HAVE_POLYHEDRON - //MESSAGE("AddPolyhedralVolumeWithID vtk " << ID); myNodeIds.resize( nodes.size() ); for ( size_t i = 0; i < nodes.size(); ++i ) myNodeIds[i] = nodes[i]->getVtkId(); @@ -1498,7 +1467,6 @@ SMDS_Mesh::AddPolyhedralVolumeWithID (const vector& nodes, } volume = volvtk; //#else - // MESSAGE("AddPolyhedralVolumeWithID smds " << ID); // for ( int i = 0; i < nodes.size(); ++i ) // if ( !nodes[ i ] ) return 0; // volume = new SMDS_PolyhedralVolumeOfNodes(nodes, quantities); @@ -1648,7 +1616,6 @@ SMDS_MeshFace* SMDS_Mesh::AddFaceFromVtkIdsWithID(const std::vector& /////////////////////////////////////////////////////////////////////////////// bool SMDS_Mesh::registerElement(int ID, SMDS_MeshElement* element) { - //MESSAGE("registerElement " << ID); if ((ID >=0) && (ID < (int)myCells.size()) && myCells[ID]) // --- already bound { MESSAGE(" ------------------ already bound "<< ID << " " << myCells[ID]->getVtkId()); @@ -1666,7 +1633,6 @@ bool SMDS_Mesh::registerElement(int ID, SMDS_MeshElement* element) if (vtkId >= (int)myCellIdVtkToSmds.size()) // --- resize local vector { -// MESSAGE(" --------------------- resize myCellIdVtkToSmds " << vtkId << " --> " << vtkId + SMDS_Mesh::chunkSize); myCellIdVtkToSmds.resize(vtkId + SMDS_Mesh::chunkSize, -1); } myCellIdVtkToSmds[vtkId] = ID; @@ -1693,9 +1659,6 @@ const SMDS_MeshNode * SMDS_Mesh::FindNode(int ID) const { if (ID < 1 || ID >= (int)myNodes.size()) { -// MESSAGE("------------------------------------------------------------------------- "); -// MESSAGE("----------------------------------- bad ID " << ID << " " << myNodes.size()); -// MESSAGE("------------------------------------------------------------------------- "); return 0; } return (const SMDS_MeshNode *)myNodes[ID]; @@ -1762,7 +1725,6 @@ SMDS_MeshFace * SMDS_Mesh::createTriangle(const SMDS_MeshNode * node1, face = facevtk; adjustmyCellsCapacity(ID); myCells[ID] = face; - //MESSAGE("createTriangle " << ID << " " << face); myInfo.myNbTriangles++; return face; } @@ -1782,7 +1744,6 @@ SMDS_MeshFace * SMDS_Mesh::createQuadrangle(const SMDS_MeshNode * node1, if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory(); if(hasConstructionEdges()) { - //MESSAGE("createQuadrangle hasConstructionEdges "<< ID); SMDS_MeshEdge *edge1, *edge2, *edge3, *edge4; edge1=FindEdgeOrCreate(node1,node2); edge2=FindEdgeOrCreate(node2,node3); @@ -1827,7 +1788,6 @@ SMDS_MeshFace * SMDS_Mesh::createQuadrangle(const SMDS_MeshNode * node1, void SMDS_Mesh::RemoveNode(const SMDS_MeshNode * node) { - MESSAGE("RemoveNode"); RemoveElement(node, true); } @@ -1837,7 +1797,6 @@ void SMDS_Mesh::RemoveNode(const SMDS_MeshNode * node) void SMDS_Mesh::Remove0DElement(const SMDS_Mesh0DElement * elem0d) { - MESSAGE("Remove0DElement"); RemoveElement(elem0d,true); } @@ -1847,7 +1806,6 @@ void SMDS_Mesh::Remove0DElement(const SMDS_Mesh0DElement * elem0d) void SMDS_Mesh::RemoveEdge(const SMDS_MeshEdge * edge) { - MESSAGE("RemoveEdge"); RemoveElement(edge,true); } @@ -1857,7 +1815,6 @@ void SMDS_Mesh::RemoveEdge(const SMDS_MeshEdge * edge) void SMDS_Mesh::RemoveFace(const SMDS_MeshFace * face) { - MESSAGE("RemoveFace"); RemoveElement(face, true); } @@ -1867,7 +1824,6 @@ void SMDS_Mesh::RemoveFace(const SMDS_MeshFace * face) void SMDS_Mesh::RemoveVolume(const SMDS_MeshVolume * volume) { - MESSAGE("RemoveVolume"); RemoveElement(volume, true); } @@ -1914,7 +1870,6 @@ bool SMDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * element, const SMDS_MeshNode * nodes[], const int nbnodes) { - MESSAGE("SMDS_Mesh::ChangeElementNodes"); // keep current nodes of elem set oldNodes( element->begin_nodes(), element->end_nodes() ); @@ -2428,11 +2383,6 @@ const SMDS_MeshElement* SMDS_Mesh::FindElement(int IDelem) const { if ( IDelem <= 0 || IDelem >= (int)myCells.size() ) { - MESSAGE("--------------------------------------------------------------------------------- "); - MESSAGE("----------------------------------- bad IDelem " << IDelem << " " << myCells.size()); - MESSAGE("--------------------------------------------------------------------------------- "); - // TODO raise an exception - //assert(0); return 0; } return myCells[IDelem]; @@ -2505,9 +2455,8 @@ const SMDS_MeshElement* SMDS_Mesh::FindElement (const vectormore()) ; //MESSAGE(itnode->next()); + SMDS_NodeIteratorPtr itnode=nodesIterator(); + while(itnode->more()) ; //MESSAGE(itnode->next()); } //======================================================================= @@ -2516,7 +2465,6 @@ void SMDS_Mesh::DumpNodes() const //======================================================================= void SMDS_Mesh::Dump0DElements() const { - MESSAGE("dump 0D elements of mesh : "); SMDS_ElemIteratorPtr it0d = elementsIterator(SMDSAbs_0DElement); while(it0d->more()) ; //MESSAGE(it0d->next()); } @@ -2528,9 +2476,8 @@ void SMDS_Mesh::Dump0DElements() const void SMDS_Mesh::DumpEdges() const { - MESSAGE("dump edges of mesh : "); - SMDS_EdgeIteratorPtr itedge=edgesIterator(); - while(itedge->more()) ; //MESSAGE(itedge->next()); + SMDS_EdgeIteratorPtr itedge=edgesIterator(); + while(itedge->more()) ; //MESSAGE(itedge->next()); } //======================================================================= @@ -2540,9 +2487,8 @@ void SMDS_Mesh::DumpEdges() const void SMDS_Mesh::DumpFaces() const { - MESSAGE("dump faces of mesh : "); - SMDS_FaceIteratorPtr itface=facesIterator(); - while(itface->more()) ; //MESSAGE(itface->next()); + SMDS_FaceIteratorPtr itface=facesIterator(); + while(itface->more()) ; //MESSAGE(itface->next()); } //======================================================================= @@ -2552,9 +2498,8 @@ void SMDS_Mesh::DumpFaces() const void SMDS_Mesh::DumpVolumes() const { - MESSAGE("dump volumes of mesh : "); - SMDS_VolumeIteratorPtr itvol=volumesIterator(); - while(itvol->more()) ; //MESSAGE(itvol->next()); + SMDS_VolumeIteratorPtr itvol=volumesIterator(); + while(itvol->more()) ; //MESSAGE(itvol->next()); } //======================================================================= @@ -2612,10 +2557,7 @@ void SMDS_Mesh::DebugStats() const /////////////////////////////////////////////////////////////////////////////// int SMDS_Mesh::NbNodes() const { - //MESSAGE(myGrid->GetNumberOfPoints()); - //MESSAGE(myInfo.NbNodes()); - //MESSAGE(myNodeMax); - return myInfo.NbNodes(); + return myInfo.NbNodes(); } /////////////////////////////////////////////////////////////////////////////// @@ -2718,7 +2660,6 @@ SMDS_Mesh::~SMDS_Mesh() void SMDS_Mesh::Clear() { - MESSAGE("SMDS_Mesh::Clear"); if (myParent!=NULL) { SMDS_ElemIteratorPtr eIt = elementsIterator(); @@ -3077,34 +3018,31 @@ static set * intersectionOfSets( /////////////////////////////////////////////////////////////////////////////// static set * getFinitElements(const SMDS_MeshElement * element) { - int numberOfSets=element->NbNodes(); - set *initSet = new set[numberOfSets]; + int numberOfSets=element->NbNodes(); + set *initSet = new set[numberOfSets]; - SMDS_ElemIteratorPtr itNodes=element->nodesIterator(); + SMDS_ElemIteratorPtr itNodes=element->nodesIterator(); - int i=0; - while(itNodes->more()) - { - const SMDS_MeshElement* node = itNodes->next(); - MYASSERT(node); - const SMDS_MeshNode * n=static_cast(node); - SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator(); + int i = 0; + while ( itNodes->more() ) + { + const SMDS_MeshElement* node = itNodes->next(); + MYASSERT(node); + const SMDS_MeshNode * n=static_cast(node); + SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator(); - //initSet[i]=set(); - while(itFe->more()) - { - const SMDS_MeshElement* elem = itFe->next(); - MYASSERT(elem); - initSet[i].insert(elem); + while ( itFe->more() ) + { + const SMDS_MeshElement* elem = itFe->next(); + MYASSERT(elem); + initSet[i].insert(elem); + } - } - - i++; - } - set *retSet=intersectionOfSets(initSet, numberOfSets); -// MESSAGE("nb elems " << i << " intersection " << retSet->size()); - delete [] initSet; - return retSet; + i++; + } + set *retSet = intersectionOfSets( initSet, numberOfSets ); + delete [] initSet; + return retSet; } /////////////////////////////////////////////////////////////////////////////// @@ -3401,11 +3339,9 @@ void SMDS_Mesh::RemoveFreeElement(const SMDS_MeshElement * elem) { int elemId = elem->GetID(); int vtkId = elem->getVtkId(); - //MESSAGE("RemoveFreeElement " << elemId); SMDSAbs_ElementType aType = elem->GetType(); SMDS_MeshElement* todest = (SMDS_MeshElement*)(elem); if (aType == SMDSAbs_Node) { - //MESSAGE("Remove free node " << elemId); // only free node can be removed by this method const SMDS_MeshNode* n = static_cast(todest); SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator(); @@ -3422,7 +3358,6 @@ void SMDS_Mesh::RemoveFreeElement(const SMDS_MeshElement * elem) // this methods is only for meshes without descendants return; - //MESSAGE("Remove free element " << elemId); // Remove element from of its nodes SMDS_ElemIteratorPtr itn = elem->nodesIterator(); while (itn->more()) { @@ -3538,7 +3473,6 @@ int SMDS_Mesh::MinElementID() const void SMDS_Mesh::Renumber (const bool isNodes, const int startID, const int deltaID) { - MESSAGE("Renumber"); if ( deltaID == 0 ) return; @@ -4709,17 +4643,14 @@ void SMDS_Mesh::incrementNodesCapacity(int nbNodes) // MESSAGE(" ------------------- resize myCellIdSmdsToVtk " << val << " --> " << val + nbNodes); // myCellIdSmdsToVtk.resize(val + nbNodes, -1); // fill new elements with -1 int val = myNodes.size(); - MESSAGE(" ------------------- resize myNodes " << val << " --> " << val + nbNodes); myNodes.resize(val +nbNodes, 0); } void SMDS_Mesh::incrementCellsCapacity(int nbCells) { int val = myCellIdVtkToSmds.size(); - MESSAGE(" ------------------- resize myCellIdVtkToSmds " << val << " --> " << val + nbCells); myCellIdVtkToSmds.resize(val + nbCells, -1); // fill new elements with -1 val = myCells.size(); - MESSAGE(" ------------------- resize myCells " << val << " --> " << val + nbCells); myNodes.resize(val +nbCells, 0); } @@ -4730,48 +4661,45 @@ void SMDS_Mesh::adjustStructure() void SMDS_Mesh::dumpGrid(string ficdump) { - MESSAGE("SMDS_Mesh::dumpGrid " << ficdump); -// vtkUnstructuredGridWriter* aWriter = vtkUnstructuredGridWriter::New(); -// aWriter->SetFileName(ficdump.c_str()); -// aWriter->SetInput(myGrid); -// if(myGrid->GetNumberOfCells()) -// { -// aWriter->Write(); -// } -// aWriter->Delete(); + // vtkUnstructuredGridWriter* aWriter = vtkUnstructuredGridWriter::New(); + // aWriter->SetFileName(ficdump.c_str()); + // aWriter->SetInput(myGrid); + // if(myGrid->GetNumberOfCells()) + // { + // aWriter->Write(); + // } + // aWriter->Delete(); ficdump = ficdump + "_connectivity"; ofstream ficcon(ficdump.c_str(), ios::out); int nbPoints = myGrid->GetNumberOfPoints(); ficcon << "-------------------------------- points " << nbPoints << endl; for (int i=0; iGetPoint(i)) << " " << *(myGrid->GetPoint(i)+1) << " " << " " << *(myGrid->GetPoint(i)+2) << endl; + ficcon << i << " " << *(myGrid->GetPoint(i)) << " " << *(myGrid->GetPoint(i)+1) << " " << " " << *(myGrid->GetPoint(i)+2) << endl; } int nbCells = myGrid->GetNumberOfCells(); ficcon << "-------------------------------- cells " << nbCells << endl; for (int i=0; iGetCell(i)); -// MESSAGE(" " << myGrid->GetCell(i)->GetCellType()); - ficcon << i << " - " << myGrid->GetCell(i)->GetCellType() << " -"; - int nbptcell = myGrid->GetCell(i)->GetNumberOfPoints(); - vtkIdList *listid = myGrid->GetCell(i)->GetPointIds(); - for (int j=0; jGetId(j); - } - ficcon << endl; + ficcon << i << " - " << myGrid->GetCell(i)->GetCellType() << " -"; + int nbptcell = myGrid->GetCell(i)->GetNumberOfPoints(); + vtkIdList *listid = myGrid->GetCell(i)->GetPointIds(); + for (int j=0; jGetId(j); + } + ficcon << endl; } ficcon << "-------------------------------- connectivity " << nbPoints << endl; - vtkCellLinks *links = myGrid->GetCellLinks(); + vtkCellLinks *links = myGrid->GetCellLinks(); for (int i=0; iGetNcells(i); - vtkIdType *cells = links->GetCells(i); - ficcon << i << " - " << ncells << " -"; - for (int j=0; jGetNcells(i); + vtkIdType *cells = links->GetCells(i); + ficcon << i << " - " << ncells << " -"; + for (int j=0; j dmax) dmax = xmax -xmin; if ((ymax - ymin) > dmax) dmax = ymax -ymin; if ((zmax - zmin) > dmax) dmax = zmax -zmin; - MESSAGE("getMaxDim " << dmax); return dmax; } @@ -4828,11 +4755,10 @@ double SMDS_Mesh::getMaxDim() void SMDS_Mesh::Modified() { if (this->myModified) - { - this->myModifTime++; - MESSAGE("modified"); - myModified = false; - } + { + this->myModifTime++; + myModified = false; + } } //! get last modification timeStamp @@ -4844,10 +4770,9 @@ unsigned long SMDS_Mesh::GetMTime() const bool SMDS_Mesh::isCompacted() { if (this->myModifTime > this->myCompactTime) - { - MESSAGE(" *** isCompacted " << myCompactTime << " < " << myModifTime); - this->myCompactTime = this->myModifTime; - return false; - } + { + this->myCompactTime = this->myModifTime; + return false; + } return true; } diff --git a/src/SMDS/SMDS_MeshIDFactory.cxx b/src/SMDS/SMDS_MeshIDFactory.cxx index 20c90bda0..74e5e401d 100644 --- a/src/SMDS/SMDS_MeshIDFactory.cxx +++ b/src/SMDS/SMDS_MeshIDFactory.cxx @@ -42,25 +42,23 @@ SMDS_MeshIDFactory::SMDS_MeshIDFactory():myMaxID(0), myMesh(0) int SMDS_MeshIDFactory::GetFreeID() { - int newid; - if (myPoolOfID.empty()) - { - newid = ++myMaxID; - //MESSAGE("GetFreeID new " << newid); - } - else - { - set::iterator i = myPoolOfID.begin(); - newid = *i;//myPoolOfID.top(); - myPoolOfID.erase( i );//myPoolOfID.pop(); - //MESSAGE("GetFreeID pool " << newid); - } - return newid; + int newid; + if (myPoolOfID.empty()) + { + newid = ++myMaxID; + } + else + { + set::iterator i = myPoolOfID.begin(); + newid = *i;//myPoolOfID.top(); + myPoolOfID.erase( i );//myPoolOfID.pop(); + } + return newid; } //======================================================================= //function : ReleaseID -//purpose : +//purpose : //======================================================================= void SMDS_MeshIDFactory::ReleaseID(int ID, int vtkId) { @@ -91,24 +89,23 @@ void SMDS_MeshIDFactory::ReleaseID(int ID, int vtkId) void SMDS_MeshIDFactory::Clear() { - myMaxID = 0; - myPoolOfID.clear(); + myMaxID = 0; + myPoolOfID.clear(); } void SMDS_MeshIDFactory::SetMesh(SMDS_Mesh *mesh) { - myMesh = mesh; + myMesh = mesh; } SMDS_Mesh* SMDS_MeshIDFactory::GetMesh() { - return myMesh; + return myMesh; } void SMDS_MeshIDFactory::emptyPool(int maxId) { - MESSAGE("SMDS_MeshIDFactory::emptyPool " << myMaxID << " --> " << maxId); - myMaxID = maxId; - myPoolOfID.clear(); + myMaxID = maxId; + myPoolOfID.clear(); } diff --git a/src/SMDS/SMDS_UnstructuredGrid.cxx b/src/SMDS/SMDS_UnstructuredGrid.cxx index 5f8e73b19..b3f743a4f 100644 --- a/src/SMDS/SMDS_UnstructuredGrid.cxx +++ b/src/SMDS/SMDS_UnstructuredGrid.cxx @@ -40,7 +40,6 @@ using namespace std; SMDS_CellLinks* SMDS_CellLinks::New() { - MESSAGE("SMDS_CellLinks::New"); return new SMDS_CellLinks(); } @@ -65,7 +64,6 @@ SMDS_CellLinks::~SMDS_CellLinks() SMDS_UnstructuredGrid* SMDS_UnstructuredGrid::New() { - MESSAGE("SMDS_UnstructuredGrid::New"); return new SMDS_UnstructuredGrid(); } @@ -85,27 +83,23 @@ SMDS_UnstructuredGrid::~SMDS_UnstructuredGrid() unsigned long SMDS_UnstructuredGrid::GetMTime() { unsigned long mtime = vtkUnstructuredGrid::GetMTime(); - MESSAGE("vtkUnstructuredGrid::GetMTime: " << mtime); return mtime; } // OUV_PORTING_VTK6: seems to be useless /* void SMDS_UnstructuredGrid::Update() { - MESSAGE("SMDS_UnstructuredGrid::Update"); return vtkUnstructuredGrid::Update(); } void SMDS_UnstructuredGrid::UpdateInformation() { - MESSAGE("SMDS_UnstructuredGrid::UpdateInformation"); return vtkUnstructuredGrid::UpdateInformation(); } */ vtkPoints* SMDS_UnstructuredGrid::GetPoints() { // TODO erreur incomprehensible de la macro vtk GetPoints apparue avec la version paraview de fin aout 2010 - //MESSAGE("*********************** SMDS_UnstructuredGrid::GetPoints " << this->Points << " " << vtkUnstructuredGrid::GetPoints()); return this->Points; } @@ -116,7 +110,6 @@ int SMDS_UnstructuredGrid::InsertNextLinkedCell(int type, int npts, vtkIdType *p return vtkUnstructuredGrid::InsertNextLinkedCell(type, npts, pts); // --- type = VTK_POLYHEDRON - //MESSAGE("InsertNextLinkedCell VTK_POLYHEDRON"); int cellid = this->InsertNextCell(type, npts, pts); set setOfNodes; @@ -129,7 +122,6 @@ int SMDS_UnstructuredGrid::InsertNextLinkedCell(int type, int npts, vtkIdType *p i++; for (int k = 0; k < nbnodes; k++) { - //MESSAGE(" cell " << cellid << " face " << nf << " node " << pts[i]); setOfNodes.insert(pts[i]); i++; } @@ -138,7 +130,6 @@ int SMDS_UnstructuredGrid::InsertNextLinkedCell(int type, int npts, vtkIdType *p set::iterator it = setOfNodes.begin(); for (; it != setOfNodes.end(); ++it) { - //MESSAGE("reverse link for node " << *it << " cell " << cellid); this->Links->ResizeCellList(*it, 1); this->Links->AddCellReference(cellid, *it); } @@ -155,7 +146,7 @@ void SMDS_UnstructuredGrid::setSMDS_mesh(SMDS_Mesh *mesh) void SMDS_UnstructuredGrid::compactGrid(std::vector& idNodesOldToNew, int newNodeSize, std::vector& idCellsOldToNew, int newCellSize) { - MESSAGE("------------------------- SMDS_UnstructuredGrid::compactGrid " << newNodeSize << " " << newCellSize);//CHRONO(1); + //MESSAGE("------------------------- compactGrid " << newNodeSize << " " << newCellSize);//CHRONO(1); int alreadyCopied = 0; // --- if newNodeSize, create a new compacted vtkPoints @@ -165,7 +156,6 @@ void SMDS_UnstructuredGrid::compactGrid(std::vector& idNodesOldToNew, int n newPoints->SetNumberOfPoints(newNodeSize); if (newNodeSize) { - MESSAGE("-------------- compactGrid, newNodeSize " << newNodeSize); // rnv: to fix bug "21125: EDF 1233 SMESH: Degradation of precision in a test case for quadratic conversion" // using double type for storing coordinates of nodes instead float. int oldNodeSize = idNodesOldToNew.size(); @@ -194,7 +184,6 @@ void SMDS_UnstructuredGrid::compactGrid(std::vector& idNodesOldToNew, int n newConnectivity->Initialize(); int oldCellDataSize = this->Connectivity->GetData()->GetSize(); newConnectivity->Allocate(oldCellDataSize); - MESSAGE("oldCellSize="<< oldCellSize << " oldCellDataSize=" << oldCellDataSize); vtkUnsignedCharArray *newTypes = vtkUnsignedCharArray::New(); newTypes->Initialize(); @@ -230,11 +219,9 @@ void SMDS_UnstructuredGrid::compactGrid(std::vector& idNodesOldToNew, int n newConnectivity->Squeeze(); if (1/*newNodeSize*/) - { - MESSAGE("------- newNodeSize, setPoints"); - this->SetPoints(newPoints); - MESSAGE("NumberOfPoints: " << this->GetNumberOfPoints()); - } + { + this->SetPoints(newPoints); + } if (vtkDoubleArray* diameters = vtkDoubleArray::SafeDownCast( vtkDataSet::CellData->GetScalars() )) // Balls @@ -250,46 +237,46 @@ void SMDS_UnstructuredGrid::compactGrid(std::vector& idNodesOldToNew, int n } if (this->FaceLocations) + { + vtkIdTypeArray *newFaceLocations = vtkIdTypeArray::New(); + newFaceLocations->Initialize(); + newFaceLocations->Allocate(newTypes->GetSize()); + vtkIdTypeArray *newFaces = vtkIdTypeArray::New(); + newFaces->Initialize(); + newFaces->Allocate(this->Faces->GetSize()); + for (int i = 0; i < oldCellSize; i++) { - vtkIdTypeArray *newFaceLocations = vtkIdTypeArray::New(); - newFaceLocations->Initialize(); - newFaceLocations->Allocate(newTypes->GetSize()); - vtkIdTypeArray *newFaces = vtkIdTypeArray::New(); - newFaces->Initialize(); - newFaces->Allocate(this->Faces->GetSize()); - for (int i = 0; i < oldCellSize; i++) + if (this->Types->GetValue(i) == VTK_EMPTY_CELL) + continue; + int newCellId = idCellsOldToNew[i]; + if (newTypes->GetValue(newCellId) == VTK_POLYHEDRON) + { + newFaceLocations->InsertNextValue(newFaces->GetMaxId()+1); + int oldFaceLoc = this->FaceLocations->GetValue(i); + int nCellFaces = this->Faces->GetValue(oldFaceLoc++); + newFaces->InsertNextValue(nCellFaces); + for (int n=0; nTypes->GetValue(i) == VTK_EMPTY_CELL) - continue; - int newCellId = idCellsOldToNew[i]; - if (newTypes->GetValue(newCellId) == VTK_POLYHEDRON) - { - newFaceLocations->InsertNextValue(newFaces->GetMaxId()+1); - int oldFaceLoc = this->FaceLocations->GetValue(i); - int nCellFaces = this->Faces->GetValue(oldFaceLoc++); - newFaces->InsertNextValue(nCellFaces); - for (int n=0; nFaces->GetValue(oldFaceLoc++); - newFaces->InsertNextValue(nptsInFace); - for (int k=0; kFaces->GetValue(oldFaceLoc++); - newFaces->InsertNextValue(idNodesOldToNew[oldpt]); - } - } - } - else - { - newFaceLocations->InsertNextValue(-1); - } + int nptsInFace = this->Faces->GetValue(oldFaceLoc++); + newFaces->InsertNextValue(nptsInFace); + for (int k=0; kFaces->GetValue(oldFaceLoc++); + newFaces->InsertNextValue(idNodesOldToNew[oldpt]); + } } - newFaceLocations->Squeeze(); - newFaces->Squeeze(); - this->SetCells(newTypes, newLocations, newConnectivity, newFaceLocations, newFaces); - newFaceLocations->Delete(); - newFaces->Delete(); + } + else + { + newFaceLocations->InsertNextValue(-1); + } } + newFaceLocations->Squeeze(); + newFaces->Squeeze(); + this->SetCells(newTypes, newLocations, newConnectivity, newFaceLocations, newFaces); + newFaceLocations->Delete(); + newFaces->Delete(); + } else { this->SetCells(newTypes, newLocations, newConnectivity, FaceLocations, Faces); @@ -302,10 +289,12 @@ void SMDS_UnstructuredGrid::compactGrid(std::vector& idNodesOldToNew, int n this->BuildLinks(); } -void SMDS_UnstructuredGrid::copyNodes(vtkPoints *newPoints, std::vector& idNodesOldToNew, int& alreadyCopied, - int start, int end) +void SMDS_UnstructuredGrid::copyNodes(vtkPoints * newPoints, + std::vector& idNodesOldToNew, + int& alreadyCopied, + int start, + int end) { - MESSAGE("copyNodes " << alreadyCopied << " " << start << " " << end << " size: " << end - start << " total: " << alreadyCopied + end - start); void *target = newPoints->GetVoidPointer(3 * alreadyCopied); void *source = this->Points->GetVoidPointer(3 * start); int nbPoints = end - start; @@ -327,7 +316,6 @@ void SMDS_UnstructuredGrid::copyBloc(vtkUnsignedCharArray *newTypes, int start, int end) { - //MESSAGE("copyBloc " << alreadyCopied << " " << start << " " << end << " size: " << end - start << " total: " << alreadyCopied + end - start); for (int j = start; j < end; j++) { newTypes->SetValue(alreadyCopied, this->Types->GetValue(j)); @@ -337,16 +325,13 @@ void SMDS_UnstructuredGrid::copyBloc(vtkUnsignedCharArray *newTypes, vtkIdType *oldPtsCell = 0; this->Connectivity->GetCell(oldLoc, nbpts, oldPtsCell); assert(nbpts < NBMAXNODESINCELL); - //MESSAGE(j << " " << alreadyCopied << " " << (int)this->Types->GetValue(j) << " " << oldLoc << " " << nbpts ); for (int l = 0; l < nbpts; l++) { int oldval = oldPtsCell[l]; pointsCell[l] = idNodesOldToNew[oldval]; - //MESSAGE(" " << oldval << " " << pointsCell[l]); } /*int newcnt = */newConnectivity->InsertNextCell(nbpts, pointsCell); int newLoc = newConnectivity->GetInsertLocation(nbpts); - //MESSAGE(newcnt << " " << newLoc); newLocations->SetValue(alreadyCopied, newLoc); alreadyCopied++; } @@ -356,8 +341,6 @@ int SMDS_UnstructuredGrid::CellIdToDownId(int vtkCellId) { if ((vtkCellId < 0) || (vtkCellId >= (int)_cellIdToDownId.size())) { - //MESSAGE("SMDS_UnstructuredGrid::CellIdToDownId structure not up to date: vtkCellId=" - // << vtkCellId << " max="<< _cellIdToDownId.size()); return -1; } return _cellIdToDownId[vtkCellId]; @@ -1016,12 +999,13 @@ void SMDS_UnstructuredGrid::BuildLinks() * @param nodeDomains: map(original id --> map(domain --> duplicated node id)) * @return ok if success. */ -SMDS_MeshCell* SMDS_UnstructuredGrid::extrudeVolumeFromFace(int vtkVolId, - int domain1, - int domain2, - std::set& originalNodes, - std::map >& nodeDomains, - std::map >& nodeQuadDomains) +SMDS_MeshCell* +SMDS_UnstructuredGrid::extrudeVolumeFromFace(int vtkVolId, + int domain1, + int domain2, + std::set& originalNodes, + std::map >& nodeDomains, + std::map >& nodeQuadDomains) { //MESSAGE("extrudeVolumeFromFace " << vtkVolId); vector orderedOriginals; @@ -1037,16 +1021,16 @@ SMDS_MeshCell* SMDS_UnstructuredGrid::extrudeVolumeFromFace(int vtkVolId, bool isQuadratic = false; switch (orderedOriginals.size()) { - case 3: - if (dim == 2) - isQuadratic = true; - break; - case 6: - case 8: + case 3: + if (dim == 2) isQuadratic = true; - break; - default: - isQuadratic = false; + break; + case 6: + case 8: + isQuadratic = true; + break; + default: + isQuadratic = false; break; } diff --git a/src/SMESH/SMESH_Gen.cxx b/src/SMESH/SMESH_Gen.cxx index 217806cd1..84ffb381c 100644 --- a/src/SMESH/SMESH_Gen.cxx +++ b/src/SMESH/SMESH_Gen.cxx @@ -64,12 +64,10 @@ using namespace std; SMESH_Gen::SMESH_Gen() { - MESSAGE("SMESH_Gen::SMESH_Gen"); _localId = 0; _hypId = 0; _segmentation = _nbSegments = 10; SMDS_Mesh::_meshList.clear(); - MESSAGE(SMDS_Mesh::_meshList.size()); _compute_canceled = false; //vtkDebugLeaks::SetExitError(0); } @@ -82,7 +80,6 @@ SMESH_Gen::SMESH_Gen() SMESH_Gen::~SMESH_Gen() { - MESSAGE("SMESH_Gen::~SMESH_Gen"); std::map < int, StudyContextStruct * >::iterator i_sc = _mapStudyContext.begin(); for ( ; i_sc != _mapStudyContext.end(); ++i_sc ) { @@ -102,7 +99,6 @@ SMESH_Mesh* SMESH_Gen::CreateMesh(int theStudyId, bool theIsEmbeddedMode) throw(SALOME_Exception) { Unexpect aCatch(SalomeException); - MESSAGE("SMESH_Gen::CreateMesh"); // Get studyContext, create it if it does'nt exist, with a SMESHDS_Document StudyContextStruct *aStudyContext = GetStudyContext(theStudyId); @@ -131,7 +127,6 @@ bool SMESH_Gen::Compute(SMESH_Mesh & aMesh, const ::MeshDimension aDim /*=::MeshDim_3D*/, TSetOfInt* aShapesId /*=0*/) { - MESSAGE("SMESH_Gen::Compute"); MEMOSTAT; bool ret = true; @@ -369,11 +364,10 @@ bool SMESH_Gen::Compute(SMESH_Mesh & aMesh, ret = Compute( aMesh, aShape, aShapeOnly, /*anUpward=*/true, aDim, aShapesId ); } - MESSAGE( "VSR - SMESH_Gen::Compute() finished, OK = " << ret); MEMOSTAT; SMESHDS_Mesh *myMesh = aMesh.GetMeshDS(); - MESSAGE("*** compactMesh after compute"); + //MESSAGE("*** compactMesh after compute"); myMesh->compactMesh(); // fix quadratic mesh by bending iternal links near concave boundary @@ -463,8 +457,6 @@ bool SMESH_Gen::Evaluate(SMESH_Mesh & aMesh, const bool anUpward, TSetOfInt* aShapesId) { - MESSAGE("SMESH_Gen::Evaluate"); - bool ret = true; SMESH_subMesh *sm = aMesh.GetSubMesh(aShape); @@ -707,8 +699,6 @@ static bool checkMissing(SMESH_Gen* aGen, if ( aCheckedMap.count( aSubMesh )) return true; - //MESSAGE("=====checkMissing"); - int ret = true; SMESH_Algo* algo = 0; @@ -829,8 +819,6 @@ bool SMESH_Gen::GetAlgoState(SMESH_Mesh& theMesh, const TopoDS_Shape& theShape, list< TAlgoStateError > & theErrors) { - //MESSAGE("SMESH_Gen::CheckAlgoState"); - bool ret = true; bool hasAlgo = false; @@ -908,8 +896,6 @@ bool SMESH_Gen::GetAlgoState(SMESH_Mesh& theMesh, // well defined // ---------------------------------------------------------------- - //MESSAGE( "---info on missing hypothesis and find out if all needed algos are"); - // find max dim of global algo int aTopAlgoDim = 0; for (dim = 3; dim > 0; dim--) diff --git a/src/SMESH/SMESH_Hypothesis.cxx b/src/SMESH/SMESH_Hypothesis.cxx index ac9ca2040..d51ae2a45 100644 --- a/src/SMESH/SMESH_Hypothesis.cxx +++ b/src/SMESH/SMESH_Hypothesis.cxx @@ -59,7 +59,6 @@ SMESH_Hypothesis::SMESH_Hypothesis(int hypId, SMESH_Hypothesis::~SMESH_Hypothesis() { - MESSAGE("SMESH_Hypothesis::~SMESH_Hypothesis"); StudyContextStruct* myStudyContext = _gen->GetStudyContext(_studyId); myStudyContext->mapHypothesis[_hypId] = 0; } @@ -115,8 +114,6 @@ int SMESH_Hypothesis::GetStudyId() const void SMESH_Hypothesis::NotifySubMeshesHypothesisModification() { - MESSAGE("SMESH_Hypothesis::NotifySubMeshesHypothesisModification"); - // for all meshes in study StudyContextStruct* myStudyContext = _gen->GetStudyContext(_studyId); diff --git a/src/SMESH/SMESH_Mesh.cxx b/src/SMESH/SMESH_Mesh.cxx index 4119c5fba..746486f11 100644 --- a/src/SMESH/SMESH_Mesh.cxx +++ b/src/SMESH/SMESH_Mesh.cxx @@ -112,7 +112,7 @@ SMESH_Mesh::SMESH_Mesh(int theLocalId, SMESHDS_Document* theDocument): _groupId( 0 ), _nbSubShapes( 0 ) { - MESSAGE("SMESH_Mesh::SMESH_Mesh(int localId)"); + if(MYDEBUG) MESSAGE("SMESH_Mesh::SMESH_Mesh(int localId)"); _id = theLocalId; _studyId = theStudyId; _gen = theGen; @@ -179,7 +179,7 @@ namespace SMESH_Mesh::~SMESH_Mesh() { - MESSAGE("SMESH_Mesh::~SMESH_Mesh"); + if(MYDEBUG) MESSAGE("SMESH_Mesh::~SMESH_Mesh"); // avoid usual removal of elements while processing RemoveHypothesis( algo ) event SMESHDS_SubMeshIteratorPtr smIt = _myMeshDS->SubMeshes(); @@ -361,10 +361,19 @@ double SMESH_Mesh::GetShapeDiagonalSize(const TopoDS_Shape & aShape) int nbFaces = 0; for ( TopExp_Explorer f( aShape, TopAbs_FACE ); f.More() && nbFaces < maxNbFaces; f.Next() ) ++nbFaces; + bool isPrecise = false; if ( nbFaces < maxNbFaces ) - GEOMUtils::PreciseBoundingBox(aShape, Box); - else - BRepBndLib::Add( aShape, Box); + try { + GEOMUtils::PreciseBoundingBox( aShape, Box ); + isPrecise = true; + } + catch (...) { + isPrecise = false; + } + if ( !isPrecise ) + { + BRepBndLib::Add( aShape, Box ); + } if ( !Box.IsVoid() ) return sqrt( Box.SquareExtent() ); } diff --git a/src/SMESH/SMESH_MeshEditor.cxx b/src/SMESH/SMESH_MeshEditor.cxx index a37950e41..e4f2bda00 100644 --- a/src/SMESH/SMESH_MeshEditor.cxx +++ b/src/SMESH/SMESH_MeshEditor.cxx @@ -683,7 +683,6 @@ static bool getNodesFromTwoTria(const SMDS_MeshElement * theTria1, bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshElement * theTria1, const SMDS_MeshElement * theTria2 ) { - MESSAGE("InverseDiag"); myLastCreatedElems.Clear(); myLastCreatedNodes.Clear(); @@ -888,8 +887,6 @@ bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshNode * theNode1, myLastCreatedElems.Clear(); myLastCreatedNodes.Clear(); - MESSAGE( "::InverseDiag()" ); - const SMDS_MeshElement *tr1, *tr2; if ( !findTriangles( theNode1, theNode2, tr1, tr2 )) return false; @@ -1011,8 +1008,6 @@ bool SMESH_MeshEditor::DeleteDiag (const SMDS_MeshNode * theNode1, myLastCreatedElems.Clear(); myLastCreatedNodes.Clear(); - MESSAGE( "::DeleteDiag()" ); - const SMDS_MeshElement *tr1, *tr2; if ( !findTriangles( theNode1, theNode2, tr1, tr2 )) return false; @@ -1105,7 +1100,6 @@ bool SMESH_MeshEditor::DeleteDiag (const SMDS_MeshNode * theNode1, bool SMESH_MeshEditor::Reorient (const SMDS_MeshElement * theElem) { - MESSAGE("Reorient"); myLastCreatedElems.Clear(); myLastCreatedNodes.Clear(); @@ -1518,7 +1512,7 @@ void SMESH_MeshEditor::QuadTo4Tri (TIDSortedElemSet & theElems) gp_XY uv [9]; uv[8] = gp_XY(0,0); gp_XYZ xyz[9]; vector< const SMDS_MeshNode* > nodes; - SMESHDS_SubMesh* subMeshDS; + SMESHDS_SubMesh* subMeshDS = 0; TopoDS_Face F; Handle(Geom_Surface) surface; TopLoc_Location loc; @@ -2931,8 +2925,6 @@ bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet & theElems, myLastCreatedElems.Clear(); myLastCreatedNodes.Clear(); - MESSAGE( "::QuadToTri()" ); - SMESHDS_Mesh * aMesh = GetMeshDS(); Handle(Geom_Surface) surface; @@ -3153,8 +3145,6 @@ bool SMESH_MeshEditor::TriToQuad (TIDSortedElemSet & theElems, myLastCreatedElems.Clear(); myLastCreatedNodes.Clear(); - MESSAGE( "::TriToQuad()" ); - if ( !theCrit.get() ) return false; @@ -3259,7 +3249,7 @@ bool SMESH_MeshEditor::TriToQuad (TIDSortedElemSet & theElems, if ( startElem ) { // Get candidates to be fused const SMDS_MeshElement *tr1 = startElem, *tr2 = 0, *tr3 = 0; - const SMESH_TLink *link12, *link13; + const SMESH_TLink *link12 = 0, *link13 = 0; startElem = 0; ASSERT( mapEl_setLi.find( tr1 ) != mapEl_setLi.end() ); set< SMESH_TLink >& setLi = mapEl_setLi[ tr1 ]; @@ -3938,8 +3928,6 @@ void SMESH_MeshEditor::Smooth (TIDSortedElemSet & theElems, myLastCreatedElems.Clear(); myLastCreatedNodes.Clear(); - MESSAGE((theSmoothMethod==LAPLACIAN ? "LAPLACIAN" : "CENTROIDAL") << "--::Smooth()"); - if ( theTgtAspectRatio < 1.0 ) theTgtAspectRatio = 1.0; @@ -4476,7 +4464,6 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement* elem, const size_t nbSteps, SMESH_SequenceOfElemPtr& srcElements) { - //MESSAGE("sweepElement " << nbSteps); SMESHDS_Mesh* aMesh = GetMeshDS(); const int nbNodes = elem->NbNodes(); @@ -5368,7 +5355,6 @@ SMESH_MeshEditor::RotationSweep(TIDSortedElemSet theElemSets[2], // source elements for each generated one SMESH_SequenceOfElemPtr srcElems, srcNodes; - MESSAGE( "RotationSweep()"); gp_Trsf aTrsf; aTrsf.SetRotation( theAxis, theAngle ); gp_Trsf aTrsf2; @@ -5939,7 +5925,6 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet theElements[2], const gp_Pnt& theRefPoint, const bool theMakeGroups) { - MESSAGE("ExtrusionAlongTrack"); myLastCreatedElems.Clear(); myLastCreatedNodes.Clear(); @@ -6732,37 +6717,29 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems, string groupPostfix; switch ( theTrsf.Form() ) { case gp_PntMirror: - MESSAGE("gp_PntMirror"); needReverse = true; groupPostfix = "mirrored"; break; case gp_Ax1Mirror: - MESSAGE("gp_Ax1Mirror"); groupPostfix = "mirrored"; break; case gp_Ax2Mirror: - MESSAGE("gp_Ax2Mirror"); needReverse = true; groupPostfix = "mirrored"; break; case gp_Rotation: - MESSAGE("gp_Rotation"); groupPostfix = "rotated"; break; case gp_Translation: - MESSAGE("gp_Translation"); groupPostfix = "translated"; break; case gp_Scale: - MESSAGE("gp_Scale"); groupPostfix = "scaled"; break; case gp_CompoundTrsf: // different scale by axis - MESSAGE("gp_CompoundTrsf"); groupPostfix = "scaled"; break; default: - MESSAGE("default"); needReverse = false; groupPostfix = "transformed"; } @@ -7271,7 +7248,6 @@ int SMESH_MeshEditor::SimplifyFace (const vector& faceNod void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) { - MESSAGE("MergeNodes"); myLastCreatedElems.Clear(); myLastCreatedNodes.Clear(); @@ -8120,7 +8096,6 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode, myLastCreatedElems.Clear(); myLastCreatedNodes.Clear(); - MESSAGE("::SewFreeBorder()"); Sew_Error aResult = SEW_OK; // ==================================== @@ -8228,7 +8203,7 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode, //const SMDS_MeshNode* faceNodes[ 4 ]; const SMDS_MeshNode* sideNode; - const SMDS_MeshElement* sideElem; + const SMDS_MeshElement* sideElem = 0; const SMDS_MeshNode* prevSideNode = theSideFirstNode; const SMDS_MeshNode* prevBordNode = theBordFirstNode; nBordIt = bordNodes.begin(); @@ -8253,7 +8228,7 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode, { const SMDS_MeshElement* elem = invElemIt->next(); // prepare data for a loop on links coming to prevSideNode, of a face or a volume - int iPrevNode, iNode = 0, nbNodes = elem->NbNodes(); + int iPrevNode = 0, iNode = 0, nbNodes = elem->NbNodes(); vector< const SMDS_MeshNode* > faceNodes( nbNodes, (const SMDS_MeshNode*)0 ); bool isVolume = volume.Set( elem ); const SMDS_MeshNode** nodes = isVolume ? volume.GetNodes() : & faceNodes[0]; @@ -8801,7 +8776,7 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement* theElemen } // decide how to split a quadrangle: compare possible variants // and choose which of splits to be a quadrangle - int i1, i2, iSplit, nbSplits = nbLinkNodes - 1, iBestQuad; + int i1, i2, iSplit, nbSplits = nbLinkNodes - 1, iBestQuad = 0; if ( nbFaceNodes == 3 ) { iBestQuad = nbSplits; i4 = i3; @@ -9757,7 +9732,6 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet& theSide1, myLastCreatedElems.Clear(); myLastCreatedNodes.Clear(); - MESSAGE ("::::SewSideElements()"); if ( theSide1.size() != theSide2.size() ) return SEW_DIFF_NB_OF_ELEMENTS; @@ -10436,7 +10410,7 @@ void SMESH_MeshEditor::DoubleElements( const TIDSortedElemSet& theElements ) // get an element type and an iterator over elements - SMDSAbs_ElementType type; + SMDSAbs_ElementType type = SMDSAbs_All; SMDS_ElemIteratorPtr elemIt; vector< const SMDS_MeshElement* > allElems; if ( theElements.empty() ) @@ -10538,7 +10512,6 @@ bool SMESH_MeshEditor::doubleNodes(SMESHDS_Mesh* theMeshDS, TNodeNodeMap& theNodeNodeMap, const bool theIsDoubleElem ) { - MESSAGE("doubleNodes"); // iterate through element and duplicate them (by nodes duplication) bool res = false; std::vector newNodes; @@ -10603,7 +10576,6 @@ bool SMESH_MeshEditor::doubleNodes(SMESHDS_Mesh* theMeshDS, bool SMESH_MeshEditor::DoubleNodes( const std::list< int >& theListOfNodes, const std::list< int >& theListOfModifiedElems ) { - MESSAGE("DoubleNodes"); myLastCreatedElems.Clear(); myLastCreatedNodes.Clear(); @@ -10677,10 +10649,9 @@ bool SMESH_MeshEditor::DoubleNodes( const std::list< int >& theListOfNodes, const SMDS_MeshElement* anElem = anElemToNodesIter->first; vector aNodeArr = anElemToNodesIter->second; if ( anElem ) - { - MESSAGE("ChangeElementNodes"); + { aMeshDS->ChangeElementNodes( anElem, &aNodeArr[ 0 ], anElem->NbNodes() ); - } + } } return true; @@ -10788,7 +10759,6 @@ bool SMESH_MeshEditor::AffectedElemGroupsInRegion( const TIDSortedElemSet& theEl continue; gp_XYZ normal; SMESH_MeshAlgos::FaceNormal( anElem, normal, /*normalized=*/true ); - MESSAGE("element " << ielem++ << " normal " << normal.X() << " " << normal.Y() << " " << normal.Z()); std::set nodesElem; nodesElem.clear(); SMDS_ElemIteratorPtr nodeItr = anElem->nodesIterator(); @@ -10800,7 +10770,6 @@ bool SMESH_MeshEditor::AffectedElemGroupsInRegion( const TIDSortedElemSet& theEl std::set::iterator nodit = nodesElem.begin(); for (; nodit != nodesElem.end(); nodit++) { - MESSAGE(" noeud "); const SMDS_MeshNode* aNode = *nodit; if ( !aNode || theNodesNot.find(aNode) != theNodesNot.end() ) continue; @@ -10810,7 +10779,6 @@ bool SMESH_MeshEditor::AffectedElemGroupsInRegion( const TIDSortedElemSet& theEl SMDS_ElemIteratorPtr backElemItr = aNode->GetInverseElementIterator(); while ( backElemItr->more() ) { - MESSAGE(" backelem "); const SMDS_MeshElement* curElem = backElemItr->next(); if (alreadyCheckedElems.find(curElem) != alreadyCheckedElems.end()) continue; @@ -10832,10 +10800,8 @@ bool SMESH_MeshEditor::AffectedElemGroupsInRegion( const TIDSortedElemSet& theEl p.SetCoord( x/nb -aNode->X(), y/nb -aNode->Y(), z/nb -aNode->Z() ); - MESSAGE(" check " << p.X() << " " << p.Y() << " " << p.Z()); if (normal*p > 0) { - MESSAGE(" --- inserted") theAffectedElems.insert( curElem ); } else if (curElem->GetType() == SMDSAbs_Edge) @@ -10861,7 +10827,6 @@ bool SMESH_MeshEditor::AffectedElemGroupsInRegion( const TIDSortedElemSet& theEl } if (onside) { - MESSAGE(" --- edge onside inserted") theAffectedElems.insert(anEdge); } } @@ -10886,21 +10851,18 @@ bool SMESH_MeshEditor::AffectedElemGroupsInRegion( const TIDSortedElemSet& theEl int ielem; for ( ielem = 1; elemItr != theElems.end(); ++elemItr ) { - MESSAGE("element " << ielem++); SMDS_MeshElement* anElem = (SMDS_MeshElement*)*elemItr; if (!anElem) continue; SMDS_ElemIteratorPtr nodeItr = anElem->nodesIterator(); while ( nodeItr->more() ) { - MESSAGE(" noeud "); const SMDS_MeshNode* aNode = cast2Node(nodeItr->next()); if ( !aNode || theNodesNot.find(aNode) != theNodesNot.end() ) continue; SMDS_ElemIteratorPtr backElemItr = aNode->GetInverseElementIterator(); while ( backElemItr->more() ) { - MESSAGE(" backelem "); const SMDS_MeshElement* curElem = backElemItr->next(); if ( curElem && theElems.find(curElem) == theElems.end() && ( bsc3d.get() ? @@ -10986,10 +10948,6 @@ bool SMESH_MeshEditor::DoubleNodesInRegion( const TIDSortedElemSet& theElems, */ double SMESH_MeshEditor::OrientedAngle(const gp_Pnt& p0, const gp_Pnt& p1, const gp_Pnt& g1, const gp_Pnt& g2) { -// MESSAGE(" p0: " << p0.X() << " " << p0.Y() << " " << p0.Z()); -// MESSAGE(" p1: " << p1.X() << " " << p1.Y() << " " << p1.Z()); -// MESSAGE(" g1: " << g1.X() << " " << g1.Y() << " " << g1.Z()); -// MESSAGE(" g2: " << g2.X() << " " << g2.Y() << " " << g2.Z()); gp_Vec vref(p0, p1); gp_Vec v1(p0, g1); gp_Vec v2(p0, g2); diff --git a/src/SMESH/SMESH_MesherHelper.cxx b/src/SMESH/SMESH_MesherHelper.cxx index 3877d8a7b..35973eb99 100644 --- a/src/SMESH/SMESH_MesherHelper.cxx +++ b/src/SMESH/SMESH_MesherHelper.cxx @@ -308,11 +308,18 @@ void SMESH_MesherHelper::SetSubShape(const TopoDS_Shape& aSh) { double f,l, r = 0.2345; Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface( edge, face, f, l ); - uv2 = C2d->Value( f * r + l * ( 1.-r )); - if ( du < Precision::PConfusion() ) - isSeam = ( Abs( uv1.Coord(1) - uv2.Coord(1) ) < Precision::PConfusion() ); + if ( C2d.IsNull() ) + { + isSeam = false; + } else - isSeam = ( Abs( uv1.Coord(2) - uv2.Coord(2) ) < Precision::PConfusion() ); + { + uv2 = C2d->Value( f * r + l * ( 1.-r )); + if ( du < Precision::PConfusion() ) + isSeam = ( Abs( uv1.Coord(1) - uv2.Coord(1) ) < Precision::PConfusion() ); + else + isSeam = ( Abs( uv1.Coord(2) - uv2.Coord(2) ) < Precision::PConfusion() ); + } } } if ( isSeam ) @@ -653,8 +660,7 @@ gp_XY SMESH_MesherHelper::GetNodeUV(const TopoDS_Face& F, { if ( !IsSubShape( V, F )) { - MESSAGE ( "SMESH_MesherHelper::GetNodeUV(); Vertex " << vertexID - << " not in face " << GetMeshDS()->ShapeToIndex( F ) ); + MESSAGE("GetNodeUV() Vertex "<< vertexID <<" not in face "<< GetMeshDS()->ShapeToIndex(F)); // get UV of a vertex closest to the node double dist = 1e100; gp_Pnt pn = XYZ( n ); @@ -1073,7 +1079,6 @@ bool SMESH_MesherHelper::CheckNodeU(const TopoDS_Edge& E, } Quantity_Parameter U = projector->LowerDistanceParameter(); u = double( U ); - MESSAGE(" f " << f << " l " << l << " u " << u); curvPnt = curve->Value( u ); dist = nodePnt.Distance( curvPnt ); if ( distXYZ ) { @@ -1083,8 +1088,7 @@ bool SMESH_MesherHelper::CheckNodeU(const TopoDS_Edge& E, } if ( dist > tol ) { - MESSAGE( "SMESH_MesherHelper::CheckNodeU(), invalid projection" ); - MESSAGE("distance " << dist << " " << tol ); + MESSAGE( "CheckNodeU(), invalid projection; distance " << dist << "; tol " << tol ); return false; } // store the fixed U on the edge @@ -1609,7 +1613,7 @@ const SMDS_MeshNode* SMESH_MesherHelper::GetMediumNode(const SMDS_MeshNode* n1, // get type of shape for the new medium node int faceID = -1, edgeID = -1; - TopoDS_Edge E; double u [2]; + TopoDS_Edge E; double u [2] = {0.,0.}; TopoDS_Face F; gp_XY uv[2]; bool uvOK[2] = { true, true }; const bool useCurSubShape = ( !myShape.IsNull() && myShape.ShapeType() == TopAbs_EDGE ); @@ -3049,8 +3053,6 @@ bool SMESH_MesherHelper::IsSubShape( const TopoDS_Shape& shape, if ( shape.IsSame( exp.Current() )) return true; } - SCRUTE((shape.IsNull())); - SCRUTE((mainShape.IsNull())); return false; } @@ -5324,3 +5326,19 @@ void SMESH_MesherHelper::FixQuadraticElements(SMESH_ComputeErrorPtr& compError, } } } + +//================================================================================ +/*! + * \brief DEBUG + */ +//================================================================================ + +void SMESH_MesherHelper::WriteShape(const TopoDS_Shape& s) +{ + const char* name = "/tmp/shape.brep"; + BRepTools::Write( s, name ); +#ifdef _DEBUG_ + std::cout << name << std::endl; +#endif +} + diff --git a/src/SMESH/SMESH_MesherHelper.hxx b/src/SMESH/SMESH_MesherHelper.hxx index fe888c750..834cd8e87 100644 --- a/src/SMESH/SMESH_MesherHelper.hxx +++ b/src/SMESH/SMESH_MesherHelper.hxx @@ -684,6 +684,8 @@ public: virtual ~SMESH_MesherHelper(); + static void WriteShape(const TopoDS_Shape& s); + protected: /*! diff --git a/src/SMESH/SMESH_Pattern.cxx b/src/SMESH/SMESH_Pattern.cxx index 0a50cd9dd..f38622a34 100644 --- a/src/SMESH/SMESH_Pattern.cxx +++ b/src/SMESH/SMESH_Pattern.cxx @@ -499,7 +499,7 @@ static gp_XY project (const SMDS_MeshNode* theNode, MESSAGE( "SMESH_Pattern: point projection FAILED"); return gp_XY(0.,0.); } - double u, v, minVal = DBL_MAX; + double u =0, v =0, minVal = DBL_MAX; for ( int i = theProjectorPS.NbExt(); i > 0; i-- ) if ( theProjectorPS.SquareDistance( i ) < minVal ) { minVal = theProjectorPS.SquareDistance( i ); @@ -2339,7 +2339,7 @@ bool SMESH_Pattern::sortSameSizeWires (TListOfEdgesList & theWire // " \t vertex: " << vGcVec[iW].X() << " " << vGcVec[iW].Y() << endl; double minDist = DBL_MAX; gp_XY & wGc = vGcVec[ iW ]; - int bIndex; + int bIndex = 0; for ( int iB = 0; iB < nbWires; iB++ ) { if ( bndFound[ iB ] ) continue; double dist = ( wGc - gcVec[ iB ] ).SquareModulus(); diff --git a/src/SMESH/memoire.h b/src/SMESH/memoire.h index b9d6415d1..b153ac73d 100644 --- a/src/SMESH/memoire.h +++ b/src/SMESH/memoire.h @@ -30,14 +30,18 @@ void memostat(const char* f, int l) #ifdef WIN32 //rnv: TODO: find alternative of the malloc_stats() on windows platform #else - /* struct mallinfo mem = mallinfo(); */ - /* std::cerr << f << ":"<< l << " " << mem.arena << " " << mem.ordblks << " " << mem.hblks << " " << mem.hblkhd << " " << mem.uordblks << " " << mem.fordblks << " " << mem.keepcost << std::endl; */ + struct mallinfo mem = mallinfo(); + std::cerr << f << ":"<< l << " " << mem.arena << " " << mem.ordblks << " " << mem.hblks << " " << mem.hblkhd << " " << mem.uordblks << " " << mem.fordblks << " " << mem.keepcost << std::endl; std::cerr << f << ":" << l << " --------------------------" << std::endl; malloc_stats(); std::cerr << f << ":" << l << " --------------------------" << std::endl; #endif } +#if defined(_DEBUG_) || defined(_DEBUG) #define MEMOSTAT //memostat( __FILE__, __LINE__ ) +#else +#define MEMOSTAT +#endif #endif diff --git a/src/SMESHClient/SMESH_Client.cxx b/src/SMESHClient/SMESH_Client.cxx index a2a29c7bc..c9c4fdc7f 100644 --- a/src/SMESHClient/SMESH_Client.cxx +++ b/src/SMESHClient/SMESH_Client.cxx @@ -54,7 +54,7 @@ #endif #ifdef _DEBUG_ -static int MYDEBUG = 1; +static int MYDEBUG = 0; #else static int MYDEBUG = 0; #endif @@ -886,20 +886,22 @@ bool SMESH_Client::Update(bool theIsClear) { bool anIsModified = true; - if(mySMESHDSMesh){ - MESSAGE("Update mySMESHDSMesh"); + if(mySMESHDSMesh) + { + if ( MYDEBUG ) MESSAGE("Update mySMESHDSMesh"); SMESHDS_Script* aScript = mySMESHDSMesh->GetScript(); anIsModified = aScript->IsModified(); aScript->SetModified(false); - }else{ - MESSAGE("Update CORBA"); + } + else + { + if ( MYDEBUG ) MESSAGE("Update CORBA"); SMESH::log_array_var aSeq = myMeshServer->GetLog( theIsClear ); CORBA::Long aLength = aSeq->length(); anIsModified = aLength > 0; - if( MYDEBUG ) - MESSAGE( "Update: length of the script is "< SMESHDS_Mesh::RemoveFreeElement " << subMesh << " " << fromGroups); if (elt->GetType() == SMDSAbs_Node) { RemoveFreeNode( static_cast(elt), subMesh, fromGroups); return; @@ -1345,7 +1343,6 @@ int SMESHDS_Mesh::AddCompoundSubmesh(const TopoDS_Shape& S, bool all = ( type == TopAbs_SHAPE ); if ( all ) // corresponding simple submesh may exist aMainIndex = -aMainIndex; - //MESSAGE("AddCompoundSubmesh index = " << aMainIndex ); SMESHDS_SubMesh * aNewSub = NewSubMesh( aMainIndex ); if ( !aNewSub->IsComplexSubmesh() ) // is empty { @@ -2116,18 +2113,18 @@ SMDS_MeshVolume* SMESHDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1, const SMDS_MeshNode * n2, const SMDS_MeshNode * n3, const SMDS_MeshNode * n4, - const SMDS_MeshNode * n5, - const SMDS_MeshNode * n6, + const SMDS_MeshNode * n5, + const SMDS_MeshNode * n6, const SMDS_MeshNode * n7, - const SMDS_MeshNode * n8, + const SMDS_MeshNode * n8, const SMDS_MeshNode * n12, const SMDS_MeshNode * n23, const SMDS_MeshNode * n34, - const SMDS_MeshNode * n41, + const SMDS_MeshNode * n41, const SMDS_MeshNode * n56, const SMDS_MeshNode * n67, const SMDS_MeshNode * n78, - const SMDS_MeshNode * n85, + const SMDS_MeshNode * n85, const SMDS_MeshNode * n15, const SMDS_MeshNode * n26, const SMDS_MeshNode * n37, @@ -2155,7 +2152,7 @@ void SMESHDS_Mesh::compactMesh() int newNodeSize = 0; int nbNodes = myNodes.size(); int nbVtkNodes = myGrid->GetNumberOfPoints(); - MESSAGE("nbNodes=" << nbNodes << " nbVtkNodes=" << nbVtkNodes); + //MESSAGE("nbNodes=" << nbNodes << " nbVtkNodes=" << nbVtkNodes); int nbNodeTemp = nbVtkNodes; if (nbNodes > nbVtkNodes) nbNodeTemp = nbNodes; @@ -2164,22 +2161,22 @@ void SMESHDS_Mesh::compactMesh() idNodesOldToNew.resize(nbNodeTemp, -1); // all unused id will be -1 for (int i = 0; i < nbNodes; i++) + { + if (myNodes[i]) { - if (myNodes[i]) - { - int vtkid = myNodes[i]->getVtkId(); - idNodesOldToNew[vtkid] = i; // old vtkId --> old smdsId (valid smdsId are >= 0) - newNodeSize++; - } + int vtkid = myNodes[i]->getVtkId(); + idNodesOldToNew[vtkid] = i; // old vtkId --> old smdsId (valid smdsId are >= 0) + newNodeSize++; } + } bool areNodesModified = (newNodeSize < nbVtkNodes); - MESSAGE("------------------------- compactMesh Nodes Modified: " << areNodesModified); + //MESSAGE("------------------------- compactMesh Nodes Modified: " << areNodesModified); areNodesModified = true; int newCellSize = 0; int nbCells = myCells.size(); int nbVtkCells = myGrid->GetNumberOfCells(); - MESSAGE("nbCells=" << nbCells << " nbVtkCells=" << nbVtkCells); + //MESSAGE("nbCells=" << nbCells << " nbVtkCells=" << nbVtkCells); int nbCellTemp = nbVtkCells; if (nbCells > nbVtkCells) nbCellTemp = nbCells; @@ -2188,15 +2185,15 @@ void SMESHDS_Mesh::compactMesh() idCellsOldToNew.resize(nbCellTemp, -1); // all unused id will be -1 for (int i = 0; i < nbCells; i++) + { + if (myCells[i]) { - if (myCells[i]) - { -// //idCellsOldToNew[i] = myCellIdVtkToSmds[i]; // valid vtk indexes are > = 0 -// int vtkid = myCells[i]->getVtkId(); -// idCellsOldToNew[vtkid] = i; // old vtkId --> old smdsId (not used in input) - newCellSize++; - } + // //idCellsOldToNew[i] = myCellIdVtkToSmds[i]; // valid vtk indexes are > = 0 + // int vtkid = myCells[i]->getVtkId(); + // idCellsOldToNew[vtkid] = i; // old vtkId --> old smdsId (not used in input) + newCellSize++; } + } if (areNodesModified) myGrid->compactGrid(idNodesOldToNew, newNodeSize, idCellsOldToNew, newCellSize); else @@ -2205,62 +2202,62 @@ void SMESHDS_Mesh::compactMesh() int nbVtkPts = myGrid->GetNumberOfPoints(); nbVtkCells = myGrid->GetNumberOfCells(); if (nbVtkPts != newNodeSize) - { - MESSAGE("===> nbVtkPts != newNodeSize " << nbVtkPts << " " << newNodeSize); - if (nbVtkPts > newNodeSize) newNodeSize = nbVtkPts; // several points with same SMDS Id - } + { + MESSAGE("===> nbVtkPts != newNodeSize " << nbVtkPts << " " << newNodeSize); + if (nbVtkPts > newNodeSize) newNodeSize = nbVtkPts; // several points with same SMDS Id + } if (nbVtkCells != newCellSize) - { - MESSAGE("===> nbVtkCells != newCellSize " << nbVtkCells << " " << newCellSize); - if (nbVtkCells > newCellSize) newCellSize = nbVtkCells; // several cells with same SMDS Id - } + { + MESSAGE("===> nbVtkCells != newCellSize " << nbVtkCells << " " << newCellSize); + if (nbVtkCells > newCellSize) newCellSize = nbVtkCells; // several cells with same SMDS Id + } // --- SMDS_MeshNode and myNodes (id in SMDS and in VTK are the same), myNodeIdFactory if (areNodesModified) + { + //MESSAGE("-------------- modify myNodes"); + SetOfNodes newNodes; + newNodes.resize(newNodeSize+1,0); // 0 not used, SMDS numbers 1..n + int newSmdsId = 0; + for (int i = 0; i < nbNodes; i++) { - MESSAGE("-------------- modify myNodes"); - SetOfNodes newNodes; - newNodes.resize(newNodeSize+1,0); // 0 not used, SMDS numbers 1..n - int newSmdsId = 0; - for (int i = 0; i < nbNodes; i++) - { - if (myNodes[i]) - { - newSmdsId++; // SMDS id start to 1 - int oldVtkId = myNodes[i]->getVtkId(); - int newVtkId = idNodesOldToNew[oldVtkId]; - //MESSAGE("myNodes["<< i << "] vtkId " << oldVtkId << " --> " << newVtkId); - myNodes[i]->setVtkId(newVtkId); - myNodes[i]->setId(newSmdsId); - newNodes[newSmdsId] = myNodes[i]; - //MESSAGE("myNodes["<< i << "] --> newNodes[" << newSmdsId << "]"); - } - } - myNodes.swap(newNodes); - this->myNodeIDFactory->emptyPool(newSmdsId); // newSmdsId = number of nodes - MESSAGE("myNodes.size " << myNodes.size()); + if (myNodes[i]) + { + newSmdsId++; // SMDS id start to 1 + int oldVtkId = myNodes[i]->getVtkId(); + int newVtkId = idNodesOldToNew[oldVtkId]; + //MESSAGE("myNodes["<< i << "] vtkId " << oldVtkId << " --> " << newVtkId); + myNodes[i]->setVtkId(newVtkId); + myNodes[i]->setId(newSmdsId); + newNodes[newSmdsId] = myNodes[i]; + //MESSAGE("myNodes["<< i << "] --> newNodes[" << newSmdsId << "]"); + } } + myNodes.swap(newNodes); + this->myNodeIDFactory->emptyPool(newSmdsId); // newSmdsId = number of nodes + //MESSAGE("myNodes.size " << myNodes.size()); + } // --- SMDS_MeshCell, myCellIdVtkToSmds, myCellIdSmdsToVtk, myCells int vtkIndexSize = myCellIdVtkToSmds.size(); int maxVtkId = -1; for (int oldVtkId = 0; oldVtkId < vtkIndexSize; oldVtkId++) + { + int oldSmdsId = this->myCellIdVtkToSmds[oldVtkId]; + if (oldSmdsId > 0) { - int oldSmdsId = this->myCellIdVtkToSmds[oldVtkId]; - if (oldSmdsId > 0) - { - int newVtkId = idCellsOldToNew[oldVtkId]; - if (newVtkId > maxVtkId) - maxVtkId = newVtkId; - //MESSAGE("myCells["<< oldSmdsId << "] vtkId " << oldVtkId << " --> " << newVtkId); - myCells[oldSmdsId]->setVtkId(newVtkId); - } + int newVtkId = idCellsOldToNew[oldVtkId]; + if (newVtkId > maxVtkId) + maxVtkId = newVtkId; + //MESSAGE("myCells["<< oldSmdsId << "] vtkId " << oldVtkId << " --> " << newVtkId); + myCells[oldSmdsId]->setVtkId(newVtkId); } -// MESSAGE("myCells.size()=" << myCells.size() -// << " myCellIdSmdsToVtk.size()=" << myCellIdSmdsToVtk.size() -// << " myCellIdVtkToSmds.size()=" << myCellIdVtkToSmds.size() ); + } + // MESSAGE("myCells.size()=" << myCells.size() + // << " myCellIdSmdsToVtk.size()=" << myCellIdSmdsToVtk.size() + // << " myCellIdVtkToSmds.size()=" << myCellIdVtkToSmds.size() ); SetOfCells newCells; //vector newSmdsToVtk; @@ -2292,8 +2289,7 @@ void SMESHDS_Mesh::compactMesh() myCells.swap(newCells); //myCellIdSmdsToVtk.swap(newSmdsToVtk); myCellIdVtkToSmds.swap(newVtkToSmds); - MESSAGE("myCells.size()=" << myCells.size() - << " myCellIdVtkToSmds.size()=" << myCellIdVtkToSmds.size() ); + //MESSAGE("myCells.size()="<< myCells.size()<<" myCellIdVtkToSmds.size()="<myElementIDFactory->emptyPool(newSmdsId); this->myScript->SetModified(true); // notify GUI client for buildPrs when update diff --git a/src/SMESHDS/SMESHDS_SubMesh.cxx b/src/SMESHDS/SMESHDS_SubMesh.cxx index 11dbb124a..21d6da43a 100644 --- a/src/SMESHDS/SMESHDS_SubMesh.cxx +++ b/src/SMESHDS/SMESHDS_SubMesh.cxx @@ -154,7 +154,7 @@ bool SMESHDS_SubMesh::RemoveElement(const SMDS_MeshElement * ME, bool isElemDele //======================================================================= //function : AddNode -//purpose : +//purpose : //======================================================================= void SMESHDS_SubMesh::AddNode(const SMDS_MeshNode * N) @@ -240,7 +240,7 @@ int SMESHDS_SubMesh::NbElements() const //======================================================================= //function : NbNodes -//purpose : +//purpose : //======================================================================= int SMESHDS_SubMesh::NbNodes() const @@ -299,10 +299,10 @@ public: template class MyIterator : public SMDS_Iterator { - public: +public: MyIterator (const set& theSubMeshes) : myMore(false), mySubIt( theSubMeshes.begin() ), mySubEnd( theSubMeshes.end() ) - {} + {} bool more() { while (( !myElemIt.get() || !myElemIt->more() ) && mySubIt != mySubEnd) @@ -320,11 +320,11 @@ template class MyIterator : public SMDS_Iterator elem = myElemIt->next(); return elem; } - protected: +protected: virtual boost::shared_ptr< SMDS_Iterator > - getElements(const SMESHDS_SubMesh*) const = 0; + getElements(const SMESHDS_SubMesh*) const = 0; - private: +private: bool myMore; set::const_iterator mySubIt, mySubEnd; boost::shared_ptr< SMDS_Iterator > myElemIt; @@ -336,7 +336,7 @@ template class MyIterator : public SMDS_Iterator class MyElemIterator: public MyIterator { - public: +public: MyElemIterator (const set& theSubMeshes) :MyIterator( theSubMeshes ) {} SMDS_ElemIteratorPtr getElements(const SMESHDS_SubMesh* theSubMesh) const @@ -349,28 +349,30 @@ class MyElemIterator: public MyIterator class MyNodeIterator: public MyIterator { - public: +public: MyNodeIterator (const set& theSubMeshes) :MyIterator( theSubMeshes ) {} SMDS_NodeIteratorPtr getElements(const SMESHDS_SubMesh* theSubMesh) const { return theSubMesh->GetNodes(); } }; - + //======================================================================= //function : GetElements -//purpose : +//purpose : //======================================================================= SMDS_ElemIteratorPtr SMESHDS_SubMesh::GetElements() const { if ( IsComplexSubmesh() ) return SMDS_ElemIteratorPtr( new MyElemIterator( mySubMeshes )); - return SMDS_ElemIteratorPtr(new MySetIterator >(myElements)); + + return SMDS_ElemIteratorPtr + (new MySetIterator >(myElements)); } //======================================================================= //function : GetNodes -//purpose : +//purpose : //======================================================================= SMDS_NodeIteratorPtr SMESHDS_SubMesh::GetNodes() const @@ -378,7 +380,8 @@ SMDS_NodeIteratorPtr SMESHDS_SubMesh::GetNodes() const if ( IsComplexSubmesh() ) return SMDS_NodeIteratorPtr( new MyNodeIterator( mySubMeshes )); - return SMDS_NodeIteratorPtr(new MySetIterator >(myNodes)); + return SMDS_NodeIteratorPtr + (new MySetIterator >(myNodes)); } //======================================================================= @@ -444,7 +447,7 @@ bool SMESHDS_SubMesh::IsQuadratic() const //======================================================================= //function : AddSubMesh -//purpose : +//purpose : //======================================================================= void SMESHDS_SubMesh::AddSubMesh( const SMESHDS_SubMesh* theSubMesh ) @@ -503,6 +506,24 @@ SMESHDS_SubMeshIteratorPtr SMESHDS_SubMesh::GetSubMeshIterator() const void SMESHDS_SubMesh::Clear() { + if ( myParent && myParent->NbNodes() > 0 ) + { + for ( size_t i = 0; i < myElements.size(); ++i ) + { + if ( myElements[i] && + myElements[i]->GetID() > 0 && + myElements[i] == myParent->FindElement( myElements[i]->GetID() )) // not deleted + const_cast< SMDS_MeshElement* >( myElements[i] )->setShapeId( 0 ); + } + for ( size_t i = 0; i < myNodes.size(); ++i ) + { + if ( myNodes[i] && + myNodes[i]->GetID() > 0 && + myNodes[i] == myParent->FindNode( myNodes[i]->GetID() )) // not deleted + const_cast< SMDS_MeshNode* >( myNodes[i] )->setShapeId( 0 ); + } + } + clearVector( myElements ); clearVector( myNodes ); myUnusedIdNodes = 0; @@ -530,12 +551,12 @@ void SMESHDS_SubMesh::compactList() { std::vector newElems; newElems.reserve( myElements.size() - myUnusedIdElements ); - for (size_t i = 0; i < myElements.size(); i++) - if (myElements[i]) + for ( size_t i = 0; i < myElements.size(); i++) + if ( myElements[i] ) { SMDS_MeshElement* elem = (SMDS_MeshElement*)myElements[i]; - elem->setIdInShape(newElems.size()); - newElems.push_back(elem); + elem->setIdInShape( newElems.size() ); + newElems.push_back( elem ); } myElements.swap(newElems); myUnusedIdElements = 0; @@ -545,12 +566,12 @@ void SMESHDS_SubMesh::compactList() { std::vector newNodes; newNodes.reserve( myNodes.size() - myUnusedIdNodes ); - for (size_t i = 0; i < myNodes.size(); i++) - if (myNodes[i]) + for ( size_t i = 0; i < myNodes.size(); i++ ) + if ( myNodes[i] ) { SMDS_MeshNode* node = (SMDS_MeshNode*)myNodes[i]; - node->setIdInShape(newNodes.size()); - newNodes.push_back(node); + node->setIdInShape( newNodes.size() ); + newNodes.push_back( node ); } myNodes.swap(newNodes); myUnusedIdNodes = 0; diff --git a/src/SMESHGUI/SMESHGUI.cxx b/src/SMESHGUI/SMESHGUI.cxx index 93b579798..d696c0ba2 100644 --- a/src/SMESHGUI/SMESHGUI.cxx +++ b/src/SMESHGUI/SMESHGUI.cxx @@ -608,7 +608,7 @@ namespace // Get parameters of export operation QString aFilename; - SMESH::MED_VERSION aFormat; + SMESH::MED_VERSION aFormat = SMESH::MED_V2_2; // Init the parameters with the default values bool aIsASCII_STL = true; bool toCreateGroups = false; @@ -1649,19 +1649,17 @@ namespace if(!anIO.IsNull()){ _PTR(SObject) SO = aStudy->FindObjectID( It.Value()->getEntry() ); if ( SO ) { - CORBA::Object_var aObject = SMESH::SObjectToObject( SO ); - SMESH::SMESH_Mesh_var aMesh = SMESH::SMESH_Mesh::_narrow( aObject ); - SMESH::SMESH_subMesh_var aSubMesh = SMESH::SMESH_subMesh::_narrow( aObject ); - SMESH::SMESH_GroupBase_var aGroup = SMESH::SMESH_GroupBase::_narrow( aObject ); - if ( !aMesh->_is_nil() || !aSubMesh->_is_nil() || !aGroup->_is_nil() ) { - if ( SMESH_Actor *anActor = SMESH::FindActorByEntry(anIO->getEntry()) ) { - anActor->SetControlMode(aControl); - anActor->GetScalarBarActor()->SetTitle( functorToString( anActor->GetFunctor() ).toLatin1().constData() ); + CORBA::Object_var aObject = SMESH::SObjectToObject( SO ); + SMESH::SMESH_IDSource_var anIDSrc = SMESH::SMESH_IDSource::_narrow( aObject ); + if ( !anIDSrc->_is_nil() ) { + if ( SMESH_Actor *anActor = SMESH::FindActorByEntry( anIO->getEntry()) ) { + QString functorName = functorToString( anActor->GetFunctor() ); + anActor->SetControlMode( aControl ); + anActor->GetScalarBarActor()->SetTitle( functorName.toLatin1().constData() ); SMESH::RepaintCurrentView(); #ifndef DISABLE_PLOT2DVIEWER if ( anActor->GetPlot2Histogram() ) { SPlot2d_Histogram* aHistogram = anActor->UpdatePlot2Histogram(); - QString functorName = functorToString( anActor->GetFunctor() ); QString aHistogramName("%1 : %2"); aHistogramName = aHistogramName.arg( anIO->getName() ).arg( functorName ); aHistogram->setName( aHistogramName ); @@ -1956,7 +1954,7 @@ SalomeApp_Module( "SMESH" ) { CORBA::Boolean anIsEmbeddedMode; myComponentSMESH = SMESH_Client::GetSMESHGen(getApp()->orb(),anIsEmbeddedMode); - MESSAGE("-------------------------------> anIsEmbeddedMode=" << anIsEmbeddedMode); + //MESSAGE("-------------------------------> anIsEmbeddedMode=" << anIsEmbeddedMode); // 0019923: EDF 765 SMESH : default values of hypothesis SUIT_ResourceMgr* aResourceMgr = SMESH::GetResourceMgr(this); @@ -2596,6 +2594,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) case SMESHOp::OpShow: case SMESHOp::OpShowOnly: { + SUIT_OverrideCursor wc; SMESH::EDisplaing anAction; switch (theCommandID) { case SMESHOp::OpHide: anAction = SMESH::eErase; break; @@ -2610,7 +2609,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) if ( theCommandID==SMESHOp::OpShowOnly ) { - MESSAGE("anAction = SMESH::eDisplayOnly"); + //MESSAGE("anAction = SMESH::eDisplayOnly"); startOperation( myEraseAll ); } @@ -2639,7 +2638,6 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) // PAL13338 + PAL15161 --> if ( ( theCommandID==SMESHOp::OpShow || theCommandID==SMESHOp::OpShowOnly ) && !checkLock(aStudy)) { - MESSAGE("anAction = SMESH::eDisplayOnly"); SMESH::UpdateView(); SMESHGUI::GetSMESHGUI()->EmitSignalVisibilityChanged(); } @@ -2650,7 +2648,6 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) } if (anAction == SMESH::eErase) { - MESSAGE("anAction == SMESH::eErase"); SALOME_ListIO l1; aSel->setSelectedObjects( l1 ); } @@ -2670,9 +2667,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) ( new SMESHGUI_NodesDlg( this ) )->show(); } else { - SUIT_MessageBox::warning(desktop(), - tr("SMESH_WRN_WARNING"), - tr("SMESH_WRN_VIEWER_VTK")); + SUIT_MessageBox::warning(desktop(),tr("SMESH_WRN_WARNING"),tr("SMESH_WRN_VIEWER_VTK")); } break; } @@ -2706,8 +2701,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) { if ( !vtkwnd ) { - SUIT_MessageBox::warning( desktop(), tr( "SMESH_WRN_WARNING" ), - tr( "NOT_A_VTK_VIEWER" ) ); + SUIT_MessageBox::warning( desktop(), tr( "SMESH_WRN_WARNING" ), tr( "NOT_A_VTK_VIEWER" ) ); break; } @@ -2737,8 +2731,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) { if ( !vtkwnd ) { - SUIT_MessageBox::warning( desktop(), tr( "SMESH_WRN_WARNING" ), - tr( "NOT_A_VTK_VIEWER" ) ); + SUIT_MessageBox::warning( desktop(), tr( "SMESH_WRN_WARNING" ), tr( "NOT_A_VTK_VIEWER" ) ); break; } @@ -2767,8 +2760,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) ( new SMESHGUI_SmoothingDlg( this ) )->show(); } else { - SUIT_MessageBox::warning(desktop(), - tr("SMESH_WRN_WARNING"), tr("SMESH_WRN_VIEWER_VTK")); + SUIT_MessageBox::warning(desktop(), tr("SMESH_WRN_WARNING"), tr("SMESH_WRN_VIEWER_VTK")); } break; } @@ -2779,8 +2771,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) EmitSignalDeactivateDialog(); ( new SMESHGUI_ExtrusionDlg ( this ) )->show(); } else { - SUIT_MessageBox::warning(desktop(), - tr("SMESH_WRN_WARNING"), tr("SMESH_WRN_VIEWER_VTK")); + SUIT_MessageBox::warning(desktop(),tr("SMESH_WRN_WARNING"), tr("SMESH_WRN_VIEWER_VTK")); } break; } @@ -2791,8 +2782,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) EmitSignalDeactivateDialog(); ( new SMESHGUI_ExtrusionAlongPathDlg( this ) )->show(); } else { - SUIT_MessageBox::warning(desktop(), - tr("SMESH_WRN_WARNING"), tr("SMESH_WRN_VIEWER_VTK")); + SUIT_MessageBox::warning(desktop(),tr("SMESH_WRN_WARNING"), tr("SMESH_WRN_VIEWER_VTK")); } break; } @@ -2804,8 +2794,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) ( new SMESHGUI_RevolutionDlg( this ) )->show(); } else { - SUIT_MessageBox::warning(desktop(), - tr("SMESH_WRN_WARNING"), tr("SMESH_WRN_VIEWER_VTK")); + SUIT_MessageBox::warning(desktop(),tr("SMESH_WRN_WARNING"), tr("SMESH_WRN_VIEWER_VTK")); } break; } @@ -2819,8 +2808,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) ( new SMESHGUI_MeshPatternDlg( this ) )->show(); } else { - SUIT_MessageBox::warning(desktop(), - tr("SMESH_WRN_WARNING"), tr("SMESH_WRN_VIEWER_VTK")); + SUIT_MessageBox::warning(desktop(),tr("SMESH_WRN_WARNING"), tr("SMESH_WRN_VIEWER_VTK")); } break; } @@ -2837,8 +2825,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) { if ( !vtkwnd ) { - SUIT_MessageBox::warning( desktop(), tr( "SMESH_WRN_WARNING" ), - tr( "NOT_A_VTK_VIEWER" ) ); + SUIT_MessageBox::warning( desktop(), tr( "SMESH_WRN_WARNING" ),tr( "NOT_A_VTK_VIEWER" ) ); break; } @@ -2865,8 +2852,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) { if ( !vtkwnd ) { - SUIT_MessageBox::warning( desktop(), tr( "SMESH_WRN_WARNING" ), - tr( "NOT_A_VTK_VIEWER" ) ); + SUIT_MessageBox::warning( desktop(), tr( "SMESH_WRN_WARNING" ),tr( "NOT_A_VTK_VIEWER" ) ); break; } @@ -2943,8 +2929,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) { if ( !vtkwnd ) { - SUIT_MessageBox::warning( desktop(), tr( "SMESH_WRN_WARNING" ), - tr( "NOT_A_VTK_VIEWER" ) ); + SUIT_MessageBox::warning( desktop(), tr( "SMESH_WRN_WARNING" ),tr( "NOT_A_VTK_VIEWER" ) ); break; } @@ -3000,8 +2985,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) { if ( !vtkwnd ) { - SUIT_MessageBox::warning( desktop(), tr( "SMESH_WRN_WARNING" ), - tr( "NOT_A_VTK_VIEWER" ) ); + SUIT_MessageBox::warning( desktop(), tr( "SMESH_WRN_WARNING" ),tr( "NOT_A_VTK_VIEWER" ) ); break; } @@ -3041,8 +3025,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) { if ( !vtkwnd ) { - SUIT_MessageBox::warning( desktop(), tr( "SMESH_WRN_WARNING" ), - tr( "NOT_A_VTK_VIEWER" ) ); + SUIT_MessageBox::warning( desktop(), tr( "SMESH_WRN_WARNING" ),tr( "NOT_A_VTK_VIEWER" ) ); break; } @@ -3080,8 +3063,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) { if ( !vtkwnd ) { - SUIT_MessageBox::warning( desktop(), tr( "SMESH_WRN_WARNING" ), - tr( "NOT_A_VTK_VIEWER" ) ); + SUIT_MessageBox::warning( desktop(), tr( "SMESH_WRN_WARNING" ),tr( "NOT_A_VTK_VIEWER" ) ); break; } @@ -3223,8 +3205,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) ( new SMESHGUI_AddMeshElementDlg( this, type ) )->show(); } else { - SUIT_MessageBox::warning(desktop(), - tr("SMESH_WRN_WARNING"), tr("SMESH_WRN_VIEWER_VTK")); + SUIT_MessageBox::warning(desktop(),tr("SMESH_WRN_WARNING"), tr("SMESH_WRN_VIEWER_VTK")); } break; } @@ -3236,8 +3217,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) ( new SMESHGUI_CreatePolyhedralVolumeDlg( this ) )->show(); } else { - SUIT_MessageBox::warning(SMESHGUI::desktop(), - tr("SMESH_WRN_WARNING"), tr("SMESH_WRN_VIEWER_VTK")); + SUIT_MessageBox::warning(desktop(),tr("SMESH_WRN_WARNING"), tr("SMESH_WRN_VIEWER_VTK")); } break; } @@ -6067,6 +6047,12 @@ void SMESHGUI::restoreVisualParameters (int savePoint) continue; TPlaneData aPlaneData; + aPlaneData.AbsoluteOrientation = false; + aPlaneData.RelativeOrientation = 0; + aPlaneData.Distance = aPlaneData.Angle[0] = aPlaneData.Angle[1] = 0; + aPlaneData.X = aPlaneData.Y = aPlaneData.Z = 0; + aPlaneData.Dx = aPlaneData.Dy = aPlaneData.Dz = 0; + aPlaneData.Id = aClippingPlaneId; ok = false; diff --git a/src/SMESHGUI/SMESHGUI_AddQuadraticElementDlg.cxx b/src/SMESHGUI/SMESHGUI_AddQuadraticElementDlg.cxx index 97075dd5f..c24dbc4b3 100644 --- a/src/SMESHGUI/SMESHGUI_AddQuadraticElementDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_AddQuadraticElementDlg.cxx @@ -537,7 +537,7 @@ void SMESHGUI_AddQuadraticElementDlg::Init() myNbMidFaceNodes = 0; myNbCenterNodes = 0; - int aNumRows; + int aNumRows = 0; switch (myGeomType) { case SMDSEntity_Quad_Edge: @@ -768,7 +768,7 @@ bool SMESHGUI_AddQuadraticElementDlg::ClickOnApply() } } - SMESH::ElementType anElementType; + SMESH::ElementType anElementType = SMESH::ALL; long anElemId = -1, nbElemsBefore = 0; SMESH::SMESH_MeshEditor_var aMeshEditor = myMesh->GetMeshEditor(); switch (myGeomType) { @@ -1055,7 +1055,7 @@ void SMESHGUI_AddQuadraticElementDlg::SelectionIntoArgument() // process groups if ( !myMesh->_is_nil() && myEntry != aCurrentEntry ) { - SMESH::ElementType anElementType; + SMESH::ElementType anElementType = SMESH::ALL; switch ( myGeomType ) { case SMDSEntity_Quad_Edge: anElementType = SMESH::EDGE; break; @@ -1371,8 +1371,8 @@ void SMESHGUI_AddQuadraticElementDlg::UpdateTable( bool theConersValidity ) for ( int row = 0; row < myTable->rowCount(); row++ ) myTable->item( row, 1 )->setText(""); - int* aFirstColIds; - int* aLastColIds; + int* aFirstColIds = 0; + int* aLastColIds = 0; switch (myGeomType) { case SMDSEntity_Quad_Edge: diff --git a/src/SMESHGUI/SMESHGUI_ClippingDlg.cxx b/src/SMESHGUI/SMESHGUI_ClippingDlg.cxx index 371a0582a..e1047b874 100644 --- a/src/SMESHGUI/SMESHGUI_ClippingDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_ClippingDlg.cxx @@ -766,7 +766,7 @@ bool SMESHGUI_ClippingDlg::AddPlane ( SMESH::TActorList theActorList, double aDir[2][3] = {{0, 0, 0}, {0, 0, 0}}; static double aCoeff = vtkMath::Pi()/180.0; - int anOrientation; + int anOrientation = 0; if ( thePlane->PlaneMode == SMESH::Absolute ) anOrientation = thePlane->myAbsoluteOrientation; else if ( thePlane->PlaneMode == SMESH::Relative ) @@ -1436,7 +1436,7 @@ void SMESHGUI_ClippingDlg::SetCurrentPlaneParam() static double aCoeff = vtkMath::Pi()/180.0; double aRot[2] = { getRotation1(), getRotation2() }; - int anOrient; + int anOrient = 0; if ( aPlane->PlaneMode == SMESH::Absolute ) anOrient = CBAbsoluteOrientation->currentIndex(); else if ( aPlane->PlaneMode == SMESH::Relative ) @@ -1623,8 +1623,8 @@ void SMESHGUI_ClippingDlg::absolutePlaneToRelative ( double theOrigin[3], double double eps = 0.0001; int anOrientation = CBRelativeOrientation->currentIndex(); - double aDirection[3]; - double aRotation1, aRotation2; + double aDirection[3] = { 0.,0.,0. }; + double aRotation1 = 0, aRotation2 = 0; switch( anOrientation ) { case 0: aDirection[0] = theDir[0] + eps; diff --git a/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx b/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx index 1e8e270de..c4de8a507 100644 --- a/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx @@ -943,7 +943,9 @@ void SMESHGUI_BaseComputeOp::computeMesh() if ( !smSObj ) continue; SMESH::SMESH_IDSource_var aSubMeshObj = SMESH::SObjectToInterface( smSObj ); - aListToUpdate.append( TListOf_IDSrc_SObj::value_type( aSubMeshObj, smSObj )); + SMESH_Actor *anActor = SMESH::FindActorByObject( aSubMeshObj ); + if ( anActor && anActor->GetVisibility() ) + aListToUpdate.append( TListOf_IDSrc_SObj::value_type( aSubMeshObj, smSObj )); } // put Groups into list SMESH::ListOfGroups_var aGroups = myMesh->GetGroups(); @@ -959,7 +961,9 @@ void SMESHGUI_BaseComputeOp::computeMesh() if ( !aGroupSO ) continue; SMESH::SMESH_IDSource_var aGroupObj = SMESH::SObjectToInterface( aGroupSO ); - aListToUpdate.append( TListOf_IDSrc_SObj::value_type( aGroupObj, aGroupSO )); + SMESH_Actor *anActor = SMESH::FindActorByObject( aGroupObj ); + if ( anActor && anActor->GetVisibility() ) + aListToUpdate.append( TListOf_IDSrc_SObj::value_type( aGroupObj, aGroupSO )); } // update mesh, sub-mesh and groups, if it's possible diff --git a/src/SMESHGUI/SMESHGUI_DeleteGroupDlg.cxx b/src/SMESHGUI/SMESHGUI_DeleteGroupDlg.cxx index 6952b96c9..7711022c3 100644 --- a/src/SMESHGUI/SMESHGUI_DeleteGroupDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_DeleteGroupDlg.cxx @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -205,6 +206,8 @@ bool SMESHGUI_DeleteGroupDlg::onApply() if (!isValid()) return false; + SUIT_OverrideCursor wc; + myBlockSelection = true; QList::iterator anIter; diff --git a/src/SMESHGUI/SMESHGUI_GroupDlg.cxx b/src/SMESHGUI/SMESHGUI_GroupDlg.cxx index d954febb2..ea5c5fe03 100644 --- a/src/SMESHGUI/SMESHGUI_GroupDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_GroupDlg.cxx @@ -936,7 +936,7 @@ bool SMESHGUI_GroupDlg::onApply() QStringList anEntryList; SMESH::SMESH_GroupBase_var resultGroup; - bool isCreation, isConversion = false; + bool isCreation = false, isConversion = false; SUIT_OverrideCursor wc; diff --git a/src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx b/src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx index dce31dfb8..f93ec46ea 100644 --- a/src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx +++ b/src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx @@ -378,7 +378,7 @@ namespace SMESH return false; if ( algoData->BasicHypos.contains( hypType )) return true; - if ( algoData->OptionalHypos.contains( hypType)) { + if ( algoData->OptionalHypos.contains( hypType )) { isAuxiliary = true; return true; } diff --git a/src/SMESHGUI/SMESHGUI_MeshInfo.cxx b/src/SMESHGUI/SMESHGUI_MeshInfo.cxx index d6603652e..b0b1a6ed7 100644 --- a/src/SMESHGUI/SMESHGUI_MeshInfo.cxx +++ b/src/SMESHGUI/SMESHGUI_MeshInfo.cxx @@ -1227,7 +1227,7 @@ void SMESHGUI_SimpleElemInfo::information( const QList& ids ) int shapeID = pos->shapeID; if ( shapeID > 0 ) { QString shapeType; - double u, v; + double u = 0, v = 0; switch ( pos->shapeType ) { case GEOM::EDGE: shapeType = SMESHGUI_ElemInfo::tr( "GEOM_EDGE" ); @@ -1751,7 +1751,7 @@ void SMESHGUI_TreeElemInfo::information( const QList& ids ) int shapeID = pos->shapeID; if ( shapeID > 0 ) { QString shapeType; - double u, v; + double u = 0, v = 0; switch ( pos->shapeType ) { case GEOM::EDGE: shapeType = SMESHGUI_ElemInfo::tr( "GEOM_EDGE" ); diff --git a/src/SMESHGUI/SMESHGUI_SewingDlg.cxx b/src/SMESHGUI/SMESHGUI_SewingDlg.cxx index 8e27e662f..22253c4d6 100644 --- a/src/SMESHGUI/SMESHGUI_SewingDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_SewingDlg.cxx @@ -1308,7 +1308,7 @@ bool SMESHGUI_SewingDlg::ClickOnApply() SMESH::SMESH_MeshEditor_var aMeshEditor = myMesh->GetMeshEditor(); int aConstructorId = GetConstructorId(); - SMESH::SMESH_MeshEditor::Sew_Error anError; + SMESH::SMESH_MeshEditor::Sew_Error anError = SMESH::SMESH_MeshEditor::SEW_OK; if (aConstructorId == 0) { @@ -1954,11 +1954,15 @@ void SMESHGUI_SewingDlg::BorderGroupDisplayer::getPartEnds( int p ids.push_back( aBRD.nodeIDs[ aPART.node1 ]); ids.push_back( aBRD.nodeIDs[ aPART.nodeLast ]); + if ( aPART.node1 == aPART.nodeLast ) + ids.push_back( aBRD.nodeIDs[ aPART.node2 ]); SMDS_Mesh* mesh = myPartActors[ partIndex ]->GetObject()->GetMesh(); coords.push_back( SMESH_TNodeXYZ( mesh->FindNode( aPART.node1+1 ))); coords.push_back( SMESH_TNodeXYZ( mesh->FindNode( aPART.nodeLast+1 ))); + if ( aPART.node1 == aPART.nodeLast ) + coords.push_back( SMESH_TNodeXYZ( mesh->FindNode( aPART.node2+1 ))); } void SMESHGUI_SewingDlg::BorderGroupDisplayer::Update() diff --git a/src/SMESHGUI/SMESHGUI_VTKUtils.cxx b/src/SMESHGUI/SMESHGUI_VTKUtils.cxx index db9df6c71..323c9c154 100644 --- a/src/SMESHGUI/SMESHGUI_VTKUtils.cxx +++ b/src/SMESHGUI/SMESHGUI_VTKUtils.cxx @@ -854,7 +854,7 @@ namespace SMESH bool Update(const Handle(SALOME_InteractiveObject)& theIO, bool theDisplay) { - MESSAGE("Update"); + //MESSAGE("Update"); _PTR(Study) aStudy = GetActiveStudyDocument(); CORBA::Long anId = aStudy->StudyId(); if ( TVisualObjPtr aVisualObj = SMESH::GetVisualObj(anId,theIO->getEntry())) { @@ -867,7 +867,7 @@ namespace SMESH bool UpdateNulData(const Handle(SALOME_InteractiveObject)& theIO, bool theDisplay) { - MESSAGE("UpdateNulData"); + //MESSAGE("UpdateNulData"); _PTR(Study) aStudy = GetActiveStudyDocument(); CORBA::Long anId = aStudy->StudyId(); if ( TVisualObjPtr aVisualObj = SMESH::GetVisualObj(anId,theIO->getEntry(), true)) { @@ -878,7 +878,8 @@ namespace SMESH return false; } - void UpdateSelectionProp( SMESHGUI* theModule ) { + void UpdateSelectionProp( SMESHGUI* theModule ) + { if( !theModule ) return; @@ -905,25 +906,29 @@ namespace SMESH return; } - QColor aHiColor = mgr->colorValue( "SMESH", "selection_object_color", Qt::white ), - aSelColor = mgr->colorValue( "SMESH", "selection_element_color", Qt::yellow ), - aPreColor = mgr->colorValue( "SMESH", "highlight_color", Qt::cyan ); + QColor + aHiColor = mgr->colorValue( "SMESH", "selection_object_color", Qt::white ), + aSelColor = mgr->colorValue( "SMESH", "selection_element_color", Qt::yellow ), + aPreColor = mgr->colorValue( "SMESH", "highlight_color", Qt::cyan ); int aElem0DSize = mgr->integerValue("SMESH", "elem0d_size", 5); - // int aBallSize = mgr->integerValue("SMESH", "ball_elem_size", 5); + // int aBallSize = mgr->integerValue("SMESH", "ball_elem_size", 5); int aLineWidth = mgr->integerValue("SMESH", "element_width", 1); int maxSize = aElem0DSize; if (aElem0DSize > maxSize) maxSize = aElem0DSize; if (aLineWidth > maxSize) maxSize = aLineWidth; - // if (aBallSize > maxSize) maxSize = aBallSize; + // if (aBallSize > maxSize) maxSize = aBallSize; - double SP1 = mgr->doubleValue( "SMESH", "selection_precision_node", 0.025 ), - SP2 = mgr->doubleValue( "SMESH", "selection_precision_element", 0.001 ), - SP3 = mgr->doubleValue( "SMESH", "selection_precision_object", 0.025 ); + double + SP1 = mgr->doubleValue( "SMESH", "selection_precision_node", 0.025 ), + SP2 = mgr->doubleValue( "SMESH", "selection_precision_element", 0.001 ), + SP3 = mgr->doubleValue( "SMESH", "selection_precision_object", 0.025 ); - for ( int i=0, n=views.count(); iSetSelectionProp(aSelColor.red()/255., aSelColor.green()/255., @@ -940,8 +945,8 @@ namespace SMESH VTK::ActorCollectionCopy aCopy(aRenderer->GetActors()); vtkActorCollection *aCollection = aCopy.GetActors(); aCollection->InitTraversal(); - while(vtkActor *anAct = aCollection->GetNextActor()){ - if(SMESH_Actor *anActor = dynamic_cast(anAct)){ + while ( vtkActor *anAct = aCollection->GetNextActor() ) { + if ( SMESH_Actor *anActor = dynamic_cast(anAct) ) { anActor->SetHighlightColor(aHiColor.red()/255., aHiColor.green()/255., aHiColor.blue()/255.); @@ -1076,8 +1081,9 @@ namespace SMESH //---------------------------------------------------------------------------- - void SetPointRepresentation(bool theIsVisible){ - if(SVTK_ViewWindow* aViewWindow = GetCurrentVtkView()){ + void SetPointRepresentation(bool theIsVisible) + { + if ( SVTK_ViewWindow* aViewWindow = GetCurrentVtkView() ) { vtkRenderer *aRenderer = aViewWindow->getRenderer(); VTK::ActorCollectionCopy aCopy(aRenderer->GetActors()); vtkActorCollection *aCollection = aCopy.GetActors(); @@ -1094,8 +1100,9 @@ namespace SMESH } - void SetPickable(SMESH_Actor* theActor){ - if(SVTK_ViewWindow* aWnd = GetCurrentVtkView()){ + void SetPickable(SMESH_Actor* theActor) + { + if ( SVTK_ViewWindow* aWnd = GetCurrentVtkView() ) { int anIsAllPickable = (theActor == NULL); vtkRenderer *aRenderer = aWnd->getRenderer(); VTK::ActorCollectionCopy aCopy(aRenderer->GetActors()); @@ -1116,9 +1123,9 @@ namespace SMESH //---------------------------------------------------------------------------- - int GetNameOfSelectedNodes(SVTK_Selector* theSelector, + int GetNameOfSelectedNodes(SVTK_Selector* theSelector, const Handle(SALOME_InteractiveObject)& theIO, - QString& theName) + QString& theName) { theName = ""; TColStd_IndexedMapOfInteger aMapIndex; @@ -1204,7 +1211,8 @@ namespace SMESH return -1; } - int GetNameOfSelectedNodes(LightApp_SelectionMgr *theMgr, QString& theName){ + int GetNameOfSelectedNodes(LightApp_SelectionMgr *theMgr, QString& theName) + { theName = ""; SALOME_ListIO selected; theMgr->selectedObjects( selected ); if(selected.Extent() == 1){ @@ -1215,9 +1223,9 @@ namespace SMESH } - int GetNameOfSelectedElements(LightApp_SelectionMgr *theMgr, + int GetNameOfSelectedElements(LightApp_SelectionMgr * theMgr, const Handle(SALOME_InteractiveObject)& theIO, - QString& theName) + QString& theName) { theName = ""; if(theIO->hasEntry()){ @@ -1342,13 +1350,13 @@ namespace SMESH } double aBoundPoints[8][3] = { {theBounds[0],theBounds[2],theBounds[4]}, - {theBounds[1],theBounds[2],theBounds[4]}, - {theBounds[0],theBounds[3],theBounds[4]}, - {theBounds[1],theBounds[3],theBounds[4]}, - {theBounds[0],theBounds[2],theBounds[5]}, - {theBounds[1],theBounds[2],theBounds[5]}, - {theBounds[0],theBounds[3],theBounds[5]}, - {theBounds[1],theBounds[3],theBounds[5]}}; + {theBounds[1],theBounds[2],theBounds[4]}, + {theBounds[0],theBounds[3],theBounds[4]}, + {theBounds[1],theBounds[3],theBounds[4]}, + {theBounds[0],theBounds[2],theBounds[5]}, + {theBounds[1],theBounds[2],theBounds[5]}, + {theBounds[0],theBounds[3],theBounds[5]}, + {theBounds[1],theBounds[3],theBounds[5]}}; int aMaxId = 0; theMaxBoundPrj = vtkMath::Dot(theDirection,aBoundPoints[aMaxId]); @@ -1445,8 +1453,9 @@ namespace SMESH */ //================================================================================ - void ClearPlot2Viewers( SUIT_ViewWindow* theWindow ) { - if(SVTK_ViewWindow* aViewWindow = GetVtkViewWindow(theWindow)){ + void ClearPlot2Viewers( SUIT_ViewWindow* theWindow ) + { + if ( SVTK_ViewWindow* aViewWindow = GetVtkViewWindow(theWindow) ) { vtkRenderer *aRenderer = aViewWindow->getRenderer(); VTK::ActorCollectionCopy aCopy(aRenderer->GetActors()); vtkActorCollection *aCollection = aCopy.GetActors(); @@ -1460,7 +1469,7 @@ namespace SMESH } } } - + #endif } // end of namespace SMESH diff --git a/src/SMESHGUI/SMESHGUI_XmlHandler.cxx b/src/SMESHGUI/SMESHGUI_XmlHandler.cxx index 6f6060216..ec8ed41cd 100644 --- a/src/SMESHGUI/SMESHGUI_XmlHandler.cxx +++ b/src/SMESHGUI/SMESHGUI_XmlHandler.cxx @@ -104,7 +104,7 @@ bool SMESHGUI_XmlHandler::startElement (const QString&, const QString&, QString aResName = atts.value("resources"); if (aResName != "") { - MESSAGE("Loading Resources " << aResName.toLatin1().data()); + //MESSAGE("Loading Resources " << aResName.toLatin1().data()); SUIT_ResourceMgr* resMgr = SMESHGUI::resourceMgr(); QString lang = resMgr->stringValue( resMgr->langSection(), "language", "en" ); resMgr->loadTranslator( "resources", QString( "%1_msg_%2.qm" ).arg( aResName, lang ) ); diff --git a/src/SMESHUtils/SMESH_Block.cxx b/src/SMESHUtils/SMESH_Block.cxx index 986d55aea..90bd9bce6 100644 --- a/src/SMESHUtils/SMESH_Block.cxx +++ b/src/SMESHUtils/SMESH_Block.cxx @@ -930,6 +930,7 @@ void SMESH_Block::refineParametersOnFace( const gp_Pnt& thePoint, { // find UV of thePoint on the FACE Standard_Real U,V; + U=V=0; const TFace& tface = myFace[ theFaceID - ID_FirstF ]; if ( !tface.Surface() ) return; @@ -1778,7 +1779,7 @@ bool SMESH_Block::FindBlockShapes(const TopoDS_Shell& theShell, if ( V000.IsNull() ) { // find vertex 000 - the one with smallest coordinates - double minVal = DBL_MAX, minX, val; + double minVal = DBL_MAX, minX = DBL_MAX, val; for ( int i = 1; i <= 8; i++ ) { const TopoDS_Vertex& v = TopoDS::Vertex( vfMap.FindKey( i )); gp_Pnt P = BRep_Tool::Pnt( v ); @@ -1822,7 +1823,7 @@ bool SMESH_Block::FindBlockShapes(const TopoDS_Shell& theShell, return false; } TopTools_ListIteratorOfListOfShape f001It, f000It ( f000List ); - int i, j, iFound1, iFound2; + int i, j, iFound1=0, iFound2=0; for ( j = 0; f000It.More(); f000It.Next(), j++ ) { if ( NB_FACES_BY_VERTEX == 6 && j % 2 ) continue; // each face encounters twice diff --git a/src/SMESHUtils/SMESH_FreeBorders.cxx b/src/SMESHUtils/SMESH_FreeBorders.cxx index 93aefb881..ae6efa6db 100644 --- a/src/SMESHUtils/SMESH_FreeBorders.cxx +++ b/src/SMESHUtils/SMESH_FreeBorders.cxx @@ -36,6 +36,7 @@ #include #include +#include #include using namespace SMESH_MeshAlgos; @@ -62,6 +63,7 @@ namespace bool HasCloseEdgeWithNode( const BNode* n ) const; bool IsCloseEdge( const BEdge*, double * u = 0 ) const; bool operator<(const BNode& other) const { return Node()->GetID() < other.Node()->GetID(); } + double SquareDistance(const BNode& e2) const { return ( e2 - *this ).SquareModulus(); } }; /*! * \brief Edge of a free border @@ -133,6 +135,12 @@ namespace myNext->SetID( id + 1 ); } } + //================================================================================ + /*! + * \brief Checks if a point is closer to this BEdge than tol + */ + //================================================================================ + bool IsOut( const gp_XYZ& point, const double tol, double& u ) const { gp_XYZ me = *myBNode2 - *myBNode1; @@ -145,6 +153,12 @@ namespace double dist2 = ( point - proj ).SquareModulus(); return ( dist2 > tol * tol ); } + //================================================================================ + /*! + * \brief Checks if two BEdges can be considered as overlapping + */ + //================================================================================ + bool IsOverlappingProjection( const BEdge* toE, const double u, bool is1st ) const { // is1st shows which end of toE is projected on this at u @@ -160,6 +174,12 @@ namespace return Abs( u - u2 ) > eps; return false; } + //================================================================================ + /*! + * \brief Finds all neighbor BEdge's having the same close borders + */ + //================================================================================ + bool GetRangeOfSameCloseBorders(BEdge* eRange[2], const std::set< int >& bordIDs) { if ( this->myCloseBorders != bordIDs ) @@ -221,6 +241,64 @@ namespace } }; // class BEdge + //================================================================================ + /*! + * \brief Checks if all border parts include the whole closed border, and if so + * returns \c true and choose starting BEdge's with most coincident nodes + */ + //================================================================================ + + bool chooseStartOfClosedBorders( std::vector< BEdge* >& ranges ) // PAL23078#c21002 + { + bool allClosed = true; + for ( size_t iR = 1; iR < ranges.size() && allClosed; iR += 2 ) + allClosed = ( ranges[ iR-1 ]->myPrev == ranges[ iR ] ); + if ( !allClosed ) + return allClosed; + + double u, minDiff = Precision::Infinite(); + std::vector< BEdge* > start( ranges.size() / 2 ); + BEdge* range0 = start[0] = ranges[0]; + do + { + double maxDiffU = 0; + double maxDiff = 0; + for ( size_t iR = 3; iR < ranges.size(); iR += 2 ) + { + int borderID = ranges[iR]->myBorderID; + if ( BEdge* e = start[0]->myBNode1->GetCloseEdgeOfBorder( borderID, & u )) + { + start[ iR / 2 ] = e; + double diffU = Min( Abs( u ), Abs( 1.-u )); + double diff = e->myBNode1->SquareDistance( *e->myBNode2 ) * diffU * diffU; + maxDiffU = Max( diffU, maxDiffU ); + maxDiff = Max( diff, maxDiff ); + } + } + if ( maxDiff < minDiff ) + { + minDiff = maxDiff; + for ( size_t iR = 1; iR < ranges.size(); iR += 2 ) + { + ranges[ iR-1 ] = start[ iR/2 ]; + ranges[ iR ] = ranges[ iR-1]->myPrev; + } + } + if ( maxDiffU < 1e-6 ) + break; + start[0] = start[0]->myNext; + } + while ( start[0] != range0 ); + + return allClosed; + } + + //================================================================================ + /*! + * \brief Tries to include neighbor BEdge's into a border part + */ + //================================================================================ + void extendPart( BEdge* & e1, BEdge* & e2, const std::set< int >& bordIDs, int groupID ) { if (( e1->myPrev == e2 ) || @@ -268,6 +346,12 @@ namespace } } + //================================================================================ + /*! + * \brief Connect BEdge's incident at this node + */ + //================================================================================ + void BNode::AddLinked( BEdge* e ) const { myLinkedEdges.reserve(2); @@ -670,8 +754,9 @@ void SMESH_MeshAlgos::FindCoincidentFreeBorders(SMDS_Mesh& mesh, if ( ranges.size() > 2 ) { - for ( size_t iR = 1; iR < ranges.size(); iR += 2 ) - extendPart( ranges[ iR-1 ], ranges[ iR ], be1st->myCloseBorders, groupID ); + if ( !chooseStartOfClosedBorders( ranges )) + for ( size_t iR = 1; iR < ranges.size(); iR += 2 ) + extendPart( ranges[ iR-1 ], ranges[ iR ], be1st->myCloseBorders, groupID ); // fill in a group beRange[0] = ranges[0]; diff --git a/src/SMESHUtils/SMESH_MeshAlgos.cxx b/src/SMESHUtils/SMESH_MeshAlgos.cxx index dfdaf42d9..a9ad04af5 100644 --- a/src/SMESHUtils/SMESH_MeshAlgos.cxx +++ b/src/SMESHUtils/SMESH_MeshAlgos.cxx @@ -1194,7 +1194,7 @@ bool SMESH_MeshAlgos::IsOut( const SMDS_MeshElement* element, const gp_Pnt& poin dist.back() = dist.front(); // find the closest intersection int iClosest = -1; - double rClosest, distClosest = 1e100;; + double rClosest = 0, distClosest = 1e100;; gp_Pnt pClosest; for ( i = 0; i < nbNodes; ++i ) { diff --git a/src/SMESHUtils/SMESH_TypeDefs.hxx b/src/SMESHUtils/SMESH_TypeDefs.hxx index d73f8ca56..77c095cc1 100644 --- a/src/SMESHUtils/SMESH_TypeDefs.hxx +++ b/src/SMESHUtils/SMESH_TypeDefs.hxx @@ -186,6 +186,7 @@ typedef struct uvPtStruct uvPtStruct(): node(NULL) {} inline gp_XY UV() const { return gp_XY( u, v ); } + inline void SetUV( const gp_XY& uv ) { u = uv.X(); v = uv.Y(); } struct NodeAccessor // accessor to iterate on nodes in UVPtStructVec { diff --git a/src/SMESH_I/SMESH_2D_Algo_i.cxx b/src/SMESH_I/SMESH_2D_Algo_i.cxx index fb9235dca..04a9bf389 100644 --- a/src/SMESH_I/SMESH_2D_Algo_i.cxx +++ b/src/SMESH_I/SMESH_2D_Algo_i.cxx @@ -45,7 +45,6 @@ SMESH_2D_Algo_i::SMESH_2D_Algo_i( PortableServer::POA_ptr thePOA ) SMESH_Hypothesis_i( thePOA ), SMESH_Algo_i( thePOA ) { - MESSAGE( "SMESH_2D_Algo_i::SMESH_2D_Algo_i" ); } //============================================================================= @@ -58,7 +57,6 @@ SMESH_2D_Algo_i::SMESH_2D_Algo_i( PortableServer::POA_ptr thePOA ) SMESH_2D_Algo_i::~SMESH_2D_Algo_i() { - MESSAGE( "SMESH_2D_Algo_i::~SMESH_2D_Algo_i" ); } //================================================================================ diff --git a/src/SMESH_I/SMESH_3D_Algo_i.cxx b/src/SMESH_I/SMESH_3D_Algo_i.cxx index 7daba667e..dfa30a628 100644 --- a/src/SMESH_I/SMESH_3D_Algo_i.cxx +++ b/src/SMESH_I/SMESH_3D_Algo_i.cxx @@ -45,7 +45,6 @@ SMESH_3D_Algo_i::SMESH_3D_Algo_i( PortableServer::POA_ptr thePOA ) SMESH_Hypothesis_i( thePOA ), SMESH_Algo_i( thePOA ) { - MESSAGE( "SMESH_3D_Algo_i::SMESH_3D_Algo_i" ); } //============================================================================= @@ -58,7 +57,6 @@ SMESH_3D_Algo_i::SMESH_3D_Algo_i( PortableServer::POA_ptr thePOA ) SMESH_3D_Algo_i::~SMESH_3D_Algo_i() { - MESSAGE( "SMESH_3D_Algo_i::~SMESH_3D_Algo_i" ); } //================================================================================ diff --git a/src/SMESH_I/SMESH_Algo_i.cxx b/src/SMESH_I/SMESH_Algo_i.cxx index c9cd4afc9..5c0f6bb80 100644 --- a/src/SMESH_I/SMESH_Algo_i.cxx +++ b/src/SMESH_I/SMESH_Algo_i.cxx @@ -48,7 +48,6 @@ SMESH_Algo_i::SMESH_Algo_i( PortableServer::POA_ptr thePOA ) : SALOME::GenericObj_i( thePOA ), SMESH_Hypothesis_i( thePOA ) { - MESSAGE( "SMESH_Algo_i::SMESH_Algo_i" ); } //============================================================================= @@ -61,7 +60,6 @@ SMESH_Algo_i::SMESH_Algo_i( PortableServer::POA_ptr thePOA ) SMESH_Algo_i::~SMESH_Algo_i() { - MESSAGE( "SMESH_Algo_i::~SMESH_Algo_i" ); } //============================================================================= @@ -74,7 +72,6 @@ SMESH_Algo_i::~SMESH_Algo_i() SMESH::ListOfHypothesisName* SMESH_Algo_i::GetCompatibleHypothesis() { - MESSAGE( "SMESH_Algo_i::GetCompatibleHypothesis" ); SMESH::ListOfHypothesisName_var listOfHypothesis = new SMESH::ListOfHypothesisName; const vector& hypList = ( ( ::SMESH_Algo* )myBaseImpl )->GetCompatibleHypothesis(); int nbHyp = hypList.size(); diff --git a/src/SMESH_I/SMESH_Gen_i.cxx b/src/SMESH_I/SMESH_Gen_i.cxx index 204466afe..a279a4ada 100644 --- a/src/SMESH_I/SMESH_Gen_i.cxx +++ b/src/SMESH_I/SMESH_Gen_i.cxx @@ -285,7 +285,6 @@ SMESH_Gen_i::SMESH_Gen_i( CORBA::ORB_ptr orb, const char* interfaceName ) : Engines_Component_i( orb, poa, contId, instanceName, interfaceName ) { - MESSAGE( "SMESH_Gen_i::SMESH_Gen_i : standard constructor" ); myOrb = CORBA::ORB::_duplicate(orb); myPoa = PortableServer::POA::_duplicate(poa); @@ -335,8 +334,6 @@ SMESH_Gen_i::SMESH_Gen_i( CORBA::ORB_ptr orb, SMESH_Gen_i::~SMESH_Gen_i() { - MESSAGE( "SMESH_Gen_i::~SMESH_Gen_i" ); - // delete hypothesis creators map::iterator itHyp, itHyp2; for (itHyp = myHypCreatorMap.begin(); itHyp != myHypCreatorMap.end(); itHyp++) @@ -512,7 +509,7 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::createMesh() // create a new mesh object servant, store it in a map in study context SMESH_Mesh_i* meshServant = new SMESH_Mesh_i( GetPOA(), this, GetCurrentStudyID() ); // create a new mesh object - MESSAGE("myIsEmbeddedMode " << myIsEmbeddedMode); + if(MYDEBUG) MESSAGE("myIsEmbeddedMode " << myIsEmbeddedMode); meshServant->SetImpl( myGen.CreateMesh( GetCurrentStudyID(), myIsEmbeddedMode )); // activate the CORBA servant of Mesh @@ -571,7 +568,6 @@ void SMESH_Gen_i::SetGeomEngine( GEOM::GEOM_Gen_ptr geomcompo ) void SMESH_Gen_i::SetEmbeddedMode( CORBA::Boolean theMode ) { myIsEmbeddedMode = theMode; - MESSAGE("myIsEmbeddedMode " << myIsEmbeddedMode); if ( !myIsEmbeddedMode ) { //PAL10867: disable signals catching with "noexcepthandler" option @@ -4489,7 +4485,7 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent, // --> try to find SUB-MESHES containers for each type of submesh for ( int j = GetSubMeshOnVertexTag(); j <= GetSubMeshOnCompoundTag(); j++ ) { - const char* name_meshgroup; + const char* name_meshgroup = 0; if ( j == GetSubMeshOnVertexTag() ) name_meshgroup = "SubMeshes On Vertex"; else if ( j == GetSubMeshOnEdgeTag() ) diff --git a/src/SMESH_I/SMESH_Gen_i_1.cxx b/src/SMESH_I/SMESH_Gen_i_1.cxx index 30ef9e5c6..af12566d8 100644 --- a/src/SMESH_I/SMESH_Gen_i_1.cxx +++ b/src/SMESH_I/SMESH_Gen_i_1.cxx @@ -771,8 +771,7 @@ SALOMEDS::SObject_ptr SMESH_Gen_i::PublishGroup (SALOMEDS::Study_ptr theStudy SetName( aRootSO, aRootNames[aType] ); // Add new group to corresponding sub-tree - SMESH::array_of_ElementType_var elemTypes = theGroup->GetTypes(); - int isEmpty = ( elemTypes->length() == 0 ); + int isEmpty = false; std::string pm[2] = { "ICON_SMESH_TREE_GROUP", "ICON_SMESH_TREE_MESH_WARN" }; if ( SMESH::DownCast< SMESH_GroupOnFilter_i* > ( theGroup )) { diff --git a/src/SMESH_I/SMESH_Group_i.cxx b/src/SMESH_I/SMESH_Group_i.cxx index cee8097de..84e405e9b 100644 --- a/src/SMESH_I/SMESH_Group_i.cxx +++ b/src/SMESH_I/SMESH_Group_i.cxx @@ -72,7 +72,6 @@ SMESH_Group_i::SMESH_Group_i( PortableServer::POA_ptr thePOA, : SALOME::GenericObj_i( thePOA ), SMESH_GroupBase_i( thePOA, theMeshServant, theLocalID ) { - //MESSAGE("SMESH_Group_i; this = "<Extent(); - MESSAGE("get size of a vague group"); return 0; } @@ -240,7 +234,6 @@ CORBA::Boolean SMESH_GroupBase_i::IsEmpty() SMESHDS_GroupBase* aGroupDS = GetGroupDS(); if (aGroupDS) return aGroupDS->IsEmpty(); - MESSAGE("checking IsEmpty of a vague group"); return true; } @@ -280,8 +273,6 @@ void SMESH_Group_i::Clear() return; } Modified(); // notify dependent Filter with FT_BelongToMeshGroup criterion - - MESSAGE("attempt to clear a vague group"); } //============================================================================= @@ -298,7 +289,6 @@ CORBA::Boolean SMESH_GroupBase_i::Contains( CORBA::Long theID ) SMESHDS_GroupBase* aGroupDS = GetGroupDS(); if (aGroupDS) return aGroupDS->Contains(theID); - MESSAGE("attempt to check contents of a vague group"); return false; } @@ -631,7 +621,6 @@ SALOMEDS::Color SMESH_GroupBase_i::GetColor() return aColor; } - MESSAGE("get color of a group"); return SALOMEDS::Color(); } @@ -889,7 +878,6 @@ SMESH::long_array* SMESH_GroupOnFilter_i::GetListOfID() if ( 0 < aRes->length() && aRes->length() < 100 ) // for comfortable testing ;) std::sort( &aRes[0], &aRes[0] + aRes->length() ); } - MESSAGE("get list of IDs of a vague group"); return aRes._retn(); } diff --git a/src/SMESH_I/SMESH_Mesh_i.cxx b/src/SMESH_I/SMESH_Mesh_i.cxx index 1390b2276..05043f6f2 100644 --- a/src/SMESH_I/SMESH_Mesh_i.cxx +++ b/src/SMESH_I/SMESH_Mesh_i.cxx @@ -108,7 +108,6 @@ SMESH_Mesh_i::SMESH_Mesh_i( PortableServer::POA_ptr thePOA, CORBA::Long studyId ) : SALOME::GenericObj_i( thePOA ) { - MESSAGE("SMESH_Mesh_i"); _impl = NULL; _gen_i = gen_i; _id = _idGenerator++; @@ -127,8 +126,6 @@ SMESH_Mesh_i::SMESH_Mesh_i( PortableServer::POA_ptr thePOA, SMESH_Mesh_i::~SMESH_Mesh_i() { - MESSAGE("~SMESH_Mesh_i"); - // destroy groups map::iterator itGr; for (itGr = _mapGroups.begin(); itGr != _mapGroups.end(); itGr++) @@ -4079,7 +4076,7 @@ SMESH::long_array* SMESH_Mesh_i::GetNodesId() SMESH::ElementType SMESH_Mesh_i::GetElementType( const CORBA::Long id, const bool iselem ) throw (SALOME::SALOME_Exception) { - SMESH::ElementType type; + SMESH::ElementType type = SMESH::ALL; SMESH_TRY; if ( _preMeshInfo ) @@ -4227,7 +4224,7 @@ SMESH::long_array* SMESH_Mesh_i::GetSubMeshNodesId(const CORBA::Long ShapeID, SMESH::ElementType SMESH_Mesh_i::GetSubMeshElementType(const CORBA::Long ShapeID) throw (SALOME::SALOME_Exception) { - SMESH::ElementType type; + SMESH::ElementType type = SMESH::ALL; SMESH_TRY; if ( _preMeshInfo ) @@ -4265,8 +4262,7 @@ CORBA::LongLong SMESH_Mesh_i::GetMeshPtr() _preMeshInfo->FullLoadFromFile(); CORBA::LongLong pointeur = CORBA::LongLong(_impl); - if ( MYDEBUG ) - MESSAGE("CORBA::LongLong SMESH_Mesh_i::GetMeshPtr() "<_shapes.FindIndex( SMESH_MesherHelper::IthVertex( 0, *e ))) && diff --git a/src/StdMeshers/StdMeshers_CompositeHexa_3D.cxx b/src/StdMeshers/StdMeshers_CompositeHexa_3D.cxx index cd047490a..cb0512d1f 100644 --- a/src/StdMeshers/StdMeshers_CompositeHexa_3D.cxx +++ b/src/StdMeshers/StdMeshers_CompositeHexa_3D.cxx @@ -382,12 +382,12 @@ namespace const TopTools_MapOfShape& cornerVV, TopTools_MapOfShape& internEE) { - TopTools_IndexedMapOfShape subEE, subFF; + TopTools_IndexedMapOfShape subEE; TopExp::MapShapes( shape, TopAbs_EDGE, subEE ); - TopExp::MapShapes( shape, TopAbs_FACE, subFF ); + //TopExp::MapShapes( shape, TopAbs_FACE, subFF ); TopoDS_Vertex VV[2]; - TopTools_MapOfShape subChecked/*, ridgeEE*/; + TopTools_MapOfShape subChecked, ridgeEE; TopTools_MapIteratorOfMapOfShape vIt( cornerVV ); for ( ; vIt.More(); vIt.Next() ) { @@ -401,6 +401,8 @@ namespace TopoDS_Edge ridgeE = TopoDS::Edge( *riE ); while ( !ridgeE.IsNull() ) { + if ( !ridgeEE.Add( ridgeE )) + break; TopExp::Vertices( ridgeE, VV[0], VV[1] ); TopoDS_Shape V1 = VV[ V0.IsSame( VV[0] )]; if ( cornerVV.Contains( V1 ) ) @@ -451,6 +453,11 @@ namespace } // loop on ridge EDGEs around a corner VERTEX } // loop on on corner VERTEXes + if ( subEE.Extent() > ridgeEE.Extent() + internEE.Extent() ) // PAL23269 + for ( int i = 1; i < subEE.Extent(); ++i ) + if ( !ridgeEE.Contains( subEE(i) )) + internEE.Add( subEE(i) ); + return true; } // getInternalEdges() } // namespace diff --git a/src/StdMeshers/StdMeshers_FaceSide.cxx b/src/StdMeshers/StdMeshers_FaceSide.cxx index 470b5b6e7..ab76ddf93 100644 --- a/src/StdMeshers/StdMeshers_FaceSide.cxx +++ b/src/StdMeshers/StdMeshers_FaceSide.cxx @@ -144,7 +144,6 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face& theFace, double p4 = myFirst[i]+(myLast[i]-myFirst[i])/4.; double d2 = GCPnts_AbscissaPoint::Length( A2dC, myFirst[i], p2 ); double d4 = GCPnts_AbscissaPoint::Length( A2dC, myFirst[i], p4 ); - //cout<<"len = "<& Edges() const { return myEdge; } + /*! + * \brief Return the FACE + */ + const TopoDS_Face& Face() const { return myFace; } /*! * \brief Return 1st vertex of the i-th edge (count starts from zero) */ diff --git a/src/StdMeshers/StdMeshers_Penta_3D.cxx b/src/StdMeshers/StdMeshers_Penta_3D.cxx index 69485a746..8a852edb9 100644 --- a/src/StdMeshers/StdMeshers_Penta_3D.cxx +++ b/src/StdMeshers/StdMeshers_Penta_3D.cxx @@ -1367,7 +1367,7 @@ bool StdMeshers_Penta_3D::LoadIJNodes(StdMeshers_IJNodeMap & theIJNodes, // find the other edges of theFace and orientation of e1 TopoDS_Edge e1, e2, eTop; - bool rev1, CumOri = false; + bool rev1 = false, CumOri = false; TopExp_Explorer exp( theFace, TopAbs_EDGE ); int nbEdges = 0; for ( ; exp.More(); exp.Next() ) { diff --git a/src/StdMeshers/StdMeshers_Prism_3D.cxx b/src/StdMeshers/StdMeshers_Prism_3D.cxx index c7a44bada..d0c4410e7 100644 --- a/src/StdMeshers/StdMeshers_Prism_3D.cxx +++ b/src/StdMeshers/StdMeshers_Prism_3D.cxx @@ -1116,7 +1116,7 @@ bool StdMeshers_Prism_3D::compute(const Prism_3D::TPrismTopo& thePrism) ( ! botSM->GetAlgo() || ! _gen->Compute( *botSM->GetFather(), botSM->GetSubShape(), /*shapeOnly=*/true ))) return error( COMPERR_BAD_INPUT_MESH, - TCom( "No mesher defined to compute the face #") + TCom( "No mesher defined to compute the base face #") << shapeID( thePrism.myBottom )); // Make all side FACEs of thePrism meshed with quads @@ -3155,7 +3155,7 @@ bool StdMeshers_Prism_3D::initPrism(Prism_3D::TPrismTopo& thePrism, // find vertex 000 - the one with smallest coordinates (for easy DEBUG :-) TopoDS_Vertex V000; - double minVal = DBL_MAX, minX, val; + double minVal = DBL_MAX, minX = 0, val; for ( TopExp_Explorer exp( botSM->GetSubShape(), TopAbs_VERTEX ); exp.More(); exp.Next() ) { diff --git a/src/StdMeshers/StdMeshers_Projection_2D.cxx b/src/StdMeshers/StdMeshers_Projection_2D.cxx index c4375bac9..7f476aa82 100644 --- a/src/StdMeshers/StdMeshers_Projection_2D.cxx +++ b/src/StdMeshers/StdMeshers_Projection_2D.cxx @@ -1147,6 +1147,51 @@ namespace { return true; } + //======================================================================= + /* + * Set initial association of VERTEXes for the case of projection + * from a quadrangle FACE to a closed FACE, where opposite src EDGEs + * have different nb of segments + */ + //======================================================================= + + void initAssoc4Quad2Closed(const TopoDS_Shape& tgtFace, + SMESH_MesherHelper& tgtHelper, + const TopoDS_Shape& srcFace, + SMESH_Mesh* srcMesh, + TAssocTool::TShapeShapeMap & assocMap) + { + if ( !tgtHelper.HasRealSeam() || srcFace.ShapeType() != TopAbs_FACE ) + return; // no seam edge + list< TopoDS_Edge > tgtEdges, srcEdges; + list< int > tgtNbEW, srcNbEW; + int tgtNbW = SMESH_Block::GetOrderedEdges( TopoDS::Face( tgtFace ), tgtEdges, tgtNbEW ); + int srcNbW = SMESH_Block::GetOrderedEdges( TopoDS::Face( srcFace ), srcEdges, srcNbEW ); + if ( tgtNbW != 1 || srcNbW != 1 || + tgtNbEW.front() != 4 || srcNbEW.front() != 4 ) + return; // not quads + + int srcNbSeg[4]; + list< TopoDS_Edge >::iterator edgeS = srcEdges.begin(), edgeT = tgtEdges.begin(); + for ( int i = 0; edgeS != srcEdges.end(); ++i, ++edgeS ) + if ( SMESHDS_SubMesh* sm = srcMesh->GetMeshDS()->MeshElements( *edgeS )) + srcNbSeg[ i ] = sm->NbNodes(); + else + return; // not meshed + if ( srcNbSeg[0] == srcNbSeg[2] && srcNbSeg[1] == srcNbSeg[3] ) + return; // same nb segments + if ( srcNbSeg[0] != srcNbSeg[2] && srcNbSeg[1] != srcNbSeg[3] ) + return; // all different nb segments + + edgeS = srcEdges.begin(); + if ( srcNbSeg[0] != srcNbSeg[2] ) + ++edgeS; + TAssocTool::InsertAssociation( tgtHelper.IthVertex( 0,*edgeT ), + tgtHelper.IthVertex( 0,*edgeS ), assocMap ); + TAssocTool::InsertAssociation( tgtHelper.IthVertex( 1,*edgeT ), + tgtHelper.IthVertex( 1,*edgeS ), assocMap ); + } + } // namespace @@ -1159,7 +1204,6 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& { _src2tgtNodes.clear(); - MESSAGE("Projection_2D Compute"); if ( !_sourceHypo ) return false; @@ -1178,8 +1222,12 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& TopoDS_Face tgtFace = TopoDS::Face( theShape.Oriented(TopAbs_FORWARD)); TopoDS_Shape srcShape = _sourceHypo->GetSourceFace().Oriented(TopAbs_FORWARD); + helper.SetSubShape( tgtFace ); + TAssocTool::TShapeShapeMap shape2ShapeMap; TAssocTool::InitVertexAssociation( _sourceHypo, shape2ShapeMap ); + if ( shape2ShapeMap.IsEmpty() ) + initAssoc4Quad2Closed( tgtFace, helper, srcShape, srcMesh, shape2ShapeMap ); if ( !TAssocTool::FindSubShapeAssociation( tgtFace, tgtMesh, srcShape, srcMesh, shape2ShapeMap) || !shape2ShapeMap.IsBound( tgtFace )) @@ -1257,7 +1305,7 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& { // projection in case if the faces are similar in 2D space projDone = projectBy2DSimilarity( tgtFace, srcFace, tgtWires, srcWires, - shape2ShapeMap, _src2tgtNodes, is1DComputed); + shape2ShapeMap, _src2tgtNodes, is1DComputed ); } if ( !projDone ) { @@ -1266,8 +1314,6 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& // shape2ShapeMap, _src2tgtNodes, is1DComputed); } - helper.SetSubShape( tgtFace ); - // it will remove mesh built on edges and vertices in failure case MeshCleaner cleaner( tgtSubMesh ); diff --git a/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx b/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx index 989a2d501..955fc1147 100644 --- a/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx +++ b/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx @@ -519,7 +519,7 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh& aMesh, // for each node of the down edge find nearest node // in the first row of the regular grid and link them for (i = 0; i < stop; i++) { - const SMDS_MeshNode *a, *b, *c, *d; + const SMDS_MeshNode *a, *b, *c=0, *d; a = uv_e0[i].node; b = uv_e0[i + 1].node; gp_Pnt pb (b->X(), b->Y(), b->Z()); @@ -533,6 +533,7 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh& aMesh, } else { // find in the grid node c, nearest to the b + c = 0; double mind = RealLast(); for (int k = g; k <= iup; k++) { @@ -734,6 +735,7 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh& aMesh, gp_Pnt pb (b->X(), b->Y(), b->Z()); // find node c in the grid, nearest to the b + c = 0; int near = g; if (i == stop - 1) { // up bondary reached c = quad->uv_grid[nbhoriz*(jup + 1) - 2].node; @@ -2138,7 +2140,7 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh & aMesh, npl.Append(uv_el[i].normParam); } - int dl,dr; + int dl = 0, dr = 0; if (OldVersion) { // add some params to right and left after the first param // insert to right @@ -2380,7 +2382,7 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh & aMesh, TColgp_SequenceOfXY UVtmp; double drparam = npr.Value(nr) - npr.Value(nnn-1); double dlparam = npl.Value(nnn) - npl.Value(nnn-1); - double y0,y1; + double y0 = 0, y1 = 0; for (i=1; i<=drl; i++) { // add existed nodes from right edge NodesC.SetValue(nb,i+1,uv_er[nnn+i-2].node); @@ -3296,7 +3298,11 @@ bool StdMeshers_Quadrangle_2D::computeReduced (SMESH_Mesh & aMesh, vector curr_base = uv_eb, next_base; - UVPtStruct nullUVPtStruct; nullUVPtStruct.node = 0; + UVPtStruct nullUVPtStruct; + nullUVPtStruct.node = 0; + nullUVPtStruct.x = nullUVPtStruct.y = nullUVPtStruct.u = nullUVPtStruct.y = 0; + nullUVPtStruct.param = 0; + int curr_base_len = nb; int next_base_len = 0; @@ -4108,7 +4114,7 @@ bool StdMeshers_Quadrangle_2D::check() StdMeshers_FaceSidePtr wire = wireVec[0]; // find a right angle VERTEX - int iVertex; + int iVertex = 0; double maxAngle = -1e100; for ( int i = 0; i < wire->NbEdges(); ++i ) { @@ -5145,6 +5151,8 @@ void StdMeshers_Quadrangle_2D::updateSideUV( FaceQuadStruct::Side& side, for ( iS = 0; iS < q->side.size(); ++iS ) if ( side.grid == q->side[ iS ].grid ) break; + if ( iS == q->side.size() ) + continue; bool isOut; if ( !q->side[ iS ].IsReversed() ) isOut = ( q->side[ iS ].from > iCur || q->side[ iS ].to-1 <= iCur ); diff --git a/src/StdMeshers/StdMeshers_Regular_1D.cxx b/src/StdMeshers/StdMeshers_Regular_1D.cxx index 3f3cb47ff..7025642b3 100644 --- a/src/StdMeshers/StdMeshers_Regular_1D.cxx +++ b/src/StdMeshers/StdMeshers_Regular_1D.cxx @@ -72,15 +72,15 @@ using namespace StdMeshers; //============================================================================= /*! - * + * */ //============================================================================= -StdMeshers_Regular_1D::StdMeshers_Regular_1D(int hypId, int studyId, +StdMeshers_Regular_1D::StdMeshers_Regular_1D(int hypId, + int studyId, SMESH_Gen * gen) - :SMESH_1D_Algo(hypId, studyId, gen) + :SMESH_1D_Algo( hypId, studyId, gen ) { - MESSAGE("StdMeshers_Regular_1D::StdMeshers_Regular_1D"); _name = "Regular_1D"; _shapeType = (1 << TopAbs_EDGE); _fpHyp = 0; @@ -155,7 +155,7 @@ bool StdMeshers_Regular_1D::CheckHypothesis( SMESH_Mesh& aMesh, string hypName = theHyp->GetName(); - if (hypName == "LocalLength") + if ( hypName == "LocalLength" ) { const StdMeshers_LocalLength * hyp = dynamic_cast (theHyp); @@ -167,7 +167,7 @@ bool StdMeshers_Regular_1D::CheckHypothesis( SMESH_Mesh& aMesh, aStatus = SMESH_Hypothesis::HYP_OK; } - else if (hypName == "MaxLength") + else if ( hypName == "MaxLength" ) { const StdMeshers_MaxLength * hyp = dynamic_cast (theHyp); @@ -182,7 +182,7 @@ bool StdMeshers_Regular_1D::CheckHypothesis( SMESH_Mesh& aMesh, aStatus = SMESH_Hypothesis::HYP_OK; } - else if (hypName == "NumberOfSegments") + else if ( hypName == "NumberOfSegments" ) { const StdMeshers_NumberOfSegments * hyp = dynamic_cast (theHyp); @@ -217,7 +217,7 @@ bool StdMeshers_Regular_1D::CheckHypothesis( SMESH_Mesh& aMesh, aStatus = SMESH_Hypothesis::HYP_OK; } - else if (hypName == "Arithmetic1D") + else if ( hypName == "Arithmetic1D" ) { const StdMeshers_Arithmetic1D * hyp = dynamic_cast (theHyp); @@ -232,7 +232,7 @@ bool StdMeshers_Regular_1D::CheckHypothesis( SMESH_Mesh& aMesh, aStatus = SMESH_Hypothesis::HYP_OK; } - else if (hypName == "GeometricProgression") + else if ( hypName == "GeometricProgression" ) { const StdMeshers_Geometric1D * hyp = dynamic_cast (theHyp); @@ -247,7 +247,7 @@ bool StdMeshers_Regular_1D::CheckHypothesis( SMESH_Mesh& aMesh, aStatus = SMESH_Hypothesis::HYP_OK; } - else if (hypName == "FixedPoints1D") { + else if ( hypName == "FixedPoints1D" ) { _fpHyp = dynamic_cast (theHyp); ASSERT(_fpHyp); _hypType = FIXED_POINTS_1D; @@ -257,7 +257,7 @@ bool StdMeshers_Regular_1D::CheckHypothesis( SMESH_Mesh& aMesh, aStatus = SMESH_Hypothesis::HYP_OK; } - else if (hypName == "StartEndLength") + else if ( hypName == "StartEndLength" ) { const StdMeshers_StartEndLength * hyp = dynamic_cast (theHyp); @@ -272,7 +272,7 @@ bool StdMeshers_Regular_1D::CheckHypothesis( SMESH_Mesh& aMesh, aStatus = SMESH_Hypothesis::HYP_OK; } - else if (hypName == "Deflection1D") + else if ( hypName == "Deflection1D" ) { const StdMeshers_Deflection1D * hyp = dynamic_cast (theHyp); @@ -283,7 +283,7 @@ bool StdMeshers_Regular_1D::CheckHypothesis( SMESH_Mesh& aMesh, aStatus = SMESH_Hypothesis::HYP_OK; } - else if (hypName == "AutomaticLength") + else if ( hypName == "AutomaticLength" ) { StdMeshers_AutomaticLength * hyp = const_cast (dynamic_cast (theHyp)); @@ -293,7 +293,7 @@ bool StdMeshers_Regular_1D::CheckHypothesis( SMESH_Mesh& aMesh, _hypType = MAX_LENGTH; aStatus = SMESH_Hypothesis::HYP_OK; } - else if (hypName == "Adaptive1D") + else if ( hypName == "Adaptive1D" ) { _adaptiveHyp = dynamic_cast < const StdMeshers_Adaptive1D* >(theHyp); ASSERT(_adaptiveHyp); @@ -351,13 +351,11 @@ static bool computeParamByFunc(Adaptor3d_Curve& C3d, // never do this way //OSD::SetSignal( true ); - if (nbSeg <= 0) + if ( nbSeg <= 0 ) return false; - MESSAGE( "computeParamByFunc" ); - int nbPnt = 1 + nbSeg; - vector x(nbPnt, 0.); + vector x( nbPnt, 0. ); if ( !buildDistribution( func, 0.0, 1.0, nbSeg, x, 1E-4 )) return false; @@ -374,7 +372,7 @@ static bool computeParamByFunc(Adaptor3d_Curve& C3d, for ( int i = 1; i < nbSeg; i++ ) { double curvLength = length * (x[i] - x[i-1]) * sign; - double tol = Min( Precision::Confusion(), curvLength / 100. ); + double tol = Min( Precision::Confusion(), curvLength / 100. ); GCPnts_AbscissaPoint Discret( tol, C3d, curvLength, prevU ); if ( !Discret.IsDone() ) return false; @@ -686,7 +684,6 @@ bool StdMeshers_Regular_1D::computeInternalParameters(SMESH_Mesh & theMesh, if ( ! SMESH_Algo::GetSortedNodesOnEdge( theMesh.GetMeshDS(), mainEdge, _quadraticMesh, mainEdgeParamsOfNodes, SMDSAbs_Edge )) return error("Bad node parameters on the source edge of Propagation Of Distribution"); - vector< double > segLen( mainEdgeParamsOfNodes.size() - 1 ); double totalLen = 0; BRepAdaptor_Curve mainEdgeCurve( mainEdge ); @@ -715,7 +712,7 @@ bool StdMeshers_Regular_1D::computeInternalParameters(SMESH_Mesh & theMesh, ++nbParams; } if ( nbParams != segLen.size()-1 ) - return error( SMESH_Comment("Can't divide into ") << segLen.size() << " segements"); + return error( SMESH_Comment("Can't divide into ") << segLen.size() << " segments"); compensateError( segLen[ theReverse ? segLen.size()-1 : 0 ], segLen[ theReverse ? 0 : segLen.size()-1 ], @@ -728,8 +725,8 @@ bool StdMeshers_Regular_1D::computeInternalParameters(SMESH_Mesh & theMesh, { case LOCAL_LENGTH: case MAX_LENGTH: - case NB_SEGMENTS: { - + case NB_SEGMENTS: + { double eltSize = 1; int nbSegments; if ( _hypType == MAX_LENGTH ) @@ -761,7 +758,7 @@ bool StdMeshers_Regular_1D::computeInternalParameters(SMESH_Mesh & theMesh, } if (computed) { SMESHDS_SubMesh* smds = sm->GetSubMeshDS(); - int nb_segments = smds->NbElements(); + int nb_segments = smds->NbElements(); if (nbseg - 1 <= nb_segments && nb_segments <= nbseg + 1) { isFound = true; nbseg = nb_segments; @@ -893,18 +890,18 @@ bool StdMeshers_Regular_1D::computeInternalParameters(SMESH_Mesh & theMesh, return true; } - case ARITHMETIC_1D: { - + case ARITHMETIC_1D: + { // arithmetic progression: SUM(n) = ( an - a1 + q ) * ( a1 + an ) / ( 2 * q ) = theLength double a1 = _value[ BEG_LENGTH_IND ]; double an = _value[ END_LENGTH_IND ]; - if ( 1.01*theLength < a1 + an) + if ( 1.01*theLength < a1 + an ) return error ( SMESH_Comment("Invalid segment lengths (")< numeric_limits::min() ? ( 1+( an-a1 )/q ) : ( 1+theLength/a1 )); + double q = ( an - a1 ) / ( 2 *theLength/( a1 + an ) - 1 ); + int n = int(fabs(q) > numeric_limits::min() ? ( 1+( an-a1 )/q ) : ( 1+theLength/a1 )); double U1 = theReverse ? l : f; double Un = theReverse ? f : l; @@ -927,14 +924,14 @@ bool StdMeshers_Regular_1D::computeInternalParameters(SMESH_Mesh & theMesh, eltSize += q; } compensateError( a1, an, U1, Un, theLength, theC3d, theParams ); - if (theReverse) theParams.reverse(); // NPAL18025 + if ( theReverse ) theParams.reverse(); // NPAL18025 return true; } - case GEOMETRIC_1D: { - - double a1 = _value[ BEG_LENGTH_IND ], an; + case GEOMETRIC_1D: + { + double a1 = _value[ BEG_LENGTH_IND ], an = 0; double q = _value[ END_LENGTH_IND ]; double U1 = theReverse ? l : f; @@ -977,7 +974,8 @@ bool StdMeshers_Regular_1D::computeInternalParameters(SMESH_Mesh & theMesh, return true; } - case FIXED_POINTS_1D: { + case FIXED_POINTS_1D: + { const std::vector& aPnts = _fpHyp->GetPoints(); const std::vector& nbsegs = _fpHyp->GetNbSegments(); TColStd_SequenceOfReal Params; @@ -986,22 +984,22 @@ bool StdMeshers_Regular_1D::computeInternalParameters(SMESH_Mesh & theMesh, if( aPnts[i]<0.0001 || aPnts[i]>0.9999 ) continue; int j=1; bool IsExist = false; - for(; j<=Params.Length(); j++) { - if( fabs(aPnts[i]-Params.Value(j)) < 1e-4 ) { + for ( ; j <= Params.Length(); j++ ) { + if ( Abs( aPnts[i] - Params.Value(j) ) < 1e-4 ) { IsExist = true; break; } - if( aPnts[i] (int)nbsegs.size()-1 ) ? nbsegs[0] : nbsegs[i]; - segmentSize = Params.Value(i+1)*theLength - currAbscissa; + segmentSize = Params.Value( i+1 ) * theLength - currAbscissa; currAbscissa += segmentSize; - GCPnts_AbscissaPoint APnt(theC3d, sign*segmentSize, par1); - if( !APnt.IsDone() ) + GCPnts_AbscissaPoint APnt( theC3d, sign*segmentSize, par1 ); + if ( !APnt.IsDone() ) return error( "GCPnts_AbscissaPoint failed"); - par2 = APnt.Parameter(); + par2 = APnt.Parameter(); eltSize = segmentSize/nbseg; - GCPnts_UniformAbscissa Discret(theC3d, eltSize, par1, par2); - if(theReverse) - Discret.Initialize(theC3d, eltSize, par2, par1); + GCPnts_UniformAbscissa Discret( theC3d, eltSize, par1, par2 ); + if ( theReverse ) + Discret.Initialize( theC3d, eltSize, par2, par1 ); else - Discret.Initialize(theC3d, eltSize, par1, par2); + Discret.Initialize( theC3d, eltSize, par1, par2 ); if ( !Discret.IsDone() ) return error( "GCPnts_UniformAbscissa failed"); int NbPoints = Discret.NbPoints(); list tmpParams; - for(int i=2; i::iterator itP = tmpParams.begin(); - for(; itP != tmpParams.end(); itP++) { - theParams.push_back( *(itP) ); - } + theParams.splice( theParams.end(), tmpParams ); theParams.push_back( par2 ); par1 = par2; @@ -1049,39 +1044,36 @@ bool StdMeshers_Regular_1D::computeInternalParameters(SMESH_Mesh & theMesh, segmentSize = theLength - currAbscissa; eltSize = segmentSize/nbseg; GCPnts_UniformAbscissa Discret; - if(theReverse) - Discret.Initialize(theC3d, eltSize, par1, lp); + if ( theReverse ) + Discret.Initialize( theC3d, eltSize, par1, lp ); else - Discret.Initialize(theC3d, eltSize, lp, par1); + Discret.Initialize( theC3d, eltSize, lp, par1 ); if ( !Discret.IsDone() ) return error( "GCPnts_UniformAbscissa failed"); int NbPoints = Discret.NbPoints(); list tmpParams; - for(int i=2; i::iterator itP = tmpParams.begin(); - for(; itP != tmpParams.end(); itP++) { - theParams.push_back( *(itP) ); - } + theParams.splice( theParams.end(), tmpParams ); - if (theReverse) { + if ( theReverse ) theParams.reverse(); // NPAL18025 - } + return true; } - case DEFLECTION: { - - GCPnts_UniformDeflection Discret(theC3d, _value[ DEFLECTION_IND ], f, l, true); + case DEFLECTION: + { + GCPnts_UniformDeflection Discret( theC3d, _value[ DEFLECTION_IND ], f, l, true ); if ( !Discret.IsDone() ) return false; @@ -1241,8 +1233,6 @@ bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & t } else { - //MESSAGE("************* Degenerated edge! *****************"); - // Edge is a degenerated Edge : We put n = 5 points on the edge. const int NbPoints = 5; BRep_Tool::Range( E, f, l ); // PAL15185 @@ -1345,9 +1335,8 @@ bool StdMeshers_Regular_1D::Evaluate(SMESH_Mesh & theMesh, } else { - //MESSAGE("************* Degenerated edge! *****************"); // Edge is a degenerated Edge : We put n = 5 points on the edge. - if(_quadraticMesh) { + if ( _quadraticMesh ) { aVec[SMDSEntity_Node] = 11; aVec[SMDSEntity_Quad_Edge] = 6; } diff --git a/src/StdMeshers/StdMeshers_ViscousLayers.cxx b/src/StdMeshers/StdMeshers_ViscousLayers.cxx index 1e8d0f2cc..1b4e6ab04 100644 --- a/src/StdMeshers/StdMeshers_ViscousLayers.cxx +++ b/src/StdMeshers/StdMeshers_ViscousLayers.cxx @@ -43,16 +43,21 @@ #include "SMESH_subMesh.hxx" #include "SMESH_subMeshEventListener.hxx" #include "StdMeshers_FaceSide.hxx" +#include "StdMeshers_ViscousLayers2D.hxx" #include +#include #include #include +//#include #include +#include #include #include #include #include #include +#include #include #include #include @@ -70,6 +75,7 @@ #include #include #include +#include #include #include #include @@ -81,16 +87,21 @@ #include #include -#include -#include #include #include +#include +#include +#include #ifdef _DEBUG_ -//#define __myDEBUG +#define __myDEBUG //#define __NOT_INVALIDATE_BAD_SMOOTH #endif +#define INCREMENTAL_SMOOTH // smooth only if min angle is too small +#define BLOCK_INFLATION // of individual _LayerEdge's +#define OLD_NEF_POLYGON + using namespace std; //================================================================================ @@ -102,6 +113,8 @@ namespace VISCOUS_3D const double theMinSmoothCosin = 0.1; const double theSmoothThickToElemSizeRatio = 0.3; + const double theMinSmoothTriaAngle = 30; + const double theMinSmoothQuadAngle = 45; // what part of thickness is allowed till intersection // (defined by SALOME_TESTS/Grids/smesh/viscous_layers_00/A5) @@ -111,6 +124,10 @@ namespace VISCOUS_3D { return cosin * tgtThick > theSmoothThickToElemSizeRatio * elemSize; } + double getSmoothingThickness( double cosin, double elemSize ) + { + return theSmoothThickToElemSizeRatio * elemSize / cosin; + } /*! * \brief SMESH_ProxyMesh computed by _ViscousBuilder for a SOLID. @@ -184,8 +201,9 @@ namespace VISCOUS_3D SMESH_subMeshEventListenerData* data, const SMESH_Hypothesis* hyp) { - if ( SMESH_subMesh::COMPUTE_EVENT == eventType && - SMESH_subMesh::CHECK_COMPUTE_STATE != event) + if (( SMESH_subMesh::COMPUTE_EVENT == eventType ) && + ( SMESH_subMesh::CHECK_COMPUTE_STATE != event && + SMESH_subMesh::SUBMESH_COMPUTED != event )) { // delete SMESH_ProxyMesh containing temporary faces subMesh->DeleteEventListener( this ); @@ -256,20 +274,25 @@ namespace VISCOUS_3D const SMDS_MeshNode* nNext=0, const SMDS_MeshNode* nOpp=0) : _nPrev(nPrev), _nNext(nNext), _nOpp(nOpp) {} - bool IsForward(const SMDS_MeshNode* nSrc, const gp_XYZ* pntTgt, double& vol) const + bool IsForward(const gp_XYZ* pntSrc, const gp_XYZ* pntTgt, double& vol) const { const double M[3][3] = - {{ _nNext->X() - nSrc->X(), _nNext->Y() - nSrc->Y(), _nNext->Z() - nSrc->Z() }, - { pntTgt->X() - nSrc->X(), pntTgt->Y() - nSrc->Y(), pntTgt->Z() - nSrc->Z() }, - { _nPrev->X() - nSrc->X(), _nPrev->Y() - nSrc->Y(), _nPrev->Z() - nSrc->Z() }}; - vol = ( + M[0][0]*M[1][1]*M[2][2] - + M[0][1]*M[1][2]*M[2][0] - + M[0][2]*M[1][0]*M[2][1] - - M[0][0]*M[1][2]*M[2][1] - - M[0][1]*M[1][0]*M[2][2] - - M[0][2]*M[1][1]*M[2][0]); + {{ _nNext->X() - pntSrc->X(), _nNext->Y() - pntSrc->Y(), _nNext->Z() - pntSrc->Z() }, + { pntTgt->X() - pntSrc->X(), pntTgt->Y() - pntSrc->Y(), pntTgt->Z() - pntSrc->Z() }, + { _nPrev->X() - pntSrc->X(), _nPrev->Y() - pntSrc->Y(), _nPrev->Z() - pntSrc->Z() }}; + vol = ( + M[0][0] * M[1][1] * M[2][2] + + M[0][1] * M[1][2] * M[2][0] + + M[0][2] * M[1][0] * M[2][1] + - M[0][0] * M[1][2] * M[2][1] + - M[0][1] * M[1][0] * M[2][2] + - M[0][2] * M[1][1] * M[2][0]); return vol > 1e-100; } + bool IsForward(const SMDS_MeshNode* nSrc, const gp_XYZ& pTgt, double& vol) const + { + SMESH_TNodeXYZ pSrc( nSrc ); + return IsForward( &pSrc, &pTgt, vol ); + } bool IsForward(const gp_XY& tgtUV, const SMDS_MeshNode* smoothedNode, const TopoDS_Face& face, @@ -282,10 +305,50 @@ namespace VISCOUS_3D double d = v1 ^ v2; return d*refSign > 1e-100; } + bool IsMinAngleOK( const gp_XYZ& pTgt, double& minAngle ) const + { + SMESH_TNodeXYZ pPrev( _nPrev ), pNext( _nNext ); + if ( !_nOpp ) // triangle + { + gp_Vec tp( pPrev - pTgt ), pn( pNext - pPrev ), nt( pTgt - pNext ); + double tp2 = tp.SquareMagnitude(); + double pn2 = pn.SquareMagnitude(); + double nt2 = nt.SquareMagnitude(); + + if ( tp2 < pn2 && tp2 < nt2 ) + minAngle = ( nt * -pn ) * ( nt * -pn ) / nt2 / pn2; + else if ( pn2 < nt2 ) + minAngle = ( tp * -nt ) * ( tp * -nt ) / tp2 / nt2; + else + minAngle = ( pn * -tp ) * ( pn * -tp ) / pn2 / tp2; + + static double theMaxCos2 = ( Cos( theMinSmoothTriaAngle * M_PI / 180. ) * + Cos( theMinSmoothTriaAngle * M_PI / 180. )); + return minAngle < theMaxCos2; + } + else // quadrangle + { + SMESH_TNodeXYZ pOpp( _nOpp ); + gp_Vec tp( pPrev - pTgt ), po( pOpp - pPrev ), on( pNext - pOpp), nt( pTgt - pNext ); + double tp2 = tp.SquareMagnitude(); + double po2 = po.SquareMagnitude(); + double on2 = on.SquareMagnitude(); + double nt2 = nt.SquareMagnitude(); + minAngle = Max( Max((( tp * -nt ) * ( tp * -nt ) / tp2 / nt2 ), + (( po * -tp ) * ( po * -tp ) / po2 / tp2 )), + Max((( on * -po ) * ( on * -po ) / on2 / po2 ), + (( nt * -on ) * ( nt * -on ) / nt2 / on2 ))); + + static double theMaxCos2 = ( Cos( theMinSmoothQuadAngle * M_PI / 180. ) * + Cos( theMinSmoothQuadAngle * M_PI / 180. )); + return minAngle < theMaxCos2; + } + } bool IsNeighbour(const _Simplex& other) const { return _nPrev == other._nNext || _nNext == other._nPrev; } + bool Includes( const SMDS_MeshNode* node ) const { return _nPrev == node || _nNext == node; } static void GetSimplices( const SMDS_MeshNode* node, vector<_Simplex>& simplices, const set& ingnoreShapes, @@ -299,9 +362,10 @@ namespace VISCOUS_3D */ struct _Curvature { - double _r; // radius - double _k; // factor to correct node smoothed position - double _h2lenRatio; // avgNormProj / (2*avgDist) + double _r; // radius + double _k; // factor to correct node smoothed position + double _h2lenRatio; // avgNormProj / (2*avgDist) + gp_Pnt2d _uv; // UV used in putOnOffsetSurface() public: static _Curvature* New( double avgNormProj, double avgDist ) { @@ -314,6 +378,8 @@ namespace VISCOUS_3D //c->_k = avgNormProj / c->_r; c->_k *= ( c->_r < 0 ? 1/1.1 : 1.1 ); // not to be too restrictive c->_h2lenRatio = avgNormProj / ( avgDist + avgDist ); + + c->_uv.SetCoord( 0., 0. ); } return c; } @@ -325,6 +391,7 @@ namespace VISCOUS_3D struct _2NearEdges; struct _LayerEdge; struct _EdgesOnShape; + struct _Smoother1D; typedef map< const SMDS_MeshNode*, _LayerEdge*, TIDCompare > TNode2Edge; //-------------------------------------------------------------------------------- @@ -338,23 +405,42 @@ namespace VISCOUS_3D vector< const SMDS_MeshNode*> _nodes; - gp_XYZ _normal; // to solid surface - vector _pos; // points computed during inflation - double _len; // length achived with the last inflation step - double _cosin; // of angle (_normal ^ surface) + gp_XYZ _normal; // to boundary of solid + vector _pos; // points computed during inflation + double _len; // length achived with the last inflation step + double _maxLen; // maximal possible length + double _cosin; // of angle (_normal ^ surface) + double _minAngle; // of _simplices double _lenFactor; // to compute _len taking _cosin into account + int _flags; - // face or edge w/o layer along or near which _LayerEdge is inflated - //TopoDS_Shape* _sWOL; // simplices connected to the source node (_nodes[0]); // used for smoothing and quality check of _LayerEdge's based on the FACE vector<_Simplex> _simplices; + vector<_LayerEdge*> _neibors; // all surrounding _LayerEdge's PSmooFun _smooFunction; // smoothing function + _Curvature* _curvature; // data for smoothing of _LayerEdge's based on the EDGE _2NearEdges* _2neibors; - _Curvature* _curvature; - // TODO:: detele _Curvature, _plnNorm + enum EFlags { TO_SMOOTH = 1, + MOVED = 2, // set by _neibors[i]->SetNewLength() + SMOOTHED = 4, // set by this->Smooth() + DIFFICULT = 8, // near concave VERTEX + ON_CONCAVE_FACE = 16, + BLOCKED = 32, // not to inflate any more + INTERSECTED = 64, // close intersection with a face found + NORMAL_UPDATED = 128, + MARKED = 256, // local usage + MULTI_NORMAL = 512, // a normal is invisible by some of surrounding faces + NEAR_BOUNDARY = 1024,// is near FACE boundary forcing smooth + SMOOTHED_C1 = 2048,// is on _eosC1 + DISTORTED = 4096,// was bad before smoothing + RISKY_SWOL = 8192 // SWOL is parallel to a source FACE + }; + bool Is ( EFlags f ) const { return _flags & f; } + void Set ( EFlags f ) { _flags |= f; } + void Unset( EFlags f ) { _flags &= ~f; } void SetNewLength( double len, _EdgesOnShape& eos, SMESH_MesherHelper& helper ); bool SetNewLength2d( Handle(Geom_Surface)& surface, @@ -365,30 +451,57 @@ namespace VISCOUS_3D const SMDS_MeshNode* n2, const _EdgesOnShape& eos, SMESH_MesherHelper& helper); - void InvalidateStep( int curStep, const _EdgesOnShape& eos, bool restoreLength=false ); + void Block( _SolidData& data ); + void InvalidateStep( size_t curStep, const _EdgesOnShape& eos, bool restoreLength=false ); void ChooseSmooFunction(const set< TGeomID >& concaveVertices, const TNode2Edge& n2eMap); - int Smooth(const int step, const bool isConcaveFace, const bool findBest); - bool SmoothOnEdge(Handle(Geom_Surface)& surface, - const TopoDS_Face& F, - SMESH_MesherHelper& helper); + void SmoothPos( const vector< double >& segLen, const double tol ); + int Smooth(const int step, const bool isConcaveFace, bool findBest); + int Smooth(const int step, bool findBest, vector< _LayerEdge* >& toSmooth ); + int CheckNeiborsOnBoundary(vector< _LayerEdge* >* badNeibors = 0, bool * needSmooth = 0 ); + void SmoothWoCheck(); + bool SmoothOnEdge(Handle(ShapeAnalysis_Surface)& surface, + const TopoDS_Face& F, + SMESH_MesherHelper& helper); + void MoveNearConcaVer( const _EdgesOnShape* eov, + const _EdgesOnShape* eos, + const int step, + vector< _LayerEdge* > & badSmooEdges); bool FindIntersection( SMESH_ElementSearcher& searcher, double & distance, const double& epsilon, _EdgesOnShape& eos, const SMDS_MeshElement** face = 0); + bool SegTriaInter( const gp_Ax1& lastSegment, + const gp_XYZ& p0, + const gp_XYZ& p1, + const gp_XYZ& p2, + double& dist, + const double& epsilon) const; bool SegTriaInter( const gp_Ax1& lastSegment, const SMDS_MeshNode* n0, const SMDS_MeshNode* n1, const SMDS_MeshNode* n2, double& dist, - const double& epsilon) const; + const double& epsilon) const + { return SegTriaInter( lastSegment, + SMESH_TNodeXYZ( n0 ), SMESH_TNodeXYZ( n1 ), SMESH_TNodeXYZ( n2 ), + dist, epsilon ); + } + const gp_XYZ& PrevPos() const { return _pos[ _pos.size() - 2 ]; } + const gp_XYZ& PrevCheckPos() const { return _pos[ Is( NORMAL_UPDATED ) ? _pos.size()-2 : 0 ]; } gp_Ax1 LastSegment(double& segLen, _EdgesOnShape& eos) const; gp_XY LastUV( const TopoDS_Face& F, _EdgesOnShape& eos ) const; bool IsOnEdge() const { return _2neibors; } gp_XYZ Copy( _LayerEdge& other, _EdgesOnShape& eos, SMESH_MesherHelper& helper ); void SetCosin( double cosin ); + void SetNormal( const gp_XYZ& n ) { _normal = n; } int NbSteps() const { return _pos.size() - 1; } // nb inlation steps + bool IsNeiborOnEdge( const _LayerEdge* edge ) const; + void SetSmooLen( double len ) { // set _len at which smoothing is needed + _cosin = len; // as for _LayerEdge's on FACE _cosin is not used + } + double GetSmooLen() { return _cosin; } // for _LayerEdge's on FACE _cosin is not used gp_XYZ smoothLaplacian(); gp_XYZ smoothAngular(); @@ -432,9 +545,9 @@ namespace VISCOUS_3D { return _inNorm * ( p - _pos ) < -tol; } - bool FindInterestion( const _halfPlane& hp, gp_XY & intPnt ) + bool FindIntersection( const _halfPlane& hp, gp_XY & intPnt ) { - const double eps = 1e-10; + //const double eps = 1e-10; double D = _dir.Crossed( hp._dir ); if ( fabs(D) < std::numeric_limits::min()) return false; @@ -467,6 +580,12 @@ namespace VISCOUS_3D std::swap( _wgt [0], _wgt [1] ); std::swap( _edges[0], _edges[1] ); } + void set( _LayerEdge* e1, _LayerEdge* e2, double w1, double w2 ) { + _edges[0] = e1; _edges[1] = e2; _wgt[0] = w1; _wgt[1] = w2; + } + bool include( const _LayerEdge* e ) { + return ( _edges[0] == e || _edges[1] == e ); + } }; @@ -477,7 +596,7 @@ namespace VISCOUS_3D struct AverageHyp { AverageHyp( const StdMeshers_ViscousLayers* hyp = 0 ) - :_nbLayers(0), _nbHyps(0), _thickness(0), _stretchFactor(0), _method(0) + :_nbLayers(0), _nbHyps(0), _method(0), _thickness(0), _stretchFactor(0) { Add( hyp ); } @@ -523,18 +642,32 @@ namespace VISCOUS_3D SMESH_subMesh * _subMesh; // face or edge w/o layer along or near which _edges are inflated TopoDS_Shape _sWOL; + bool _isRegularSWOL; // w/o singularities // averaged StdMeshers_ViscousLayers parameters AverageHyp _hyp; bool _toSmooth; + _Smoother1D* _edgeSmoother; + vector< _EdgesOnShape* > _eosConcaVer; // edges at concave VERTEXes of a FACE + vector< _EdgesOnShape* > _eosC1; // to smooth together several C1 continues shapes - vector< gp_XYZ > _faceNormals; // if _shape is FACE + vector< gp_XYZ > _faceNormals; // if _shape is FACE vector< _EdgesOnShape* > _faceEOS; // to get _faceNormals of adjacent FACEs + Handle(ShapeAnalysis_Surface) _offsetSurf; + _LayerEdge* _edgeForOffset; + + _SolidData* _data; // parent SOLID + TopAbs_ShapeEnum ShapeType() const { return _shape.IsNull() ? TopAbs_SHAPE : _shape.ShapeType(); } TopAbs_ShapeEnum SWOLType() const { return _sWOL.IsNull() ? TopAbs_SHAPE : _sWOL.ShapeType(); } + bool HasC1( const _EdgesOnShape* other ) const + { return std::find( _eosC1.begin(), _eosC1.end(), other ) != _eosC1.end(); } bool GetNormal( const SMDS_MeshElement* face, gp_Vec& norm ); + _SolidData& GetData() const { return *_data; } + + _EdgesOnShape(): _shapeID(-1), _subMesh(0), _toSmooth(false), _edgeSmoother(0) {} }; //-------------------------------------------------------------------------------- @@ -547,7 +680,7 @@ namespace VISCOUS_3D { TopoDS_Face _face; - // edges whose _simplices are used to detect prism destorsion + // edges whose _simplices are used to detect prism distortion vector< _LayerEdge* > _simplexTestEdges; // map a sub-shape to _SolidData::_edgesOnShape @@ -562,6 +695,20 @@ namespace VISCOUS_3D bool CheckPrisms() const; }; + //-------------------------------------------------------------------------------- + /*! + * \brief Structure holding _LayerEdge's based on EDGEs that will collide + * at inflation up to the full thickness. A detected collision + * is fixed in updateNormals() + */ + struct _CollisionEdges + { + _LayerEdge* _edge; + vector< _LayerEdge* > _intEdges; // each pair forms an intersected quadrangle + const SMDS_MeshNode* nSrc(int i) const { return _intEdges[i]->_nodes[0]; } + const SMDS_MeshNode* nTgt(int i) const { return _intEdges[i]->_nodes.back(); } + }; + //-------------------------------------------------------------------------------- /*! * \brief Data of a SOLID @@ -603,9 +750,9 @@ namespace VISCOUS_3D int _nbShapesToSmooth; - // to -- for analytic smooth - map< TGeomID,Handle(Geom_Curve)> _edge2curve; + //map< TGeomID,Handle(Geom_Curve)> _edge2curve; + vector< _CollisionEdges > _collisionEdges; set< TGeomID > _concaveFaces; double _maxThickness; // of all _hyps @@ -613,23 +760,17 @@ namespace VISCOUS_3D double _epsilon; // precision for SegTriaInter() + SMESH_MesherHelper* _helper; + _SolidData(const TopoDS_Shape& s=TopoDS_Shape(), _MeshOfSolid* m=0) - :_solid(s), _proxyMesh(m) {} + :_solid(s), _proxyMesh(m), _helper(0) {} ~_SolidData(); - Handle(Geom_Curve) CurveForSmooth( const TopoDS_Edge& E, - _EdgesOnShape& eos, - SMESH_MesherHelper& helper); - - void SortOnEdge( const TopoDS_Edge& E, - vector< _LayerEdge* >& edges, - SMESH_MesherHelper& helper); - + void SortOnEdge( const TopoDS_Edge& E, vector< _LayerEdge* >& edges); void Sort2NeiborsOnEdge( vector< _LayerEdge* >& edges ); - _ConvexFace* GetConvexFace( const TGeomID faceID ) - { + _ConvexFace* GetConvexFace( const TGeomID faceID ) { map< TGeomID, _ConvexFace >::iterator id2face = _convexFaces.find( faceID ); return id2face == _convexFaces.end() ? 0 : & id2face->second; } @@ -638,11 +779,37 @@ namespace VISCOUS_3D _EdgesOnShape* GetShapeEdges(const _LayerEdge* edge ) { return GetShapeEdges( edge->_nodes[0]->getshapeId() ); } - void AddShapesToSmooth( const set< _EdgesOnShape* >& shape ); + SMESH_MesherHelper& GetHelper() const { return *_helper; } + + void UnmarkEdges() { + for ( size_t i = 0; i < _edgesOnShape.size(); ++i ) + for ( size_t j = 0; j < _edgesOnShape[i]._edges.size(); ++j ) + _edgesOnShape[i]._edges[j]->Unset( _LayerEdge::MARKED ); + } + void AddShapesToSmooth( const set< _EdgesOnShape* >& shape, + const set< _EdgesOnShape* >* edgesNoAnaSmooth=0 ); void PrepareEdgesToSmoothOnFace( _EdgesOnShape* eof, bool substituteSrcNodes ); }; //-------------------------------------------------------------------------------- + /*! + * \brief Offset plane used in getNormalByOffset() + */ + struct _OffsetPlane + { + gp_Pln _plane; + int _faceIndex; + int _faceIndexNext[2]; + gp_Lin _lines[2]; // line of intersection with neighbor _OffsetPlane's + bool _isLineOK[2]; + _OffsetPlane() { + _isLineOK[0] = _isLineOK[1] = false; _faceIndexNext[0] = _faceIndexNext[1] = -1; + } + void ComputeIntersectionLine( _OffsetPlane& pln ); + gp_XYZ GetCommonPoint(bool& isFound) const; + int NbLines() const { return _isLineOK[0] + _isLineOK[1]; } + }; + //-------------------------------------------------------------------------------- /*! * \brief Container of centers of curvature at nodes on an EDGE bounding _ConvexFace */ @@ -725,8 +892,8 @@ namespace VISCOUS_3D set& ignoreFaces); bool makeLayer(_SolidData& data); void setShapeData( _EdgesOnShape& eos, SMESH_subMesh* sm, _SolidData& data ); - bool setEdgeData(_LayerEdge& edge, _EdgesOnShape& eos, const set& subIds, - SMESH_MesherHelper& helper, _SolidData& data); + bool setEdgeData( _LayerEdge& edge, _EdgesOnShape& eos, + SMESH_MesherHelper& helper, _SolidData& data); gp_XYZ getFaceNormal(const SMDS_MeshNode* n, const TopoDS_Face& face, SMESH_MesherHelper& helper, @@ -736,7 +903,8 @@ namespace VISCOUS_3D const TopoDS_Face& face, SMESH_MesherHelper& helper, gp_Dir& normal ); - gp_XYZ getWeigthedNormal( const SMDS_MeshNode* n, + gp_XYZ getWeigthedNormal( const _LayerEdge* edge ); + gp_XYZ getNormalByOffset( _LayerEdge* edge, std::pair< TopoDS_Face, gp_XYZ > fId2Normal[], int nbFaces ); bool findNeiborsOnEdge(const _LayerEdge* edge, @@ -755,15 +923,26 @@ namespace VISCOUS_3D void limitStepSize( _SolidData& data, const double minSize); bool inflate(_SolidData& data); bool smoothAndCheck(_SolidData& data, const int nbSteps, double & distToIntersection); - bool smoothAnalyticEdge( _SolidData& data, - _EdgesOnShape& eos, - Handle(Geom_Surface)& surface, - const TopoDS_Face& F, - SMESH_MesherHelper& helper); - bool updateNormals( _SolidData& data, SMESH_MesherHelper& helper, int stepNb ); + int invalidateBadSmooth( _SolidData& data, + SMESH_MesherHelper& helper, + vector< _LayerEdge* >& badSmooEdges, + vector< _EdgesOnShape* >& eosC1, + const int infStep ); + void makeOffsetSurface( _EdgesOnShape& eos, SMESH_MesherHelper& ); + void putOnOffsetSurface( _EdgesOnShape& eos, int infStep, int smooStep=0, bool moveAll=false ); + void findCollisionEdges( _SolidData& data, SMESH_MesherHelper& helper ); + bool updateNormals( _SolidData& data, SMESH_MesherHelper& helper, int stepNb, double stepSize ); bool updateNormalsOfConvexFaces( _SolidData& data, SMESH_MesherHelper& helper, int stepNb ); + void updateNormalsOfC1Vertices( _SolidData& data ); + bool updateNormalsOfSmoothed( _SolidData& data, + SMESH_MesherHelper& helper, + const int nbSteps, + const double stepSize ); + bool isNewNormalOk( _SolidData& data, + _LayerEdge& edge, + const gp_XYZ& newNormal); bool refine(_SolidData& data); bool shrink(); bool prepareEdgeToShrink( _LayerEdge& edge, _EdgesOnShape& eos, @@ -806,6 +985,76 @@ namespace VISCOUS_3D void Compute(bool set3D, SMESH_MesherHelper& helper); void RestoreParams(); void SwapSrcTgtNodes(SMESHDS_Mesh* mesh); + const TopoDS_Edge& GeomEdge() const { return _geomEdge; } + const SMDS_MeshNode* TgtNode( bool is2nd ) const + { return _edges[is2nd] ? _edges[is2nd]->_nodes.back() : 0; } + const SMDS_MeshNode* SrcNode( bool is2nd ) const + { return _edges[is2nd] ? _edges[is2nd]->_nodes[0] : 0; } + }; + //-------------------------------------------------------------------------------- + /*! + * \brief Smoother of _LayerEdge's on EDGE. + */ + struct _Smoother1D + { + struct OffPnt // point of the offsetted EDGE + { + gp_XYZ _xyz; // coord of a point inflated from EDGE w/o smooth + double _len; // length reached at previous inflation step + double _param; // on EDGE + _2NearEdges _2edges; // 2 neighbor _LayerEdge's + double Distance( const OffPnt& p ) const { return ( _xyz - p._xyz ).Modulus(); } + }; + vector< OffPnt > _offPoints; + vector< double > _leParams; // normalized param of _eos._edges on EDGE + Handle(Geom_Curve) _anaCurve; // for analytic smooth + _LayerEdge _leOnV[2]; // _LayerEdge's holding normal to the EDGE at VERTEXes + size_t _iSeg[2]; // index of segment where extreme tgt node is projected + _EdgesOnShape& _eos; + double _curveLen; // length of the EDGE + + static Handle(Geom_Curve) CurveForSmooth( const TopoDS_Edge& E, + _EdgesOnShape& eos, + SMESH_MesherHelper& helper); + + _Smoother1D( Handle(Geom_Curve) curveForSmooth, + _EdgesOnShape& eos ) + : _anaCurve( curveForSmooth ), _eos( eos ) + { + } + bool Perform(_SolidData& data, + Handle(ShapeAnalysis_Surface)& surface, + const TopoDS_Face& F, + SMESH_MesherHelper& helper ) + { + if ( _leParams.empty() || ( !isAnalytic() && _offPoints.empty() )) + prepare( data ); + + if ( isAnalytic() ) + return smoothAnalyticEdge( data, surface, F, helper ); + else + return smoothComplexEdge ( data, surface, F, helper ); + } + void prepare(_SolidData& data ); + + bool smoothAnalyticEdge( _SolidData& data, + Handle(ShapeAnalysis_Surface)& surface, + const TopoDS_Face& F, + SMESH_MesherHelper& helper); + + bool smoothComplexEdge( _SolidData& data, + Handle(ShapeAnalysis_Surface)& surface, + const TopoDS_Face& F, + SMESH_MesherHelper& helper); + + void setNormalOnV( const bool is2nd, + SMESH_MesherHelper& helper); + + _LayerEdge* getLEdgeOnV( bool is2nd ) + { + return _eos._edges[ is2nd ? _eos._edges.size()-1 : 0 ]->_2neibors->_edges[ is2nd ]; + } + bool isAnalytic() const { return !_anaCurve.IsNull(); } }; //-------------------------------------------------------------------------------- /*! @@ -816,8 +1065,9 @@ namespace VISCOUS_3D struct _TmpMeshFace : public SMDS_MeshElement { vector _nn; - _TmpMeshFace( const vector& nodes, int id, int faceID=-1): - SMDS_MeshElement(id), _nn(nodes) { setShapeId(faceID); } + _TmpMeshFace( const vector& nodes, + int id, int faceID=-1, int idInFace=-1): + SMDS_MeshElement(id), _nn(nodes) { setShapeId(faceID); setIdInShape(idInFace); } virtual const SMDS_MeshNode* GetNode(const int ind) const { return _nn[ind]; } virtual SMDSAbs_ElementType GetType() const { return SMDSAbs_Face; } virtual vtkIdType GetVtkType() const { return -1; } @@ -842,6 +1092,28 @@ namespace VISCOUS_3D _nn[2]=_le2->_nodes.back(); _nn[3]=_le2->_nodes[0]; } + gp_XYZ GetDir() const // return average direction of _LayerEdge's, normal to EDGE + { + SMESH_TNodeXYZ p0s( _nn[0] ); + SMESH_TNodeXYZ p0t( _nn[1] ); + SMESH_TNodeXYZ p1t( _nn[2] ); + SMESH_TNodeXYZ p1s( _nn[3] ); + gp_XYZ v0 = p0t - p0s; + gp_XYZ v1 = p1t - p1s; + gp_XYZ v01 = p1s - p0s; + gp_XYZ n = ( v0 ^ v01 ) + ( v1 ^ v01 ); + gp_XYZ d = v01 ^ n; + d.Normalize(); + return d; + } + gp_XYZ GetDir(_LayerEdge* le1, _LayerEdge* le2) // return average direction of _LayerEdge's + { + _nn[0]=le1->_nodes[0]; + _nn[1]=le1->_nodes.back(); + _nn[2]=le2->_nodes.back(); + _nn[3]=le2->_nodes[0]; + return GetDir(); + } }; //-------------------------------------------------------------------------------- /*! @@ -882,6 +1154,21 @@ namespace VISCOUS_3D } }; + //================================================================================ + /*! + * \brief Check angle between vectors + */ + //================================================================================ + + inline bool isLessAngle( const gp_Vec& v1, const gp_Vec& v2, const double cos ) + { + double dot = v1 * v2; // cos * |v1| * |v2| + double l1 = v1.SquareMagnitude(); + double l2 = v2.SquareMagnitude(); + return (( dot * cos >= 0 ) && + ( dot * dot ) / l1 / l2 >= ( cos * cos )); + } + } // namespace VISCOUS_3D @@ -984,7 +1271,7 @@ std::istream & StdMeshers_ViscousLayers::LoadFrom(std::istream & load) { int nbFaces, faceID, shapeToTreat, method; load >> _nbLayers >> _thickness >> _stretchFactor >> nbFaces; - while ( _shapeIds.size() < nbFaces && load >> faceID ) + while ( (int) _shapeIds.size() < nbFaces && load >> faceID ) _shapeIds.push_back( faceID ); if ( load >> shapeToTreat ) { _isToIgnoreShapes = !shapeToTreat; @@ -1033,6 +1320,7 @@ namespace VISCOUS_3D gp_Vec dir; double f,l; Handle(Geom_Curve) c = BRep_Tool::Curve( E, f, l ); + if ( c.IsNull() ) return gp_XYZ( Precision::Infinite(), 1e100, 1e100 ); gp_Pnt p = BRep_Tool::Pnt( fromV ); double distF = p.SquareDistance( c->Value( f )); double distL = p.SquareDistance( c->Value( l )); @@ -1047,7 +1335,7 @@ namespace VISCOUS_3D gp_Vec dir; double f,l; gp_Pnt p; Handle(Geom_Curve) c = BRep_Tool::Curve( E, f, l ); - if ( c.IsNull() ) return gp_XYZ( 1e100, 1e100, 1e100 ); + if ( c.IsNull() ) return gp_XYZ( Precision::Infinite(), 1e100, 1e100 ); double u = helper.GetNodeU( E, atNode ); c->D1( u, p, dir ); return dir.XYZ(); @@ -1100,9 +1388,9 @@ namespace VISCOUS_3D { TopoDS_Face faceFrw = F; faceFrw.Orientation( TopAbs_FORWARD ); - double f,l; TopLoc_Location loc; + //double f,l; TopLoc_Location loc; TopoDS_Edge edges[2]; // sharing a vertex - int nbEdges = 0; + size_t nbEdges = 0; { TopoDS_Vertex VV[2]; TopExp_Explorer exp( faceFrw, TopAbs_EDGE ); @@ -1235,10 +1523,10 @@ namespace VISCOUS_3D double u1 = intervals( i ); double u2 = intervals( i+1 ); curve.D2( 0.5*( u1+u2 ), p, drv1, drv2 ); - double cross = drv2 ^ drv1; + double cross = drv1 ^ drv2; if ( E.Orientation() == TopAbs_REVERSED ) cross = -cross; - isConvex = ( cross > 0.1 ); //-1e-9 ); + isConvex = ( cross > -1e-9 ); // 0.1 ); } if ( !isConvex ) { @@ -1396,16 +1684,19 @@ namespace VISCOUS_3D { if (py) { *py<< " mesh.ChangeElemNodes( " << f->GetID()<<", ["; for ( int i=1; i < f->NbNodes(); ++i ) *py << f->GetNode(i-1)->GetID()<<", "; *py << f->GetNode( f->NbNodes()-1 )->GetID() << " ])"<< endl; }} -#define debugMsg( txt ) { cout << txt << " (line: " << __LINE__ << ")" << endl; } +#define debugMsg( txt ) { cout << "# "<< txt << " (line: " << __LINE__ << ")" << endl; } + #else + struct PyDump { PyDump(SMESH_Mesh&) {} void Finish() {} }; #define dumpFunction(f) f #define dumpMove(n) #define dumpMoveComm(n,txt) #define dumpCmd(txt) #define dumpFunctionEnd() -#define dumpChangeNodes(f) +#define dumpChangeNodes(f) { if(f) {} } // prevent "unused variable 'f'" warning #define debugMsg( txt ) {} + #endif } @@ -1629,7 +1920,7 @@ bool _ViscousBuilder::findSolidsWithLayers() list< const SMESHDS_Hypothesis *>::const_iterator hyp = allHyps.begin(); const StdMeshers_ViscousLayers* viscHyp = 0; for ( ; hyp != allHyps.end(); ++hyp ) - if ( viscHyp = dynamic_cast( *hyp )) + if (( viscHyp = dynamic_cast( *hyp ))) { TopoDS_Shape hypShape; filter.Init( filter.Is( viscHyp )); @@ -1643,6 +1934,8 @@ bool _ViscousBuilder::findSolidsWithLayers() _sdVec.push_back( _SolidData( allSolids(i), proxyMesh )); soData = & _sdVec.back(); soData->_index = getMeshDS()->ShapeToIndex( allSolids(i)); + soData->_helper = new SMESH_MesherHelper( *_mesh ); + soData->_helper->SetSubShape( allSolids(i) ); } soData->_hyps.push_back( viscHyp ); soData->_hypShapes.push_back( hypShape ); @@ -1903,7 +2196,7 @@ bool _ViscousBuilder::findFacesWithLayers(const bool onlyWith) const TopoDS_Shape& vertex = shapes(iV); // find faces WOL sharing the vertex vector< TopoDS_Shape > facesWOL; - int totalNbFaces = 0; + size_t totalNbFaces = 0; PShapeIteratorPtr fIt = helper.GetAncestors(vertex, *_mesh, TopAbs_FACE); while ( fIt->more()) { @@ -2051,12 +2344,7 @@ bool _ViscousBuilder::makeLayer(_SolidData& data) { SMESH_subMesh* fSubM = _mesh->GetSubMesh( exp.Current() ); if ( ! data._ignoreFaceIds.count( fSubM->GetId() )) - { faceIds.insert( fSubM->GetId() ); - SMESH_subMeshIteratorPtr subIt = fSubM->getDependsOnIterator(/*includeSelf=*/true); - while ( subIt->more() ) - subIds.insert( subIt->next()->GetId() ); - } } // make a map to find new nodes on sub-shapes shared with other SOLID @@ -2184,8 +2472,12 @@ bool _ViscousBuilder::makeLayer(_SolidData& data) { edge->_nodes.push_back( helper.AddNode( xyz.X(), xyz.Y(), xyz.Z() )); } - if ( !setEdgeData( *edge, edgesByGeom[ shapeID ], subIds, helper, data )) + if ( !setEdgeData( *edge, edgesByGeom[ shapeID ], helper, data )) return false; + + if ( edge->_nodes.size() < 2 ) + edge->Block( data ); + //data._noShrinkShapes.insert( shapeID ); } dumpMove(edge->_nodes.back()); @@ -2205,7 +2497,7 @@ bool _ViscousBuilder::makeLayer(_SolidData& data) // create a temporary face const SMDS_MeshElement* newFace = - new _TmpMeshFace( newNodes, --_tmpFaceID, face->getshapeId() ); + new _TmpMeshFace( newNodes, --_tmpFaceID, face->getshapeId(), face->getIdInShape() ); proxySub->AddElement( newFace ); // compute inflation step size by min size of element on a convex surface @@ -2213,7 +2505,33 @@ bool _ViscousBuilder::makeLayer(_SolidData& data) limitStepSize( data, face, maxCosinEdge ); } // loop on 2D elements on a FACE - } // loop on FACEs of a SOLID + } // loop on FACEs of a SOLID to create _LayerEdge's + + + // Set _LayerEdge::_neibors + TNode2Edge::iterator n2e; + for ( size_t iS = 0; iS < data._edgesOnShape.size(); ++iS ) + { + _EdgesOnShape& eos = data._edgesOnShape[iS]; + for ( size_t i = 0; i < eos._edges.size(); ++i ) + { + _LayerEdge* edge = eos._edges[i]; + TIDSortedNodeSet nearNodes; + SMDS_ElemIteratorPtr fIt = edge->_nodes[0]->GetInverseElementIterator(SMDSAbs_Face); + while ( fIt->more() ) + { + const SMDS_MeshElement* f = fIt->next(); + if ( !data._ignoreFaceIds.count( f->getshapeId() )) + nearNodes.insert( f->begin_nodes(), f->end_nodes() ); + } + nearNodes.erase( edge->_nodes[0] ); + edge->_neibors.reserve( nearNodes.size() ); + TIDSortedNodeSet::iterator node = nearNodes.begin(); + for ( ; node != nearNodes.end(); ++node ) + if (( n2e = data._n2eMap.find( *node )) != data._n2eMap.end() ) + edge->_neibors.push_back( n2e->second ); + } + } data._epsilon = 1e-7; if ( data._stepSize < 1. ) @@ -2226,15 +2544,13 @@ bool _ViscousBuilder::makeLayer(_SolidData& data) limitStepSizeByCurvature( data ); // !!! it must be before node substitution in _Simplex // Set target nodes into _Simplex and _LayerEdge's to _2NearEdges - TNode2Edge::iterator n2e; const SMDS_MeshNode* nn[2]; for ( size_t iS = 0; iS < data._edgesOnShape.size(); ++iS ) { _EdgesOnShape& eos = data._edgesOnShape[iS]; - vector< _LayerEdge* >& localEdges = eos._edges; - for ( size_t i = 0; i < localEdges.size(); ++i ) + for ( size_t i = 0; i < eos._edges.size(); ++i ) { - _LayerEdge* edge = localEdges[i]; + _LayerEdge* edge = eos._edges[i]; if ( edge->IsOnEdge() ) { // get neighbor nodes @@ -2283,17 +2599,18 @@ bool _ViscousBuilder::makeLayer(_SolidData& data) edge->_lenFactor = vEdge->_lenFactor; edge->_cosin = vEdge->_cosin; } - } - } + + } // loop on data._edgesOnShape._edges + } // loop on data._edgesOnShape // fix _LayerEdge::_2neibors on EDGEs to smooth - map< TGeomID,Handle(Geom_Curve)>::iterator e2c = data._edge2curve.begin(); - for ( ; e2c != data._edge2curve.end(); ++e2c ) - if ( !e2c->second.IsNull() ) - { - if ( _EdgesOnShape* eos = data.GetShapeEdges( e2c->first )) - data.Sort2NeiborsOnEdge( eos->_edges ); - } + // map< TGeomID,Handle(Geom_Curve)>::iterator e2c = data._edge2curve.begin(); + // for ( ; e2c != data._edge2curve.end(); ++e2c ) + // if ( !e2c->second.IsNull() ) + // { + // if ( _EdgesOnShape* eos = data.GetShapeEdges( e2c->first )) + // data.Sort2NeiborsOnEdge( eos->_edges ); + // } dumpFunctionEnd(); return true; @@ -2400,7 +2717,7 @@ void _ViscousBuilder::limitStepSizeByCurvature( _SolidData& data ) continue; // check concavity and curvature and limit data._stepSize const double minCurvature = - 1. / ( eos->_hyp.GetTotalThickness() * ( 1+theThickToIntersection )); + 1. / ( eos->_hyp.GetTotalThickness() * ( 1 + theThickToIntersection )); size_t iStep = Max( 1, eos->_edges.size() / nbTestPnt ); for ( size_t i = 0; i < eos->_edges.size(); i += iStep ) { @@ -2470,7 +2787,6 @@ void _ViscousBuilder::limitStepSizeByCurvature( _SolidData& data ) const SMDS_MeshNode* srcNode = ledge->_nodes[0]; if ( !usedNodes.insert( srcNode ).second ) continue; - _Simplex::GetSimplices( srcNode, ledge->_simplices, data._ignoreFaceIds, &data ); for ( size_t i = 0; i < ledge->_simplices.size(); ++i ) { usedNodes.insert( ledge->_simplices[i]._nPrev ); @@ -2492,7 +2808,7 @@ void _ViscousBuilder::limitStepSizeByCurvature( _SolidData& data ) bool _ViscousBuilder::findShapesToSmooth( _SolidData& data ) { // define allowed thickness - computeGeomSize( data ); // compute data._geomSize + computeGeomSize( data ); // compute data._geomSize and _LayerEdge::_maxLen data._maxThickness = 0; data._minThickness = 1e100; @@ -2502,7 +2818,7 @@ bool _ViscousBuilder::findShapesToSmooth( _SolidData& data ) data._maxThickness = Max( data._maxThickness, (*hyp)->GetTotalThickness() ); data._minThickness = Min( data._minThickness, (*hyp)->GetTotalThickness() ); } - const double tgtThick = /*Min( 0.5 * data._geomSize, */data._maxThickness; + //const double tgtThick = /*Min( 0.5 * data._geomSize, */data._maxThickness; // Find shapes needing smoothing; such a shape has _LayerEdge._normal on it's // boundry inclined to the shape at a sharp angle @@ -2523,44 +2839,29 @@ bool _ViscousBuilder::findShapesToSmooth( _SolidData& data ) if ( eos._edges.empty() || eos.ShapeType() != TopAbs_FACE ) continue; + double tgtThick = eos._hyp.GetTotalThickness(); TopExp_Explorer eExp( edgesByGeom[iS]._shape, TopAbs_EDGE ); for ( ; eExp.More() && !eos._toSmooth; eExp.Next() ) { TGeomID iE = getMeshDS()->ShapeToIndex( eExp.Current() ); vector<_LayerEdge*>& eE = edgesByGeom[ iE ]._edges; if ( eE.empty() ) continue; - // TopLoc_Location loc; - // Handle(Geom_Surface) surface = BRep_Tool::Surface( TopoDS::Face( S ), loc ); - // bool isPlane = GeomLib_IsPlanarSurface( surface ).IsPlanar(); - //if ( eE[0]->_sWOL.IsNull() ) - { - double faceSize; - for ( size_t i = 0; i < eE.size() && !eos._toSmooth; ++i ) - if ( eE[i]->_cosin > theMinSmoothCosin ) + + double faceSize; + for ( size_t i = 0; i < eE.size() && !eos._toSmooth; ++i ) + if ( eE[i]->_cosin > theMinSmoothCosin ) + { + SMDS_ElemIteratorPtr fIt = eE[i]->_nodes[0]->GetInverseElementIterator(SMDSAbs_Face); + while ( fIt->more() && !eos._toSmooth ) { - SMDS_ElemIteratorPtr fIt = eE[i]->_nodes[0]->GetInverseElementIterator(SMDSAbs_Face); - while ( fIt->more() && !eos._toSmooth ) + const SMDS_MeshElement* face = fIt->next(); + if ( face->getshapeId() == eos._shapeID && + getDistFromEdge( face, eE[i]->_nodes[0], faceSize )) { - const SMDS_MeshElement* face = fIt->next(); - if ( getDistFromEdge( face, eE[i]->_nodes[0], faceSize )) - eos._toSmooth = needSmoothing( eE[i]->_cosin, tgtThick, faceSize ); + eos._toSmooth = needSmoothing( eE[i]->_cosin, tgtThick, faceSize ); } } - } - // else - // { - // const TopoDS_Face& F1 = TopoDS::Face( S ); - // const TopoDS_Face& F2 = TopoDS::Face( eE[0]->_sWOL ); - // const TopoDS_Edge& E = TopoDS::Edge( eExp.Current() ); - // for ( size_t i = 0; i < eE.size() && !eos._toSmooth; ++i ) - // { - // gp_Vec dir1 = getFaceDir( F1, E, eE[i]->_nodes[0], helper, ok ); - // gp_Vec dir2 = getFaceDir( F2, E, eE[i]->_nodes[0], helper, ok ); - // double angle = dir1.Angle( ); - // double cosin = cos( angle ); - // eos._toSmooth = ( cosin > theMinSmoothCosin ); - // } - // } + } } if ( eos._toSmooth ) { @@ -2576,6 +2877,7 @@ bool _ViscousBuilder::findShapesToSmooth( _SolidData& data ) for ( size_t iS = 0; iS < edgesByGeom.size(); ++iS ) // check EDGEs { _EdgesOnShape& eos = edgesByGeom[iS]; + eos._edgeSmoother = NULL; if ( eos._edges.empty() || eos.ShapeType() != TopAbs_EDGE ) continue; if ( !eos._hyp.ToSmooth() ) continue; @@ -2583,32 +2885,41 @@ bool _ViscousBuilder::findShapesToSmooth( _SolidData& data ) if ( SMESH_Algo::isDegenerated( E ) || !edgesOfSmooFaces.Contains( E )) continue; + double tgtThick = eos._hyp.GetTotalThickness(); for ( TopoDS_Iterator vIt( E ); vIt.More() && !eos._toSmooth; vIt.Next() ) { TGeomID iV = getMeshDS()->ShapeToIndex( vIt.Value() ); vector<_LayerEdge*>& eV = edgesByGeom[ iV ]._edges; - if ( eV.empty() ) continue; - gp_Vec eDir = getEdgeDir( E, TopoDS::Vertex( vIt.Value() )); - double angle = eDir.Angle( eV[0]->_normal ); - double cosin = Cos( angle ); + if ( eV.empty() || eV[0]->Is( _LayerEdge::MULTI_NORMAL )) continue; + gp_Vec eDir = getEdgeDir( E, TopoDS::Vertex( vIt.Value() )); + double angle = eDir.Angle( eV[0]->_normal ); + double cosin = Cos( angle ); double cosinAbs = Abs( cosin ); if ( cosinAbs > theMinSmoothCosin ) { // always smooth analytic EDGEs - eos._toSmooth = ! data.CurveForSmooth( E, eos, helper ).IsNull(); + Handle(Geom_Curve) curve = _Smoother1D::CurveForSmooth( E, eos, helper ); + eos._toSmooth = ! curve.IsNull(); // compare tgtThick with the length of an end segment SMDS_ElemIteratorPtr eIt = eV[0]->_nodes[0]->GetInverseElementIterator(SMDSAbs_Edge); while ( eIt->more() && !eos._toSmooth ) { const SMDS_MeshElement* endSeg = eIt->next(); - if ( endSeg->getshapeId() == iS ) + if ( endSeg->getshapeId() == (int) iS ) { double segLen = SMESH_TNodeXYZ( endSeg->GetNode(0) ).Distance( endSeg->GetNode(1 )); eos._toSmooth = needSmoothing( cosinAbs, tgtThick, segLen ); } } + if ( eos._toSmooth ) + { + eos._edgeSmoother = new _Smoother1D( curve, eos ); + + for ( size_t i = 0; i < eos._edges.size(); ++i ) + eos._edges[i]->Set( _LayerEdge::TO_SMOOTH ); + } } } data._nbShapesToSmooth += eos._toSmooth; @@ -2627,36 +2938,160 @@ bool _ViscousBuilder::findShapesToSmooth( _SolidData& data ) } - // int nbShapes = 0; - // for ( size_t iS = 0; iS < edgesByGeom.size(); ++iS ) - // { - // nbShapes += ( edgesByGeom[iS]._edges.size() > 0 ); - // } - // data._edgesOnShape.reserve( nbShapes ); + // Fill _eosC1 to make that C1 FACEs and EGDEs between them to be smoothed as a whole + + TopTools_MapOfShape c1VV; + + for ( size_t iS = 0; iS < edgesByGeom.size(); ++iS ) // check FACEs + { + _EdgesOnShape& eos = edgesByGeom[iS]; + if ( eos._edges.empty() || + eos.ShapeType() != TopAbs_FACE || + !eos._toSmooth ) + continue; + + // check EDGEs of a FACE + TopTools_MapOfShape checkedEE, allVV; + list< SMESH_subMesh* > smQueue( 1, eos._subMesh ); // sm of FACEs + while ( !smQueue.empty() ) + { + SMESH_subMesh* sm = smQueue.front(); + smQueue.pop_front(); + SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*includeSelf=*/false); + while ( smIt->more() ) + { + sm = smIt->next(); + if ( sm->GetSubShape().ShapeType() == TopAbs_VERTEX ) + allVV.Add( sm->GetSubShape() ); + if ( sm->GetSubShape().ShapeType() != TopAbs_EDGE || + !checkedEE.Add( sm->GetSubShape() )) + continue; + + _EdgesOnShape* eoe = data.GetShapeEdges( sm->GetId() ); + vector<_LayerEdge*>& eE = eoe->_edges; + if ( eE.empty() || !eoe->_sWOL.IsNull() ) + continue; + + bool isC1 = true; // check continuity along an EDGE + for ( size_t i = 0; i < eE.size() && isC1; ++i ) + isC1 = ( Abs( eE[i]->_cosin ) < theMinSmoothCosin ); + if ( !isC1 ) + continue; + + // check that mesh faces are C1 as well + { + gp_XYZ norm1, norm2; + const SMDS_MeshNode* n = eE[ eE.size() / 2 ]->_nodes[0]; + SMDS_ElemIteratorPtr fIt = n->GetInverseElementIterator(SMDSAbs_Face); + if ( !SMESH_MeshAlgos::FaceNormal( fIt->next(), norm1, /*normalized=*/true )) + continue; + while ( fIt->more() && isC1 ) + isC1 = ( SMESH_MeshAlgos::FaceNormal( fIt->next(), norm2, /*normalized=*/true ) && + Abs( norm1 * norm2 ) >= ( 1. - theMinSmoothCosin )); + if ( !isC1 ) + continue; + } + + // add the EDGE and an adjacent FACE to _eosC1 + PShapeIteratorPtr fIt = helper.GetAncestors( sm->GetSubShape(), *_mesh, TopAbs_FACE ); + while ( const TopoDS_Shape* face = fIt->next() ) + { + _EdgesOnShape* eof = data.GetShapeEdges( *face ); + if ( !eof ) continue; // other solid + if ( !eos.HasC1( eoe )) + { + eos._eosC1.push_back( eoe ); + eoe->_toSmooth = false; + data.PrepareEdgesToSmoothOnFace( eoe, /*substituteSrcNodes=*/false ); + } + if ( eos._shapeID != eof->_shapeID && !eos.HasC1( eof )) + { + eos._eosC1.push_back( eof ); + eof->_toSmooth = false; + data.PrepareEdgesToSmoothOnFace( eof, /*substituteSrcNodes=*/false ); + smQueue.push_back( eof->_subMesh ); + } + } + } + } + if ( eos._eosC1.empty() ) + continue; + + // check VERTEXes of C1 FACEs + TopTools_MapIteratorOfMapOfShape vIt( allVV ); + for ( ; vIt.More(); vIt.Next() ) + { + _EdgesOnShape* eov = data.GetShapeEdges( vIt.Key() ); + if ( !eov || eov->_edges.empty() || !eov->_sWOL.IsNull() ) + continue; + + bool isC1 = true; // check if all adjacent FACEs are in eos._eosC1 + PShapeIteratorPtr fIt = helper.GetAncestors( vIt.Key(), *_mesh, TopAbs_FACE ); + while ( const TopoDS_Shape* face = fIt->next() ) + { + _EdgesOnShape* eof = data.GetShapeEdges( *face ); + if ( !eof ) continue; // other solid + isC1 = ( face->IsSame( eos._shape ) || eos.HasC1( eof )); + if ( !isC1 ) + break; + } + if ( isC1 ) + { + eos._eosC1.push_back( eov ); + data.PrepareEdgesToSmoothOnFace( eov, /*substituteSrcNodes=*/false ); + c1VV.Add( eov->_shape ); + } + } + + } // fill _eosC1 of FACEs + + + // Find C1 EDGEs + + vector< pair< _EdgesOnShape*, gp_XYZ > > dirOfEdges; + + for ( size_t iS = 0; iS < edgesByGeom.size(); ++iS ) // check VERTEXes + { + _EdgesOnShape& eov = edgesByGeom[iS]; + if ( eov._edges.empty() || + eov.ShapeType() != TopAbs_VERTEX || + c1VV.Contains( eov._shape )) + continue; + const TopoDS_Vertex& V = TopoDS::Vertex( eov._shape ); + + // get directions of surrounding EDGEs + dirOfEdges.clear(); + PShapeIteratorPtr fIt = helper.GetAncestors( eov._shape, *_mesh, TopAbs_EDGE ); + while ( const TopoDS_Shape* e = fIt->next() ) + { + _EdgesOnShape* eoe = data.GetShapeEdges( *e ); + if ( !eoe ) continue; // other solid + gp_XYZ eDir = getEdgeDir( TopoDS::Edge( *e ), V ); + if ( !Precision::IsInfinite( eDir.X() )) + dirOfEdges.push_back( make_pair( eoe, eDir.Normalized() )); + } + + // find EDGEs with C1 directions + for ( size_t i = 0; i < dirOfEdges.size(); ++i ) + for ( size_t j = i+1; j < dirOfEdges.size(); ++j ) + if ( dirOfEdges[i].first && dirOfEdges[j].first ) + { + double dot = dirOfEdges[i].second * dirOfEdges[j].second; + bool isC1 = ( dot < - ( 1. - theMinSmoothCosin )); + if ( isC1 ) + { + double maxEdgeLen = 3 * Min( eov._edges[0]->_maxLen, eov._hyp.GetTotalThickness() ); + double eLen1 = SMESH_Algo::EdgeLength( TopoDS::Edge( dirOfEdges[i].first->_shape )); + double eLen2 = SMESH_Algo::EdgeLength( TopoDS::Edge( dirOfEdges[j].first->_shape )); + if ( eLen1 < maxEdgeLen ) eov._eosC1.push_back( dirOfEdges[i].first ); + if ( eLen2 < maxEdgeLen ) eov._eosC1.push_back( dirOfEdges[j].first ); + dirOfEdges[i].first = 0; + dirOfEdges[j].first = 0; + } + } + } // fill _eosC1 of VERTEXes - // // first we put _LayerEdge's on shapes to smooth (EGDEs go first) - // vector< _LayerEdge* > edges; - // list< TGeomID >::iterator gIt = shapesToSmooth.begin(); - // for ( ; gIt != shapesToSmooth.end(); ++gIt ) - // { - // _EdgesOnShape& eos = edgesByGeom[ *gIt ]; - // if ( eos._edges.empty() ) continue; - // eos._edges.swap( edges ); // avoid copying array - // eos._toSmooth = true; - // data._edgesOnShape.push_back( eos ); - // data._edgesOnShape.back()._edges.swap( edges ); - // } - // // then the rest _LayerEdge's - // for ( size_t iS = 0; iS < edgesByGeom.size(); ++iS ) - // { - // _EdgesOnShape& eos = edgesByGeom[ *gIt ]; - // if ( eos._edges.empty() ) continue; - // eos._edges.swap( edges ); // avoid copying array - // eos._toSmooth = false; - // data._edgesOnShape.push_back( eos ); - // data._edgesOnShape.back()._edges.swap( edges ); - // } return ok; } @@ -2683,6 +3118,7 @@ void _ViscousBuilder::setShapeData( _EdgesOnShape& eos, if ( eos.ShapeType() == TopAbs_FACE ) eos._shape.Orientation( helper.GetSubShapeOri( data._solid, eos._shape )); eos._toSmooth = false; + eos._data = &data; // set _SWOL map< TGeomID, TopoDS_Shape >::const_iterator s2s = @@ -2690,6 +3126,14 @@ void _ViscousBuilder::setShapeData( _EdgesOnShape& eos, if ( s2s != data._shrinkShape2Shape.end() ) eos._sWOL = s2s->second; + eos._isRegularSWOL = true; + if ( eos.SWOLType() == TopAbs_FACE ) + { + const TopoDS_Face& F = TopoDS::Face( eos._sWOL ); + Handle(ShapeAnalysis_Surface) surface = helper.GetSurface( F ); + eos._isRegularSWOL = ( ! surface->HasSingularities( 1e-7 )); + } + // set _hyp if ( data._hyps.size() == 1 ) { @@ -2774,7 +3218,7 @@ bool _EdgesOnShape::GetNormal( const SMDS_MeshElement* face, gp_Vec& norm ) } if (( eos ) && - ( ok = ( face->getIdInShape() < eos->_faceNormals.size() ))) + ( ok = ( face->getIdInShape() < (int) eos->_faceNormals.size() ))) { norm = eos->_faceNormals[ face->getIdInShape() ]; } @@ -2790,28 +3234,31 @@ bool _EdgesOnShape::GetNormal( const SMDS_MeshElement* face, gp_Vec& norm ) //================================================================================ /*! * \brief Set data of _LayerEdge needed for smoothing - * \param subIds - ids of sub-shapes of a SOLID to take into account faces from */ //================================================================================ bool _ViscousBuilder::setEdgeData(_LayerEdge& edge, _EdgesOnShape& eos, - const set& subIds, SMESH_MesherHelper& helper, _SolidData& data) { const SMDS_MeshNode* node = edge._nodes[0]; // source node edge._len = 0; + edge._maxLen = Precision::Infinite(); + edge._minAngle = 0; edge._2neibors = 0; edge._curvature = 0; + edge._flags = 0; // -------------------------- // Compute _normal and _cosin // -------------------------- - edge._cosin = 0; + edge._cosin = 0; + edge._lenFactor = 1.; edge._normal.SetCoord(0,0,0); + _Simplex::GetSimplices( node, edge._simplices, data._ignoreFaceIds, &data ); int totalNbFaces = 0; TopoDS_Face F; @@ -2821,7 +3268,7 @@ bool _ViscousBuilder::setEdgeData(_LayerEdge& edge, const bool onShrinkShape = !eos._sWOL.IsNull(); const bool useGeometry = (( eos._hyp.UseSurfaceNormal() ) || - ( eos.ShapeType() != TopAbs_FACE && !onShrinkShape )); + ( eos.ShapeType() != TopAbs_FACE /*&& !onShrinkShape*/ )); // get geom FACEs the node lies on //if ( useGeometry ) @@ -2841,7 +3288,7 @@ bool _ViscousBuilder::setEdgeData(_LayerEdge& edge, for ( ; id != faceIds.end(); ++id ) { const TopoDS_Shape& s = getMeshDS()->IndexToShape( *id ); - if ( s.IsNull() || s.ShapeType() != TopAbs_FACE || !subIds.count( *id )) + if ( s.IsNull() || s.ShapeType() != TopAbs_FACE || data._ignoreFaceIds.count( *id )) continue; F = TopoDS::Face( s ); face2Norm[ totalNbFaces ].first = F; @@ -2872,9 +3319,7 @@ bool _ViscousBuilder::setEdgeData(_LayerEdge& edge, node, helper, normOK); } } - - // layers are on all faces of SOLID the node is on - else + else // layers are on all FACEs of SOLID the node is on { int nbOkNorms = 0; for ( int iF = 0; iF < totalNbFaces; ++iF ) @@ -2908,32 +3353,30 @@ bool _ViscousBuilder::setEdgeData(_LayerEdge& edge, } } - if ( totalNbFaces < 3 ) + if ( totalNbFaces >= 3 ) { - //edge._normal /= totalNbFaces; - } - else - { - edge._normal = getWeigthedNormal( node, face2Norm, totalNbFaces ); + edge._normal = getNormalByOffset( &edge, face2Norm, totalNbFaces ); } } } else // !useGeometry - get _normal using surrounding mesh faces { - set faceIds; + edge._normal = getWeigthedNormal( &edge ); - SMDS_ElemIteratorPtr fIt = node->GetInverseElementIterator(SMDSAbs_Face); - while ( fIt->more() ) - { - const SMDS_MeshElement* face = fIt->next(); - if ( eos.GetNormal( face, geomNorm )) - { - if ( onShrinkShape && !faceIds.insert( face->getshapeId() ).second ) - continue; // use only one mesh face on FACE - edge._normal += geomNorm.XYZ(); - totalNbFaces++; - } - } + // set faceIds; + // + // SMDS_ElemIteratorPtr fIt = node->GetInverseElementIterator(SMDSAbs_Face); + // while ( fIt->more() ) + // { + // const SMDS_MeshElement* face = fIt->next(); + // if ( eos.GetNormal( face, geomNorm )) + // { + // if ( onShrinkShape && !faceIds.insert( face->getshapeId() ).second ) + // continue; // use only one mesh face on FACE + // edge._normal += geomNorm.XYZ(); + // totalNbFaces++; + // } + // } } // compute _cosin @@ -2950,7 +3393,6 @@ bool _ViscousBuilder::setEdgeData(_LayerEdge& edge, gp_Vec inFaceDir = getFaceDir( F, E, node, helper, normOK ); double angle = inFaceDir.Angle( edge._normal ); // [0,PI] edge._cosin = Cos( angle ); - //cout << "Cosin on EDGE " << edge._cosin << " node " << node->GetID() << endl; break; } case TopAbs_VERTEX: { @@ -2966,11 +3408,12 @@ bool _ViscousBuilder::setEdgeData(_LayerEdge& edge, inFaceDir = getFaceDir( F, V, node, helper, normOK=true ); if ( normOK ) { double angle = inFaceDir.Angle( edge._normal ); - edge._cosin = Max( edge._cosin, Cos( angle )); + double cosin = Cos( angle ); + if ( Abs( cosin ) > edge._cosin ) + edge._cosin = cosin; } } } - //cout << "Cosin on VERTEX " << edge._cosin << " node " << node->GetID() << endl; break; } default: @@ -2984,13 +3427,22 @@ bool _ViscousBuilder::setEdgeData(_LayerEdge& edge, edge._normal /= sqrt( normSize ); - // TODO: if ( !normOK ) then get normal by mesh faces + if ( edge.Is( _LayerEdge::MULTI_NORMAL ) && edge._nodes.size() == 2 ) + { + getMeshDS()->RemoveFreeNode( edge._nodes.back(), 0, /*fromGroups=*/false ); + edge._nodes.resize( 1 ); + edge._normal.SetCoord( 0,0,0 ); + edge._maxLen = 0; + } // Set the rest data // -------------------- + + edge.SetCosin( edge._cosin ); // to update edge._lenFactor + if ( onShrinkShape ) { - SMDS_MeshNode* tgtNode = const_cast( edge._nodes.back() ); + const SMDS_MeshNode* tgtNode = edge._nodes.back(); if ( SMESHDS_SubMesh* sm = getMeshDS()->MeshElements( data._solid )) sm->RemoveNode( tgtNode , /*isNodeDeleted=*/false ); @@ -3002,13 +3454,39 @@ bool _ViscousBuilder::setEdgeData(_LayerEdge& edge, if ( edge._nodes.size() > 1 ) getMeshDS()->SetNodeOnEdge( tgtNode, TopoDS::Edge( eos._sWOL ), u ); } - else // TopAbs_FACE + else // eos.SWOLType() == TopAbs_FACE { gp_XY uv = helper.GetNodeUV( TopoDS::Face( eos._sWOL ), node, 0, &normOK ); edge._pos.push_back( gp_XYZ( uv.X(), uv.Y(), 0)); if ( edge._nodes.size() > 1 ) getMeshDS()->SetNodeOnFace( tgtNode, TopoDS::Face( eos._sWOL ), uv.X(), uv.Y() ); } + + if ( edge._nodes.size() > 1 ) + { + // check if an angle between a FACE with layers and SWOL is sharp, + // else the edge should not inflate + F.Nullify(); + for ( int iF = 0; iF < totalNbFaces && F.IsNull(); ++iF ) // find a FACE with VL + if ( ! helper.IsSubShape( eos._sWOL, face2Norm[iF].first )) + F = face2Norm[iF].first; + if ( !F.IsNull()) + { + geomNorm = getFaceNormal( node, F, helper, normOK ); + if ( helper.GetSubShapeOri( data._solid, F ) != TopAbs_REVERSED ) + geomNorm.Reverse(); // inside the SOLID + if ( geomNorm * edge._normal < -0.001 ) + { + getMeshDS()->RemoveFreeNode( tgtNode, 0, /*fromGroups=*/false ); + edge._nodes.resize( 1 ); + } + else if ( edge._lenFactor > 3 ) + { + edge._lenFactor = 2; + edge.Set( _LayerEdge::RISKY_SWOL ); + } + } + } } else { @@ -3016,29 +3494,24 @@ bool _ViscousBuilder::setEdgeData(_LayerEdge& edge, if ( eos.ShapeType() == TopAbs_FACE ) { - _Simplex::GetSimplices( node, edge._simplices, data._ignoreFaceIds, &data ); + double angle; + for ( size_t i = 0; i < edge._simplices.size(); ++i ) + { + edge._simplices[i].IsMinAngleOK( edge._pos.back(), angle ); + edge._minAngle = Max( edge._minAngle, angle ); // "angle" is actually cosine + } } } - // Set neighbour nodes for a _LayerEdge based on EDGE + // Set neighbor nodes for a _LayerEdge based on EDGE if ( eos.ShapeType() == TopAbs_EDGE /*|| ( onShrinkShape && posType == SMDS_TOP_VERTEX && fabs( edge._cosin ) < 1e-10 )*/) { edge._2neibors = new _2NearEdges; - // target node instead of source ones will be set later - // if ( ! findNeiborsOnEdge( &edge, - // edge._2neibors->_nodes[0], - // edge._2neibors->_nodes[1], eos, - // data)) - // return false; - // edge.SetDataByNeighbors( edge._2neibors->_nodes[0], - // edge._2neibors->_nodes[1], - // helper); + // target nodes instead of source ones will be set later } - edge.SetCosin( edge._cosin ); // to update edge._lenFactor - return true; } @@ -3217,111 +3690,210 @@ bool _ViscousBuilder::getFaceNormalAtSingularity( const gp_XY& uv, //================================================================================ /*! - * \brief Return a normal at a node weighted with angles taken by FACEs - * \param [in] n - the node - * \param [in] fId2Normal - FACE ids and normals - * \param [in] nbFaces - nb of FACEs meeting at the node - * \return gp_XYZ - computed normal + * \brief Return a normal at a node weighted with angles taken by faces */ //================================================================================ -gp_XYZ _ViscousBuilder::getWeigthedNormal( const SMDS_MeshNode* n, - std::pair< TopoDS_Face, gp_XYZ > fId2Normal[], +gp_XYZ _ViscousBuilder::getWeigthedNormal( const _LayerEdge* edge ) +{ + const SMDS_MeshNode* n = edge->_nodes[0]; + + gp_XYZ resNorm(0,0,0); + SMESH_TNodeXYZ p0( n ), pP, pN; + for ( size_t i = 0; i < edge->_simplices.size(); ++i ) + { + pP.Set( edge->_simplices[i]._nPrev ); + pN.Set( edge->_simplices[i]._nNext ); + gp_Vec v0P( p0, pP ), v0N( p0, pN ), vPN( pP, pN ), norm = v0P ^ v0N; + double l0P = v0P.SquareMagnitude(); + double l0N = v0N.SquareMagnitude(); + double lPN = vPN.SquareMagnitude(); + if ( l0P < std::numeric_limits::min() || + l0N < std::numeric_limits::min() || + lPN < std::numeric_limits::min() ) + continue; + double lNorm = norm.SquareMagnitude(); + double sin2 = lNorm / l0P / l0N; + double angle = ACos(( v0P * v0N ) / Sqrt( l0P ) / Sqrt( l0N )); + + double weight = sin2 * angle / lPN; + resNorm += weight * norm.XYZ() / Sqrt( lNorm ); + } + + return resNorm; +} + +//================================================================================ +/*! + * \brief Return a normal at a node by getting a common point of offset planes + * defined by the FACE normals + */ +//================================================================================ + +gp_XYZ _ViscousBuilder::getNormalByOffset( _LayerEdge* edge, + std::pair< TopoDS_Face, gp_XYZ > f2Normal[], int nbFaces ) { + SMESH_TNodeXYZ p0 = edge->_nodes[0]; + gp_XYZ resNorm(0,0,0); - TopoDS_Shape V = SMESH_MesherHelper::GetSubShapeByNode( n, getMeshDS() ); - if ( V.ShapeType() != TopAbs_VERTEX ) + TopoDS_Shape V = SMESH_MesherHelper::GetSubShapeByNode( p0._node, getMeshDS() ); + if ( V.ShapeType() != TopAbs_VERTEX || nbFaces < 3 ) { for ( int i = 0; i < nbFaces; ++i ) - resNorm += fId2Normal[i].second; + resNorm += f2Normal[i].second; return resNorm; } - // exclude equal normals - int nbUniqNorms = nbFaces; - for ( int i = 0; i < nbFaces; ++i ) { - for ( int j = i+1; j < nbFaces; ++j ) - if ( fId2Normal[i].second.IsEqual( fId2Normal[j].second, 0.1 )) - { - fId2Normal[i].second.SetCoord( 0,0,0 ); - --nbUniqNorms; - break; - } - } + // prepare _OffsetPlane's + vector< _OffsetPlane > pln( nbFaces ); for ( int i = 0; i < nbFaces; ++i ) - resNorm += fId2Normal[i].second; - - // assure that resNorm is visible by every FACE (IPAL0052675) - if ( nbUniqNorms > 3 ) { - bool change = false; - for ( int nbAttempts = 0; nbAttempts < nbFaces; ++nbAttempts) + pln[i]._faceIndex = i; + pln[i]._plane = gp_Pln( p0 + f2Normal[i].second, f2Normal[i].second ); + } + + // intersect neighboring OffsetPlane's + PShapeIteratorPtr edgeIt = SMESH_MesherHelper::GetAncestors( V, *_mesh, TopAbs_EDGE ); + while ( const TopoDS_Shape* edge = edgeIt->next() ) + { + int f1 = -1, f2 = -1; + for ( int i = 0; i < nbFaces && f2 < 0; ++i ) + if ( SMESH_MesherHelper::IsSubShape( *edge, f2Normal[i].first )) + (( f1 < 0 ) ? f1 : f2 ) = i; + + if ( f2 >= 0 ) + pln[ f1 ].ComputeIntersectionLine( pln[ f2 ]); + } + + // get a common point + gp_XYZ commonPnt( 0, 0, 0 ); + int nbPoints = 0; + bool isPointFound; + for ( int i = 0; i < nbFaces; ++i ) + { + commonPnt += pln[ i ].GetCommonPoint( isPointFound ); + nbPoints += isPointFound; + } + gp_XYZ wgtNorm = getWeigthedNormal( edge ); + if ( nbPoints == 0 ) + return wgtNorm; + + commonPnt /= nbPoints; + resNorm = commonPnt - p0; + + // choose the best among resNorm and wgtNorm + resNorm.Normalize(); + wgtNorm.Normalize(); + double resMinDot = std::numeric_limits::max(); + double wgtMinDot = std::numeric_limits::max(); + for ( int i = 0; i < nbFaces; ++i ) + { + resMinDot = Min( resMinDot, resNorm * f2Normal[i].second ); + wgtMinDot = Min( wgtMinDot, wgtNorm * f2Normal[i].second ); + } + + if ( Max( resMinDot, wgtMinDot ) < theMinSmoothCosin ) + { + edge->Set( _LayerEdge::MULTI_NORMAL ); + } + + return ( resMinDot > wgtMinDot ) ? resNorm : wgtNorm; +} + +//================================================================================ +/*! + * \brief Compute line of intersection of 2 planes + */ +//================================================================================ + +void _OffsetPlane::ComputeIntersectionLine( _OffsetPlane& pln ) +{ + int iNext = bool( _faceIndexNext[0] >= 0 ); + _faceIndexNext[ iNext ] = pln._faceIndex; + + gp_XYZ n1 = _plane.Axis().Direction().XYZ(); + gp_XYZ n2 = pln._plane.Axis().Direction().XYZ(); + + gp_XYZ lineDir = n1 ^ n2; + + double x = Abs( lineDir.X() ); + double y = Abs( lineDir.Y() ); + double z = Abs( lineDir.Z() ); + + int cooMax; // max coordinate + if (x > y) { + if (x > z) cooMax = 1; + else cooMax = 3; + } + else { + if (y > z) cooMax = 2; + else cooMax = 3; + } + + if ( Abs( lineDir.Coord( cooMax )) < 0.05 ) + return; + + gp_Pnt linePos; + // the constants in the 2 plane equations + double d1 = - ( _plane.Axis().Direction().XYZ() * _plane.Location().XYZ() ); + double d2 = - ( pln._plane.Axis().Direction().XYZ() * pln._plane.Location().XYZ() ); + + switch ( cooMax ) { + case 1: + linePos.SetX( 0 ); + linePos.SetY(( d2*n1.Z() - d1*n2.Z()) / lineDir.X() ); + linePos.SetZ(( d1*n2.Y() - d2*n1.Y()) / lineDir.X() ); + break; + case 2: + linePos.SetX(( d1*n2.Z() - d2*n1.Z()) / lineDir.Y() ); + linePos.SetY( 0 ); + linePos.SetZ(( d2*n1.X() - d1*n2.X()) / lineDir.Y() ); + break; + case 3: + linePos.SetX(( d2*n1.Y() - d1*n2.Y()) / lineDir.Z() ); + linePos.SetY(( d1*n2.X() - d2*n1.X()) / lineDir.Z() ); + linePos.SetZ( 0 ); + } + + gp_Lin& line = _lines[ iNext ]; + line.SetDirection( lineDir ); + line.SetLocation ( linePos ); + + _isLineOK[ iNext ] = true; + + + iNext = bool( pln._faceIndexNext[0] >= 0 ); + pln._lines [ iNext ] = line; + pln._faceIndexNext[ iNext ] = this->_faceIndex; + pln._isLineOK [ iNext ] = true; +} + +//================================================================================ +/*! + * \brief Computes intersection point of two _lines + */ +//================================================================================ + +gp_XYZ _OffsetPlane::GetCommonPoint(bool& isFound) const +{ + gp_XYZ p( 0,0,0 ); + isFound = false; + + if ( NbLines() == 2 ) + { + gp_Vec lPerp0 = _lines[0].Direction().XYZ() ^ _plane.Axis().Direction().XYZ(); + double dot01 = lPerp0 * _lines[1].Direction().XYZ(); + if ( Abs( dot01 ) > std::numeric_limits::min() ) { - for ( int i = 0; i < nbFaces; ++i ) - if ( resNorm * fId2Normal[i].second < 0.5 ) - { - resNorm += fId2Normal[i].second; - change = true; - } - if ( !change ) break; + gp_Vec l0l1 = _lines[1].Location().XYZ() - _lines[0].Location().XYZ(); + double u1 = - ( lPerp0 * l0l1 ) / dot01; + p = ( _lines[1].Location().XYZ() + _lines[1].Direction().XYZ() * u1 ); + isFound = true; } } - // double angles[30]; - // for ( int i = 0; i < nbFaces; ++i ) - // { - // const TopoDS_Face& F = fId2Normal[i].first; - - // // look for two EDGEs shared by F and other FACEs within fId2Normal - // TopoDS_Edge ee[2]; - // int nbE = 0; - // PShapeIteratorPtr eIt = SMESH_MesherHelper::GetAncestors( V, *_mesh, TopAbs_EDGE ); - // while ( const TopoDS_Shape* E = eIt->next() ) - // { - // if ( !SMESH_MesherHelper::IsSubShape( *E, F )) - // continue; - // bool isSharedEdge = false; - // for ( int j = 0; j < nbFaces && !isSharedEdge; ++j ) - // { - // if ( i == j ) continue; - // const TopoDS_Shape& otherF = fId2Normal[j].first; - // isSharedEdge = SMESH_MesherHelper::IsSubShape( *E, otherF ); - // } - // if ( !isSharedEdge ) - // continue; - // ee[ nbE ] = TopoDS::Edge( *E ); - // ee[ nbE ].Orientation( SMESH_MesherHelper::GetSubShapeOri( F, *E )); - // if ( ++nbE == 2 ) - // break; - // } - - // // get an angle between the two EDGEs - // angles[i] = 0; - // if ( nbE < 1 ) continue; - // if ( nbE == 1 ) - // { - // ee[ 1 ] == ee[ 0 ]; - // } - // else - // { - // if ( !V.IsSame( SMESH_MesherHelper::IthVertex( 0, ee[ 1 ] ))) - // std::swap( ee[0], ee[1] ); - // } - // angles[i] = SMESH_MesherHelper::GetAngle( ee[0], ee[1], F, TopoDS::Vertex( V )); - // } - - // // compute a weighted normal - // double sumAngle = 0; - // for ( int i = 0; i < nbFaces; ++i ) - // { - // angles[i] = ( angles[i] > 2*M_PI ) ? 0 : M_PI - angles[i]; - // sumAngle += angles[i]; - // } - // for ( int i = 0; i < nbFaces; ++i ) - // resNorm += angles[i] / sumAngle * fId2Normal[i].second; - - return resNorm; + return p; } //================================================================================ @@ -3383,7 +3955,7 @@ void _LayerEdge::SetDataByNeighbors( const SMDS_MeshNode* n1, if ( eos.ShapeType() != TopAbs_EDGE ) return; - gp_XYZ pos = SMESH_TNodeXYZ( _nodes[0] ); + gp_XYZ pos = SMESH_TNodeXYZ( _nodes[0] ); gp_XYZ vec1 = pos - SMESH_TNodeXYZ( n1 ); gp_XYZ vec2 = pos - SMESH_TNodeXYZ( n2 ); @@ -3472,7 +4044,20 @@ void _LayerEdge::SetCosin( double cosin ) { _cosin = cosin; cosin = Abs( _cosin ); - _lenFactor = ( /*0.1 < cosin &&*/ cosin < 1-1e-12 ) ? 1./sqrt(1-cosin*cosin) : 1.0; + //_lenFactor = ( cosin < 1.-1e-12 ) ? Min( 2., 1./sqrt(1-cosin*cosin )) : 1.0; + _lenFactor = ( cosin < 1.-1e-12 ) ? 1./sqrt(1-cosin*cosin ) : 1.0; +} + +//================================================================================ +/*! + * \brief Check if another _LayerEdge is a neighbor on EDGE + */ +//================================================================================ + +bool _LayerEdge::IsNeiborOnEdge( const _LayerEdge* edge ) const +{ + return (( this->_2neibors && this->_2neibors->include( edge )) || + ( edge->_2neibors && edge->_2neibors->include( this ))); } //================================================================================ @@ -3501,7 +4086,7 @@ void _Simplex::GetSimplices( const SMDS_MeshNode* node, const SMDS_MeshNode* nOpp = f->GetNode( SMESH_MesherHelper::WrapIndex( srcInd+2, nbNodes )); if ( dataToCheckOri && dataToCheckOri->_reversedFaceIds.count( shapeInd )) std::swap( nPrev, nNext ); - simplices.push_back( _Simplex( nPrev, nNext, nOpp )); + simplices.push_back( _Simplex( nPrev, nNext, ( nbNodes == 3 ? 0 : nOpp ))); } if ( toSort ) @@ -3518,7 +4103,7 @@ void _Simplex::SortSimplices(vector<_Simplex>& simplices) { vector<_Simplex> sortedSimplices( simplices.size() ); sortedSimplices[0] = simplices[0]; - int nbFound = 0; + size_t nbFound = 0; for ( size_t i = 1; i < simplices.size(); ++i ) { for ( size_t j = 1; j < simplices.size(); ++j ) @@ -3551,9 +4136,13 @@ void _ViscousBuilder::makeGroupOfLE() for ( n2e = _sdVec[i]._n2eMap.begin(); n2e != _sdVec[i]._n2eMap.end(); ++n2e ) { _LayerEdge* le = n2e->second; - for ( size_t iN = 1; iN < le->_nodes.size(); ++iN ) - dumpCmd(SMESH_Comment("mesh.AddEdge([ ") <_nodes[iN-1]->GetID() - << ", " << le->_nodes[iN]->GetID() <<"])"); + // for ( size_t iN = 1; iN < le->_nodes.size(); ++iN ) + // dumpCmd(SMESH_Comment("mesh.AddEdge([ ") <_nodes[iN-1]->GetID() + // << ", " << le->_nodes[iN]->GetID() <<"])"); + if ( le ) { + dumpCmd(SMESH_Comment("mesh.AddEdge([ ") <_nodes[0]->GetID() + << ", " << le->_nodes.back()->GetID() <<"]) # " << le->_flags ); + } } dumpFunctionEnd(); @@ -3564,7 +4153,7 @@ void _ViscousBuilder::makeGroupOfLE() SMESH_TNodeXYZ nXYZ( edge->_nodes[0] ); nXYZ += edge->_normal * _sdVec[i]._stepSize; dumpCmd(SMESH_Comment("mesh.AddEdge([ ") << edge->_nodes[0]->GetID() - << ", mesh.AddNode( " << nXYZ.X()<<","<< nXYZ.Y()<<","<< nXYZ.Z()<<")])"); + << ", mesh.AddNode( "<< nXYZ.X()<<","<< nXYZ.Y()<<","<< nXYZ.Z()<<")])"); } dumpFunctionEnd(); @@ -3573,7 +4162,7 @@ void _ViscousBuilder::makeGroupOfLE() TopExp_Explorer fExp( _sdVec[i]._solid, TopAbs_FACE ); for ( ; fExp.More(); fExp.Next() ) { - if (const SMESHDS_SubMesh* sm = _sdVec[i]._proxyMesh->GetProxySubMesh( fExp.Current())) + if ( const SMESHDS_SubMesh* sm = _sdVec[i]._proxyMesh->GetProxySubMesh( fExp.Current() )) { if ( sm->NbElements() == 0 ) continue; SMDS_ElemIteratorPtr fIt = sm->GetElements(); @@ -3581,8 +4170,8 @@ void _ViscousBuilder::makeGroupOfLE() { const SMDS_MeshElement* e = fIt->next(); SMESH_Comment cmd("mesh.AddFace(["); - for ( int j=0; j < e->NbCornerNodes(); ++j ) - cmd << e->GetNode(j)->GetID() << (j+1NbCornerNodes() ? ",": "])"); + for ( int j = 0; j < e->NbCornerNodes(); ++j ) + cmd << e->GetNode(j)->GetID() << (j+1 < e->NbCornerNodes() ? ",": "])"); dumpCmd( cmd ); } } @@ -3606,20 +4195,46 @@ void _ViscousBuilder::computeGeomSize( _SolidData& data ) { data._geomSize = Precision::Infinite(); double intersecDist; - auto_ptr searcher + const SMDS_MeshElement* face; + SMESH_MesherHelper helper( *_mesh ); + + SMESHUtils::Deleter searcher ( SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), - data._proxyMesh->GetFaces( data._solid )) ); + data._proxyMesh->GetFaces( data._solid ))); for ( size_t iS = 0; iS < data._edgesOnShape.size(); ++iS ) { _EdgesOnShape& eos = data._edgesOnShape[ iS ]; - if ( eos._edges.empty() || eos.ShapeType() == TopAbs_EDGE ) + if ( eos._edges.empty() ) continue; + // get neighbor faces intersection with which should not be considered since + // collisions are avoided by means of smoothing + set< TGeomID > neighborFaces; + if ( eos._hyp.ToSmooth() ) + { + SMESH_subMeshIteratorPtr subIt = + eos._subMesh->getDependsOnIterator(/*includeSelf=*/eos.ShapeType() != TopAbs_FACE ); + while ( subIt->more() ) + { + SMESH_subMesh* sm = subIt->next(); + PShapeIteratorPtr fIt = helper.GetAncestors( sm->GetSubShape(), *_mesh, TopAbs_FACE ); + while ( const TopoDS_Shape* face = fIt->next() ) + neighborFaces.insert( getMeshDS()->ShapeToIndex( *face )); + } + } + // find intersections + double thinkness = eos._hyp.GetTotalThickness(); for ( size_t i = 0; i < eos._edges.size(); ++i ) { - eos._edges[i]->FindIntersection( *searcher, intersecDist, data._epsilon, eos ); - if ( data._geomSize > intersecDist && intersecDist > 0 ) - data._geomSize = intersecDist; + if ( eos._edges[i]->Is( _LayerEdge::BLOCKED )) continue; + eos._edges[i]->_maxLen = thinkness; + eos._edges[i]->FindIntersection( *searcher, intersecDist, data._epsilon, eos, &face ); + if ( intersecDist > 0 && face ) + { + data._geomSize = Min( data._geomSize, intersecDist ); + if ( !neighborFaces.count( face->getshapeId() )) + eos._edges[i]->_maxLen = Min( thinkness, intersecDist / ( face->GetID() < 0 ? 3. : 2. )); + } } } } @@ -3648,6 +4263,18 @@ bool _ViscousBuilder::inflate(_SolidData& data) debugMsg( "-- geomSize = " << data._geomSize << ", stepSize = " << data._stepSize ); + findCollisionEdges( data, helper ); + + // limit length of _LayerEdge's around MULTI_NORMAL _LayerEdge's + for ( size_t i = 0; i < data._edgesOnShape.size(); ++i ) + if ( data._edgesOnShape[i].ShapeType() == TopAbs_VERTEX && + data._edgesOnShape[i]._edges.size() > 0 && + data._edgesOnShape[i]._edges[0]->Is( _LayerEdge::MULTI_NORMAL )) + { + data._edgesOnShape[i]._edges[0]->Unset( _LayerEdge::BLOCKED ); + data._edgesOnShape[i]._edges[0]->Block( data ); + } + const double safeFactor = ( 2*data._maxThickness < data._geomSize ) ? 1 : theThickToIntersection; double avgThick = 0, curThick = 0, distToIntersection = Precision::Infinite(); @@ -3655,6 +4282,7 @@ bool _ViscousBuilder::inflate(_SolidData& data) while ( avgThick < 0.99 ) { // new target length + double prevThick = curThick; curThick += data._stepSize; if ( curThick > tgtThick ) { @@ -3662,6 +4290,9 @@ bool _ViscousBuilder::inflate(_SolidData& data) nbRepeats++; } + double stepSize = curThick - prevThick; + updateNormalsOfSmoothed( data, helper, nbSteps, stepSize ); // to ease smoothing + // Elongate _LayerEdge's dumpFunction(SMESH_Comment("inflate")<_len / shapeTgtThick ); + avgThick += Min( 1., eos._edges[i]->_len / shapeTgtThick ); + nbActiveEdges += ( ! eos._edges[i]->Is( _LayerEdge::BLOCKED )); } } avgThick /= data._n2eMap.size(); debugMsg( "-- Thickness " << curThick << " ("<< avgThick*100 << "%) reached" ); +#ifdef BLOCK_INFLATION + if ( nbActiveEdges == 0 ) + { + debugMsg( "-- Stop inflation since all _LayerEdge's BLOCKED " ); + break; + } +#else if ( distToIntersection < tgtThick * avgThick * safeFactor && avgThick < 0.9 ) { debugMsg( "-- Stop inflation since " @@ -3725,6 +4365,7 @@ bool _ViscousBuilder::inflate(_SolidData& data) << tgtThick * avgThick << " ) * " << safeFactor ); break; } +#endif // new step size limitStepSize( data, 0.25 * distToIntersection ); if ( data._stepSizeNodes[0] ) @@ -3733,7 +4374,7 @@ bool _ViscousBuilder::inflate(_SolidData& data) } // while ( avgThick < 0.99 ) - if (nbSteps == 0 ) + if ( nbSteps == 0 ) return error("failed at the very first inflation step", data._index); if ( avgThick < 0.99 ) @@ -3748,7 +4389,7 @@ bool _ViscousBuilder::inflate(_SolidData& data) } } - // Restore position of src nodes moved by infaltion on _noShrinkShapes + // Restore position of src nodes moved by inflation on _noShrinkShapes dumpFunction(SMESH_Comment("restoNoShrink_So")< 0; // == true (avoid warning: unused variable 'safeFactor') } //================================================================================ @@ -3771,24 +4412,27 @@ bool _ViscousBuilder::inflate(_SolidData& data) //================================================================================ bool _ViscousBuilder::smoothAndCheck(_SolidData& data, - const int nbSteps, + const int infStep, double & distToIntersection) { if ( data._nbShapesToSmooth == 0 ) return true; // no shapes needing smoothing bool moved, improved; - vector< _LayerEdge* > badSmooEdges; + double vol; + vector< _LayerEdge* > movedEdges, badEdges; + vector< _EdgesOnShape* > eosC1; // C1 continues shapes + vector< bool > isConcaveFace; SMESH_MesherHelper helper(*_mesh); - Handle(Geom_Surface) surface; + Handle(ShapeAnalysis_Surface) surface; TopoDS_Face F; for ( int isFace = 0; isFace < 2; ++isFace ) // smooth on [ EDGEs, FACEs ] { const TopAbs_ShapeEnum shapeType = isFace ? TopAbs_FACE : TopAbs_EDGE; - for ( int iS = 0; iS < data._edgesOnShape.size(); ++iS ) + for ( size_t iS = 0; iS < data._edgesOnShape.size(); ++iS ) { _EdgesOnShape& eos = data._edgesOnShape[ iS ]; if ( !eos._toSmooth || @@ -3797,24 +4441,28 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data, continue; // already smoothed? - bool toSmooth = ( eos._edges[ 0 ]->NbSteps() >= nbSteps+1 ); - if ( !toSmooth ) continue; + // bool toSmooth = ( eos._edges[ 0 ]->NbSteps() >= infStep+1 ); + // if ( !toSmooth ) continue; if ( !eos._hyp.ToSmooth() ) { // smooth disabled by the user; check validy only if ( !isFace ) continue; - double vol; for ( size_t i = 0; i < eos._edges.size(); ++i ) { _LayerEdge* edge = eos._edges[i]; - const gp_XYZ& curPos ( ); for ( size_t iF = 0; iF < edge->_simplices.size(); ++iF ) - if ( !edge->_simplices[iF].IsForward( edge->_nodes[0], - &edge->_pos.back(), vol )) + if ( !edge->_simplices[iF].IsForward( edge->_nodes[0], edge->_pos.back(), vol )) + { + debugMsg( "-- Stop inflation. Bad simplex (" + << " "<< edge->_nodes[0]->GetID() + << " "<< edge->_nodes.back()->GetID() + << " "<< edge->_simplices[iF]._nPrev->GetID() + << " "<< edge->_simplices[iF]._nNext->GetID() << " ) "); return false; + } } - continue; // goto to the next EDGE or FACE + continue; // goto the next EDGE or FACE } // prepare data @@ -3823,7 +4471,7 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data, if ( !F.IsSame( eos._sWOL )) { F = TopoDS::Face( eos._sWOL ); helper.SetSubShape( F ); - surface = BRep_Tool::Surface( F ); + surface = helper.GetSurface( F ); } } else @@ -3836,12 +4484,11 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data, if ( eos.ShapeType() == TopAbs_EDGE ) { - dumpFunction(SMESH_Comment("smooth")<Perform( data, surface, F, helper )) { - // smooth on EDGE's + // smooth on EDGE's (normally we should not get here) int step = 0; do { moved = false; @@ -3855,118 +4502,277 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data, } dumpFunctionEnd(); } - else + + else // smooth on FACE { - // smooth on FACE's + eosC1.clear(); + eosC1.push_back( & eos ); + eosC1.insert( eosC1.end(), eos._eosC1.begin(), eos._eosC1.end() ); - const bool isConcaveFace = data._concaveFaces.count( sInd ); + movedEdges.clear(); + isConcaveFace.resize( eosC1.size() ); + for ( size_t iEOS = 0; iEOS < eosC1.size(); ++iEOS ) + { + isConcaveFace[ iEOS ] = data._concaveFaces.count( eosC1[ iEOS ]->_shapeID ); + vector< _LayerEdge* > & edges = eosC1[ iEOS ]->_edges; + for ( size_t i = 0; i < edges.size(); ++i ) + if ( edges[i]->Is( _LayerEdge::MOVED ) || + edges[i]->Is( _LayerEdge::NEAR_BOUNDARY )) + movedEdges.push_back( edges[i] ); - int step = 0, stepLimit = 5, badNb = 0; + makeOffsetSurface( *eosC1[ iEOS ], helper ); + } + + int step = 0, stepLimit = 5, nbBad = 0; while (( ++step <= stepLimit ) || improved ) { dumpFunction(SMESH_Comment("smooth")<Smooth( step, isConcaveFace, false )) - badSmooEdges.push_back( eos._edges[i] ); - } - - else { - for ( int i = eos._edges.size()-1; i >= 0; --i ) // iterate backward - if ( eos._edges[i]->Smooth( step, isConcaveFace, false )) - badSmooEdges.push_back( eos._edges[i] ); - } - badNb = badSmooEdges.size(); - improved = ( badNb < oldBadNb ); - - if ( !badSmooEdges.empty() && step >= stepLimit / 2 ) +#ifdef INCREMENTAL_SMOOTH + bool findBest = false; // ( step == stepLimit ); + for ( size_t i = 0; i < movedEdges.size(); ++i ) { - // look for the best smooth of _LayerEdge's neighboring badSmooEdges - vector<_Simplex> simplices; - for ( size_t i = 0; i < badSmooEdges.size(); ++i ) + movedEdges[i]->Unset( _LayerEdge::SMOOTHED ); + if ( movedEdges[i]->Smooth( step, findBest, movedEdges ) > 0 ) + badEdges.push_back( movedEdges[i] ); + } +#else + bool findBest = ( step == stepLimit || isConcaveFace[ iEOS ]); + for ( size_t iEOS = 0; iEOS < eosC1.size(); ++iEOS ) + { + vector< _LayerEdge* > & edges = eosC1[ iEOS ]->_edges; + for ( size_t i = 0; i < edges.size(); ++i ) { - _LayerEdge* ledge = badSmooEdges[i]; - _Simplex::GetSimplices( ledge->_nodes[0], simplices, data._ignoreFaceIds ); - for ( size_t iS = 0; iS < simplices.size(); ++iS ) + edges[i]->Unset( _LayerEdge::SMOOTHED ); + if ( edges[i]->Smooth( step, findBest, false ) > 0 ) + badEdges.push_back( eos._edges[i] ); + } + } +#endif + nbBad = badEdges.size(); + + if ( nbBad > 0 ) + debugMsg(SMESH_Comment("nbBad = ") << nbBad ); + + if ( !badEdges.empty() && step >= stepLimit / 2 ) + { + if ( badEdges[0]->Is( _LayerEdge::ON_CONCAVE_FACE )) + stepLimit = 9; + + // resolve hard smoothing situation around concave VERTEXes + for ( size_t iEOS = 0; iEOS < eosC1.size(); ++iEOS ) + { + vector< _EdgesOnShape* > & eosCoVe = eosC1[ iEOS ]->_eosConcaVer; + for ( size_t i = 0; i < eosCoVe.size(); ++i ) + eosCoVe[i]->_edges[0]->MoveNearConcaVer( eosCoVe[i], eosC1[ iEOS ], + step, badEdges ); + } + // look for the best smooth of _LayerEdge's neighboring badEdges + nbBad = 0; + for ( size_t i = 0; i < badEdges.size(); ++i ) + { + _LayerEdge* ledge = badEdges[i]; + for ( size_t iN = 0; iN < ledge->_neibors.size(); ++iN ) { - TNode2Edge::iterator n2e = data._n2eMap.find( simplices[iS]._nNext ); - if ( n2e != data._n2eMap.end()) { - _LayerEdge* ledge2 = n2e->second; - if ( ledge2->_nodes[0]->getshapeId() == sInd ) - ledge2->Smooth( step, isConcaveFace, /*findBest=*/true ); - } + ledge->_neibors[iN]->Unset( _LayerEdge::SMOOTHED ); + nbBad += ledge->_neibors[iN]->Smooth( step, true, /*findBest=*/true ); + } + ledge->Unset( _LayerEdge::SMOOTHED ); + nbBad += ledge->Smooth( step, true, /*findBest=*/true ); + } + debugMsg(SMESH_Comment("nbBad = ") << nbBad ); + } + + if ( nbBad == oldBadNb && + nbBad > 0 && + step < stepLimit ) // smooth w/o chech of validity + { + dumpFunctionEnd(); + dumpFunction(SMESH_Comment("smoothWoCheck")<SmoothWoCheck(); + } + if ( stepLimit < 9 ) + stepLimit++; + } + + improved = ( nbBad < oldBadNb ); + + dumpFunctionEnd(); + + if (( step % 3 == 1 ) || ( nbBad > 0 && step >= stepLimit / 2 )) + for ( size_t iEOS = 0; iEOS < eosC1.size(); ++iEOS ) + { + putOnOffsetSurface( *eosC1[ iEOS ], infStep, step, /*moveAll=*/step == 1 ); + } + + } // smoothing steps + + // project -- to prevent intersections or fix bad simplices + for ( size_t iEOS = 0; iEOS < eosC1.size(); ++iEOS ) + { + if ( ! eosC1[ iEOS ]->_eosConcaVer.empty() || nbBad > 0 ) + putOnOffsetSurface( *eosC1[ iEOS ], infStep ); + } + + if ( !badEdges.empty() ) + { + badEdges.clear(); + for ( size_t iEOS = 0; iEOS < eosC1.size(); ++iEOS ) + { + for ( size_t i = 0; i < eosC1[ iEOS ]->_edges.size(); ++i ) + { + if ( !eosC1[ iEOS ]->_sWOL.IsNull() ) continue; + + _LayerEdge* edge = eosC1[ iEOS ]->_edges[i]; + edge->CheckNeiborsOnBoundary( & badEdges ); + if ( nbBad > 0 ) + { + SMESH_TNodeXYZ tgtXYZ = edge->_nodes.back(); + const gp_XYZ& prevXYZ = edge->PrevCheckPos(); + for ( size_t j = 0; j < edge->_simplices.size(); ++j ) + if ( !edge->_simplices[j].IsForward( &prevXYZ, &tgtXYZ, vol )) + { + debugMsg("Bad simplex ( " << edge->_nodes[0]->GetID() + << " "<< tgtXYZ._node->GetID() + << " "<< edge->_simplices[j]._nPrev->GetID() + << " "<< edge->_simplices[j]._nNext->GetID() << " )" ); + badEdges.push_back( edge ); + break; + } } } } - // issue 22576 -- no bad faces but still there are intersections to fix - // if ( improved && badNb == 0 ) - // stepLimit = step + 3; - dumpFunctionEnd(); - } - if ( badNb > 0 ) - { -#ifdef __myDEBUG - double vol = 0; - for ( int i = 0; i < eos._edges.size(); ++i ) - { - _LayerEdge* edge = eos._edges[i]; - SMESH_TNodeXYZ tgtXYZ( edge->_nodes.back() ); - for ( size_t j = 0; j < edge->_simplices.size(); ++j ) - if ( !edge->_simplices[j].IsForward( edge->_nodes[0], &tgtXYZ, vol )) - { - cout << "Bad simplex ( " << edge->_nodes[0]->GetID()<< " "<< tgtXYZ._node->GetID() - << " "<< edge->_simplices[j]._nPrev->GetID() - << " "<< edge->_simplices[j]._nNext->GetID() << " )" << endl; - return false; - } - } -#endif - return false; + // try to fix bad simplices by removing the last inflation step of some _LayerEdge's + nbBad = invalidateBadSmooth( data, helper, badEdges, eosC1, infStep ); + + if ( nbBad > 0 ) + return false; } + } // // smooth on FACE's } // loop on shapes } // smooth on [ EDGEs, FACEs ] - // Check orientation of simplices of _ConvexFace::_simplexTestEdges - map< TGeomID, _ConvexFace >::iterator id2face = data._convexFaces.begin(); - for ( ; id2face != data._convexFaces.end(); ++id2face ) + // Check orientation of simplices of _LayerEdge's on EDGEs and VERTEXes + eosC1.resize(1); + for ( size_t iS = 0; iS < data._edgesOnShape.size(); ++iS ) { - _ConvexFace & convFace = (*id2face).second; - if ( !convFace._simplexTestEdges.empty() && - convFace._simplexTestEdges[0]->_nodes[0]->GetPosition()->GetDim() == 2 ) - continue; // _simplexTestEdges are based on FACE -- already checked while smoothing + _EdgesOnShape& eos = data._edgesOnShape[ iS ]; + if ( eos.ShapeType() == TopAbs_FACE || + eos._edges.empty() || + !eos._sWOL.IsNull() ) + continue; - if ( !convFace.CheckPrisms() ) + badEdges.clear(); + for ( size_t i = 0; i < eos._edges.size(); ++i ) + { + _LayerEdge* edge = eos._edges[i]; + if ( edge->_nodes.size() < 2 ) continue; + SMESH_TNodeXYZ tgtXYZ = edge->_nodes.back(); + const gp_XYZ& prevXYZ = edge->PrevCheckPos(); + //const gp_XYZ& prevXYZ = edge->PrevPos(); + for ( size_t j = 0; j < edge->_simplices.size(); ++j ) + if ( !edge->_simplices[j].IsForward( &prevXYZ, &tgtXYZ, vol )) + { + debugMsg("Bad simplex on bnd ( " << edge->_nodes[0]->GetID() + << " "<< tgtXYZ._node->GetID() + << " "<< edge->_simplices[j]._nPrev->GetID() + << " "<< edge->_simplices[j]._nNext->GetID() << " )" ); + badEdges.push_back( edge ); + break; + } + } + + // try to fix bad simplices by removing the last inflation step of some _LayerEdge's + eosC1[0] = &eos; + int nbBad = invalidateBadSmooth( data, helper, badEdges, eosC1, infStep ); + if ( nbBad > 0 ) return false; } + // Check if the last segments of _LayerEdge intersects 2D elements; // checked elements are either temporary faces or faces on surfaces w/o the layers - auto_ptr searcher + SMESHUtils::Deleter searcher ( SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), data._proxyMesh->GetFaces( data._solid )) ); +#ifdef BLOCK_INFLATION + const bool toBlockInfaltion = true; +#else + const bool toBlockInfaltion = false; +#endif distToIntersection = Precision::Infinite(); double dist; const SMDS_MeshElement* intFace = 0; const SMDS_MeshElement* closestFace = 0; _LayerEdge* le = 0; - for ( int iS = 0; iS < data._edgesOnShape.size(); ++iS ) + for ( size_t iS = 0; iS < data._edgesOnShape.size(); ++iS ) { _EdgesOnShape& eos = data._edgesOnShape[ iS ]; if ( eos._edges.empty() || !eos._sWOL.IsNull() ) continue; for ( size_t i = 0; i < eos._edges.size(); ++i ) { + if ( eos._edges[i]->Is( _LayerEdge::INTERSECTED ) || + eos._edges[i]->Is( _LayerEdge::MULTI_NORMAL )) + continue; if ( eos._edges[i]->FindIntersection( *searcher, dist, data._epsilon, eos, &intFace )) + { return false; - if ( distToIntersection > dist ) + // commented due to "Illegal hash-positionPosition" error in NETGEN + // on Debian60 on viscous_layers_01/B2 case + // Collision; try to deflate _LayerEdge's causing it + // badEdges.clear(); + // badEdges.push_back( eos._edges[i] ); + // eosC1[0] = & eos; + // int nbBad = invalidateBadSmooth( data, helper, badEdges, eosC1, infStep ); + // if ( nbBad > 0 ) + // return false; + + // badEdges.clear(); + // if ( _EdgesOnShape* eof = data.GetShapeEdges( intFace->getshapeId() )) + // { + // if ( const _TmpMeshFace* f = dynamic_cast< const _TmpMeshFace*>( intFace )) + // { + // const SMDS_MeshElement* srcFace = + // eof->_subMesh->GetSubMeshDS()->GetElement( f->getIdInShape() ); + // SMDS_ElemIteratorPtr nIt = srcFace->nodesIterator(); + // while ( nIt->more() ) + // { + // const SMDS_MeshNode* srcNode = static_cast( nIt->next() ); + // TNode2Edge::iterator n2e = data._n2eMap.find( srcNode ); + // if ( n2e != data._n2eMap.end() ) + // badEdges.push_back( n2e->second ); + // } + // eosC1[0] = eof; + // nbBad = invalidateBadSmooth( data, helper, badEdges, eosC1, infStep ); + // if ( nbBad > 0 ) + // return false; + // } + // } + // if ( eos._edges[i]->FindIntersection( *searcher, dist, data._epsilon, eos, &intFace )) + // return false; + // else + // continue; + } + if ( !intFace ) + { + SMESH_Comment msg("Invalid? normal at node "); msg << eos._edges[i]->_nodes[0]->GetID(); + debugMsg( msg ); + continue; + } + + const bool isShorterDist = ( distToIntersection > dist ); + if ( toBlockInfaltion || isShorterDist ) { // ignore intersection of a _LayerEdge based on a _ConvexFace with a face // lying on this _ConvexFace @@ -3979,12 +4785,78 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data, if ( intFace->getshapeId() == eos._shapeID ) continue; - distToIntersection = dist; - le = eos._edges[i]; - closestFace = intFace; - } - } - } + // ignore intersection with intFace of an adjacent FACE + if ( dist > 0 ) + { + bool toIgnore = false; + if ( eos._edges[i]->Is( _LayerEdge::TO_SMOOTH )) + { + const TopoDS_Shape& S = getMeshDS()->IndexToShape( intFace->getshapeId() ); + if ( !S.IsNull() && S.ShapeType() == TopAbs_FACE ) + { + TopExp_Explorer edge( eos._shape, TopAbs_EDGE ); + for ( ; !toIgnore && edge.More(); edge.Next() ) + // is adjacent - has a common EDGE + toIgnore = ( helper.IsSubShape( edge.Current(), S )); + + if ( toIgnore ) // check angle between normals + { + gp_XYZ normal; + if ( SMESH_MeshAlgos::FaceNormal( intFace, normal, /*normalized=*/true )) + toIgnore = ( normal * eos._edges[i]->_normal > -0.5 ); + } + } + } + if ( !toIgnore ) // check if the edge is a neighbor of intFace + { + for ( size_t iN = 0; !toIgnore && iN < eos._edges[i]->_neibors.size(); ++iN ) + { + int nInd = intFace->GetNodeIndex( eos._edges[i]->_neibors[ iN ]->_nodes.back() ); + toIgnore = ( nInd >= 0 ); + } + } + if ( toIgnore ) + continue; + } + + // intersection not ignored + + if ( toBlockInfaltion && + dist < ( eos._edges[i]->_len * theThickToIntersection )) + { + eos._edges[i]->Set( _LayerEdge::INTERSECTED ); // not to intersect + eos._edges[i]->Block( data ); // not to inflate + + if ( _EdgesOnShape* eof = data.GetShapeEdges( intFace->getshapeId() )) + { + // block _LayerEdge's, on top of which intFace is + if ( const _TmpMeshFace* f = dynamic_cast< const _TmpMeshFace*>( intFace )) + { + const SMDS_MeshElement* srcFace = + eof->_subMesh->GetSubMeshDS()->GetElement( f->getIdInShape() ); + SMDS_ElemIteratorPtr nIt = srcFace->nodesIterator(); + while ( nIt->more() ) + { + const SMDS_MeshNode* srcNode = static_cast( nIt->next() ); + TNode2Edge::iterator n2e = data._n2eMap.find( srcNode ); + if ( n2e != data._n2eMap.end() ) + n2e->second->Block( data ); + } + } + } + } + + if ( isShorterDist ) + { + distToIntersection = dist; + le = eos._edges[i]; + closestFace = intFace; + } + + } // if ( toBlockInfaltion || isShorterDist ) + } // loop on eos._edges + } // loop on data._edgesOnShape + #ifdef __myDEBUG if ( closestFace ) { @@ -3999,6 +4871,218 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data, return true; } +//================================================================================ +/*! + * \brief try to fix bad simplices by removing the last inflation step of some _LayerEdge's + * \param [in,out] badSmooEdges - _LayerEdge's to fix + * \return int - resulting nb of bad _LayerEdge's + */ +//================================================================================ + +int _ViscousBuilder::invalidateBadSmooth( _SolidData& data, + SMESH_MesherHelper& helper, + vector< _LayerEdge* >& badSmooEdges, + vector< _EdgesOnShape* >& eosC1, + const int infStep ) +{ + if ( badSmooEdges.empty() || infStep == 0 ) return 0; + + dumpFunction(SMESH_Comment("invalidateBadSmooth")<<"_S"<_shapeID<<"_InfStep"<NbSteps() < 2 /*|| edge->Is( _LayerEdge::MARKED )*/) + continue; + + _EdgesOnShape* eos = data.GetShapeEdges( edge ); + edge->InvalidateStep( edge->NbSteps(), *eos, /*restoreLength=*/true ); + edge->Block( data ); + //edge->Set( _LayerEdge::MARKED ); + + // look for _LayerEdge's of bad _simplices + SMESH_TNodeXYZ tgtXYZ = edge->_nodes.back(); + const gp_XYZ& prevXYZ1 = edge->PrevCheckPos(); + const gp_XYZ& prevXYZ2 = edge->PrevPos(); + for ( size_t j = 0; j < edge->_simplices.size(); ++j ) + { + if (( edge->_simplices[j].IsForward( &prevXYZ1, &tgtXYZ, vol )) && + ( &prevXYZ1 == &prevXYZ2 || edge->_simplices[j].IsForward( &prevXYZ2, &tgtXYZ, vol ))) + continue; + for ( size_t iN = 0; iN < edge->_neibors.size(); ++iN ) + if ( edge->_simplices[j].Includes( edge->_neibors[iN]->_nodes.back() )) + badSmooEdges.push_back( edge->_neibors[iN] ); + } + + if ( eos->ShapeType() == TopAbs_VERTEX ) + { + // re-smooth on analytical EDGEs + PShapeIteratorPtr eIt = helper.GetAncestors( eos->_shape, *_mesh, TopAbs_EDGE ); + while ( const TopoDS_Shape* e = eIt->next() ) + if ( _EdgesOnShape* eoe = data.GetShapeEdges( *e )) + if ( eoe->_edgeSmoother && eoe->_edgeSmoother->isAnalytic() ) + { + TopoDS_Face F; Handle(ShapeAnalysis_Surface) surface; + if ( eoe->SWOLType() == TopAbs_FACE ) { + F = TopoDS::Face( eoe->_sWOL ); + surface = helper.GetSurface( F ); + } + eoe->_edgeSmoother->Perform( data, surface, F, helper ); + } + + } + } // loop on badSmooEdges + + + // check result of invalidation + + int nbBad = 0; + for ( size_t iEOS = 0; iEOS < eosC1.size(); ++iEOS ) + { + for ( size_t i = 0; i < eosC1[ iEOS ]->_edges.size(); ++i ) + { + if ( !eosC1[ iEOS ]->_sWOL.IsNull() ) continue; + _LayerEdge* edge = eosC1[ iEOS ]->_edges[i]; + SMESH_TNodeXYZ tgtXYZ = edge->_nodes.back(); + const gp_XYZ& prevXYZ = edge->PrevCheckPos(); + for ( size_t j = 0; j < edge->_simplices.size(); ++j ) + if ( !edge->_simplices[j].IsForward( &prevXYZ, &tgtXYZ, vol )) + { + ++nbBad; + debugMsg("Bad simplex remains ( " << edge->_nodes[0]->GetID() + << " "<< tgtXYZ._node->GetID() + << " "<< edge->_simplices[j]._nPrev->GetID() + << " "<< edge->_simplices[j]._nNext->GetID() << " )" ); + } + } + } + dumpFunctionEnd(); + + return nbBad; +} + +//================================================================================ +/*! + * \brief Create an offset surface + */ +//================================================================================ + +void _ViscousBuilder::makeOffsetSurface( _EdgesOnShape& eos, SMESH_MesherHelper& helper ) +{ + if ( eos._offsetSurf.IsNull() || + eos._edgeForOffset == 0 || + eos._edgeForOffset->Is( _LayerEdge::BLOCKED )) + return; + + Handle(ShapeAnalysis_Surface) baseSurface = helper.GetSurface( TopoDS::Face( eos._shape )); + + // find offset + gp_Pnt tgtP = SMESH_TNodeXYZ( eos._edgeForOffset->_nodes.back() ); + gp_Pnt2d uv = baseSurface->ValueOfUV( tgtP, Precision::Confusion() ); + double offset = baseSurface->Gap(); + + eos._offsetSurf.Nullify(); + + try + { + BRepOffsetAPI_MakeOffsetShape offsetMaker( eos._shape, -offset, Precision::Confusion() ); + if ( !offsetMaker.IsDone() ) return; + + TopExp_Explorer fExp( offsetMaker.Shape(), TopAbs_FACE ); + if ( !fExp.More() ) return; + + TopoDS_Face F = TopoDS::Face( fExp.Current() ); + Handle(Geom_Surface) surf = BRep_Tool::Surface( F ); + if ( surf.IsNull() ) return; + + eos._offsetSurf = new ShapeAnalysis_Surface( surf ); + } + catch ( Standard_Failure ) + { + } +} + +//================================================================================ +/*! + * \brief Put nodes of a curved FACE to its offset surface + */ +//================================================================================ + +void _ViscousBuilder::putOnOffsetSurface( _EdgesOnShape& eos, + int infStep, + int smooStep, + bool moveAll ) +{ + if ( eos._offsetSurf.IsNull() || + eos.ShapeType() != TopAbs_FACE || + eos._edgeForOffset == 0 || + eos._edgeForOffset->Is( _LayerEdge::BLOCKED )) + return; + + double preci = BRep_Tool::Tolerance( TopoDS::Face( eos._shape )), vol; + for ( size_t i = 0; i < eos._edges.size(); ++i ) + { + _LayerEdge* edge = eos._edges[i]; + edge->Unset( _LayerEdge::MARKED ); + if ( edge->Is( _LayerEdge::BLOCKED ) || !edge->_curvature ) + continue; + if ( !moveAll && !edge->Is( _LayerEdge::MOVED )) + continue; + + int nbBlockedAround = 0; + for ( size_t iN = 0; iN < edge->_neibors.size(); ++iN ) + nbBlockedAround += edge->_neibors[iN]->Is( _LayerEdge::BLOCKED ); + if ( nbBlockedAround > 1 ) + continue; + + gp_Pnt tgtP = SMESH_TNodeXYZ( edge->_nodes.back() ); + gp_Pnt2d uv = eos._offsetSurf->NextValueOfUV( edge->_curvature->_uv, tgtP, preci ); + if ( eos._offsetSurf->Gap() > edge->_len ) continue; // NextValueOfUV() bug + edge->_curvature->_uv = uv; + if ( eos._offsetSurf->Gap() < 10 * preci ) continue; // same pos + + gp_XYZ newP = eos._offsetSurf->Value( uv ).XYZ(); + gp_XYZ prevP = edge->PrevCheckPos(); + bool ok = true; + if ( !moveAll ) + for ( size_t iS = 0; iS < edge->_simplices.size() && ok; ++iS ) + { + ok = edge->_simplices[iS].IsForward( &prevP, &newP, vol ); + } + if ( ok ) + { + SMDS_MeshNode* n = const_cast< SMDS_MeshNode* >( edge->_nodes.back() ); + n->setXYZ( newP.X(), newP.Y(), newP.Z()); + edge->_pos.back() = newP; + + edge->Set( _LayerEdge::MARKED ); + } + } + +#ifdef _DEBUG_ + // dumpMove() for debug + size_t i = 0; + for ( ; i < eos._edges.size(); ++i ) + if ( eos._edges[i]->Is( _LayerEdge::MARKED )) + break; + if ( i < eos._edges.size() ) + { + dumpFunction(SMESH_Comment("putOnOffsetSurface_F") << eos._shapeID + << "_InfStep" << infStep << "_" << smooStep ); + for ( ; i < eos._edges.size(); ++i ) + { + if ( eos._edges[i]->Is( _LayerEdge::MARKED )) + dumpMove( eos._edges[i]->_nodes.back() ); + } + dumpFunctionEnd(); + } +#endif +} + //================================================================================ /*! * \brief Return a curve of the EDGE to be used for smoothing and arrange @@ -4006,120 +5090,626 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data, */ //================================================================================ -Handle(Geom_Curve) _SolidData::CurveForSmooth( const TopoDS_Edge& E, - _EdgesOnShape& eos, - SMESH_MesherHelper& helper) +Handle(Geom_Curve) _Smoother1D::CurveForSmooth( const TopoDS_Edge& E, + _EdgesOnShape& eos, + SMESH_MesherHelper& helper) { - const TGeomID eIndex = eos._shapeID; + SMESHDS_SubMesh* smDS = eos._subMesh->GetSubMeshDS(); - map< TGeomID, Handle(Geom_Curve)>::iterator i2curve = _edge2curve.find( eIndex ); + TopLoc_Location loc; double f,l; - if ( i2curve == _edge2curve.end() ) + Handle(Geom_Line) line; + Handle(Geom_Circle) circle; + bool isLine, isCirc; + if ( eos._sWOL.IsNull() ) /////////////////////////////////////////// 3D case { - // sort _LayerEdge's by position on the EDGE - SortOnEdge( E, eos._edges, helper ); + // check if the EDGE is a line + Handle(Geom_Curve) curve = BRep_Tool::Curve( E, f, l); + if ( curve->IsKind( STANDARD_TYPE( Geom_TrimmedCurve ))) + curve = Handle(Geom_TrimmedCurve)::DownCast( curve )->BasisCurve(); - SMESHDS_SubMesh* smDS = eos._subMesh->GetSubMeshDS(); + line = Handle(Geom_Line)::DownCast( curve ); + circle = Handle(Geom_Circle)::DownCast( curve ); + isLine = (!line.IsNull()); + isCirc = (!circle.IsNull()); - TopLoc_Location loc; double f,l; - - Handle(Geom_Line) line; - Handle(Geom_Circle) circle; - bool isLine, isCirc; - if ( eos._sWOL.IsNull() ) /////////////////////////////////////////// 3D case + if ( !isLine && !isCirc ) // Check if the EDGE is close to a line { - // check if the EDGE is a line - Handle(Geom_Curve) curve = BRep_Tool::Curve( E, loc, f, l); - if ( curve->IsKind( STANDARD_TYPE( Geom_TrimmedCurve ))) - curve = Handle(Geom_TrimmedCurve)::DownCast( curve )->BasisCurve(); + isLine = SMESH_Algo::IsStraight( E ); - line = Handle(Geom_Line)::DownCast( curve ); - circle = Handle(Geom_Circle)::DownCast( curve ); - isLine = (!line.IsNull()); - isCirc = (!circle.IsNull()); - - if ( !isLine && !isCirc ) // Check if the EDGE is close to a line - { - // Bnd_B3d bndBox; - // SMDS_NodeIteratorPtr nIt = smDS->GetNodes(); - // while ( nIt->more() ) - // bndBox.Add( SMESH_TNodeXYZ( nIt->next() )); - // gp_XYZ size = bndBox.CornerMax() - bndBox.CornerMin(); - - // gp_Pnt p0, p1; - // if ( eos._edges.size() > 1 ) { - // p0 = SMESH_TNodeXYZ( eos._edges[0]->_nodes[0] ); - // p1 = SMESH_TNodeXYZ( eos._edges[1]->_nodes[0] ); - // } - // else { - // p0 = curve->Value( f ); - // p1 = curve->Value( l ); - // } - // const double lineTol = 1e-2 * p0.Distance( p1 ); - // for ( int i = 0; i < 3 && !isLine; ++i ) - // isLine = ( size.Coord( i+1 ) <= lineTol ); ////////// <--- WRONG - - isLine = SMESH_Algo::IsStraight( E ); - - if ( isLine ) - line = new Geom_Line( gp::OX() ); // only type does matter - } - if ( !isLine && !isCirc && eos._edges.size() > 2) // Check if the EDGE is close to a circle - { - // TODO - } - } - else //////////////////////////////////////////////////////////////////////// 2D case - { - const TopoDS_Face& F = TopoDS::Face( eos._sWOL ); - - // check if the EDGE is a line - Handle(Geom2d_Curve) curve = BRep_Tool::CurveOnSurface( E, F, f, l); - if ( curve->IsKind( STANDARD_TYPE( Geom2d_TrimmedCurve ))) - curve = Handle(Geom2d_TrimmedCurve)::DownCast( curve )->BasisCurve(); - - Handle(Geom2d_Line) line2d = Handle(Geom2d_Line)::DownCast( curve ); - Handle(Geom2d_Circle) circle2d = Handle(Geom2d_Circle)::DownCast( curve ); - isLine = (!line2d.IsNull()); - isCirc = (!circle2d.IsNull()); - - if ( !isLine && !isCirc) // Check if the EDGE is close to a line - { - Bnd_B2d bndBox; - SMDS_NodeIteratorPtr nIt = smDS->GetNodes(); - while ( nIt->more() ) - bndBox.Add( helper.GetNodeUV( F, nIt->next() )); - gp_XY size = bndBox.CornerMax() - bndBox.CornerMin(); - - const double lineTol = 1e-2 * sqrt( bndBox.SquareExtent() ); - for ( int i = 0; i < 2 && !isLine; ++i ) - isLine = ( size.Coord( i+1 ) <= lineTol ); - } - if ( !isLine && !isCirc && eos._edges.size() > 2) // Check if the EDGE is close to a circle - { - // TODO - } if ( isLine ) - { line = new Geom_Line( gp::OX() ); // only type does matter - } - else if ( isCirc ) + } + if ( !isLine && !isCirc && eos._edges.size() > 2) // Check if the EDGE is close to a circle + { + // TODO + } + } + else //////////////////////////////////////////////////////////////////////// 2D case + { + if ( !eos._isRegularSWOL ) // 23190 + return NULL; + + const TopoDS_Face& F = TopoDS::Face( eos._sWOL ); + + // check if the EDGE is a line + Handle(Geom2d_Curve) curve = BRep_Tool::CurveOnSurface( E, F, f, l ); + if ( curve->IsKind( STANDARD_TYPE( Geom2d_TrimmedCurve ))) + curve = Handle(Geom2d_TrimmedCurve)::DownCast( curve )->BasisCurve(); + + Handle(Geom2d_Line) line2d = Handle(Geom2d_Line)::DownCast( curve ); + Handle(Geom2d_Circle) circle2d = Handle(Geom2d_Circle)::DownCast( curve ); + isLine = (!line2d.IsNull()); + isCirc = (!circle2d.IsNull()); + + if ( !isLine && !isCirc ) // Check if the EDGE is close to a line + { + Bnd_B2d bndBox; + SMDS_NodeIteratorPtr nIt = smDS->GetNodes(); + while ( nIt->more() ) + bndBox.Add( helper.GetNodeUV( F, nIt->next() )); + gp_XY size = bndBox.CornerMax() - bndBox.CornerMin(); + + const double lineTol = 1e-2 * sqrt( bndBox.SquareExtent() ); + for ( int i = 0; i < 2 && !isLine; ++i ) + isLine = ( size.Coord( i+1 ) <= lineTol ); + } + if ( !isLine && !isCirc && eos._edges.size() > 2 ) // Check if the EDGE is close to a circle + { + // TODO + } + if ( isLine ) + { + line = new Geom_Line( gp::OX() ); // only type does matter + } + else if ( isCirc ) + { + gp_Pnt2d p = circle2d->Location(); + gp_Ax2 ax( gp_Pnt( p.X(), p.Y(), 0), gp::DX()); + circle = new Geom_Circle( ax, 1.); // only center position does matter + } + } + + if ( isLine ) + return line; + if ( isCirc ) + return circle; + + return Handle(Geom_Curve)(); +} + +//================================================================================ +/*! + * \brief smooth _LayerEdge's on a staight EDGE or circular EDGE + */ +//================================================================================ + +bool _Smoother1D::smoothAnalyticEdge( _SolidData& data, + Handle(ShapeAnalysis_Surface)& surface, + const TopoDS_Face& F, + SMESH_MesherHelper& helper) +{ + if ( !isAnalytic() ) return false; + + const size_t iFrom = 0, iTo = _eos._edges.size(); + + if ( _anaCurve->IsKind( STANDARD_TYPE( Geom_Line ))) + { + if ( F.IsNull() ) // 3D + { + SMESH_TNodeXYZ p0 ( _eos._edges[iFrom]->_2neibors->tgtNode(0) ); + SMESH_TNodeXYZ p1 ( _eos._edges[iTo-1]->_2neibors->tgtNode(1) ); + SMESH_TNodeXYZ pSrc0( _eos._edges[iFrom]->_2neibors->srcNode(0) ); + SMESH_TNodeXYZ pSrc1( _eos._edges[iTo-1]->_2neibors->srcNode(1) ); + gp_XYZ newPos; + for ( size_t i = iFrom; i < iTo; ++i ) { - gp_Pnt2d p = circle2d->Location(); - gp_Ax2 ax( gp_Pnt( p.X(), p.Y(), 0), gp::DX()); - circle = new Geom_Circle( ax, 1.); // only center position does matter + _LayerEdge* edge = _eos._edges[i]; + SMDS_MeshNode* tgtNode = const_cast( edge->_nodes.back() ); + newPos = p0 * ( 1. - _leParams[i] ) + p1 * _leParams[i]; + + if ( _eos._edges[i]->Is( _LayerEdge::NORMAL_UPDATED )) + { + gp_XYZ curPos = SMESH_TNodeXYZ ( tgtNode ); + gp_XYZ lineDir = pSrc1 - pSrc0; + double shift = ( lineDir * ( newPos - pSrc0 ) - + lineDir * ( curPos - pSrc0 )); + newPos = curPos + lineDir * shift / lineDir.SquareModulus(); + } + if ( _eos._edges[i]->Is( _LayerEdge::BLOCKED )) + { + SMESH_TNodeXYZ pSrc( edge->_nodes[0] ); + double curThick = pSrc.SquareDistance( tgtNode ); + double newThink = ( pSrc - newPos ).SquareModulus(); + if ( newThink > curThick ) + continue; + } + edge->_pos.back() = newPos; + tgtNode->setXYZ( newPos.X(), newPos.Y(), newPos.Z() ); + dumpMove( tgtNode ); } } + else // 2D + { + _LayerEdge* e0 = getLEdgeOnV( 0 ); + _LayerEdge* e1 = getLEdgeOnV( 1 ); + gp_XY uv0 = e0->LastUV( F, *data.GetShapeEdges( e0 )); + gp_XY uv1 = e1->LastUV( F, *data.GetShapeEdges( e1 )); + if ( e0->_nodes.back() == e1->_nodes.back() ) // closed edge + { + int iPeriodic = helper.GetPeriodicIndex(); + if ( iPeriodic == 1 || iPeriodic == 2 ) + { + uv1.SetCoord( iPeriodic, helper.GetOtherParam( uv1.Coord( iPeriodic ))); + if ( uv0.Coord( iPeriodic ) > uv1.Coord( iPeriodic )) + std::swap( uv0, uv1 ); + } + } + const gp_XY rangeUV = uv1 - uv0; + for ( size_t i = iFrom; i < iTo; ++i ) + { + if ( _eos._edges[i]->Is( _LayerEdge::BLOCKED )) continue; + gp_XY newUV = uv0 + _leParams[i] * rangeUV; + _eos._edges[i]->_pos.back().SetCoord( newUV.X(), newUV.Y(), 0 ); - Handle(Geom_Curve)& res = _edge2curve[ eIndex ]; - if ( isLine ) - res = line; - else if ( isCirc ) - res = circle; + gp_Pnt newPos = surface->Value( newUV.X(), newUV.Y() ); + SMDS_MeshNode* tgtNode = const_cast( _eos._edges[i]->_nodes.back() ); + tgtNode->setXYZ( newPos.X(), newPos.Y(), newPos.Z() ); + dumpMove( tgtNode ); - return res; + SMDS_FacePosition* pos = static_cast( tgtNode->GetPosition() ); + pos->SetUParameter( newUV.X() ); + pos->SetVParameter( newUV.Y() ); + } + } + return true; } - return i2curve->second; + + if ( _anaCurve->IsKind( STANDARD_TYPE( Geom_Circle ))) + { + Handle(Geom_Circle) circle = Handle(Geom_Circle)::DownCast( _anaCurve ); + gp_Pnt center3D = circle->Location(); + + if ( F.IsNull() ) // 3D + { + if ( getLEdgeOnV( 0 )->_nodes.back() == getLEdgeOnV( 1 )->_nodes.back() ) + return true; // closed EDGE - nothing to do + + // circle is a real curve of EDGE + gp_Circ circ = circle->Circ(); + + // new center is shifted along its axis + const gp_Dir& axis = circ.Axis().Direction(); + _LayerEdge* e0 = getLEdgeOnV(0); + _LayerEdge* e1 = getLEdgeOnV(1); + SMESH_TNodeXYZ p0 = e0->_nodes.back(); + SMESH_TNodeXYZ p1 = e1->_nodes.back(); + double shift1 = axis.XYZ() * ( p0 - center3D.XYZ() ); + double shift2 = axis.XYZ() * ( p1 - center3D.XYZ() ); + gp_Pnt newCenter = center3D.XYZ() + axis.XYZ() * 0.5 * ( shift1 + shift2 ); + + double newRadius = 0.5 * ( newCenter.Distance( p0 ) + newCenter.Distance( p1 )); + + gp_Ax2 newAxis( newCenter, axis, gp_Vec( newCenter, p0 )); + gp_Circ newCirc( newAxis, newRadius ); + gp_Vec vecC1 ( newCenter, p1 ); + + double uLast = newAxis.XDirection().AngleWithRef( vecC1, newAxis.Direction() ); // -PI - +PI + if ( uLast < 0 ) + uLast += 2 * M_PI; + + for ( size_t i = iFrom; i < iTo; ++i ) + { + if ( _eos._edges[i]->Is( _LayerEdge::BLOCKED )) continue; + double u = uLast * _leParams[i]; + gp_Pnt p = ElCLib::Value( u, newCirc ); + _eos._edges[i]->_pos.back() = p.XYZ(); + + SMDS_MeshNode* tgtNode = const_cast( _eos._edges[i]->_nodes.back() ); + tgtNode->setXYZ( p.X(), p.Y(), p.Z() ); + dumpMove( tgtNode ); + } + return true; + } + else // 2D + { + const gp_XY center( center3D.X(), center3D.Y() ); + + _LayerEdge* e0 = getLEdgeOnV(0); + _LayerEdge* eM = _eos._edges[ 0 ]; + _LayerEdge* e1 = getLEdgeOnV(1); + gp_XY uv0 = e0->LastUV( F, *data.GetShapeEdges( e0 ) ); + gp_XY uvM = eM->LastUV( F, *data.GetShapeEdges( eM ) ); + gp_XY uv1 = e1->LastUV( F, *data.GetShapeEdges( e1 ) ); + gp_Vec2d vec0( center, uv0 ); + gp_Vec2d vecM( center, uvM ); + gp_Vec2d vec1( center, uv1 ); + double uLast = vec0.Angle( vec1 ); // -PI - +PI + double uMidl = vec0.Angle( vecM ); + if ( uLast * uMidl <= 0. ) + uLast += ( uMidl > 0 ? +2. : -2. ) * M_PI; + const double radius = 0.5 * ( vec0.Magnitude() + vec1.Magnitude() ); + + gp_Ax2d axis( center, vec0 ); + gp_Circ2d circ( axis, radius ); + for ( size_t i = iFrom; i < iTo; ++i ) + { + if ( _eos._edges[i]->Is( _LayerEdge::BLOCKED )) continue; + double newU = uLast * _leParams[i]; + gp_Pnt2d newUV = ElCLib::Value( newU, circ ); + _eos._edges[i]->_pos.back().SetCoord( newUV.X(), newUV.Y(), 0 ); + + gp_Pnt newPos = surface->Value( newUV.X(), newUV.Y() ); + SMDS_MeshNode* tgtNode = const_cast( _eos._edges[i]->_nodes.back() ); + tgtNode->setXYZ( newPos.X(), newPos.Y(), newPos.Z() ); + dumpMove( tgtNode ); + + SMDS_FacePosition* pos = static_cast( tgtNode->GetPosition() ); + pos->SetUParameter( newUV.X() ); + pos->SetVParameter( newUV.Y() ); + } + } + return true; + } + + return false; +} + +//================================================================================ +/*! + * \brief smooth _LayerEdge's on a an EDGE + */ +//================================================================================ + +bool _Smoother1D::smoothComplexEdge( _SolidData& data, + Handle(ShapeAnalysis_Surface)& surface, + const TopoDS_Face& F, + SMESH_MesherHelper& helper) +{ + if ( _offPoints.empty() ) + return false; + + // move _offPoints to positions along normals of _LayerEdge's + + _LayerEdge* e[2] = { getLEdgeOnV(0), getLEdgeOnV(1) }; + if ( e[0]->Is( _LayerEdge::NORMAL_UPDATED )) setNormalOnV( 0, helper ); + if ( e[1]->Is( _LayerEdge::NORMAL_UPDATED )) setNormalOnV( 1, helper ); + _leOnV[0]._len = e[0]->_len; + _leOnV[1]._len = e[1]->_len; + for ( size_t i = 0; i < _offPoints.size(); i++ ) + { + _LayerEdge* e0 = _offPoints[i]._2edges._edges[0]; + _LayerEdge* e1 = _offPoints[i]._2edges._edges[1]; + const double w0 = _offPoints[i]._2edges._wgt[0]; + const double w1 = _offPoints[i]._2edges._wgt[1]; + gp_XYZ avgNorm = ( e0->_normal * w0 + e1->_normal * w1 ).Normalized(); + double avgLen = ( e0->_len * w0 + e1->_len * w1 ); + double avgFact = ( e0->_lenFactor * w0 + e1->_lenFactor * w1 ); + + _offPoints[i]._xyz += avgNorm * ( avgLen - _offPoints[i]._len ) * avgFact; + _offPoints[i]._len = avgLen; + } + + double fTol = 0; + if ( !surface.IsNull() ) // project _offPoints to the FACE + { + fTol = 100 * BRep_Tool::Tolerance( F ); + //const double segLen = _offPoints[0].Distance( _offPoints[1] ); + + gp_Pnt2d uv = surface->ValueOfUV( _offPoints[0]._xyz, fTol ); + //if ( surface->Gap() < 0.5 * segLen ) + _offPoints[0]._xyz = surface->Value( uv ).XYZ(); + + for ( size_t i = 1; i < _offPoints.size(); ++i ) + { + uv = surface->NextValueOfUV( uv, _offPoints[i]._xyz, fTol ); + //if ( surface->Gap() < 0.5 * segLen ) + _offPoints[i]._xyz = surface->Value( uv ).XYZ(); + } + } + + // project tgt nodes of extreme _LayerEdge's to the offset segments + + gp_Pnt pExtreme[2], pProj[2]; + for ( int is2nd = 0; is2nd < 2; ++is2nd ) + { + pExtreme[ is2nd ] = SMESH_TNodeXYZ( e[is2nd]->_nodes.back() ); + int i = _iSeg[ is2nd ]; + int di = is2nd ? -1 : +1; + bool projected = false; + double uOnSeg, uOnSegDiff, uOnSegBestDiff = Precision::Infinite(), uOnSegPrevDiff = 0; + int nbWorse = 0; + do { + gp_Vec v0p( _offPoints[i]._xyz, pExtreme[ is2nd ] ); + gp_Vec v01( _offPoints[i]._xyz, _offPoints[i+1]._xyz ); + uOnSeg = ( v0p * v01 ) / v01.SquareMagnitude(); + uOnSegDiff = Abs( uOnSeg - 0.5 ); + projected = ( uOnSegDiff <= 0.5 ); + if ( uOnSegDiff < uOnSegBestDiff ) + { + _iSeg[ is2nd ] = i; + pProj[ is2nd ] = _offPoints[i]._xyz + ( v01 * uOnSeg ).XYZ(); + uOnSegBestDiff = uOnSegDiff; + } + else if ( uOnSegDiff > uOnSegPrevDiff ) + { + if ( ++nbWorse > 3 ) // avoid projection to the middle of a closed EDGE + break; + } + uOnSegPrevDiff = uOnSegDiff; + i += di; + } + while ( !projected && + i >= 0 && i+1 < (int)_offPoints.size() ); + + if ( !projected ) + { + if (( is2nd && _iSeg[1] != _offPoints.size()-2 ) || ( !is2nd && _iSeg[0] != 0 )) + { + _iSeg[0] = 0; + _iSeg[1] = _offPoints.size()-2; + debugMsg( "smoothComplexEdge() failed to project nodes of extreme _LayerEdge's" ); + return false; + } + } + } + if ( _iSeg[0] > _iSeg[1] ) + { + debugMsg( "smoothComplexEdge() incorrectly projected nodes of extreme _LayerEdge's" ); + return false; + } + + // compute normalized length of the offset segments located between the projections + + size_t iSeg = 0, nbSeg = _iSeg[1] - _iSeg[0] + 1; + vector< double > len( nbSeg + 1 ); + len[ iSeg++ ] = 0; + len[ iSeg++ ] = pProj[ 0 ].Distance( _offPoints[ _iSeg[0]+1 ]._xyz ); + for ( size_t i = _iSeg[0]+1; i <= _iSeg[1]; ++i, ++iSeg ) + { + len[ iSeg ] = len[ iSeg-1 ] + _offPoints[i].Distance( _offPoints[i+1] ); + } + len[ nbSeg ] -= pProj[ 1 ].Distance( _offPoints[ _iSeg[1]+1 ]._xyz ); + + double d0 = pProj[0].Distance( pExtreme[0]); + double d1 = pProj[1].Distance( pExtreme[1]); + double fullLen = len.back() - d0 - d1; + for ( iSeg = 0; iSeg < len.size(); ++iSeg ) + len[iSeg] = ( len[iSeg] - d0 ) / fullLen; + + // temporary replace extreme _offPoints by pExtreme + gp_XYZ op[2] = { _offPoints[ _iSeg[0] ]._xyz, + _offPoints[ _iSeg[1]+1 ]._xyz }; + _offPoints[ _iSeg[0] ]._xyz = pExtreme[0].XYZ(); + _offPoints[ _iSeg[1]+ 1]._xyz = pExtreme[1].XYZ(); + + // distribute tgt nodes of _LayerEdge's between the projections + + iSeg = 0; + for ( size_t i = 0; i < _eos._edges.size(); ++i ) + { + if ( _eos._edges[i]->Is( _LayerEdge::BLOCKED )) continue; + while ( iSeg+2 < len.size() && _leParams[i] > len[ iSeg+1 ] ) + iSeg++; + double r = ( _leParams[i] - len[ iSeg ]) / ( len[ iSeg+1 ] - len[ iSeg ]); + gp_XYZ p = ( _offPoints[ iSeg + _iSeg[0] ]._xyz * ( 1 - r ) + + _offPoints[ iSeg + _iSeg[0] + 1 ]._xyz * r ); + + if ( surface.IsNull() ) + { + _eos._edges[i]->_pos.back() = p; + } + else // project a new node position to a FACE + { + gp_Pnt2d uv ( _eos._edges[i]->_pos.back().X(), _eos._edges[i]->_pos.back().Y() ); + gp_Pnt2d uv2( surface->NextValueOfUV( uv, p, fTol )); + + p = surface->Value( uv2 ).XYZ(); + _eos._edges[i]->_pos.back().SetCoord( uv2.X(), uv2.Y(), 0 ); + } + SMDS_MeshNode* tgtNode = const_cast( _eos._edges[i]->_nodes.back() ); + tgtNode->setXYZ( p.X(), p.Y(), p.Z() ); + dumpMove( tgtNode ); + } + + _offPoints[ _iSeg[0] ]._xyz = op[0]; + _offPoints[ _iSeg[1]+1 ]._xyz = op[1]; + + return true; +} + +//================================================================================ +/*! + * \brief Prepare for smoothing + */ +//================================================================================ + +void _Smoother1D::prepare(_SolidData& data) +{ + const TopoDS_Edge& E = TopoDS::Edge( _eos._shape ); + _curveLen = SMESH_Algo::EdgeLength( E ); + + // sort _LayerEdge's by position on the EDGE + data.SortOnEdge( E, _eos._edges ); + + SMESH_MesherHelper& helper = data.GetHelper(); + + // compute normalized param of _eos._edges on EDGE + _leParams.resize( _eos._edges.size() + 1 ); + { + double curLen, prevLen = _leParams[0] = 1.0; + gp_Pnt pPrev = SMESH_TNodeXYZ( getLEdgeOnV( 0 )->_nodes[0] ); + _leParams[0] = 0; + for ( size_t i = 0; i < _eos._edges.size(); ++i ) + { + gp_Pnt p = SMESH_TNodeXYZ( _eos._edges[i]->_nodes[0] ); + //curLen = prevLen * _eos._edges[i]->_2neibors->_wgt[1] / _eos._edges[i]->_2neibors->_wgt[0]; + curLen = p.Distance( pPrev ); + _leParams[i+1] = _leParams[i] + curLen; + prevLen = curLen; + pPrev = p; + } + double fullLen = _leParams.back() + pPrev.Distance( SMESH_TNodeXYZ( getLEdgeOnV(1)->_nodes[0])); + for ( size_t i = 0; i < _leParams.size()-1; ++i ) + _leParams[i] = _leParams[i+1] / fullLen; + } + + // find intersection of neighbor _LayerEdge's to limit _maxLen + // according to EDGE curvature (IPAL52648) + _LayerEdge* e0 = _eos._edges[0]; + for ( size_t i = 1; i < _eos._edges.size(); ++i ) + { + _LayerEdge* ei = _eos._edges[i]; + gp_XYZ plnNorm = e0->_normal ^ ei->_normal; + gp_XYZ perp0 = e0->_normal ^ plnNorm; + double dot0i = perp0 * ei->_normal; + if ( Abs( dot0i ) > std::numeric_limits::min() ) + { + SMESH_TNodeXYZ srci( ei->_nodes[0] ), src0( e0->_nodes[0] ); + double ui = ( perp0 * ( src0 - srci )) / dot0i; + if ( ui > 0 ) + { + ei->_maxLen = Min( ei->_maxLen, 0.75 * ui / ei->_lenFactor ); + if ( ei->_maxLen < ei->_len ) + { + ei->InvalidateStep( ei->NbSteps(), _eos, /*restoreLength=*/true ); + ei->SetNewLength( ei->_maxLen, _eos, helper ); + ei->Block( data ); + } + gp_Pnt pi = srci + ei->_normal * ui; + double u0 = pi.Distance( src0 ); + e0->_maxLen = Min( e0->_maxLen, 0.75 * u0 / e0->_lenFactor ); + if ( e0->_maxLen < e0->_len ) + { + e0->InvalidateStep( e0->NbSteps(), _eos, /*restoreLength=*/true ); + e0->SetNewLength( e0->_maxLen, _eos, helper ); + e0->Block( data ); + } + } + } + e0 = ei; + } + + if ( isAnalytic() ) + return; + + // divide E to have offset segments with low deflection + BRepAdaptor_Curve c3dAdaptor( E ); + const double curDeflect = 0.1; //0.3; // 0.01; // Curvature deflection + const double angDeflect = 0.1; //0.2; // 0.09; // Angular deflection + GCPnts_TangentialDeflection discret(c3dAdaptor, angDeflect, curDeflect); + if ( discret.NbPoints() <= 2 ) + { + _anaCurve = new Geom_Line( gp::OX() ); // only type does matter + return; + } + + const double edgeLen = SMESH_Algo::EdgeLength( E ); + const double u0 = c3dAdaptor.FirstParameter(); + _offPoints.resize( discret.NbPoints() ); + for ( size_t i = 0; i < _offPoints.size(); i++ ) + { + _offPoints[i]._xyz = discret.Value( i+1 ).XYZ(); + // use OffPnt::_len to TEMPORARY store normalized param of an offset point + double u = discret.Parameter( i+1 ); + _offPoints[i]._len = GCPnts_AbscissaPoint::Length( c3dAdaptor, u0, u ) / edgeLen; + } + + _LayerEdge* leOnV[2] = { getLEdgeOnV(0), getLEdgeOnV(1) }; + + // set _2edges + _offPoints [0]._2edges.set( &_leOnV[0], &_leOnV[0], 0.5, 0.5 ); + _offPoints.back()._2edges.set( &_leOnV[1], &_leOnV[1], 0.5, 0.5 ); + _2NearEdges tmp2edges; + tmp2edges._edges[1] = _eos._edges[0]; + _leOnV[0]._2neibors = & tmp2edges; + _leOnV[0]._nodes = leOnV[0]->_nodes; + _leOnV[1]._nodes = leOnV[1]->_nodes; + _LayerEdge* eNext, *ePrev = & _leOnV[0]; + for ( size_t iLE = 0, i = 1; i < _offPoints.size()-1; i++ ) + { + // find _LayerEdge's located before and after an offset point + // (_eos._edges[ iLE ] is next after ePrev) + while ( iLE < _eos._edges.size() && _offPoints[i]._len > _leParams[ iLE ] ) + ePrev = _eos._edges[ iLE++ ]; + eNext = ePrev->_2neibors->_edges[1]; + + gp_Pnt p0 = SMESH_TNodeXYZ( ePrev->_nodes[0] ); + gp_Pnt p1 = SMESH_TNodeXYZ( eNext->_nodes[0] ); + double r = p0.Distance( _offPoints[i]._xyz ) / p0.Distance( p1 ); + _offPoints[i]._2edges.set( ePrev, eNext, 1-r, r ); + } + + int iLBO = _offPoints.size() - 2; // last but one + _offPoints[iLBO]._2edges._edges[1] = & _leOnV[1]; + + // { + // TopoDS_Face face[2]; // FACEs sharing the EDGE + // PShapeIteratorPtr fIt = helper.GetAncestors( _eos._shape, *helper.GetMesh(), TopAbs_FACE ); + // while ( const TopoDS_Shape* F = fIt->next() ) + // { + // TGeomID fID = helper.GetMeshDS()->ShapeToIndex( *F ); + // if ( ! data._ignoreFaceIds.count( fID )) + // face[ !face[0].IsNull() ] = *F; + // } + // if ( face[0].IsNull() ) return; + // if ( face[1].IsNull() ) face[1] = face[0]; + // } + + + // set _normal of _leOnV[0] and _leOnV[1] to be normal to the EDGE + + setNormalOnV( 0, data.GetHelper() ); + setNormalOnV( 1, data.GetHelper() ); + _leOnV[ 0 ]._len = 0; + _leOnV[ 1 ]._len = 0; + _leOnV[ 0 ]._lenFactor = _offPoints[1 ]._2edges._edges[1]->_lenFactor; + _leOnV[ 1 ]._lenFactor = _offPoints[iLBO]._2edges._edges[0]->_lenFactor; + + _iSeg[0] = 0; + _iSeg[1] = _offPoints.size()-2; + + // initialize OffPnt::_len + for ( size_t i = 0; i < _offPoints.size(); ++i ) + _offPoints[i]._len = 0; + + if ( _eos._edges[0]->NbSteps() > 1 ) // already inflated several times, init _xyz + { + _leOnV[0]._len = leOnV[0]->_len; + _leOnV[1]._len = leOnV[1]->_len; + for ( size_t i = 0; i < _offPoints.size(); i++ ) + { + _LayerEdge* e0 = _offPoints[i]._2edges._edges[0]; + _LayerEdge* e1 = _offPoints[i]._2edges._edges[1]; + const double w0 = _offPoints[i]._2edges._wgt[0]; + const double w1 = _offPoints[i]._2edges._wgt[1]; + double avgLen = ( e0->_len * w0 + e1->_len * w1 ); + gp_XYZ avgXYZ = ( SMESH_TNodeXYZ( e0->_nodes.back() ) * w0 + + SMESH_TNodeXYZ( e1->_nodes.back() ) * w1 ); + _offPoints[i]._xyz = avgXYZ; + _offPoints[i]._len = avgLen; + } + } +} + +//================================================================================ +/*! + * \brief set _normal of _leOnV[is2nd] to be normal to the EDGE + */ +//================================================================================ + +void _Smoother1D::setNormalOnV( const bool is2nd, + SMESH_MesherHelper& helper) +{ + _LayerEdge* leOnV = getLEdgeOnV( is2nd ); + const TopoDS_Edge& E = TopoDS::Edge( _eos._shape ); + TopoDS_Shape V = helper.GetSubShapeByNode( leOnV->_nodes[0], helper.GetMeshDS() ); + gp_XYZ eDir = getEdgeDir( E, TopoDS::Vertex( V )); + gp_XYZ cross = leOnV->_normal ^ eDir; + gp_XYZ norm = eDir ^ cross; + double size = norm.Modulus(); + + _leOnV[ is2nd ]._normal = norm / size; } //================================================================================ @@ -4129,16 +5719,16 @@ Handle(Geom_Curve) _SolidData::CurveForSmooth( const TopoDS_Edge& E, //================================================================================ void _SolidData::SortOnEdge( const TopoDS_Edge& E, - vector< _LayerEdge* >& edges, - SMESH_MesherHelper& helper) + vector< _LayerEdge* >& edges) { map< double, _LayerEdge* > u2edge; for ( size_t i = 0; i < edges.size(); ++i ) - u2edge.insert( make_pair( helper.GetNodeU( E, edges[i]->_nodes[0] ), edges[i] )); + u2edge.insert( u2edge.end(), + make_pair( _helper->GetNodeU( E, edges[i]->_nodes[0] ), edges[i] )); ASSERT( u2edge.size() == edges.size() ); map< double, _LayerEdge* >::iterator u2e = u2edge.begin(); - for ( int i = 0; i < edges.size(); ++i, ++u2e ) + for ( size_t i = 0; i < edges.size(); ++i, ++u2e ) edges[i] = u2e->second; Sort2NeiborsOnEdge( edges ); @@ -4152,6 +5742,8 @@ void _SolidData::SortOnEdge( const TopoDS_Edge& E, void _SolidData::Sort2NeiborsOnEdge( vector< _LayerEdge* >& edges ) { + if ( edges.size() < 2 || !edges[0]->_2neibors ) return; + for ( size_t i = 0; i < edges.size()-1; ++i ) if ( edges[i]->_2neibors->tgtNode(1) != edges[i+1]->_nodes.back() ) edges[i]->_2neibors->reverse(); @@ -4170,13 +5762,13 @@ void _SolidData::Sort2NeiborsOnEdge( vector< _LayerEdge* >& edges ) _EdgesOnShape* _SolidData::GetShapeEdges(const TGeomID shapeID ) { - if ( shapeID < _edgesOnShape.size() && + if ( shapeID < (int)_edgesOnShape.size() && _edgesOnShape[ shapeID ]._shapeID == shapeID ) - return & _edgesOnShape[ shapeID ]; + return _edgesOnShape[ shapeID ]._subMesh ? & _edgesOnShape[ shapeID ] : 0; for ( size_t i = 0; i < _edgesOnShape.size(); ++i ) if ( _edgesOnShape[i]._shapeID == shapeID ) - return & _edgesOnShape[i]; + return _edgesOnShape[i]._subMesh ? & _edgesOnShape[i] : 0; return 0; } @@ -4199,28 +5791,94 @@ _EdgesOnShape* _SolidData::GetShapeEdges(const TopoDS_Shape& shape ) */ //================================================================================ -void _SolidData::PrepareEdgesToSmoothOnFace( _EdgesOnShape* eof, bool substituteSrcNodes ) +void _SolidData::PrepareEdgesToSmoothOnFace( _EdgesOnShape* eos, bool substituteSrcNodes ) { - set< TGeomID > vertices; SMESH_MesherHelper helper( *_proxyMesh->GetMesh() ); - if ( isConcave( TopoDS::Face( eof->_shape ), helper, &vertices )) - _concaveFaces.insert( eof->_shapeID ); - for ( size_t i = 0; i < eof->_edges.size(); ++i ) - eof->_edges[i]->_smooFunction = 0; - - for ( size_t i = 0; i < eof->_edges.size(); ++i ) + set< TGeomID > vertices; + TopoDS_Face F; + if ( eos->ShapeType() == TopAbs_FACE ) { - _LayerEdge* edge = eof->_edges[i]; - _Simplex::GetSimplices - ( edge->_nodes[0], edge->_simplices, _ignoreFaceIds, this, /*sort=*/true ); + // check FACE concavity and get concave VERTEXes + F = TopoDS::Face( eos->_shape ); + if ( isConcave( F, helper, &vertices )) + _concaveFaces.insert( eos->_shapeID ); + // set eos._eosConcaVer + eos->_eosConcaVer.clear(); + eos->_eosConcaVer.reserve( vertices.size() ); + for ( set< TGeomID >::iterator v = vertices.begin(); v != vertices.end(); ++v ) + { + _EdgesOnShape* eov = GetShapeEdges( *v ); + if ( eov && eov->_edges.size() == 1 ) + { + eos->_eosConcaVer.push_back( eov ); + for ( size_t i = 0; i < eov->_edges[0]->_neibors.size(); ++i ) + eov->_edges[0]->_neibors[i]->Set( _LayerEdge::DIFFICULT ); + } + } + + // SetSmooLen() to _LayerEdge's on FACE + for ( size_t i = 0; i < eos->_edges.size(); ++i ) + { + eos->_edges[i]->SetSmooLen( Precision::Infinite() ); + } + SMESH_subMeshIteratorPtr smIt = eos->_subMesh->getDependsOnIterator(/*includeSelf=*/false); + while ( smIt->more() ) // loop on sub-shapes of the FACE + { + _EdgesOnShape* eoe = GetShapeEdges( smIt->next()->GetId() ); + if ( !eoe ) continue; + + vector<_LayerEdge*>& eE = eoe->_edges; + for ( size_t iE = 0; iE < eE.size(); ++iE ) // loop on _LayerEdge's on EDGE or VERTEX + { + if ( eE[iE]->_cosin <= theMinSmoothCosin ) + continue; + + SMDS_ElemIteratorPtr segIt = eE[iE]->_nodes[0]->GetInverseElementIterator(SMDSAbs_Edge); + while ( segIt->more() ) + { + const SMDS_MeshElement* seg = segIt->next(); + if ( !eos->_subMesh->DependsOn( seg->getshapeId() )) + continue; + if ( seg->GetNode(0) != eE[iE]->_nodes[0] ) + continue; // not to check a seg twice + for ( size_t iN = 0; iN < eE[iE]->_neibors.size(); ++iN ) + { + _LayerEdge* eN = eE[iE]->_neibors[iN]; + if ( eN->_nodes[0]->getshapeId() != eos->_shapeID ) + continue; + double dist = SMESH_MeshAlgos::GetDistance( seg, SMESH_TNodeXYZ( eN->_nodes[0] )); + double smooLen = getSmoothingThickness( eE[iE]->_cosin, dist ); + eN->SetSmooLen( Min( smooLen, eN->GetSmooLen() )); + eN->Set( _LayerEdge::NEAR_BOUNDARY ); + } + } + } + } + } // if ( eos->ShapeType() == TopAbs_FACE ) + + for ( size_t i = 0; i < eos->_edges.size(); ++i ) + { + eos->_edges[i]->_smooFunction = 0; + eos->_edges[i]->Set( _LayerEdge::TO_SMOOTH ); + } + bool isCurved = false; + for ( size_t i = 0; i < eos->_edges.size(); ++i ) + { + _LayerEdge* edge = eos->_edges[i]; + + // get simplices sorted + _Simplex::SortSimplices( edge->_simplices ); + + // smoothing function edge->ChooseSmooFunction( vertices, _n2eMap ); + // set _curvature double avgNormProj = 0, avgLen = 0; - for ( size_t i = 0; i < edge->_simplices.size(); ++i ) + for ( size_t iS = 0; iS < edge->_simplices.size(); ++iS ) { - _Simplex& s = edge->_simplices[i]; + _Simplex& s = edge->_simplices[iS]; gp_XYZ vec = edge->_pos.back() - SMESH_TNodeXYZ( s._nPrev ); avgNormProj += edge->_normal * vec; @@ -4233,7 +5891,39 @@ void _SolidData::PrepareEdgesToSmoothOnFace( _EdgesOnShape* eof, bool substitute } avgNormProj /= edge->_simplices.size(); avgLen /= edge->_simplices.size(); - edge->_curvature = _Curvature::New( avgNormProj, avgLen ); + if (( edge->_curvature = _Curvature::New( avgNormProj, avgLen ))) + { + isCurved = true; + SMDS_FacePosition* fPos = dynamic_cast( edge->_nodes[0]->GetPosition() ); + if ( !fPos ) + for ( size_t iS = 0; iS < edge->_simplices.size() && !fPos; ++iS ) + fPos = dynamic_cast( edge->_simplices[iS]._nPrev->GetPosition() ); + if ( fPos ) + edge->_curvature->_uv.SetCoord( fPos->GetUParameter(), fPos->GetVParameter() ); + } + } + + // prepare for putOnOffsetSurface() + if (( eos->ShapeType() == TopAbs_FACE ) && + ( isCurved || !eos->_eosConcaVer.empty() )) + { + eos->_offsetSurf = helper.GetSurface( TopoDS::Face( eos->_shape )); + eos->_edgeForOffset = 0; + + double maxCosin = -1; + for ( TopExp_Explorer eExp( eos->_shape, TopAbs_EDGE ); eExp.More(); eExp.Next() ) + { + _EdgesOnShape* eoe = GetShapeEdges( eExp.Current() ); + if ( !eoe || eoe->_edges.empty() ) continue; + + vector<_LayerEdge*>& eE = eoe->_edges; + _LayerEdge* e = eE[ eE.size() / 2 ]; + if ( e->_cosin > maxCosin ) + { + eos->_edgeForOffset = e; + maxCosin = e->_cosin; + } + } } } @@ -4243,10 +5933,11 @@ void _SolidData::PrepareEdgesToSmoothOnFace( _EdgesOnShape* eof, bool substitute */ //================================================================================ -void _SolidData::AddShapesToSmooth( const set< _EdgesOnShape* >& eosSet ) +void _SolidData::AddShapesToSmooth( const set< _EdgesOnShape* >& eosToSmooth, + const set< _EdgesOnShape* >* edgesNoAnaSmooth ) { - set< _EdgesOnShape * >::const_iterator eos = eosSet.begin(); - for ( ; eos != eosSet.end(); ++eos ) + set< _EdgesOnShape * >::const_iterator eos = eosToSmooth.begin(); + for ( ; eos != eosToSmooth.end(); ++eos ) { if ( !*eos || (*eos)->_toSmooth ) continue; @@ -4254,151 +5945,218 @@ void _SolidData::AddShapesToSmooth( const set< _EdgesOnShape* >& eosSet ) if ( (*eos)->ShapeType() == TopAbs_FACE ) { - PrepareEdgesToSmoothOnFace( *eos, /*substituteSrcNodes=*/true ); + PrepareEdgesToSmoothOnFace( *eos, /*substituteSrcNodes=*/false ); + (*eos)->_toSmooth = true; } } + + // avoid _Smoother1D::smoothAnalyticEdge() of edgesNoAnaSmooth + if ( edgesNoAnaSmooth ) + for ( eos = edgesNoAnaSmooth->begin(); eos != edgesNoAnaSmooth->end(); ++eos ) + { + if ( (*eos)->_edgeSmoother ) + (*eos)->_edgeSmoother->_anaCurve.Nullify(); + } } //================================================================================ /*! - * \brief smooth _LayerEdge's on a staight EDGE or circular EDGE + * \brief Fill data._collisionEdges */ //================================================================================ -bool _ViscousBuilder::smoothAnalyticEdge( _SolidData& data, - _EdgesOnShape& eos, - Handle(Geom_Surface)& surface, - const TopoDS_Face& F, - SMESH_MesherHelper& helper) +void _ViscousBuilder::findCollisionEdges( _SolidData& data, SMESH_MesherHelper& helper ) { - const TopoDS_Edge& E = TopoDS::Edge( eos._shape ); + data._collisionEdges.clear(); - Handle(Geom_Curve) curve = data.CurveForSmooth( E, eos, helper ); - if ( curve.IsNull() ) return false; - - const size_t iFrom = 0, iTo = eos._edges.size(); - - // compute a relative length of segments - vector< double > len( iTo-iFrom+1 ); + // set the full thickness of the layers to LEs + for ( size_t iS = 0; iS < data._edgesOnShape.size(); ++iS ) { - double curLen, prevLen = len[0] = 1.0; - for ( int i = iFrom; i < iTo; ++i ) + _EdgesOnShape& eos = data._edgesOnShape[iS]; + if ( eos._edges.empty() ) continue; + if ( eos.ShapeType() != TopAbs_EDGE && eos.ShapeType() != TopAbs_VERTEX ) continue; + + for ( size_t i = 0; i < eos._edges.size(); ++i ) { - curLen = prevLen * eos._edges[i]->_2neibors->_wgt[0] / eos._edges[i]->_2neibors->_wgt[1]; - len[i-iFrom+1] = len[i-iFrom] + curLen; - prevLen = curLen; + if ( eos._edges[i]->Is( _LayerEdge::BLOCKED )) continue; + double maxLen = eos._edges[i]->_maxLen; + eos._edges[i]->_maxLen = Precision::Infinite(); // avoid blocking + eos._edges[i]->SetNewLength( 1.5 * maxLen, eos, helper ); + eos._edges[i]->_maxLen = maxLen; } } - if ( curve->IsKind( STANDARD_TYPE( Geom_Line ))) + // make temporary quadrangles got by extrusion of + // mesh edges along _LayerEdge._normal's + + vector< const SMDS_MeshElement* > tmpFaces; + + for ( size_t iS = 0; iS < data._edgesOnShape.size(); ++iS ) { - if ( F.IsNull() ) // 3D + _EdgesOnShape& eos = data._edgesOnShape[ iS ]; + if ( eos.ShapeType() != TopAbs_EDGE ) + continue; + if ( eos._edges.empty() ) { - SMESH_TNodeXYZ p0( eos._edges[iFrom]->_2neibors->tgtNode(0)); - SMESH_TNodeXYZ p1( eos._edges[iTo-1]->_2neibors->tgtNode(1)); - for ( int i = iFrom; i < iTo; ++i ) + _LayerEdge* edge[2] = { 0, 0 }; // LE of 2 VERTEX'es + SMESH_subMeshIteratorPtr smIt = eos._subMesh->getDependsOnIterator(/*includeSelf=*/false); + while ( smIt->more() ) + if ( _EdgesOnShape* eov = data.GetShapeEdges( smIt->next()->GetId() )) + if ( eov->_edges.size() == 1 ) + edge[ bool( edge[0]) ] = eov->_edges[0]; + + if ( edge[1] ) { - double r = len[i-iFrom] / len.back(); - gp_XYZ newPos = p0 * ( 1. - r ) + p1 * r; - eos._edges[i]->_pos.back() = newPos; - SMDS_MeshNode* tgtNode = const_cast( eos._edges[i]->_nodes.back() ); - tgtNode->setXYZ( newPos.X(), newPos.Y(), newPos.Z() ); - dumpMove( tgtNode ); + _TmpMeshFaceOnEdge* f = new _TmpMeshFaceOnEdge( edge[0], edge[1], --_tmpFaceID ); + tmpFaces.push_back( f ); } } - else + for ( size_t i = 0; i < eos._edges.size(); ++i ) { - // gp_XY uv0 = helper.GetNodeUV( F, eos._edges[iFrom]->_2neibors->tgtNode(0)); - // gp_XY uv1 = helper.GetNodeUV( F, eos._edges[iTo-1]->_2neibors->tgtNode(1)); - _LayerEdge* e0 = eos._edges[iFrom]->_2neibors->_edges[0]; - _LayerEdge* e1 = eos._edges[iTo-1]->_2neibors->_edges[1]; - gp_XY uv0 = e0->LastUV( F, *data.GetShapeEdges( e0 )); - gp_XY uv1 = e1->LastUV( F, *data.GetShapeEdges( e1 )); - if ( eos._edges[iFrom]->_2neibors->tgtNode(0) == - eos._edges[iTo-1]->_2neibors->tgtNode(1) ) // closed edge + _LayerEdge* edge = eos._edges[i]; + for ( int j = 0; j < 2; ++j ) // loop on _2NearEdges { - int iPeriodic = helper.GetPeriodicIndex(); - if ( iPeriodic == 1 || iPeriodic == 2 ) - { - uv1.SetCoord( iPeriodic, helper.GetOtherParam( uv1.Coord( iPeriodic ))); - if ( uv0.Coord( iPeriodic ) > uv1.Coord( iPeriodic )) - std::swap( uv0, uv1 ); + const SMDS_MeshNode* src2 = edge->_2neibors->srcNode(j); + if ( src2->GetPosition()->GetDim() > 0 && + src2->GetID() < edge->_nodes[0]->GetID() ) + continue; // avoid using same segment twice + + // a _LayerEdge containg tgt2 + _LayerEdge* neiborEdge = edge->_2neibors->_edges[j]; + + _TmpMeshFaceOnEdge* f = new _TmpMeshFaceOnEdge( edge, neiborEdge, --_tmpFaceID ); + tmpFaces.push_back( f ); + } + } + } + + // Find _LayerEdge's intersecting tmpFaces. + + SMDS_ElemIteratorPtr fIt( new SMDS_ElementVectorIterator( tmpFaces.begin(), + tmpFaces.end())); + SMESHUtils::Deleter searcher + ( SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), fIt )); + + double dist1, dist2, segLen, eps; + _CollisionEdges collEdges; + vector< const SMDS_MeshElement* > suspectFaces; + const double angle30 = Cos( 30. * M_PI / 180. ); + + for ( size_t iS = 0; iS < data._edgesOnShape.size(); ++iS ) + { + _EdgesOnShape& eos = data._edgesOnShape[ iS ]; + if ( eos.ShapeType() == TopAbs_FACE || !eos._sWOL.IsNull() ) + continue; + // find sub-shapes whose VL can influence VL on eos + set< TGeomID > neighborShapes; + PShapeIteratorPtr fIt = helper.GetAncestors( eos._shape, *_mesh, TopAbs_FACE ); + while ( const TopoDS_Shape* face = fIt->next() ) + { + TGeomID faceID = getMeshDS()->ShapeToIndex( *face ); + if ( _EdgesOnShape* eof = data.GetShapeEdges( faceID )) + { + SMESH_subMeshIteratorPtr subIt = eof->_subMesh->getDependsOnIterator(/*includeSelf=*/false); + while ( subIt->more() ) + neighborShapes.insert( subIt->next()->GetId() ); + } + } + if ( eos.ShapeType() == TopAbs_VERTEX ) + { + PShapeIteratorPtr eIt = helper.GetAncestors( eos._shape, *_mesh, TopAbs_EDGE ); + while ( const TopoDS_Shape* edge = eIt->next() ) + neighborShapes.erase( getMeshDS()->ShapeToIndex( *edge )); + } + // find intersecting _LayerEdge's + for ( size_t i = 0; i < eos._edges.size(); ++i ) + { + _LayerEdge* edge = eos._edges[i]; + gp_Ax1 lastSegment = edge->LastSegment( segLen, eos ); + eps = 0.5 * edge->_len; + segLen *= 1.2; + + gp_Vec eSegDir0, eSegDir1; + if ( edge->IsOnEdge() ) + { + SMESH_TNodeXYZ eP( edge->_nodes[0] ); + eSegDir0 = SMESH_TNodeXYZ( edge->_2neibors->srcNode(0) ) - eP; + eSegDir1 = SMESH_TNodeXYZ( edge->_2neibors->srcNode(1) ) - eP; + } + suspectFaces.clear(); + searcher->GetElementsInSphere( SMESH_TNodeXYZ( edge->_nodes.back()), edge->_len, + SMDSAbs_Face, suspectFaces ); + collEdges._intEdges.clear(); + for ( size_t j = 0 ; j < suspectFaces.size(); ++j ) + { + const _TmpMeshFaceOnEdge* f = (const _TmpMeshFaceOnEdge*) suspectFaces[j]; + if ( f->_le1 == edge || f->_le2 == edge ) continue; + if ( !neighborShapes.count( f->_le1->_nodes[0]->getshapeId() )) continue; + if ( !neighborShapes.count( f->_le2->_nodes[0]->getshapeId() )) continue; + if ( edge->IsOnEdge() ) { + if ( edge->_2neibors->include( f->_le1 ) || + edge->_2neibors->include( f->_le2 )) continue; } + else { + if (( f->_le1->IsOnEdge() && f->_le1->_2neibors->include( edge )) || + ( f->_le2->IsOnEdge() && f->_le2->_2neibors->include( edge ))) continue; + } + dist1 = dist2 = Precision::Infinite(); + if ( !edge->SegTriaInter( lastSegment, f->_nn[0], f->_nn[1], f->_nn[2], dist1, eps )) + dist1 = Precision::Infinite(); + if ( !edge->SegTriaInter( lastSegment, f->_nn[3], f->_nn[2], f->_nn[0], dist2, eps )) + dist2 = Precision::Infinite(); + if (( dist1 > segLen ) && ( dist2 > segLen )) + continue; + + if ( edge->IsOnEdge() ) + { + // skip perpendicular EDGEs + gp_Vec fSegDir = SMESH_TNodeXYZ( f->_nn[0] ) - SMESH_TNodeXYZ( f->_nn[3] ); + bool isParallel = ( isLessAngle( eSegDir0, fSegDir, angle30 ) || + isLessAngle( eSegDir1, fSegDir, angle30 ) || + isLessAngle( eSegDir0, fSegDir.Reversed(), angle30 ) || + isLessAngle( eSegDir1, fSegDir.Reversed(), angle30 )); + if ( !isParallel ) + continue; + } + + // either limit inflation of edges or remember them for updating _normal + // double dot = edge->_normal * f->GetDir(); + // if ( dot > 0.1 ) + { + collEdges._intEdges.push_back( f->_le1 ); + collEdges._intEdges.push_back( f->_le2 ); + } + // else + // { + // double shortLen = 0.75 * ( Min( dist1, dist2 ) / edge->_lenFactor ); + // edge->_maxLen = Min( shortLen, edge->_maxLen ); + // } } - const gp_XY rangeUV = uv1 - uv0; - for ( int i = iFrom; i < iTo; ++i ) + + if ( !collEdges._intEdges.empty() ) { - double r = len[i-iFrom] / len.back(); - gp_XY newUV = uv0 + r * rangeUV; - eos._edges[i]->_pos.back().SetCoord( newUV.X(), newUV.Y(), 0 ); - - gp_Pnt newPos = surface->Value( newUV.X(), newUV.Y() ); - SMDS_MeshNode* tgtNode = const_cast( eos._edges[i]->_nodes.back() ); - tgtNode->setXYZ( newPos.X(), newPos.Y(), newPos.Z() ); - dumpMove( tgtNode ); - - SMDS_FacePosition* pos = static_cast( tgtNode->GetPosition() ); - pos->SetUParameter( newUV.X() ); - pos->SetVParameter( newUV.Y() ); + collEdges._edge = edge; + data._collisionEdges.push_back( collEdges ); } } - return true; } - if ( curve->IsKind( STANDARD_TYPE( Geom_Circle ))) + for ( size_t i = 0 ; i < tmpFaces.size(); ++i ) + delete tmpFaces[i]; + + // restore the zero thickness + for ( size_t iS = 0; iS < data._edgesOnShape.size(); ++iS ) { - Handle(Geom_Circle) circle = Handle(Geom_Circle)::DownCast( curve ); - gp_Pnt center3D = circle->Location(); + _EdgesOnShape& eos = data._edgesOnShape[iS]; + if ( eos._edges.empty() ) continue; + if ( eos.ShapeType() != TopAbs_EDGE && eos.ShapeType() != TopAbs_VERTEX ) continue; - if ( F.IsNull() ) // 3D + for ( size_t i = 0; i < eos._edges.size(); ++i ) { - if ( eos._edges[iFrom]->_2neibors->tgtNode(0) == - eos._edges[iTo-1]->_2neibors->tgtNode(1) ) - return true; // closed EDGE - nothing to do - - return false; // TODO ??? + eos._edges[i]->InvalidateStep( 1, eos ); + eos._edges[i]->_len = 0; } - else // 2D - { - const gp_XY center( center3D.X(), center3D.Y() ); - - _LayerEdge* e0 = eos._edges[iFrom]->_2neibors->_edges[0]; - _LayerEdge* eM = eos._edges[iFrom]; - _LayerEdge* e1 = eos._edges[iTo-1]->_2neibors->_edges[1]; - gp_XY uv0 = e0->LastUV( F, *data.GetShapeEdges( e0 ) ); - gp_XY uvM = eM->LastUV( F, *data.GetShapeEdges( eM ) ); - gp_XY uv1 = e1->LastUV( F, *data.GetShapeEdges( e1 ) ); - gp_Vec2d vec0( center, uv0 ); - gp_Vec2d vecM( center, uvM ); - gp_Vec2d vec1( center, uv1 ); - double uLast = vec0.Angle( vec1 ); // -PI - +PI - double uMidl = vec0.Angle( vecM ); - if ( uLast * uMidl <= 0. ) - uLast += ( uMidl > 0 ? +2. : -2. ) * M_PI; - const double radius = 0.5 * ( vec0.Magnitude() + vec1.Magnitude() ); - - gp_Ax2d axis( center, vec0 ); - gp_Circ2d circ( axis, radius ); - for ( int i = iFrom; i < iTo; ++i ) - { - double newU = uLast * len[i-iFrom] / len.back(); - gp_Pnt2d newUV = ElCLib::Value( newU, circ ); - eos._edges[i]->_pos.back().SetCoord( newUV.X(), newUV.Y(), 0 ); - - gp_Pnt newPos = surface->Value( newUV.X(), newUV.Y() ); - SMDS_MeshNode* tgtNode = const_cast( eos._edges[i]->_nodes.back() ); - tgtNode->setXYZ( newPos.X(), newPos.Y(), newPos.Z() ); - dumpMove( tgtNode ); - - SMDS_FacePosition* pos = static_cast( tgtNode->GetPosition() ); - pos->SetUParameter( newUV.X() ); - pos->SetVParameter( newUV.Y() ); - } - } - return true; } - - return false; } //================================================================================ @@ -4410,224 +6168,195 @@ bool _ViscousBuilder::smoothAnalyticEdge( _SolidData& data, bool _ViscousBuilder::updateNormals( _SolidData& data, SMESH_MesherHelper& helper, - int stepNb ) + int stepNb, + double stepSize) { - if ( stepNb > 0 ) - return updateNormalsOfConvexFaces( data, helper, stepNb ); + updateNormalsOfC1Vertices( data ); - // make temporary quadrangles got by extrusion of - // mesh edges along _LayerEdge._normal's + if ( stepNb > 0 && !updateNormalsOfConvexFaces( data, helper, stepNb )) + return false; - vector< const SMDS_MeshElement* > tmpFaces; + // map to store new _normal and _cosin for each intersected edge + map< _LayerEdge*, _LayerEdge, _LayerEdgeCmp > edge2newEdge; + map< _LayerEdge*, _LayerEdge, _LayerEdgeCmp >::iterator e2neIt; + _LayerEdge zeroEdge; + zeroEdge._normal.SetCoord( 0,0,0 ); + zeroEdge._maxLen = Precision::Infinite(); + zeroEdge._nodes.resize(1); // to init _TmpMeshFaceOnEdge + + set< _EdgesOnShape* > shapesToSmooth, edgesNoAnaSmooth; + + double segLen, dist1, dist2; + vector< pair< _LayerEdge*, double > > intEdgesDist; + _TmpMeshFaceOnEdge quad( &zeroEdge, &zeroEdge, 0 ); + + for ( int iter = 0; iter < 5; ++iter ) { - set< SMESH_TLink > extrudedLinks; // contains target nodes - vector< const SMDS_MeshNode*> nodes(4); // of a tmp mesh face + edge2newEdge.clear(); - dumpFunction(SMESH_Comment("makeTmpFacesOnEdges")<_nodes.back(); - for ( int j = 0; j < 2; ++j ) // loop on _2NearEdges - { - const SMDS_MeshNode* tgt2 = edge->_2neibors->tgtNode(j); - pair< set< SMESH_TLink >::iterator, bool > link_isnew = - extrudedLinks.insert( SMESH_TLink( tgt1, tgt2 )); - if ( !link_isnew.second ) - { - extrudedLinks.erase( link_isnew.first ); - continue; // already extruded and will no more encounter - } - // a _LayerEdge containg tgt2 - _LayerEdge* neiborEdge = edge->_2neibors->_edges[j]; - - _TmpMeshFaceOnEdge* f = new _TmpMeshFaceOnEdge( edge, neiborEdge, --_tmpFaceID ); - tmpFaces.push_back( f ); - - dumpCmd(SMESH_Comment("mesh.AddFace([ ") - <_nn[0]->GetID()<<", "<_nn[1]->GetID()<<", " - <_nn[2]->GetID()<<", "<_nn[3]->GetID()<<" ])"); - } - } - } - dumpFunctionEnd(); - } - // Check if _LayerEdge's based on EDGE's intersects tmpFaces. - // Perform two loops on _LayerEdge on EDGE's: - // 1) to find and fix intersection - // 2) to check that no new intersection appears as result of 1) - - SMDS_ElemIteratorPtr fIt( new SMDS_ElementVectorIterator( tmpFaces.begin(), - tmpFaces.end())); - auto_ptr searcher - ( SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), fIt )); - - // 1) Find intersections - double dist; - const SMDS_MeshElement* face; - typedef map< _LayerEdge*, set< _LayerEdge*, _LayerEdgeCmp >, _LayerEdgeCmp > TLEdge2LEdgeSet; - TLEdge2LEdgeSet edge2CloseEdge; - - const double eps = data._epsilon * data._epsilon; - for ( size_t iS = 0; iS < data._edgesOnShape.size(); ++iS ) - { - _EdgesOnShape& eos = data._edgesOnShape[ iS ]; - if (( eos.ShapeType() != TopAbs_EDGE ) && - ( eos._sWOL.IsNull() || eos.SWOLType() != TopAbs_FACE )) - continue; - for ( size_t i = 0; i < eos._edges.size(); ++i ) - { - _LayerEdge* edge = eos._edges[i]; - if ( edge->FindIntersection( *searcher, dist, eps, eos, &face )) - { - const _TmpMeshFaceOnEdge* f = (const _TmpMeshFaceOnEdge*) face; - set< _LayerEdge*, _LayerEdgeCmp > & ee = edge2CloseEdge[ edge ]; - ee.insert( f->_le1 ); - ee.insert( f->_le2 ); - if ( f->_le1->IsOnEdge() && data.GetShapeEdges( f->_le1 )->_sWOL.IsNull() ) - edge2CloseEdge[ f->_le1 ].insert( edge ); - if ( f->_le2->IsOnEdge() && data.GetShapeEdges( f->_le2 )->_sWOL.IsNull() ) - edge2CloseEdge[ f->_le2 ].insert( edge ); - } - } - } - - // Set _LayerEdge._normal - - if ( !edge2CloseEdge.empty() ) - { - dumpFunction(SMESH_Comment("updateNormals")< shapesToSmooth; - - // vector to store new _normal and _cosin for each edge in edge2CloseEdge - vector< pair< _LayerEdge*, _LayerEdge > > edge2newEdge( edge2CloseEdge.size() ); - - TLEdge2LEdgeSet::iterator e2ee = edge2CloseEdge.begin(); - for ( size_t iE = 0; e2ee != edge2CloseEdge.end(); ++e2ee, ++iE ) - { - _LayerEdge* edge1 = e2ee->first; - _LayerEdge* edge2 = 0; - set< _LayerEdge*, _LayerEdgeCmp >& ee = e2ee->second; - - edge2newEdge[ iE ].first = NULL; - + _CollisionEdges& ce = data._collisionEdges[iE]; + _LayerEdge* edge1 = ce._edge; + if ( !edge1 || edge1->Is( _LayerEdge::BLOCKED )) continue; _EdgesOnShape* eos1 = data.GetShapeEdges( edge1 ); if ( !eos1 ) continue; - // find EDGEs the edges reside - // TopoDS_Edge E1, E2; - // TopoDS_Shape S = helper.GetSubShapeByNode( edge1->_nodes[0], getMeshDS() ); - // if ( S.ShapeType() != TopAbs_EDGE ) - // continue; // TODO: find EDGE by VERTEX - // E1 = TopoDS::Edge( S ); - set< _LayerEdge*, _LayerEdgeCmp >::iterator eIt = ee.begin(); - for ( ; !edge2 && eIt != ee.end(); ++eIt ) + // detect intersections + gp_Ax1 lastSeg = edge1->LastSegment( segLen, *eos1 ); + double testLen = 1.5 * edge1->_maxLen; //2 + edge1->_len * edge1->_lenFactor; + double eps = 0.5 * edge1->_len; + intEdgesDist.clear(); + double minIntDist = Precision::Infinite(); + for ( size_t i = 0; i < ce._intEdges.size(); i += 2 ) { - if ( eos1->_sWOL == data.GetShapeEdges( *eIt )->_sWOL ) - edge2 = *eIt; + if ( ce._intEdges[i ]->Is( _LayerEdge::BLOCKED ) || + ce._intEdges[i+1]->Is( _LayerEdge::BLOCKED )) + continue; + double dot = edge1->_normal * quad.GetDir( ce._intEdges[i], ce._intEdges[i+1] ); + double fact = ( 1.1 + dot * dot ); + SMESH_TNodeXYZ pSrc0( ce.nSrc(i) ), pSrc1( ce.nSrc(i+1) ); + SMESH_TNodeXYZ pTgt0( ce.nTgt(i) ), pTgt1( ce.nTgt(i+1) ); + gp_XYZ pLast0 = pSrc0 + ( pTgt0 - pSrc0 ) * fact; + gp_XYZ pLast1 = pSrc1 + ( pTgt1 - pSrc1 ) * fact; + dist1 = dist2 = Precision::Infinite(); + if ( !edge1->SegTriaInter( lastSeg, pSrc0, pTgt0, pSrc1, dist1, eps ) && + !edge1->SegTriaInter( lastSeg, pSrc1, pTgt1, pTgt0, dist2, eps )) + continue; + if (( dist1 > testLen || dist1 < 0 ) && + ( dist2 > testLen || dist2 < 0 )) + continue; + + // choose a closest edge + gp_Pnt intP( lastSeg.Location().XYZ() + + lastSeg.Direction().XYZ() * ( Min( dist1, dist2 ) + segLen )); + double d1 = intP.SquareDistance( pSrc0 ); + double d2 = intP.SquareDistance( pSrc1 ); + int iClose = i + ( d2 < d1 ); + _LayerEdge* edge2 = ce._intEdges[iClose]; + edge2->Unset( _LayerEdge::MARKED ); + + // choose a closest edge among neighbors + gp_Pnt srcP( SMESH_TNodeXYZ( edge1->_nodes[0] )); + d1 = srcP.SquareDistance( SMESH_TNodeXYZ( edge2->_nodes[0] )); + for ( size_t j = 0; j < intEdgesDist.size(); ++j ) + { + _LayerEdge * edgeJ = intEdgesDist[j].first; + if ( edge2->IsNeiborOnEdge( edgeJ )) + { + d2 = srcP.SquareDistance( SMESH_TNodeXYZ( edgeJ->_nodes[0] )); + ( d1 < d2 ? edgeJ : edge2 )->Set( _LayerEdge::MARKED ); + } + } + intEdgesDist.push_back( make_pair( edge2, Min( dist1, dist2 ))); + // if ( Abs( d2 - d1 ) / Max( d2, d1 ) < 0.5 ) + // { + // iClose = i + !( d2 < d1 ); + // intEdges.push_back( ce._intEdges[iClose] ); + // ce._intEdges[iClose]->Unset( _LayerEdge::MARKED ); + // } + minIntDist = Min( edge1->_len * edge1->_lenFactor - segLen + dist1, minIntDist ); + minIntDist = Min( edge1->_len * edge1->_lenFactor - segLen + dist2, minIntDist ); } - if ( !edge2 ) continue; - edge2newEdge[ iE ].first = edge1; - _LayerEdge& newEdge = edge2newEdge[ iE ].second; - // while ( E2.IsNull() && eIt != ee.end()) - // { - // _LayerEdge* e2 = *eIt++; - // TopoDS_Shape S = helper.GetSubShapeByNode( e2->_nodes[0], getMeshDS() ); - // if ( S.ShapeType() == TopAbs_EDGE ) - // E2 = TopoDS::Edge( S ), edge2 = e2; - // } - // if ( E2.IsNull() ) continue; // TODO: find EDGE by VERTEX + //ce._edge = 0; - // find 3 FACEs sharing 2 EDGEs + // compute new _normals + for ( size_t i = 0; i < intEdgesDist.size(); ++i ) + { + _LayerEdge* edge2 = intEdgesDist[i].first; + double distWgt = edge1->_len / intEdgesDist[i].second; + if ( edge2->Is( _LayerEdge::MARKED )) continue; + edge2->Set( _LayerEdge::MARKED ); - // TopoDS_Face FF1[2], FF2[2]; - // PShapeIteratorPtr fIt = helper.GetAncestors(E1, *_mesh, TopAbs_FACE); - // while ( fIt->more() && FF1[1].IsNull() ) - // { - // const TopoDS_Face *F = (const TopoDS_Face*) fIt->next(); - // if ( helper.IsSubShape( *F, data._solid)) - // FF1[ FF1[0].IsNull() ? 0 : 1 ] = *F; - // } - // fIt = helper.GetAncestors(E2, *_mesh, TopAbs_FACE); - // while ( fIt->more() && FF2[1].IsNull()) - // { - // const TopoDS_Face *F = (const TopoDS_Face*) fIt->next(); - // if ( helper.IsSubShape( *F, data._solid)) - // FF2[ FF2[0].IsNull() ? 0 : 1 ] = *F; - // } - // // exclude a FACE common to E1 and E2 (put it to FFn[1] ) - // if ( FF1[0].IsSame( FF2[0]) || FF1[0].IsSame( FF2[1])) - // std::swap( FF1[0], FF1[1] ); - // if ( FF2[0].IsSame( FF1[0]) ) - // std::swap( FF2[0], FF2[1] ); - // if ( FF1[0].IsNull() || FF2[0].IsNull() ) - // continue; + // get a new normal + gp_XYZ dir1 = edge1->_normal, dir2 = edge2->_normal; - // get a new normal for edge1 - //bool ok; - gp_Vec dir1 = edge1->_normal, dir2 = edge2->_normal; - // if ( edge1->_cosin < 0 ) - // dir1 = getFaceDir( FF1[0], E1, edge1->_nodes[0], helper, ok ).Normalized(); - // if ( edge2->_cosin < 0 ) - // dir2 = getFaceDir( FF2[0], E2, edge2->_nodes[0], helper, ok ).Normalized(); + double cos1 = Abs( edge1->_cosin ), cos2 = Abs( edge2->_cosin ); + double wgt1 = ( cos1 + 0.001 ) / ( cos1 + cos2 + 0.002 ); + double wgt2 = ( cos2 + 0.001 ) / ( cos1 + cos2 + 0.002 ); + // double cos1 = Abs( edge1->_cosin ), cos2 = Abs( edge2->_cosin ); + // double sgn1 = 0.1 * ( 1 + edge1->_cosin ), sgn2 = 0.1 * ( 1 + edge2->_cosin ); + // double wgt1 = ( cos1 + sgn1 ) / ( cos1 + cos2 + sgn1 + sgn2 ); + // double wgt2 = ( cos2 + sgn2 ) / ( cos1 + cos2 + sgn1 + sgn2 ); + gp_XYZ newNormal = wgt1 * dir1 + wgt2 * dir2; + newNormal.Normalize(); - double cos1 = Abs( edge1->_cosin ), cos2 = Abs( edge2->_cosin ); - double wgt1 = ( cos1 + 0.001 ) / ( cos1 + cos2 + 0.002 ); - double wgt2 = ( cos2 + 0.001 ) / ( cos1 + cos2 + 0.002 ); - newEdge._normal = ( wgt1 * dir1 + wgt2 * dir2 ).XYZ(); + // get new cosin + double newCos; + double sgn1 = edge1->_cosin / cos1, sgn2 = edge2->_cosin / cos2; + if ( cos1 < theMinSmoothCosin ) + { + newCos = cos2 * sgn1; + } + else if ( cos2 > theMinSmoothCosin ) // both cos1 and cos2 > theMinSmoothCosin + { + newCos = ( wgt1 * cos1 + wgt2 * cos2 ) * edge1->_cosin / cos1; + } + else + { + newCos = edge1->_cosin; + } + + e2neIt = edge2newEdge.insert( make_pair( edge1, zeroEdge )).first; + e2neIt->second._normal += distWgt * newNormal; + e2neIt->second._cosin = newCos; + e2neIt->second._maxLen = 0.7 * minIntDist / edge1->_lenFactor; + if ( iter > 0 && sgn1 * sgn2 < 0 && edge1->_cosin < 0 ) + e2neIt->second._normal += dir2; + e2neIt = edge2newEdge.insert( make_pair( edge2, zeroEdge )).first; + e2neIt->second._normal += distWgt * newNormal; + e2neIt->second._cosin = edge2->_cosin; + if ( iter > 0 && sgn1 * sgn2 < 0 && edge2->_cosin < 0 ) + e2neIt->second._normal += dir1; + } + } + + if ( edge2newEdge.empty() ) + break; //return true; + + dumpFunction(SMESH_Comment("updateNormals")<< data._index << "_" << stepNb << "_it" << iter); + + // Update data of edges depending on a new _normal + + data.UnmarkEdges(); + for ( e2neIt = edge2newEdge.begin(); e2neIt != edge2newEdge.end(); ++e2neIt ) + { + _LayerEdge* edge = e2neIt->first; + _LayerEdge& newEdge = e2neIt->second; + _EdgesOnShape* eos = data.GetShapeEdges( edge ); + + // Check if a new _normal is OK: newEdge._normal.Normalize(); - - // cout << edge1->_nodes[0]->GetID() << " " - // << edge2->_nodes[0]->GetID() << " NORM: " - // << newEdge._normal.X() << ", " << newEdge._normal.Y() << ", " << newEdge._normal.Z() << endl; - - // get new cosin - if ( cos1 < theMinSmoothCosin ) + if ( !isNewNormalOk( data, *edge, newEdge._normal )) { - newEdge._cosin = edge2->_cosin; - } - else if ( cos2 > theMinSmoothCosin ) // both cos1 and cos2 > theMinSmoothCosin - { - // gp_Vec dirInFace; - // if ( edge1->_cosin < 0 ) - // dirInFace = dir1; - // else - // dirInFace = getFaceDir( FF1[0], E1, edge1->_nodes[0], helper, ok ); - // double angle = dirInFace.Angle( edge1->_normal ); // [0,PI] - // edge1->SetCosin( Cos( angle )); - //newEdge._cosin = 0; // ??????????? - newEdge._cosin = ( wgt1 * cos1 + wgt2 * cos2 ) * edge1->_cosin / cos1; - } - else - { - newEdge._cosin = edge1->_cosin; + if ( newEdge._maxLen < edge->_len && iter > 0 ) // limit _maxLen + { + edge->InvalidateStep( stepNb + 1, *eos, /*restoreLength=*/true ); + edge->_maxLen = newEdge._maxLen; + edge->SetNewLength( newEdge._maxLen, *eos, helper ); + } + continue; // the new _normal is bad } + // the new _normal is OK // find shapes that need smoothing due to change of _normal - if ( edge1->_cosin < theMinSmoothCosin && + if ( edge->_cosin < theMinSmoothCosin && newEdge._cosin > theMinSmoothCosin ) { - if ( eos1->_sWOL.IsNull() ) + if ( eos->_sWOL.IsNull() ) { - SMDS_ElemIteratorPtr fIt = edge1->_nodes[0]->GetInverseElementIterator(SMDSAbs_Face); + SMDS_ElemIteratorPtr fIt = edge->_nodes[0]->GetInverseElementIterator(SMDSAbs_Face); while ( fIt->more() ) shapesToSmooth.insert( data.GetShapeEdges( fIt->next()->getshapeId() )); - //limitStepSize( data, fIt->next(), edge1->_cosin ); // too late } - else // edge1 inflates along a FACE + else // edge inflates along a FACE { - TopoDS_Shape V = helper.GetSubShapeByNode( edge1->_nodes[0], getMeshDS() ); + TopoDS_Shape V = helper.GetSubShapeByNode( edge->_nodes[0], getMeshDS() ); PShapeIteratorPtr eIt = helper.GetAncestors( V, *_mesh, TopAbs_EDGE ); while ( const TopoDS_Shape* E = eIt->next() ) { - if ( !helper.IsSubShape( *E, /*FACE=*/eos1->_sWOL )) + if ( !helper.IsSubShape( *E, /*FACE=*/eos->_sWOL )) continue; gp_Vec edgeDir = getEdgeDir( TopoDS::Edge( *E ), TopoDS::Vertex( V )); double angle = edgeDir.Angle( newEdge._normal ); // [0,PI] @@ -4636,25 +6365,27 @@ bool _ViscousBuilder::updateNormals( _SolidData& data, } } } + + double len = edge->_len; + edge->InvalidateStep( stepNb + 1, *eos, /*restoreLength=*/true ); + edge->SetNormal( newEdge._normal ); + edge->SetCosin( newEdge._cosin ); + edge->SetNewLength( len, *eos, helper ); + edge->Set( _LayerEdge::MARKED ); + edge->Set( _LayerEdge::NORMAL_UPDATED ); + edgesNoAnaSmooth.insert( eos ); } - data.AddShapesToSmooth( shapesToSmooth ); + // Update normals and other dependent data of not intersecting _LayerEdge's + // neighboring the intersecting ones - // Update data of edges depending on a new _normal - - for ( size_t iE = 0; iE < edge2newEdge.size(); ++iE ) + for ( e2neIt = edge2newEdge.begin(); e2neIt != edge2newEdge.end(); ++e2neIt ) { - _LayerEdge* edge1 = edge2newEdge[ iE ].first; - _LayerEdge& newEdge = edge2newEdge[ iE ].second; - if ( !edge1 ) continue; + _LayerEdge* edge1 = e2neIt->first; _EdgesOnShape* eos1 = data.GetShapeEdges( edge1 ); - if ( !eos1 ) continue; + if ( !edge1->Is( _LayerEdge::MARKED )) + continue; - edge1->_normal = newEdge._normal; - edge1->SetCosin( newEdge._cosin ); - edge1->InvalidateStep( 1, *eos1 ); - edge1->_len = 0; - edge1->SetNewLength( data._stepSize, *eos1, helper ); if ( edge1->IsOnEdge() ) { const SMDS_MeshNode * n1 = edge1->_2neibors->srcNode(0); @@ -4662,42 +6393,52 @@ bool _ViscousBuilder::updateNormals( _SolidData& data, edge1->SetDataByNeighbors( n1, n2, *eos1, helper ); } - // Update normals and other dependent data of not intersecting _LayerEdge's - // neighboring the intersecting ones - if ( !edge1->_2neibors ) continue; for ( int j = 0; j < 2; ++j ) // loop on 2 neighbors { _LayerEdge* neighbor = edge1->_2neibors->_edges[j]; - if ( edge2CloseEdge.count ( neighbor )) + if ( neighbor->Is( _LayerEdge::MARKED ) /*edge2newEdge.count ( neighbor )*/) continue; // j-th neighbor is also intersected - _EdgesOnShape* eos = data.GetShapeEdges( neighbor ); - if ( !eos ) continue; _LayerEdge* prevEdge = edge1; const int nbSteps = 10; for ( int step = nbSteps; step; --step ) // step from edge1 in j-th direction { - if ( !neighbor->_2neibors ) - break; // neighbor is on VERTEX - int iNext = 0; - _LayerEdge* nextEdge = neighbor->_2neibors->_edges[iNext]; - if ( nextEdge == prevEdge ) - nextEdge = neighbor->_2neibors->_edges[ ++iNext ]; + if ( neighbor->Is( _LayerEdge::BLOCKED ) || + neighbor->Is( _LayerEdge::MARKED )) + break; + _EdgesOnShape* eos = data.GetShapeEdges( neighbor ); + if ( !eos ) continue; + _LayerEdge* nextEdge = neighbor; + if ( neighbor->_2neibors ) + { + int iNext = 0; + nextEdge = neighbor->_2neibors->_edges[iNext]; + if ( nextEdge == prevEdge ) + nextEdge = neighbor->_2neibors->_edges[ ++iNext ]; + } double r = double(step-1)/nbSteps; if ( !nextEdge->_2neibors ) - r = 0.5; + r = Min( r, 0.5 ); gp_XYZ newNorm = prevEdge->_normal * r + nextEdge->_normal * (1-r); newNorm.Normalize(); + if ( !isNewNormalOk( data, *neighbor, newNorm )) + break; - neighbor->_normal = newNorm; + double len = neighbor->_len; + neighbor->InvalidateStep( stepNb + 1, *eos, /*restoreLength=*/true ); + neighbor->SetNormal( newNorm ); neighbor->SetCosin( prevEdge->_cosin * r + nextEdge->_cosin * (1-r) ); - neighbor->SetDataByNeighbors( prevEdge->_nodes[0], nextEdge->_nodes[0], *eos, helper ); + if ( neighbor->_2neibors ) + neighbor->SetDataByNeighbors( prevEdge->_nodes[0], nextEdge->_nodes[0], *eos, helper ); + neighbor->SetNewLength( len, *eos, helper ); + neighbor->Set( _LayerEdge::MARKED ); + neighbor->Set( _LayerEdge::NORMAL_UPDATED ); + edgesNoAnaSmooth.insert( eos ); - neighbor->InvalidateStep( 1, *eos ); - neighbor->_len = 0; - neighbor->SetNewLength( data._stepSize, *eos, helper ); + if ( !neighbor->_2neibors ) + break; // neighbor is on VERTEX // goto the next neighbor prevEdge = neighbor; @@ -4706,16 +6447,147 @@ bool _ViscousBuilder::updateNormals( _SolidData& data, } } dumpFunctionEnd(); - } - // 2) Check absence of intersections - // TODO? + } // iterations - for ( size_t i = 0 ; i < tmpFaces.size(); ++i ) - delete tmpFaces[i]; + data.AddShapesToSmooth( shapesToSmooth, &edgesNoAnaSmooth ); return true; } +//================================================================================ +/*! + * \brief Check if a new normal is OK + */ +//================================================================================ + +bool _ViscousBuilder::isNewNormalOk( _SolidData& data, + _LayerEdge& edge, + const gp_XYZ& newNormal) +{ + // check a min angle between the newNormal and surrounding faces + vector<_Simplex> simplices; + SMESH_TNodeXYZ n0( edge._nodes[0] ), n1, n2; + _Simplex::GetSimplices( n0._node, simplices, data._ignoreFaceIds, &data ); + double newMinDot = 1, curMinDot = 1; + for ( size_t i = 0; i < simplices.size(); ++i ) + { + n1.Set( simplices[i]._nPrev ); + n2.Set( simplices[i]._nNext ); + gp_XYZ normFace = ( n1 - n0 ) ^ ( n2 - n0 ); + double normLen2 = normFace.SquareModulus(); + if ( normLen2 < std::numeric_limits::min() ) + continue; + normFace /= Sqrt( normLen2 ); + newMinDot = Min( newNormal * normFace, newMinDot ); + curMinDot = Min( edge._normal * normFace, curMinDot ); + } + if ( newMinDot < 0.5 ) + { + return ( newMinDot >= curMinDot * 0.9 ); + //return ( newMinDot >= ( curMinDot * ( 0.8 + 0.1 * edge.NbSteps() ))); + // double initMinDot2 = 1. - edge._cosin * edge._cosin; + // return ( newMinDot * newMinDot ) >= ( 0.8 * initMinDot2 ); + } + return true; +} + +//================================================================================ +/*! + * \brief Modify normals of _LayerEdge's on FACE to reflex smoothing + */ +//================================================================================ + +bool _ViscousBuilder::updateNormalsOfSmoothed( _SolidData& data, + SMESH_MesherHelper& helper, + const int nbSteps, + const double stepSize ) +{ + if ( data._nbShapesToSmooth == 0 || nbSteps == 0 ) + return true; // no shapes needing smoothing + + for ( size_t iS = 0; iS < data._edgesOnShape.size(); ++iS ) + { + _EdgesOnShape& eos = data._edgesOnShape[ iS ]; + if ( //!eos._toSmooth || _eosC1 have _toSmooth == false + !eos._hyp.ToSmooth() || + eos.ShapeType() != TopAbs_FACE || + eos._edges.empty() ) + continue; + + bool toSmooth = ( eos._edges[ 0 ]->NbSteps() >= nbSteps+1 ); + if ( !toSmooth ) continue; + + for ( size_t i = 0; i < eos._edges.size(); ++i ) + { + _LayerEdge* edge = eos._edges[i]; + if ( !edge->Is( _LayerEdge::SMOOTHED )) + continue; + if ( edge->Is( _LayerEdge::DIFFICULT ) && nbSteps != 1 ) + continue; + + const gp_XYZ& pPrev = edge->PrevPos(); + const gp_XYZ& pLast = edge->_pos.back(); + gp_XYZ stepVec = pLast - pPrev; + double realStepSize = stepVec.Modulus(); + if ( realStepSize < numeric_limits::min() ) + continue; + + edge->_lenFactor = realStepSize / stepSize; + edge->_normal = stepVec / realStepSize; + edge->Set( _LayerEdge::NORMAL_UPDATED ); + } + } + + return true; +} + +//================================================================================ +/*! + * \brief Modify normals of _LayerEdge's on C1 VERTEXes + */ +//================================================================================ + +void _ViscousBuilder::updateNormalsOfC1Vertices( _SolidData& data ) +{ + for ( size_t iS = 0; iS < data._edgesOnShape.size(); ++iS ) + { + _EdgesOnShape& eov = data._edgesOnShape[ iS ]; + if ( eov._eosC1.empty() || + eov.ShapeType() != TopAbs_VERTEX || + eov._edges.empty() ) + continue; + + gp_XYZ newNorm = eov._edges[0]->_normal; + double curThick = eov._edges[0]->_len * eov._edges[0]->_lenFactor; + bool normChanged = false; + + for ( size_t i = 0; i < eov._eosC1.size(); ++i ) + { + _EdgesOnShape* eoe = eov._eosC1[i]; + const TopoDS_Edge& e = TopoDS::Edge( eoe->_shape ); + const double eLen = SMESH_Algo::EdgeLength( e ); + TopoDS_Shape oppV = SMESH_MesherHelper::IthVertex( 0, e ); + if ( oppV.IsSame( eov._shape )) + oppV = SMESH_MesherHelper::IthVertex( 1, e ); + _EdgesOnShape* eovOpp = data.GetShapeEdges( oppV ); + if ( !eovOpp || eovOpp->_edges.empty() ) continue; + + double curThickOpp = eovOpp->_edges[0]->_len * eovOpp->_edges[0]->_lenFactor; + if ( curThickOpp + curThick < eLen ) + continue; + + double wgt = 2. * curThick / eLen; + newNorm += wgt * eovOpp->_edges[0]->_normal; + normChanged = true; + } + if ( normChanged ) + { + eov._edges[0]->SetNormal( newNorm.Normalized() ); + eov._edges[0]->Set( _LayerEdge::NORMAL_UPDATED ); + } + } +} + //================================================================================ /*! * \brief Modify normals of _LayerEdge's on _ConvexFace's @@ -4844,7 +6716,10 @@ bool _ViscousBuilder::updateNormalsOfConvexFaces( _SolidData& data, eos._edges[ i ]->_cosin = avgCosin; for ( size_t i = 0; i < eos._edges.size(); ++i ) - eos._edges[ i ]->_normal = avgNormal; + { + eos._edges[ i ]->SetNormal( avgNormal ); + eos._edges[ i ]->Set( _LayerEdge::NORMAL_UPDATED ); + } } } else // if ( isSpherical ) @@ -4888,7 +6763,7 @@ bool _ViscousBuilder::updateNormalsOfConvexFaces( _SolidData& data, else { if ( ! eos->_toSmooth ) - data.SortOnEdge( edge, eos->_edges, helper ); + data.SortOnEdge( edge, eos->_edges ); edgeLEdge = &eos->_edges[ 0 ]; edgeLEdgeEnd = edgeLEdge + eos->_edges.size(); vertexLEdges[0] = eos->_edges.front()->_2neibors->_edges[0]; @@ -4966,7 +6841,10 @@ bool _ViscousBuilder::updateNormalsOfConvexFaces( _SolidData& data, if ( centerCurves[ iE ]._isDegenerated ) continue; for ( size_t iLE = 0; iLE < centerCurves[ iE ]._ledges.size(); ++iLE ) - centerCurves[ iE ]._ledges[ iLE ]->_normal = centerCurves[ iE ]._normals[ iLE ]; + { + centerCurves[ iE ]._ledges[ iLE ]->SetNormal( centerCurves[ iE ]._normals[ iLE ]); + centerCurves[ iE ]._ledges[ iLE ]->Set( _LayerEdge::NORMAL_UPDATED ); + } } // set new normals to _LayerEdge's of degenerated central curves for ( size_t iE = 0; iE < centerCurves.size(); ++iE ) @@ -4986,8 +6864,9 @@ bool _ViscousBuilder::updateNormalsOfConvexFaces( _SolidData& data, 0.5 * centerCurves[ iE ]._ledges.back ()->_cosin ); for ( size_t iLE = 1, nb = centerCurves[ iE ]._ledges.size() - 1; iLE < nb; ++iLE ) { - centerCurves[ iE ]._ledges[ iLE ]->_normal = newNorm; - centerCurves[ iE ]._ledges[ iLE ]->_cosin = newCosin; + centerCurves[ iE ]._ledges[ iLE ]->SetNormal( newNorm ); + centerCurves[ iE ]._ledges[ iLE ]->_cosin = newCosin; + centerCurves[ iE ]._ledges[ iLE ]->Set( _LayerEdge::NORMAL_UPDATED ); } } @@ -5015,8 +6894,9 @@ bool _ViscousBuilder::updateNormalsOfConvexFaces( _SolidData& data, newNorm.SetCoord( 0,0,0 ); if ( centerCurves[ iE ].FindNewNormal( center, newNorm )) { - ledge->_normal = newNorm; + ledge->SetNormal( newNorm ); ledge->_cosin = avgCosin; + ledge->Set( _LayerEdge::NORMAL_UPDATED ); break; } } @@ -5042,7 +6922,21 @@ bool _ViscousBuilder::updateNormalsOfConvexFaces( _SolidData& data, ledge->SetCosin( ledge->_cosin ); ledge->SetNewLength( len, eos, helper ); } - + if ( eos.ShapeType() != TopAbs_FACE ) + for ( size_t i = 0; i < eos._edges.size(); ++i ) + { + _LayerEdge* ledge = eos._edges[ i ]; + for ( size_t iN = 0; iN < ledge->_neibors.size(); ++iN ) + { + _LayerEdge* neibor = ledge->_neibors[iN]; + if ( neibor->_nodes[0]->GetPosition()->GetDim() == 2 ) + { + neibor->Set( _LayerEdge::NEAR_BOUNDARY ); + neibor->Set( _LayerEdge::MOVED ); + neibor->SetSmooLen( neibor->_len ); + } + } + } } // loop on sub-shapes of convFace._face // Find FACEs adjacent to convFace._face that got necessity to smooth @@ -5114,7 +7008,7 @@ bool _ConvexFace::CheckPrisms() const const _LayerEdge* edge = _simplexTestEdges[i]; SMESH_TNodeXYZ tgtXYZ( edge->_nodes.back() ); for ( size_t j = 0; j < edge->_simplices.size(); ++j ) - if ( !edge->_simplices[j].IsForward( edge->_nodes[0], &tgtXYZ, vol )) + if ( !edge->_simplices[j].IsForward( edge->_nodes[0], tgtXYZ, vol )) { debugMsg( "Bad simplex of _simplexTestEdges (" << " "<< edge->_nodes[0]->GetID()<< " "<< tgtXYZ._node->GetID() @@ -5209,7 +7103,7 @@ bool _LayerEdge::FindIntersection( SMESH_ElementSearcher& searcher, double & distance, const double& epsilon, _EdgesOnShape& eos, - const SMDS_MeshElement** face) + const SMDS_MeshElement** intFace) { vector< const SMDS_MeshElement* > suspectFaces; double segLen; @@ -5253,23 +7147,23 @@ bool _LayerEdge::FindIntersection( SMESH_ElementSearcher& searcher, distance = dist, iFace = j; } } - if ( iFace != -1 && face ) *face = suspectFaces[iFace]; + if ( intFace ) *intFace = ( iFace != -1 ) ? suspectFaces[iFace] : 0; + + distance -= segLen; if ( segmentIntersected ) { #ifdef __myDEBUG SMDS_MeshElement::iterator nIt = suspectFaces[iFace]->begin_nodes(); - gp_XYZ intP( lastSegment.Location().XYZ() + lastSegment.Direction().XYZ() * distance ); + gp_XYZ intP( lastSegment.Location().XYZ() + lastSegment.Direction().XYZ() * ( distance+segLen )); cout << "nodes: tgt " << _nodes.back()->GetID() << " src " << _nodes[0]->GetID() << ", intersection with face (" << (*nIt++)->GetID()<<" "<< (*nIt++)->GetID()<<" "<< (*nIt++)->GetID() << ") at point (" << intP.X() << ", " << intP.Y() << ", " << intP.Z() - << ") distance = " << distance - segLen<< endl; + << ") distance = " << distance << endl; #endif } - distance -= segLen; - return segmentIntersected; } @@ -5283,13 +7177,14 @@ gp_Ax1 _LayerEdge::LastSegment(double& segLen, _EdgesOnShape& eos) const { // find two non-coincident positions gp_XYZ orig = _pos.back(); - gp_XYZ dir; + gp_XYZ vec; int iPrev = _pos.size() - 2; - const double tol = ( _len > 0 ) ? 0.3*_len : 1e-100; // adjusted for IPAL52478 + PAL22576 + //const double tol = ( _len > 0 ) ? 0.3*_len : 1e-100; // adjusted for IPAL52478 + PAL22576 + const double tol = ( _len > 0 ) ? ( 1e-6 * _len ) : 1e-100; while ( iPrev >= 0 ) { - dir = orig - _pos[iPrev]; - if ( dir.SquareModulus() > tol*tol ) + vec = orig - _pos[iPrev]; + if ( vec.SquareModulus() > tol*tol ) break; else iPrev--; @@ -5320,11 +7215,11 @@ gp_Ax1 _LayerEdge::LastSegment(double& segLen, _EdgesOnShape& eos) const Handle(Geom_Surface) surface = BRep_Tool::Surface( TopoDS::Face( eos._sWOL ), loc ); pPrev = surface->Value( pPrev.X(), pPrev.Y() ).Transformed( loc ); } - dir = SMESH_TNodeXYZ( _nodes.back() ) - pPrev.XYZ(); + vec = SMESH_TNodeXYZ( _nodes.back() ) - pPrev.XYZ(); } segDir.SetLocation( pPrev ); - segDir.SetDirection( dir ); - segLen = dir.Modulus(); + segDir.SetDirection( vec ); + segLen = vec.Modulus(); } return segDir; @@ -5363,22 +7258,16 @@ gp_XY _LayerEdge::LastUV( const TopoDS_Face& F, _EdgesOnShape& eos ) const */ //================================================================================ -bool _LayerEdge::SegTriaInter( const gp_Ax1& lastSegment, - const SMDS_MeshNode* n0, - const SMDS_MeshNode* n1, - const SMDS_MeshNode* n2, - double& t, - const double& EPSILON) const +bool _LayerEdge::SegTriaInter( const gp_Ax1& lastSegment, + const gp_XYZ& vert0, + const gp_XYZ& vert1, + const gp_XYZ& vert2, + double& t, + const double& EPSILON) const { - //const double EPSILON = 1e-6; - const gp_Pnt& orig = lastSegment.Location(); const gp_Dir& dir = lastSegment.Direction(); - SMESH_TNodeXYZ vert0( n0 ); - SMESH_TNodeXYZ vert1( n1 ); - SMESH_TNodeXYZ vert2( n2 ); - /* calculate distance from vert0 to ray origin */ gp_XYZ tvec = orig.XYZ() - vert0; @@ -5395,13 +7284,14 @@ bool _LayerEdge::SegTriaInter( const gp_Ax1& lastSegment, /* if determinant is near zero, ray lies in plane of triangle */ double det = edge1 * pvec; - if (det > -EPSILON && det < EPSILON) + const double ANGL_EPSILON = 1e-12; + if ( det > -ANGL_EPSILON && det < ANGL_EPSILON ) return false; /* calculate U parameter and test bounds */ double u = ( tvec * pvec ) / det; //if (u < 0.0 || u > 1.0) - if (u < -EPSILON || u > 1.0 + EPSILON) + if ( u < -EPSILON || u > 1.0 + EPSILON ) return false; /* prepare to test V parameter */ @@ -5410,7 +7300,7 @@ bool _LayerEdge::SegTriaInter( const gp_Ax1& lastSegment, /* calculate V parameter and test bounds */ double v = (dir.XYZ() * qvec) / det; //if ( v < 0.0 || u + v > 1.0 ) - if ( v < -EPSILON || u + v > 1.0 + EPSILON) + if ( v < -EPSILON || u + v > 1.0 + EPSILON ) return false; /* calculate t, ray intersects triangle */ @@ -5420,6 +7310,158 @@ bool _LayerEdge::SegTriaInter( const gp_Ax1& lastSegment, return t > 0.; } +//================================================================================ +/*! + * \brief _LayerEdge, located at a concave VERTEX of a FACE, moves target nodes of + * neighbor _LayerEdge's by it's own inflation vector. + * \param [in] eov - EOS of the VERTEX + * \param [in] eos - EOS of the FACE + * \param [in] step - inflation step + * \param [in,out] badSmooEdges - not untangled _LayerEdge's + */ +//================================================================================ + +void _LayerEdge::MoveNearConcaVer( const _EdgesOnShape* eov, + const _EdgesOnShape* eos, + const int step, + vector< _LayerEdge* > & badSmooEdges ) +{ + // check if any of _neibors is in badSmooEdges + if ( std::find_first_of( _neibors.begin(), _neibors.end(), + badSmooEdges.begin(), badSmooEdges.end() ) == _neibors.end() ) + return; + + // get all edges to move + + set< _LayerEdge* > edges; + + // find a distance between _LayerEdge on VERTEX and its neighbors + gp_XYZ curPosV = SMESH_TNodeXYZ( _nodes.back() ); + double dist2 = 0; + for ( size_t i = 0; i < _neibors.size(); ++i ) + { + _LayerEdge* nEdge = _neibors[i]; + if ( nEdge->_nodes[0]->getshapeId() == eos->_shapeID ) + { + edges.insert( nEdge ); + dist2 = Max( dist2, ( curPosV - nEdge->_pos.back() ).SquareModulus() ); + } + } + // add _LayerEdge's close to curPosV + size_t nbE; + do { + nbE = edges.size(); + for ( set< _LayerEdge* >::iterator e = edges.begin(); e != edges.end(); ++e ) + { + _LayerEdge* edgeF = *e; + for ( size_t i = 0; i < edgeF->_neibors.size(); ++i ) + { + _LayerEdge* nEdge = edgeF->_neibors[i]; + if ( nEdge->_nodes[0]->getshapeId() == eos->_shapeID && + dist2 > ( curPosV - nEdge->_pos.back() ).SquareModulus() ) + edges.insert( nEdge ); + } + } + } + while ( nbE < edges.size() ); + + // move the target node of the got edges + + gp_XYZ prevPosV = PrevPos(); + if ( eov->SWOLType() == TopAbs_EDGE ) + { + BRepAdaptor_Curve curve ( TopoDS::Edge( eov->_sWOL )); + prevPosV = curve.Value( prevPosV.X() ).XYZ(); + } + else if ( eov->SWOLType() == TopAbs_FACE ) + { + BRepAdaptor_Surface surface( TopoDS::Face( eov->_sWOL )); + prevPosV = surface.Value( prevPosV.X(), prevPosV.Y() ).XYZ(); + } + + SMDS_FacePosition* fPos; + //double r = 1. - Min( 0.9, step / 10. ); + for ( set< _LayerEdge* >::iterator e = edges.begin(); e != edges.end(); ++e ) + { + _LayerEdge* edgeF = *e; + const gp_XYZ prevVF = edgeF->PrevPos() - prevPosV; + const gp_XYZ newPosF = curPosV + prevVF; + SMDS_MeshNode* tgtNodeF = const_cast( edgeF->_nodes.back() ); + tgtNodeF->setXYZ( newPosF.X(), newPosF.Y(), newPosF.Z() ); + edgeF->_pos.back() = newPosF; + dumpMoveComm( tgtNodeF, "MoveNearConcaVer" ); // debug + + // set _curvature to make edgeF updated by putOnOffsetSurface() + if ( !edgeF->_curvature ) + if (( fPos = dynamic_cast( edgeF->_nodes[0]->GetPosition() ))) + { + edgeF->_curvature = new _Curvature; + edgeF->_curvature->_r = 0; + edgeF->_curvature->_k = 0; + edgeF->_curvature->_h2lenRatio = 0; + edgeF->_curvature->_uv.SetCoord( fPos->GetUParameter(), fPos->GetVParameter() ); + } + } + // gp_XYZ inflationVec( SMESH_TNodeXYZ( _nodes.back() ) - + // SMESH_TNodeXYZ( _nodes[0] )); + // for ( set< _LayerEdge* >::iterator e = edges.begin(); e != edges.end(); ++e ) + // { + // _LayerEdge* edgeF = *e; + // gp_XYZ newPos = SMESH_TNodeXYZ( edgeF->_nodes[0] ) + inflationVec; + // SMDS_MeshNode* tgtNode = const_cast( edgeF->_nodes.back() ); + // tgtNode->setXYZ( newPos.X(), newPos.Y(), newPos.Z() ); + // edgeF->_pos.back() = newPosF; + // dumpMoveComm( tgtNode, "MoveNearConcaVer" ); // debug + // } + + // smooth _LayerEdge's around moved nodes + //size_t nbBadBefore = badSmooEdges.size(); + for ( set< _LayerEdge* >::iterator e = edges.begin(); e != edges.end(); ++e ) + { + _LayerEdge* edgeF = *e; + for ( size_t j = 0; j < edgeF->_neibors.size(); ++j ) + if ( edgeF->_neibors[j]->_nodes[0]->getshapeId() == eos->_shapeID ) + //&& !edges.count( edgeF->_neibors[j] )) + { + _LayerEdge* edgeFN = edgeF->_neibors[j]; + edgeFN->Unset( SMOOTHED ); + int nbBad = edgeFN->Smooth( step, /*isConcaFace=*/true, /*findBest=*/true ); + // if ( nbBad > 0 ) + // { + // gp_XYZ newPos = SMESH_TNodeXYZ( edgeFN->_nodes[0] ) + inflationVec; + // const gp_XYZ& prevPos = edgeFN->_pos[ edgeFN->_pos.size()-2 ]; + // int nbBadAfter = edgeFN->_simplices.size(); + // double vol; + // for ( size_t iS = 0; iS < edgeFN->_simplices.size(); ++iS ) + // { + // nbBadAfter -= edgeFN->_simplices[iS].IsForward( &prevPos, &newPos, vol ); + // } + // if ( nbBadAfter <= nbBad ) + // { + // SMDS_MeshNode* tgtNode = const_cast( edgeFN->_nodes.back() ); + // tgtNode->setXYZ( newPos.X(), newPos.Y(), newPos.Z() ); + // edgeF->_pos.back() = newPosF; + // dumpMoveComm( tgtNode, "MoveNearConcaVer 2" ); // debug + // nbBad = nbBadAfter; + // } + // } + if ( nbBad > 0 ) + badSmooEdges.push_back( edgeFN ); + } + } + // move a bit not smoothed around moved nodes + // for ( size_t i = nbBadBefore; i < badSmooEdges.size(); ++i ) + // { + // _LayerEdge* edgeF = badSmooEdges[i]; + // SMDS_MeshNode* tgtNode = const_cast( edgeF->_nodes.back() ); + // gp_XYZ newPos1 = SMESH_TNodeXYZ( edgeF->_nodes[0] ) + inflationVec; + // gp_XYZ newPos2 = 0.5 * ( newPos1 + SMESH_TNodeXYZ( tgtNode )); + // tgtNode->setXYZ( newPos2.X(), newPos2.Y(), newPos2.Z() ); + // edgeF->_pos.back() = newPosF; + // dumpMoveComm( tgtNode, "MoveNearConcaVer 2" ); // debug + // } +} + //================================================================================ /*! * \brief Perform smooth of _LayerEdge's based on EDGE's @@ -5427,9 +7469,9 @@ bool _LayerEdge::SegTriaInter( const gp_Ax1& lastSegment, */ //================================================================================ -bool _LayerEdge::SmoothOnEdge(Handle(Geom_Surface)& surface, - const TopoDS_Face& F, - SMESH_MesherHelper& helper) +bool _LayerEdge::SmoothOnEdge(Handle(ShapeAnalysis_Surface)& surface, + const TopoDS_Face& F, + SMESH_MesherHelper& helper) { ASSERT( IsOnEdge() ); @@ -5471,7 +7513,7 @@ bool _LayerEdge::SmoothOnEdge(Handle(Geom_Surface)& surface, helper.CheckNodeUV( F, tgtNode, uv, 1e-10, /*force=*/true ); _pos.back().SetCoord( uv.X(), uv.Y(), 0 ); - newPos = surface->Value( uv.X(), uv.Y() ); + newPos = surface->Value( uv ); tgtNode->setXYZ( newPos.X(), newPos.Y(), newPos.Z() ); } @@ -5491,38 +7533,153 @@ bool _LayerEdge::SmoothOnEdge(Handle(Geom_Surface)& surface, //================================================================================ /*! - * \brief Perform laplacian smooth in 3D of nodes inflated from FACE - * \retval bool - true if _tgtNode has been moved + * \brief Perform 3D smooth of nodes inflated from FACE. No check of validity */ //================================================================================ -int _LayerEdge::Smooth(const int step, const bool isConcaveFace, const bool findBest ) +void _LayerEdge::SmoothWoCheck() { + if ( Is( DIFFICULT )) + return; + + bool moved = Is( SMOOTHED ); + for ( size_t i = 0; i < _neibors.size() && !moved; ++i ) + moved = _neibors[i]->Is( SMOOTHED ); + if ( !moved ) + return; + + gp_XYZ newPos = (this->*_smooFunction)(); // fun chosen by ChooseSmooFunction() + + SMDS_MeshNode* n = const_cast< SMDS_MeshNode* >( _nodes.back() ); + n->setXYZ( newPos.X(), newPos.Y(), newPos.Z()); + _pos.back() = newPos; + + dumpMoveComm( n, SMESH_Comment("No check - ") << _funNames[ smooFunID() ]); +} + +//================================================================================ +/*! + * \brief Checks validity of _neibors on EDGEs and VERTEXes + */ +//================================================================================ + +int _LayerEdge::CheckNeiborsOnBoundary( vector< _LayerEdge* >* badNeibors, bool * needSmooth ) +{ + if ( ! Is( NEAR_BOUNDARY )) + return 0; + + int nbBad = 0; + double vol; + for ( size_t iN = 0; iN < _neibors.size(); ++iN ) + { + _LayerEdge* eN = _neibors[iN]; + if ( eN->_nodes[0]->getshapeId() == _nodes[0]->getshapeId() ) + continue; + if ( needSmooth ) + *needSmooth |= ( eN->Is( _LayerEdge::BLOCKED ) || eN->Is( _LayerEdge::NORMAL_UPDATED )); + + SMESH_TNodeXYZ curPosN ( eN->_nodes.back() ); + SMESH_TNodeXYZ prevPosN( eN->_nodes[0] ); + for ( size_t i = 0; i < eN->_simplices.size(); ++i ) + if ( eN->_nodes.size() > 1 && + eN->_simplices[i].Includes( _nodes.back() ) && + !eN->_simplices[i].IsForward( &prevPosN, &curPosN, vol )) + { + ++nbBad; + if ( badNeibors ) + { + badNeibors->push_back( eN ); + debugMsg("Bad boundary simplex ( " + << " "<< eN->_nodes[0]->GetID() + << " "<< eN->_nodes.back()->GetID() + << " "<< eN->_simplices[i]._nPrev->GetID() + << " "<< eN->_simplices[i]._nNext->GetID() << " )" ); + } + else + { + break; + } + } + } + return nbBad; +} + +//================================================================================ +/*! + * \brief Perform 'smart' 3D smooth of nodes inflated from FACE + * \retval int - nb of bad simplices around this _LayerEdge + */ +//================================================================================ + +int _LayerEdge::Smooth(const int step, bool findBest, vector< _LayerEdge* >& toSmooth ) +{ + if ( !Is( MOVED ) || Is( SMOOTHED ) || Is( BLOCKED )) + return 0; // shape of simplices not changed if ( _simplices.size() < 2 ) return 0; // _LayerEdge inflated along EDGE or FACE - const gp_XYZ& curPos ( _pos.back() ); - const gp_XYZ& prevPos( _pos[ _pos.size()-2 ]); + if ( Is( DIFFICULT )) // || Is( ON_CONCAVE_FACE ) + findBest = true; + + const gp_XYZ& curPos = _pos.back(); + const gp_XYZ& prevPos = PrevCheckPos(); // quality metrics (orientation) of tetras around _tgtNode int nbOkBefore = 0; double vol, minVolBefore = 1e100; for ( size_t i = 0; i < _simplices.size(); ++i ) { - nbOkBefore += _simplices[i].IsForward( _nodes[0], &curPos, vol ); + nbOkBefore += _simplices[i].IsForward( &prevPos, &curPos, vol ); minVolBefore = Min( minVolBefore, vol ); } int nbBad = _simplices.size() - nbOkBefore; + bool bndNeedSmooth = false; + if ( nbBad == 0 ) + nbBad = CheckNeiborsOnBoundary( 0, & bndNeedSmooth ); + if ( nbBad > 0 ) + Set( DISTORTED ); + + // evaluate min angle + if ( nbBad == 0 && !findBest && !bndNeedSmooth ) + { + size_t nbGoodAngles = _simplices.size(); + double angle; + for ( size_t i = 0; i < _simplices.size(); ++i ) + { + if ( !_simplices[i].IsMinAngleOK( curPos, angle ) && angle > _minAngle ) + --nbGoodAngles; + } + if ( nbGoodAngles == _simplices.size() ) + { + Unset( MOVED ); + return 0; + } + } + if ( Is( ON_CONCAVE_FACE )) + findBest = true; + + if ( step % 2 == 0 ) + findBest = false; + + if ( Is( ON_CONCAVE_FACE ) && !findBest ) // alternate FUN_CENTROIDAL and FUN_LAPLACIAN + { + if ( _smooFunction == _funs[ FUN_LAPLACIAN ] ) + _smooFunction = _funs[ FUN_CENTROIDAL ]; + else + _smooFunction = _funs[ FUN_LAPLACIAN ]; + } + // compute new position for the last _pos using different _funs gp_XYZ newPos; + bool moved = false; for ( int iFun = -1; iFun < theNbSmooFuns; ++iFun ) { if ( iFun < 0 ) newPos = (this->*_smooFunction)(); // fun chosen by ChooseSmooFunction() else if ( _funs[ iFun ] == _smooFunction ) continue; // _smooFunction again - else if ( step > 0 ) + else if ( step > 1 ) newPos = (this->*_funs[ iFun ])(); // try other smoothing fun else break; // let "easy" functions improve elements around distorted ones @@ -5546,7 +7703,122 @@ int _LayerEdge::Smooth(const int step, const bool isConcaveFace, const bool find double minVolAfter = 1e100; for ( size_t i = 0; i < _simplices.size(); ++i ) { - nbOkAfter += _simplices[i].IsForward( _nodes[0], &newPos, vol ); + nbOkAfter += _simplices[i].IsForward( &prevPos, &newPos, vol ); + minVolAfter = Min( minVolAfter, vol ); + } + // get worse? + if ( nbOkAfter < nbOkBefore ) + continue; + + if (( findBest ) && + ( nbOkAfter == nbOkBefore ) && + ( minVolAfter <= minVolBefore )) + continue; + + nbBad = _simplices.size() - nbOkAfter; + minVolBefore = minVolAfter; + nbOkBefore = nbOkAfter; + moved = true; + + SMDS_MeshNode* n = const_cast< SMDS_MeshNode* >( _nodes.back() ); + n->setXYZ( newPos.X(), newPos.Y(), newPos.Z()); + _pos.back() = newPos; + + dumpMoveComm( n, SMESH_Comment( _funNames[ iFun < 0 ? smooFunID() : iFun ] ) + << (nbBad ? " --BAD" : "")); + + if ( iFun > -1 ) + { + continue; // look for a better function + } + + if ( !findBest ) + break; + + } // loop on smoothing functions + + if ( moved ) // notify _neibors + { + Set( SMOOTHED ); + for ( size_t i = 0; i < _neibors.size(); ++i ) + if ( !_neibors[i]->Is( MOVED )) + { + _neibors[i]->Set( MOVED ); + toSmooth.push_back( _neibors[i] ); + } + } + + return nbBad; +} + +//================================================================================ +/*! + * \brief Perform 'smart' 3D smooth of nodes inflated from FACE + * \retval int - nb of bad simplices around this _LayerEdge + */ +//================================================================================ + +int _LayerEdge::Smooth(const int step, const bool isConcaveFace, bool findBest ) +{ + if ( !_smooFunction ) + return 0; // _LayerEdge inflated along EDGE or FACE + if ( Is( BLOCKED )) + return 0; // not inflated + + const gp_XYZ& curPos = _pos.back(); + const gp_XYZ& prevPos = PrevCheckPos(); + + // quality metrics (orientation) of tetras around _tgtNode + int nbOkBefore = 0; + double vol, minVolBefore = 1e100; + for ( size_t i = 0; i < _simplices.size(); ++i ) + { + nbOkBefore += _simplices[i].IsForward( &prevPos, &curPos, vol ); + minVolBefore = Min( minVolBefore, vol ); + } + int nbBad = _simplices.size() - nbOkBefore; + + if ( isConcaveFace ) // alternate FUN_CENTROIDAL and FUN_LAPLACIAN + { + if ( _smooFunction == _funs[ FUN_CENTROIDAL ] && step % 2 ) + _smooFunction = _funs[ FUN_LAPLACIAN ]; + else if ( _smooFunction == _funs[ FUN_LAPLACIAN ] && !( step % 2 )) + _smooFunction = _funs[ FUN_CENTROIDAL ]; + } + + // compute new position for the last _pos using different _funs + gp_XYZ newPos; + for ( int iFun = -1; iFun < theNbSmooFuns; ++iFun ) + { + if ( iFun < 0 ) + newPos = (this->*_smooFunction)(); // fun chosen by ChooseSmooFunction() + else if ( _funs[ iFun ] == _smooFunction ) + continue; // _smooFunction again + else if ( step > 1 ) + newPos = (this->*_funs[ iFun ])(); // try other smoothing fun + else + break; // let "easy" functions improve elements around distorted ones + + if ( _curvature ) + { + double delta = _curvature->lenDelta( _len ); + if ( delta > 0 ) + newPos += _normal * delta; + else + { + double segLen = _normal * ( newPos - prevPos ); + if ( segLen + delta > 0 ) + newPos += _normal * delta; + } + // double segLenChange = _normal * ( curPos - newPos ); + // newPos += 0.5 * _normal * segLenChange; + } + + int nbOkAfter = 0; + double minVolAfter = 1e100; + for ( size_t i = 0; i < _simplices.size(); ++i ) + { + nbOkAfter += _simplices[i].IsForward( &prevPos, &newPos, vol ); minVolAfter = Min( minVolAfter, vol ); } // get worse? @@ -5554,23 +7826,26 @@ int _LayerEdge::Smooth(const int step, const bool isConcaveFace, const bool find continue; if (( isConcaveFace || findBest ) && ( nbOkAfter == nbOkBefore ) && - //( iFun > -1 || nbOkAfter < _simplices.size() ) && - ( minVolAfter <= minVolBefore )) + ( minVolAfter <= minVolBefore ) + ) continue; + nbBad = _simplices.size() - nbOkAfter; + minVolBefore = minVolAfter; + nbOkBefore = nbOkAfter; + SMDS_MeshNode* n = const_cast< SMDS_MeshNode* >( _nodes.back() ); + n->setXYZ( newPos.X(), newPos.Y(), newPos.Z()); + _pos.back() = newPos; + + dumpMoveComm( n, SMESH_Comment( _funNames[ iFun < 0 ? smooFunID() : iFun ] ) + << ( nbBad ? "--BAD" : "")); // commented for IPAL0052478 // _len -= prevPos.Distance(SMESH_TNodeXYZ( n )); // _len += prevPos.Distance(newPos); - n->setXYZ( newPos.X(), newPos.Y(), newPos.Z()); - _pos.back() = newPos; - dumpMoveComm( n, _funNames[ iFun < 0 ? smooFunID() : iFun ]); - - nbBad = _simplices.size() - nbOkAfter; - - if ( iFun > -1 ) + if ( iFun > -1 ) // findBest || the chosen _fun makes worse { //_smooFunction = _funs[ iFun ]; // cout << "# " << _funNames[ iFun ] << "\t N:" << _nodes.back()->GetID() @@ -5578,8 +7853,6 @@ int _LayerEdge::Smooth(const int step, const bool isConcaveFace, const bool find // << " minVol: " << minVolAfter // << " " << newPos.X() << " " << newPos.Y() << " " << newPos.Z() // << endl; - minVolBefore = minVolAfter; - nbOkBefore = nbOkAfter; continue; // look for a better function } @@ -5606,6 +7879,10 @@ void _LayerEdge::ChooseSmooFunction( const set< TGeomID >& concaveVertices, // use smoothNefPolygon() near concaveVertices if ( !concaveVertices.empty() ) { + _smooFunction = _funs[ FUN_CENTROIDAL ]; + + Set( ON_CONCAVE_FACE ); + for ( size_t i = 0; i < _simplices.size(); ++i ) { if ( concaveVertices.count( _simplices[i]._nPrev->getshapeId() )) @@ -5613,39 +7890,36 @@ void _LayerEdge::ChooseSmooFunction( const set< TGeomID >& concaveVertices, _smooFunction = _funs[ FUN_NEFPOLY ]; // set FUN_CENTROIDAL to neighbor edges - TNode2Edge::const_iterator n2e; - for ( i = 0; i < _simplices.size(); ++i ) + for ( i = 0; i < _neibors.size(); ++i ) { - if (( _simplices[i]._nPrev->GetPosition()->GetDim() == 2 ) && - (( n2e = n2eMap.find( _simplices[i]._nPrev )) != n2eMap.end() )) + if ( _neibors[i]->_nodes[0]->GetPosition()->GetDim() == 2 ) { - n2e->second->_smooFunction = _funs[ FUN_CENTROIDAL ]; + _neibors[i]->_smooFunction = _funs[ FUN_CENTROIDAL ]; } } return; } } - //} - // this coice is done only if ( !concaveVertices.empty() ) for Grids/smesh/bugs_19/X1 - // where the nodes are smoothed too far along a sphere thus creating - // inverted _simplices - double dist[theNbSmooFuns]; - //double coef[theNbSmooFuns] = { 1., 1.2, 1.4, 1.4 }; - double coef[theNbSmooFuns] = { 1., 1., 1., 1. }; + // // this coice is done only if ( !concaveVertices.empty() ) for Grids/smesh/bugs_19/X1 + // // where the nodes are smoothed too far along a sphere thus creating + // // inverted _simplices + // double dist[theNbSmooFuns]; + // //double coef[theNbSmooFuns] = { 1., 1.2, 1.4, 1.4 }; + // double coef[theNbSmooFuns] = { 1., 1., 1., 1. }; - double minDist = Precision::Infinite(); - gp_Pnt p = SMESH_TNodeXYZ( _nodes[0] ); - for ( int i = 0; i < FUN_NEFPOLY; ++i ) - { - gp_Pnt newP = (this->*_funs[i])(); - dist[i] = p.SquareDistance( newP ); - if ( dist[i]*coef[i] < minDist ) - { - _smooFunction = _funs[i]; - minDist = dist[i]*coef[i]; - } - } + // double minDist = Precision::Infinite(); + // gp_Pnt p = SMESH_TNodeXYZ( _nodes[0] ); + // for ( int i = 0; i < FUN_NEFPOLY; ++i ) + // { + // gp_Pnt newP = (this->*_funs[i])(); + // dist[i] = p.SquareDistance( newP ); + // if ( dist[i]*coef[i] < minDist ) + // { + // _smooFunction = _funs[i]; + // minDist = dist[i]*coef[i]; + // } + // } } else { @@ -5714,9 +7988,9 @@ gp_XYZ _LayerEdge::smoothLaplacian() gp_XYZ _LayerEdge::smoothAngular() { - vector< gp_Vec > edgeDir; edgeDir. reserve( _simplices.size() + 1); - vector< double > edgeSize; edgeSize.reserve( _simplices.size() ); - vector< gp_XYZ > points; points. reserve( _simplices.size() ); + vector< gp_Vec > edgeDir; edgeDir. reserve( _simplices.size() + 1 ); + vector< double > edgeSize; edgeSize.reserve( _simplices.size() ); + vector< gp_XYZ > points; points. reserve( _simplices.size() + 1 ); gp_XYZ pPrev = SMESH_TNodeXYZ( _simplices.back()._nPrev ); gp_XYZ pN( 0,0,0 ); @@ -5725,7 +7999,6 @@ gp_XYZ _LayerEdge::smoothAngular() gp_XYZ p = SMESH_TNodeXYZ( _simplices[i]._nPrev ); edgeDir.push_back( p - pPrev ); edgeSize.push_back( edgeDir.back().Magnitude() ); - //double edgeSize = edgeDir.back().Magnitude(); if ( edgeSize.back() < numeric_limits::min() ) { edgeDir.pop_back(); @@ -5744,18 +8017,17 @@ gp_XYZ _LayerEdge::smoothAngular() pN /= points.size(); gp_XYZ newPos(0,0,0); - //gp_XYZ pN = SMESH_TNodeXYZ( _nodes.back() ); double sumSize = 0; for ( size_t i = 0; i < points.size(); ++i ) { - gp_Vec toN( pN - points[i]); + gp_Vec toN = pN - points[i]; double toNLen = toN.Magnitude(); if ( toNLen < numeric_limits::min() ) { newPos += pN; continue; } - gp_Vec bisec = edgeDir[i] + edgeDir[i+1]; + gp_Vec bisec = edgeDir[i] + edgeDir[i+1]; double bisecLen = bisec.SquareMagnitude(); if ( bisecLen < numeric_limits::min() ) { @@ -5767,7 +8039,6 @@ gp_XYZ _LayerEdge::smoothAngular() bisec /= bisecLen; #if 1 - //bisecLen = 1.; gp_XYZ pNew = ( points[i] + bisec.XYZ() * toNLen ) * bisecLen; sumSize += bisecLen; #else @@ -5778,6 +8049,29 @@ gp_XYZ _LayerEdge::smoothAngular() } newPos /= sumSize; + // project newPos to an average plane + + gp_XYZ norm(0,0,0); // plane normal + points.push_back( points[0] ); + for ( size_t i = 1; i < points.size(); ++i ) + { + gp_XYZ vec1 = points[ i-1 ] - pN; + gp_XYZ vec2 = points[ i ] - pN; + gp_XYZ cross = vec1 ^ vec2; + try { + cross.Normalize(); + if ( cross * norm < numeric_limits::min() ) + norm += cross.Reversed(); + else + norm += cross; + } + catch (Standard_Failure) { // if |cross| == 0. + } + } + gp_XYZ vec = newPos - pN; + double r = ( norm * vec ) / norm.SquareModulus(); // param [0,1] on norm + newPos = newPos - r * norm; + return newPos; } @@ -5853,6 +8147,7 @@ gp_XYZ _LayerEdge::smoothCentroidal() //================================================================================ gp_XYZ _LayerEdge::smoothNefPolygon() +#ifdef OLD_NEF_POLYGON { gp_XYZ newPos(0,0,0); @@ -5963,7 +8258,7 @@ gp_XYZ _LayerEdge::smoothNefPolygon() ips1.first = halfPlns[ iHP1 ]._pos; else if ( iHP2 == iNext ) ips1.first = halfPlns[ iHP2 ]._pos; - else if ( !halfPlns[ iHP1 ].FindInterestion( halfPlns[ iHP2 ], ips1.first )) + else if ( !halfPlns[ iHP1 ].FindIntersection( halfPlns[ iHP2 ], ips1.first )) ips1.second = NO_INT; // classify the found intersection point @@ -6043,6 +8338,208 @@ gp_XYZ _LayerEdge::smoothNefPolygon() return newPos; } +#else // OLD_NEF_POLYGON +{ ////////////////////////////////// NEW + gp_XYZ newPos(0,0,0); + + // get a plane to seach a solution on + + size_t i; + gp_XYZ center(0,0,0); + for ( i = 0; i < _simplices.size(); ++i ) + center += SMESH_TNodeXYZ( _simplices[i]._nPrev ); + center /= _simplices.size(); + + vector< gp_XYZ > vecs( _simplices.size() + 1 ); + for ( i = 0; i < _simplices.size(); ++i ) + vecs[i] = SMESH_TNodeXYZ( _simplices[i]._nPrev ) - center; + vecs.back() = vecs[0]; + + const double tol = numeric_limits::min(); + gp_XYZ zAxis(0,0,0); + for ( i = 0; i < _simplices.size(); ++i ) + { + gp_XYZ cross = vecs[i] ^ vecs[i+1]; + try { + cross.Normalize(); + if ( cross * zAxis < tol ) + zAxis += cross.Reversed(); + else + zAxis += cross; + } + catch (Standard_Failure) { // if |cross| == 0. + } + } + + gp_XYZ yAxis; + for ( i = 0; i < _simplices.size(); ++i ) + { + yAxis = vecs[i]; + if ( yAxis.SquareModulus() > tol ) + break; + } + gp_XYZ xAxis = yAxis ^ zAxis; + // SMESH_TNodeXYZ p0( _simplices[0]._nPrev ); + // const double tol = 1e-6 * ( p0.Distance( _simplices[1]._nPrev ) + + // p0.Distance( _simplices[2]._nPrev )); + // gp_XYZ center = smoothLaplacian(); + // gp_XYZ xAxis, yAxis, zAxis; + // for ( i = 0; i < _simplices.size(); ++i ) + // { + // xAxis = SMESH_TNodeXYZ( _simplices[i]._nPrev ) - center; + // if ( xAxis.SquareModulus() > tol*tol ) + // break; + // } + // for ( i = 1; i < _simplices.size(); ++i ) + // { + // yAxis = SMESH_TNodeXYZ( _simplices[i]._nPrev ) - center; + // zAxis = xAxis ^ yAxis; + // if ( zAxis.SquareModulus() > tol*tol ) + // break; + // } + // if ( i == _simplices.size() ) return newPos; + + yAxis = zAxis ^ xAxis; + xAxis /= xAxis.Modulus(); + yAxis /= yAxis.Modulus(); + + // get half-planes of _simplices + + vector< _halfPlane > halfPlns( _simplices.size() ); + int nbHP = 0; + for ( size_t i = 0; i < _simplices.size(); ++i ) + { + const gp_XYZ& OP1 = vecs[ i ]; + const gp_XYZ& OP2 = vecs[ i+1 ]; + gp_XY p1( OP1 * xAxis, OP1 * yAxis ); + gp_XY p2( OP2 * xAxis, OP2 * yAxis ); + gp_XY vec12 = p2 - p1; + double dist12 = vec12.Modulus(); + if ( dist12 < tol ) + continue; + vec12 /= dist12; + halfPlns[ nbHP ]._pos = p1; + halfPlns[ nbHP ]._dir = vec12; + halfPlns[ nbHP ]._inNorm.SetCoord( -vec12.Y(), vec12.X() ); + ++nbHP; + } + + // intersect boundaries of half-planes, define state of intersection points + // in relation to all half-planes and calculate internal point of a 2D polygon + + double sumLen = 0; + gp_XY newPos2D (0,0); + + enum { UNDEF = -1, NOT_OUT, IS_OUT, NO_INT }; + typedef std::pair< gp_XY, int > TIntPntState; // coord and isOut state + TIntPntState undefIPS( gp_XY(1e100,1e100), UNDEF ); + + vector< vector< TIntPntState > > allIntPnts( nbHP ); + for ( int iHP1 = 0; iHP1 < nbHP; ++iHP1 ) + { + vector< TIntPntState > & intPnts1 = allIntPnts[ iHP1 ]; + if ( intPnts1.empty() ) intPnts1.resize( nbHP, undefIPS ); + + int iPrev = SMESH_MesherHelper::WrapIndex( iHP1 - 1, nbHP ); + int iNext = SMESH_MesherHelper::WrapIndex( iHP1 + 1, nbHP ); + + int nbNotOut = 0; + const gp_XY* segEnds[2] = { 0, 0 }; // NOT_OUT points + + for ( int iHP2 = 0; iHP2 < nbHP; ++iHP2 ) + { + if ( iHP1 == iHP2 ) continue; + + TIntPntState & ips1 = intPnts1[ iHP2 ]; + if ( ips1.second == UNDEF ) + { + // find an intersection point of boundaries of iHP1 and iHP2 + + if ( iHP2 == iPrev ) // intersection with neighbors is known + ips1.first = halfPlns[ iHP1 ]._pos; + else if ( iHP2 == iNext ) + ips1.first = halfPlns[ iHP2 ]._pos; + else if ( !halfPlns[ iHP1 ].FindIntersection( halfPlns[ iHP2 ], ips1.first )) + ips1.second = NO_INT; + + // classify the found intersection point + if ( ips1.second != NO_INT ) + { + ips1.second = NOT_OUT; + for ( int i = 0; i < nbHP && ips1.second == NOT_OUT; ++i ) + if ( i != iHP1 && i != iHP2 && + halfPlns[ i ].IsOut( ips1.first, tol )) + ips1.second = IS_OUT; + } + vector< TIntPntState > & intPnts2 = allIntPnts[ iHP2 ]; + if ( intPnts2.empty() ) intPnts2.resize( nbHP, undefIPS ); + TIntPntState & ips2 = intPnts2[ iHP1 ]; + ips2 = ips1; + } + if ( ips1.second == NOT_OUT ) + { + ++nbNotOut; + segEnds[ bool(segEnds[0]) ] = & ips1.first; + } + } + + // find a NOT_OUT segment of boundary which is located between + // two NOT_OUT int points + + if ( nbNotOut < 2 ) + continue; // no such a segment + + if ( nbNotOut > 2 ) + { + // sort points along the boundary + map< double, TIntPntState* > ipsByParam; + for ( int iHP2 = 0; iHP2 < nbHP; ++iHP2 ) + { + TIntPntState & ips1 = intPnts1[ iHP2 ]; + if ( ips1.second != NO_INT ) + { + gp_XY op = ips1.first - halfPlns[ iHP1 ]._pos; + double param = op * halfPlns[ iHP1 ]._dir; + ipsByParam.insert( make_pair( param, & ips1 )); + } + } + // look for two neighboring NOT_OUT points + nbNotOut = 0; + map< double, TIntPntState* >::iterator u2ips = ipsByParam.begin(); + for ( ; u2ips != ipsByParam.end(); ++u2ips ) + { + TIntPntState & ips1 = *(u2ips->second); + if ( ips1.second == NOT_OUT ) + segEnds[ bool( nbNotOut++ ) ] = & ips1.first; + else if ( nbNotOut >= 2 ) + break; + else + nbNotOut = 0; + } + } + + if ( nbNotOut >= 2 ) + { + double len = ( *segEnds[0] - *segEnds[1] ).Modulus(); + sumLen += len; + + newPos2D += 0.5 * len * ( *segEnds[0] + *segEnds[1] ); + } + } + + if ( sumLen > 0 ) + { + newPos2D /= sumLen; + newPos = center + xAxis * newPos2D.X() + yAxis * newPos2D.Y(); + } + else + { + newPos = center; + } + + return newPos; +} +#endif // OLD_NEF_POLYGON //================================================================================ /*! @@ -6052,9 +8549,18 @@ gp_XYZ _LayerEdge::smoothNefPolygon() void _LayerEdge::SetNewLength( double len, _EdgesOnShape& eos, SMESH_MesherHelper& helper ) { - if ( _len - len > -1e-6 ) + if ( Is( BLOCKED )) + return; + + if ( len > _maxLen ) { - //_pos.push_back( _pos.back() ); + len = _maxLen; + Block( eos.GetData() ); + } + const double lenDelta = len - _len; + if ( lenDelta < len * 1e-3 ) + { + Block( eos.GetData() ); return; } @@ -6073,36 +8579,37 @@ void _LayerEdge::SetNewLength( double len, _EdgesOnShape& eos, SMESH_MesherHelpe continue; // translate plane of a face - gp_XYZ baryCenter = oldXYZ + faceNorm.XYZ() * ( len - _len ); + gp_XYZ baryCenter = oldXYZ + faceNorm.XYZ() * lenDelta; // find point of intersection of the face plane located at baryCenter // and _normal located at newXYZ double d = -( faceNorm.XYZ() * baryCenter ); // d of plane equation ax+by+cz+d=0 double dot = ( faceNorm.XYZ() * _normal ); if ( dot < std::numeric_limits::min() ) - dot = ( len - _len ) * 1e-3; + dot = lenDelta * 1e-3; double step = -( faceNorm.XYZ() * newXYZ + d ) / dot; newXYZ += step * _normal; } } else { - newXYZ = oldXYZ + _normal * ( len - _len ) * _lenFactor; + newXYZ = oldXYZ + _normal * lenDelta * _lenFactor; } - n->setXYZ( newXYZ.X(), newXYZ.Y(), newXYZ.Z() ); + n->setXYZ( newXYZ.X(), newXYZ.Y(), newXYZ.Z() ); _pos.push_back( newXYZ ); - _len = len; if ( !eos._sWOL.IsNull() ) { double distXYZ[4]; + bool uvOK = false; if ( eos.SWOLType() == TopAbs_EDGE ) { double u = Precision::Infinite(); // to force projection w/o distance check - helper.CheckNodeU( TopoDS::Edge( eos._sWOL ), n, u, 1e-10, /*force=*/true, distXYZ ); + uvOK = helper.CheckNodeU( TopoDS::Edge( eos._sWOL ), n, u, + /*tol=*/2*lenDelta, /*force=*/true, distXYZ ); _pos.back().SetCoord( u, 0, 0 ); - if ( _nodes.size() > 1 ) + if ( _nodes.size() > 1 && uvOK ) { SMDS_EdgePosition* pos = static_cast( n->GetPosition() ); pos->SetUParameter( u ); @@ -6111,36 +8618,113 @@ void _LayerEdge::SetNewLength( double len, _EdgesOnShape& eos, SMESH_MesherHelpe else // TopAbs_FACE { gp_XY uv( Precision::Infinite(), 0 ); - helper.CheckNodeUV( TopoDS::Face( eos._sWOL ), n, uv, 1e-10, /*force=*/true, distXYZ ); + uvOK = helper.CheckNodeUV( TopoDS::Face( eos._sWOL ), n, uv, + /*tol=*/2*lenDelta, /*force=*/true, distXYZ ); _pos.back().SetCoord( uv.X(), uv.Y(), 0 ); - if ( _nodes.size() > 1 ) + if ( _nodes.size() > 1 && uvOK ) { SMDS_FacePosition* pos = static_cast( n->GetPosition() ); pos->SetUParameter( uv.X() ); pos->SetVParameter( uv.Y() ); } } - n->setXYZ( distXYZ[1], distXYZ[2], distXYZ[3]); + if ( uvOK ) + { + n->setXYZ( distXYZ[1], distXYZ[2], distXYZ[3]); + } + else + { + n->setXYZ( oldXYZ.X(), oldXYZ.Y(), oldXYZ.Z() ); + _pos.pop_back(); + Block( eos.GetData() ); + return; + } + } + + _len = len; + + // notify _neibors + if ( eos.ShapeType() != TopAbs_FACE ) + { + for ( size_t i = 0; i < _neibors.size(); ++i ) + //if ( _len > _neibors[i]->GetSmooLen() ) + _neibors[i]->Set( MOVED ); + + Set( MOVED ); } dumpMove( n ); //debug } +//================================================================================ +/*! + * \brief Set BLOCKED flag and propagate limited _maxLen to _neibors + */ +//================================================================================ + +void _LayerEdge::Block( _SolidData& data ) +{ + if ( Is( BLOCKED )) return; + Set( BLOCKED ); + + _maxLen = _len; + std::queue<_LayerEdge*> queue; + queue.push( this ); + + gp_Pnt pSrc, pTgt, pSrcN, pTgtN; + while ( !queue.empty() ) + { + _LayerEdge* edge = queue.front(); queue.pop(); + pSrc = SMESH_TNodeXYZ( edge->_nodes[0] ); + pTgt = SMESH_TNodeXYZ( edge->_nodes.back() ); + for ( size_t iN = 0; iN < edge->_neibors.size(); ++iN ) + { + _LayerEdge* neibor = edge->_neibors[iN]; + if ( neibor->Is( BLOCKED ) || + neibor->_maxLen < edge->_maxLen ) + continue; + pSrcN = SMESH_TNodeXYZ( neibor->_nodes[0] ); + pTgtN = SMESH_TNodeXYZ( neibor->_nodes.back() ); + double minDist = pSrc.SquareDistance( pSrcN ); + minDist = Min( pTgt.SquareDistance( pTgtN ), minDist ); + minDist = Min( pSrc.SquareDistance( pTgtN ), minDist ); + minDist = Min( pTgt.SquareDistance( pSrcN ), minDist ); + double newMaxLen = edge->_maxLen + 0.5 * Sqrt( minDist ); + if ( edge->_nodes[0]->getshapeId() == neibor->_nodes[0]->getshapeId() ) + { + newMaxLen *= edge->_lenFactor / neibor->_lenFactor; + } + if ( neibor->_maxLen > newMaxLen ) + { + neibor->_maxLen = newMaxLen; + if ( neibor->_maxLen < neibor->_len ) + { + _EdgesOnShape* eos = data.GetShapeEdges( neibor ); + while ( neibor->_len > neibor->_maxLen && + neibor->NbSteps() > 1 ) + neibor->InvalidateStep( neibor->NbSteps(), *eos, /*restoreLength=*/true ); + neibor->SetNewLength( neibor->_maxLen, *eos, data.GetHelper() ); + } + queue.push( neibor ); + } + } + } +} + //================================================================================ /*! * \brief Remove last inflation step */ //================================================================================ -void _LayerEdge::InvalidateStep( int curStep, const _EdgesOnShape& eos, bool restoreLength ) +void _LayerEdge::InvalidateStep( size_t curStep, const _EdgesOnShape& eos, bool restoreLength ) { - if ( _pos.size() > curStep ) + if ( _pos.size() > curStep && _nodes.size() > 1 ) { - if ( restoreLength ) - _len -= ( _pos[ curStep-1 ] - _pos.back() ).Modulus(); - _pos.resize( curStep ); - gp_Pnt nXYZ = _pos.back(); + + gp_Pnt nXYZ = _pos.back(); SMDS_MeshNode* n = const_cast< SMDS_MeshNode*>( _nodes.back() ); + SMESH_TNodeXYZ curXYZ( n ); if ( !eos._sWOL.IsNull() ) { TopLoc_Location loc; @@ -6163,9 +8747,90 @@ void _LayerEdge::InvalidateStep( int curStep, const _EdgesOnShape& eos, bool res } n->setXYZ( nXYZ.X(), nXYZ.Y(), nXYZ.Z() ); dumpMove( n ); + + if ( restoreLength ) + { + _len -= ( nXYZ.XYZ() - curXYZ ).Modulus() / _lenFactor; + } } } +//================================================================================ +/*! + * \brief Smooth a path formed by _pos of a _LayerEdge smoothed on FACE + */ +//================================================================================ + +void _LayerEdge::SmoothPos( const vector< double >& segLen, const double tol ) +{ + //return; + if ( /*Is( NORMAL_UPDATED ) ||*/ _pos.size() <= 2 ) + return; + + // find the 1st smoothed _pos + int iSmoothed = 0; + for ( size_t i = 1; i < _pos.size() && !iSmoothed; ++i ) + { + double normDist = ( _pos[i] - _pos[0] ).Crossed( _normal ).SquareModulus(); + if ( normDist > tol * tol ) + iSmoothed = i; + } + if ( !iSmoothed ) return; + + if ( 1 || Is( DISTORTED )) + { + // if ( segLen[ iSmoothed ] / segLen.back() < 0.5 ) + // return; + gp_XYZ normal = _normal; + if ( Is( NORMAL_UPDATED )) + for ( size_t i = 1; i < _pos.size(); ++i ) + { + normal = _pos[i] - _pos[0]; + double size = normal.Modulus(); + if ( size > RealSmall() ) + { + normal /= size; + break; + } + } + const double r = 0.2; + for ( int iter = 0; iter < 3; ++iter ) + { + double minDot = 1; + for ( size_t i = Max( 1, iSmoothed-1-iter ); i < _pos.size()-1; ++i ) + { + gp_XYZ midPos = 0.5 * ( _pos[i-1] + _pos[i+1] ); + gp_XYZ newPos = ( 1-r ) * midPos + r * _pos[i]; + _pos[i] = newPos; + double midLen = 0.5 * ( segLen[i-1] + segLen[i+1] ); + double newLen = ( 1-r ) * midLen + r * segLen[i]; + const_cast< double& >( segLen[i] ) = newLen; + // check angle between normal and (_pos[i+1], _pos[i] ) + gp_XYZ posDir = _pos[i+1] - _pos[i]; + double size = posDir.Modulus(); + if ( size > RealSmall() ) + minDot = Min( minDot, ( normal * posDir ) / size ); + } + if ( minDot > 0.5 ) + break; + } + } + // else + // { + // for ( size_t i = 1; i < _pos.size()-1; ++i ) + // { + // if ((int) i < iSmoothed && ( segLen[i] / segLen.back() < 0.5 )) + // continue; + + // double wgt = segLen[i] / segLen.back(); + // gp_XYZ normPos = _pos[0] + _normal * wgt * _len; + // gp_XYZ tgtPos = ( 1 - wgt ) * _pos[0] + wgt * _pos.back(); + // gp_XYZ newPos = ( 1 - wgt ) * normPos + wgt * tgtPos; + // _pos[i] = newPos; + // } + // } +} + //================================================================================ /*! * \brief Create layers of prisms @@ -6174,18 +8839,17 @@ void _LayerEdge::InvalidateStep( int curStep, const _EdgesOnShape& eos, bool res bool _ViscousBuilder::refine(_SolidData& data) { - SMESH_MesherHelper helper( *_mesh ); - helper.SetSubShape( data._solid ); + SMESH_MesherHelper& helper = data.GetHelper(); helper.SetElementsOnShape(false); Handle(Geom_Curve) curve; - Handle(Geom_Surface) surface; + Handle(ShapeAnalysis_Surface) surface; TopoDS_Edge geomEdge; TopoDS_Face geomFace; - TopoDS_Shape prevSWOL; TopLoc_Location loc; - double f,l, u; + double f,l, u = 0; gp_XY uv; + vector< gp_XYZ > pos3D; bool isOnEdge; TGeomID prevBaseId = -1; TNode2Edge* n2eMap = 0; @@ -6201,15 +8865,143 @@ bool _ViscousBuilder::refine(_SolidData& data) if ( eos._edges[0]->_nodes.size() < 2 ) continue; // on _noShrinkShapes + // get data of a shrink shape + isOnEdge = false; + geomEdge.Nullify(); geomFace.Nullify(); + curve.Nullify(); surface.Nullify(); + if ( !eos._sWOL.IsNull() ) + { + isOnEdge = ( eos.SWOLType() == TopAbs_EDGE ); + if ( isOnEdge ) + { + geomEdge = TopoDS::Edge( eos._sWOL ); + curve = BRep_Tool::Curve( geomEdge, loc, f,l); + } + else + { + geomFace = TopoDS::Face( eos._sWOL ); + surface = helper.GetSurface( geomFace ); + } + } + else if ( eos.ShapeType() == TopAbs_FACE && eos._toSmooth ) + { + geomFace = TopoDS::Face( eos._shape ); + surface = helper.GetSurface( geomFace ); + // propagate _toSmooth back to _eosC1, which was unset in findShapesToSmooth() + for ( size_t i = 0; i < eos._eosC1.size(); ++i ) + { + eos._eosC1[ i ]->_toSmooth = true; + for ( size_t j = 0; j < eos._eosC1[i]->_edges.size(); ++j ) + eos._eosC1[i]->_edges[j]->Set( _LayerEdge::SMOOTHED_C1 ); + } + } + + vector< double > segLen; for ( size_t i = 0; i < eos._edges.size(); ++i ) { _LayerEdge& edge = *eos._edges[i]; + if ( edge._pos.size() < 2 ) + continue; // get accumulated length of segments - vector< double > segLen( edge._pos.size() ); + segLen.resize( edge._pos.size() ); segLen[0] = 0.0; - for ( size_t j = 1; j < edge._pos.size(); ++j ) - segLen[j] = segLen[j-1] + (edge._pos[j-1] - edge._pos[j] ).Modulus(); + if ( eos._sWOL.IsNull() ) + { + bool useNormal = true; + bool usePos = false; + bool smoothed = false; + const double preci = 0.1 * edge._len; + if ( eos._toSmooth ) + { + gp_Pnt tgtExpected = edge._pos[0] + edge._normal * edge._len; + smoothed = tgtExpected.SquareDistance( edge._pos.back() ) > preci * preci; + } + if ( smoothed ) + { + if ( !surface.IsNull() && + !data._convexFaces.count( eos._shapeID )) // edge smoothed on FACE + { + useNormal = usePos = false; + gp_Pnt2d uv = helper.GetNodeUV( geomFace, edge._nodes[0] ); + for ( size_t j = 1; j < edge._pos.size() && !useNormal; ++j ) + { + uv = surface->NextValueOfUV( uv, edge._pos[j], preci ); + if ( surface->Gap() < 2. * edge._len ) + segLen[j] = surface->Gap(); + else + useNormal = true; + } + } + } + else + { + useNormal = usePos = false; + edge._pos[1] = edge._pos.back(); + edge._pos.resize( 2 ); + segLen.resize( 2 ); + segLen[ 1 ] = edge._len; + } + if ( useNormal && edge.Is( _LayerEdge::NORMAL_UPDATED )) + { + useNormal = usePos = false; + _LayerEdge tmpEdge; // get original _normal + tmpEdge._nodes.push_back( edge._nodes[0] ); + if ( !setEdgeData( tmpEdge, eos, helper, data )) + usePos = true; + else + for ( size_t j = 1; j < edge._pos.size(); ++j ) + segLen[j] = ( edge._pos[j] - edge._pos[0] ) * tmpEdge._normal; + } + if ( useNormal ) + { + for ( size_t j = 1; j < edge._pos.size(); ++j ) + segLen[j] = ( edge._pos[j] - edge._pos[0] ) * edge._normal; + } + if ( usePos ) + { + for ( size_t j = 1; j < edge._pos.size(); ++j ) + segLen[j] = segLen[j-1] + ( edge._pos[j-1] - edge._pos[j] ).Modulus(); + } + else + { + bool swapped = ( edge._pos.size() > 2 ); + while ( swapped ) + { + swapped = false; + for ( size_t j = 1; j < edge._pos.size(); ++j ) + if ( segLen[j] > segLen.back() ) + { + segLen.erase( segLen.begin() + j ); + edge._pos.erase( edge._pos.begin() + j ); + } + else if ( segLen[j] < segLen[j-1] ) + { + std::swap( segLen[j], segLen[j-1] ); + std::swap( edge._pos[j], edge._pos[j-1] ); + swapped = true; + } + } + } + // smooth a path formed by edge._pos + if (( smoothed ) /*&& + ( eos.ShapeType() == TopAbs_FACE || edge.Is( _LayerEdge::SMOOTHED_C1 ))*/) + edge.SmoothPos( segLen, preci ); + } + else if ( eos._isRegularSWOL ) // usual SWOL + { + for ( size_t j = 1; j < edge._pos.size(); ++j ) + segLen[j] = segLen[j-1] + (edge._pos[j-1] - edge._pos[j] ).Modulus(); + } + else if ( !surface.IsNull() ) // SWOL surface with singularities + { + pos3D.resize( edge._pos.size() ); + for ( size_t j = 0; j < edge._pos.size(); ++j ) + pos3D[j] = surface->Value( edge._pos[j].X(), edge._pos[j].Y() ).XYZ(); + + for ( size_t j = 1; j < edge._pos.size(); ++j ) + segLen[j] = segLen[j-1] + ( pos3D[j-1] - pos3D[j] ).Modulus(); + } // allocate memory for new nodes if it is not yet refined const SMDS_MeshNode* tgtNode = edge._nodes.back(); @@ -6219,34 +9011,20 @@ bool _ViscousBuilder::refine(_SolidData& data) edge._nodes[1] = 0; edge._nodes.back() = tgtNode; } - // get data of a shrink shape - if ( !eos._sWOL.IsNull() && eos._sWOL != prevSWOL ) - { - isOnEdge = ( eos.SWOLType() == TopAbs_EDGE ); - if ( isOnEdge ) - { - geomEdge = TopoDS::Edge( eos._sWOL ); - curve = BRep_Tool::Curve( geomEdge, loc, f,l); - } - else - { - geomFace = TopoDS::Face( eos._sWOL ); - surface = BRep_Tool::Surface( geomFace, loc ); - } - prevSWOL = eos._sWOL; - } // restore shapePos of the last node by already treated _LayerEdge of another _SolidData const TGeomID baseShapeId = edge._nodes[0]->getshapeId(); if ( baseShapeId != prevBaseId ) { map< TGeomID, TNode2Edge* >::iterator s2ne = data._s2neMap.find( baseShapeId ); - n2eMap = ( s2ne == data._s2neMap.end() ) ? 0 : n2eMap = s2ne->second; + n2eMap = ( s2ne == data._s2neMap.end() ) ? 0 : s2ne->second; prevBaseId = baseShapeId; } _LayerEdge* edgeOnSameNode = 0; + bool useExistingPos = false; if ( n2eMap && (( n2e = n2eMap->find( edge._nodes[0] )) != n2eMap->end() )) { edgeOnSameNode = n2e->second; + useExistingPos = ( edgeOnSameNode->_len < edge._len ); const gp_XYZ& otherTgtPos = edgeOnSameNode->_pos.back(); SMDS_PositionPtr lastPos = tgtNode->GetPosition(); if ( isOnEdge ) @@ -6282,12 +9060,12 @@ bool _ViscousBuilder::refine(_SolidData& data) // compute an intermediate position hi *= f; hSum += hi; - while ( hSum > segLen[iSeg] && iSeg < segLen.size()-1) + while ( hSum > segLen[iSeg] && iSeg < segLen.size()-1 ) ++iSeg; int iPrevSeg = iSeg-1; while ( fabs( segLen[iPrevSeg] - segLen[iSeg]) <= zeroLen && iPrevSeg > 0 ) --iPrevSeg; - double r = ( segLen[iSeg] - hSum ) / ( segLen[iSeg] - segLen[iPrevSeg] ); + double r = ( segLen[iSeg] - hSum ) / ( segLen[iSeg] - segLen[iPrevSeg] ); gp_Pnt pos = r * edge._pos[iPrevSeg] + (1-r) * edge._pos[iSeg]; SMDS_MeshNode*& node = const_cast< SMDS_MeshNode*& >( edge._nodes[ iStep ]); @@ -6300,11 +9078,19 @@ bool _ViscousBuilder::refine(_SolidData& data) if ( !node ) pos = curve->Value( u ).Transformed(loc); } - else + else if ( eos._isRegularSWOL ) { uv.SetCoord( pos.X(), pos.Y() ); if ( !node ) - pos = surface->Value( pos.X(), pos.Y() ).Transformed(loc); + pos = surface->Value( pos.X(), pos.Y() ); + } + else + { + uv.SetCoord( pos.X(), pos.Y() ); + gp_Pnt p = r * pos3D[ iPrevSeg ] + (1-r) * pos3D[ iSeg ]; + uv = surface->NextValueOfUV( uv, p, BRep_Tool::Tolerance( geomFace )).XY(); + if ( !node ) + pos = surface->Value( uv ); } } // create or update the node @@ -6330,7 +9116,9 @@ bool _ViscousBuilder::refine(_SolidData& data) // make average pos from new and current parameters if ( isOnEdge ) { - u = 0.5 * ( u + helper.GetNodeU( geomEdge, node )); + //u = 0.5 * ( u + helper.GetNodeU( geomEdge, node )); + if ( useExistingPos ) + u = helper.GetNodeU( geomEdge, node ); pos = curve->Value( u ).Transformed(loc); SMDS_EdgePosition* epos = static_cast( node->GetPosition() ); @@ -6338,8 +9126,10 @@ bool _ViscousBuilder::refine(_SolidData& data) } else { - uv = 0.5 * ( uv + helper.GetNodeUV( geomFace, node )); - pos = surface->Value( uv.X(), uv.Y()).Transformed(loc); + //uv = 0.5 * ( uv + helper.GetNodeUV( geomFace, node )); + if ( useExistingPos ) + uv = helper.GetNodeUV( geomFace, node ); + pos = surface->Value( uv ); SMDS_FacePosition* fpos = static_cast( node->GetPosition() ); fpos->SetUParameter( uv.X() ); @@ -6380,8 +9170,9 @@ bool _ViscousBuilder::refine(_SolidData& data) vector< vector* > nnVec; set< vector* > nnSet; - set< int > degenEdgeInd; - vector degenVols; + set< int > degenEdgeInd; + vector degenVols; + vector isRiskySWOL; TopExp_Explorer exp( data._solid, TopAbs_FACE ); for ( ; exp.More(); exp.Next() ) @@ -6399,110 +9190,113 @@ bool _ViscousBuilder::refine(_SolidData& data) nnVec.resize( nbNodes ); nnSet.clear(); degenEdgeInd.clear(); - int nbZ = 0; + isRiskySWOL.resize( nbNodes ); + size_t maxZ = 0, minZ = std::numeric_limits::max(); SMDS_NodeIteratorPtr nIt = face->nodeIterator(); for ( int iN = 0; iN < nbNodes; ++iN ) { const SMDS_MeshNode* n = nIt->next(); + _LayerEdge* edge = data._n2eMap[ n ]; const int i = isReversedFace ? nbNodes-1-iN : iN; - nnVec[ i ] = & data._n2eMap[ n ]->_nodes; - if ( nnVec[ i ]->size() < 2 ) - degenEdgeInd.insert( iN ); - else - nbZ = nnVec[ i ]->size(); + nnVec[ i ] = & edge->_nodes; + maxZ = std::max( maxZ, nnVec[ i ]->size() ); + minZ = std::min( minZ, nnVec[ i ]->size() ); + //isRiskySWOL[ i ] = edge->Is( _LayerEdge::RISKY_SWOL ); if ( helper.HasDegeneratedEdges() ) nnSet.insert( nnVec[ i ]); } - if ( nbZ == 0 ) + + if ( maxZ == 0 ) continue; if ( 0 < nnSet.size() && nnSet.size() < 3 ) continue; switch ( nbNodes ) { - case 3: - switch ( degenEdgeInd.size() ) - { - case 0: // PENTA - { - for ( int iZ = 1; iZ < nbZ; ++iZ ) - helper.AddVolume( (*nnVec[0])[iZ-1], (*nnVec[1])[iZ-1], (*nnVec[2])[iZ-1], - (*nnVec[0])[iZ], (*nnVec[1])[iZ], (*nnVec[2])[iZ]); - break; - } - case 1: // PYRAM - { - int i2 = *degenEdgeInd.begin(); - int i0 = helper.WrapIndex( i2 - 1, nbNodes ); - int i1 = helper.WrapIndex( i2 + 1, nbNodes ); - for ( int iZ = 1; iZ < nbZ; ++iZ ) - helper.AddVolume( (*nnVec[i0])[iZ-1], (*nnVec[i1])[iZ-1], - (*nnVec[i1])[iZ], (*nnVec[i0])[iZ], (*nnVec[i2])[0]); - break; - } - case 2: // TETRA - { - int i3 = !degenEdgeInd.count(0) ? 0 : !degenEdgeInd.count(1) ? 1 : 2; - for ( int iZ = 1; iZ < nbZ; ++iZ ) - helper.AddVolume( (*nnVec[0])[iZ-1], (*nnVec[1])[iZ-1], (*nnVec[2])[iZ-1], - (*nnVec[i3])[iZ]); - break; - } - } - break; + case 3: // TRIA + { + // PENTA + for ( size_t iZ = 1; iZ < minZ; ++iZ ) + helper.AddVolume( (*nnVec[0])[iZ-1], (*nnVec[1])[iZ-1], (*nnVec[2])[iZ-1], + (*nnVec[0])[iZ], (*nnVec[1])[iZ], (*nnVec[2])[iZ]); - case 4: - switch ( degenEdgeInd.size() ) + for ( size_t iZ = minZ; iZ < maxZ; ++iZ ) { - case 0: // HEX - { - for ( int iZ = 1; iZ < nbZ; ++iZ ) - helper.AddVolume( (*nnVec[0])[iZ-1], (*nnVec[1])[iZ-1], - (*nnVec[2])[iZ-1], (*nnVec[3])[iZ-1], - (*nnVec[0])[iZ], (*nnVec[1])[iZ], - (*nnVec[2])[iZ], (*nnVec[3])[iZ]); - break; - } - case 2: // PENTA? - { - int i2 = *degenEdgeInd.begin(); - int i3 = *degenEdgeInd.rbegin(); - bool ok = ( i3 - i2 == 1 ); - if ( i2 == 0 && i3 == 3 ) { i2 = 3; i3 = 0; ok = true; } - int i0 = helper.WrapIndex( i3 + 1, nbNodes ); - int i1 = helper.WrapIndex( i0 + 1, nbNodes ); - for ( int iZ = 1; iZ < nbZ; ++iZ ) + for ( int iN = 0; iN < nbNodes; ++iN ) + if ( nnVec[ iN ]->size() < iZ+1 ) + degenEdgeInd.insert( iN ); + + if ( degenEdgeInd.size() == 1 ) // PYRAM { + int i2 = *degenEdgeInd.begin(); + int i0 = helper.WrapIndex( i2 - 1, nbNodes ); + int i1 = helper.WrapIndex( i2 + 1, nbNodes ); + helper.AddVolume( (*nnVec[i0])[iZ-1], (*nnVec[i1])[iZ-1], + (*nnVec[i1])[iZ ], (*nnVec[i0])[iZ ], (*nnVec[i2]).back()); + } + else // TETRA + { + int i3 = !degenEdgeInd.count(0) ? 0 : !degenEdgeInd.count(1) ? 1 : 2; + helper.AddVolume( (*nnVec[ 0 ])[ i3 == 0 ? iZ-1 : nnVec[0]->size()-1 ], + (*nnVec[ 1 ])[ i3 == 1 ? iZ-1 : nnVec[1]->size()-1 ], + (*nnVec[ 2 ])[ i3 == 2 ? iZ-1 : nnVec[2]->size()-1 ], + (*nnVec[ i3 ])[ iZ ]); + } + } + break; // TRIA + } + case 4: // QUAD + { + // HEX + for ( size_t iZ = 1; iZ < minZ; ++iZ ) + helper.AddVolume( (*nnVec[0])[iZ-1], (*nnVec[1])[iZ-1], + (*nnVec[2])[iZ-1], (*nnVec[3])[iZ-1], + (*nnVec[0])[iZ], (*nnVec[1])[iZ], + (*nnVec[2])[iZ], (*nnVec[3])[iZ]); + + for ( size_t iZ = minZ; iZ < maxZ; ++iZ ) + { + for ( int iN = 0; iN < nbNodes; ++iN ) + if ( nnVec[ iN ]->size() < iZ+1 ) + degenEdgeInd.insert( iN ); + + switch ( degenEdgeInd.size() ) + { + case 2: // PENTA + { + int i2 = *degenEdgeInd.begin(); + int i3 = *degenEdgeInd.rbegin(); + bool ok = ( i3 - i2 == 1 ); + if ( i2 == 0 && i3 == 3 ) { i2 = 3; i3 = 0; ok = true; } + int i0 = helper.WrapIndex( i3 + 1, nbNodes ); + int i1 = helper.WrapIndex( i0 + 1, nbNodes ); + const SMDS_MeshElement* vol = - helper.AddVolume( (*nnVec[i3])[0], (*nnVec[i0])[iZ], (*nnVec[i0])[iZ-1], - (*nnVec[i2])[0], (*nnVec[i1])[iZ], (*nnVec[i1])[iZ-1]); + helper.AddVolume( nnVec[i3]->back(), (*nnVec[i0])[iZ], (*nnVec[i0])[iZ-1], + nnVec[i2]->back(), (*nnVec[i1])[iZ], (*nnVec[i1])[iZ-1]); if ( !ok && vol ) degenVols.push_back( vol ); } break; - } - case 3: // degen HEX - { - const SMDS_MeshNode* nn[8]; - for ( int iZ = 1; iZ < nbZ; ++iZ ) + + default: // degen HEX { const SMDS_MeshElement* vol = - helper.AddVolume( nnVec[0]->size() > 1 ? (*nnVec[0])[iZ-1] : (*nnVec[0])[0], - nnVec[1]->size() > 1 ? (*nnVec[1])[iZ-1] : (*nnVec[1])[0], - nnVec[2]->size() > 1 ? (*nnVec[2])[iZ-1] : (*nnVec[2])[0], - nnVec[3]->size() > 1 ? (*nnVec[3])[iZ-1] : (*nnVec[3])[0], - nnVec[0]->size() > 1 ? (*nnVec[0])[iZ] : (*nnVec[0])[0], - nnVec[1]->size() > 1 ? (*nnVec[1])[iZ] : (*nnVec[1])[0], - nnVec[2]->size() > 1 ? (*nnVec[2])[iZ] : (*nnVec[2])[0], - nnVec[3]->size() > 1 ? (*nnVec[3])[iZ] : (*nnVec[3])[0]); + helper.AddVolume( nnVec[0]->size() > iZ-1 ? (*nnVec[0])[iZ-1] : nnVec[0]->back(), + nnVec[1]->size() > iZ-1 ? (*nnVec[1])[iZ-1] : nnVec[1]->back(), + nnVec[2]->size() > iZ-1 ? (*nnVec[2])[iZ-1] : nnVec[2]->back(), + nnVec[3]->size() > iZ-1 ? (*nnVec[3])[iZ-1] : nnVec[3]->back(), + nnVec[0]->size() > iZ ? (*nnVec[0])[iZ] : nnVec[0]->back(), + nnVec[1]->size() > iZ ? (*nnVec[1])[iZ] : nnVec[1]->back(), + nnVec[2]->size() > iZ ? (*nnVec[2])[iZ] : nnVec[2]->back(), + nnVec[3]->size() > iZ ? (*nnVec[3])[iZ] : nnVec[3]->back()); degenVols.push_back( vol ); } + } } - break; - } - break; - + break; // HEX + } default: return error("Not supported type of element", data._index); @@ -6588,7 +9382,7 @@ bool _ViscousBuilder::shrink() // =========================== // Collect nodes to smooth, as src nodes are not yet replaced by tgt ones - // and thus all nodes on a FACE connected to 2d elements are to be smoothed + // and hence all nodes on a FACE connected to 2d elements are to be smoothed vector < const SMDS_MeshNode* > smoothNodes; { SMDS_NodeIteratorPtr nIt = smDS->GetNodes(); @@ -6743,9 +9537,10 @@ bool _ViscousBuilder::shrink() // ================== bool shrinked = true; - int badNb, shriStep=0, smooStep=0; + int nbBad, shriStep=0, smooStep=0; _SmoothNode::SmoothType smoothType = isConcaveFace ? _SmoothNode::ANGULAR : _SmoothNode::LAPLACIAN; + SMESH_Comment errMsg; while ( shrinked ) { shriStep++; @@ -6773,32 +9568,36 @@ bool _ViscousBuilder::shrink() // ----------------- int nbNoImpSteps = 0; bool moved = true; - badNb = 1; - while (( nbNoImpSteps < 5 && badNb > 0) && moved) + nbBad = 1; + while (( nbNoImpSteps < 5 && nbBad > 0) && moved) { dumpFunction(SMESH_Comment("shrinkFace")<first<<"_st"<<++smooStep); // debug - int oldBadNb = badNb; - badNb = 0; + int oldBadNb = nbBad; + nbBad = 0; moved = false; // '% 5' minimizes NB FUNCTIONS on viscous_layers_00/B2 case _SmoothNode::SmoothType smooTy = ( smooStep % 5 ) ? smoothType : _SmoothNode::LAPLACIAN; for ( size_t i = 0; i < nodesToSmooth.size(); ++i ) { - moved |= nodesToSmooth[i].Smooth( badNb, surface, helper, refSign, + moved |= nodesToSmooth[i].Smooth( nbBad, surface, helper, refSign, smooTy, /*set3D=*/isConcaveFace); } - if ( badNb < oldBadNb ) + if ( nbBad < oldBadNb ) nbNoImpSteps = 0; else nbNoImpSteps++; dumpFunctionEnd(); } - if ( badNb > 0 ) - return error(SMESH_Comment("Can't shrink 2D mesh on face ") << f2sd->first ); + + errMsg.clear(); + if ( nbBad > 0 ) + errMsg << "Can't shrink 2D mesh on face " << f2sd->first; if ( shriStep > 200 ) - return error(SMESH_Comment("Infinite loop at shrinking 2D mesh on face ") << f2sd->first ); + errMsg << "Infinite loop at shrinking 2D mesh on face " << f2sd->first; + if ( !errMsg.empty() ) + break; // Fix narrow triangles by swapping diagonals // --------------------------------------- @@ -6840,48 +9639,211 @@ bool _ViscousBuilder::shrink() // dumpFunction(SMESH_Comment("shrinkFace")<first<<"_st"<<++smooStep); // debug // for ( size_t i = 0; i < nodesToSmooth.size(); ++i ) // { - // nodesToSmooth[i].Smooth( badNb,surface,helper,refSign, + // nodesToSmooth[i].Smooth( nbBad,surface,helper,refSign, // _SmoothNode::LAPLACIAN,/*set3D=*/false); // } // } + } // while ( shrinked ) - // No wrongly shaped faces remain; final smooth. Set node XYZ. - bool isStructuredFixed = false; - if ( SMESH_2D_Algo* algo = dynamic_cast( sm->GetAlgo() )) - isStructuredFixed = algo->FixInternalNodes( *data._proxyMesh, F ); - if ( !isStructuredFixed ) + if ( !errMsg.empty() ) // Try to re-compute the shrink FACE { - if ( isConcaveFace ) // fix narrow faces by swapping diagonals - fixBadFaces( F, helper, /*is2D=*/false, ++shriStep ); - - for ( int st = 3; st; --st ) + // remove faces + SMESHDS_SubMesh* psm = data._proxyMesh->getFaceSubM( F ); { - switch( st ) { - case 1: smoothType = _SmoothNode::LAPLACIAN; break; - case 2: smoothType = _SmoothNode::LAPLACIAN; break; - case 3: smoothType = _SmoothNode::ANGULAR; break; + vector< const SMDS_MeshElement* > facesToRm; + if ( psm ) + { + facesToRm.reserve( psm->NbElements() ); + for ( SMDS_ElemIteratorPtr ite = psm->GetElements(); ite->more(); ) + facesToRm.push_back( ite->next() ); + + for ( size_t i = 0 ; i < _sdVec.size(); ++i ) + if (( psm = _sdVec[i]._proxyMesh->getFaceSubM( F ))) + psm->Clear(); } - dumpFunction(SMESH_Comment("shrinkFace")<first<<"_st"<<++smooStep); // debug + for ( size_t i = 0; i < facesToRm.size(); ++i ) + getMeshDS()->RemoveFreeElement( facesToRm[i], smDS, /*fromGroups=*/false ); + } + // remove nodes + { + TIDSortedNodeSet nodesToKeep; // nodes of _LayerEdge to keep + for ( size_t iS = 0; iS < subEOS.size(); ++iS ) { + for ( size_t i = 0; i < subEOS[iS]->_edges.size(); ++i ) + nodesToKeep.insert( ++( subEOS[iS]->_edges[i]->_nodes.begin() ), + subEOS[iS]->_edges[i]->_nodes.end() ); + } + SMDS_NodeIteratorPtr itn = smDS->GetNodes(); + while ( itn->more() ) { + const SMDS_MeshNode* n = itn->next(); + if ( !nodesToKeep.count( n )) + getMeshDS()->RemoveFreeNode( n, smDS, /*fromGroups=*/false ); + } + } + // restore position and UV of target nodes + gp_Pnt p; + for ( size_t iS = 0; iS < subEOS.size(); ++iS ) + for ( size_t i = 0; i < subEOS[iS]->_edges.size(); ++i ) + { + _LayerEdge* edge = subEOS[iS]->_edges[i]; + SMDS_MeshNode* tgtNode = const_cast< SMDS_MeshNode*& >( edge->_nodes.back() ); + if ( edge->_pos.empty() ) continue; + if ( subEOS[iS]->SWOLType() == TopAbs_FACE ) + { + SMDS_FacePosition* pos = static_cast( tgtNode->GetPosition() ); + pos->SetUParameter( edge->_pos[0].X() ); + pos->SetVParameter( edge->_pos[0].Y() ); + p = surface->Value( edge->_pos[0].X(), edge->_pos[0].Y() ); + } + else + { + SMDS_EdgePosition* pos = static_cast( tgtNode->GetPosition() ); + pos->SetUParameter( edge->_pos[0].Coord( U_TGT )); + p = BRepAdaptor_Curve( TopoDS::Edge( subEOS[iS]->_sWOL )).Value( pos->GetUParameter() ); + } + tgtNode->setXYZ( p.X(), p.Y(), p.Z() ); + dumpMove( tgtNode ); + } + // shrink EDGE sub-meshes and set proxy sub-meshes + UVPtStructVec uvPtVec; + set< _Shrinker1D* >::iterator shrIt = eShri1D.begin(); + for ( shrIt = eShri1D.begin(); shrIt != eShri1D.end(); ++shrIt ) + { + _Shrinker1D* shr = (*shrIt); + shr->Compute( /*set3D=*/true, helper ); + + // set proxy mesh of EDGEs w/o layers + map< double, const SMDS_MeshNode* > nodes; + SMESH_Algo::GetSortedNodesOnEdge( getMeshDS(), shr->GeomEdge(),/*skipMedium=*/true, nodes); + // remove refinement nodes + const SMDS_MeshNode* sn0 = shr->SrcNode(0), *sn1 = shr->SrcNode(1); + const SMDS_MeshNode* tn0 = shr->TgtNode(0), *tn1 = shr->TgtNode(1); + map< double, const SMDS_MeshNode* >::iterator u2n = nodes.begin(); + if ( u2n->second == sn0 || u2n->second == sn1 ) + { + while ( u2n->second != tn0 && u2n->second != tn1 ) + ++u2n; + nodes.erase( nodes.begin(), u2n ); + } + u2n = --nodes.end(); + if ( u2n->second == sn0 || u2n->second == sn1 ) + { + while ( u2n->second != tn0 && u2n->second != tn1 ) + --u2n; + nodes.erase( ++u2n, nodes.end() ); + } + // set proxy sub-mesh + uvPtVec.resize( nodes.size() ); + u2n = nodes.begin(); + BRepAdaptor_Curve2d curve( shr->GeomEdge(), F ); + for ( size_t i = 0; i < nodes.size(); ++i, ++u2n ) + { + uvPtVec[ i ].node = u2n->second; + uvPtVec[ i ].param = u2n->first; + uvPtVec[ i ].SetUV( curve.Value( u2n->first ).XY() ); + } + StdMeshers_FaceSide fSide( uvPtVec, F, shr->GeomEdge(), _mesh ); + StdMeshers_ViscousLayers2D::SetProxyMeshOfEdge( fSide ); + } + + // set proxy mesh of EDGEs with layers + vector< _LayerEdge* > edges; + for ( size_t iS = 0; iS < subEOS.size(); ++iS ) + { + _EdgesOnShape& eos = * subEOS[ iS ]; + if ( eos.ShapeType() != TopAbs_EDGE ) continue; + + const TopoDS_Edge& E = TopoDS::Edge( eos._shape ); + data.SortOnEdge( E, eos._edges ); + + edges.clear(); + if ( _EdgesOnShape* eov = data.GetShapeEdges( helper.IthVertex( 0, E, /*CumOri=*/false ))) + if ( !eov->_edges.empty() ) + edges.push_back( eov->_edges[0] ); // on 1st VERTEX + + edges.insert( edges.end(), eos._edges.begin(), eos._edges.end() ); + + if ( _EdgesOnShape* eov = data.GetShapeEdges( helper.IthVertex( 1, E, /*CumOri=*/false ))) + if ( !eov->_edges.empty() ) + edges.push_back( eov->_edges[0] ); // on last VERTEX + + uvPtVec.resize( edges.size() ); + for ( size_t i = 0; i < edges.size(); ++i ) + { + uvPtVec[ i ].node = edges[i]->_nodes.back(); + uvPtVec[ i ].param = helper.GetNodeU( E, edges[i]->_nodes[0] ); + uvPtVec[ i ].SetUV( helper.GetNodeUV( F, edges[i]->_nodes.back() )); + } + BRep_Tool::Range( E, uvPtVec[0].param, uvPtVec.back().param ); + StdMeshers_FaceSide fSide( uvPtVec, F, E, _mesh ); + StdMeshers_ViscousLayers2D::SetProxyMeshOfEdge( fSide ); + } + // temporary clear the FACE sub-mesh from faces made by refine() + vector< const SMDS_MeshElement* > elems; + elems.reserve( smDS->NbElements() + smDS->NbNodes() ); + for ( SMDS_ElemIteratorPtr ite = smDS->GetElements(); ite->more(); ) + elems.push_back( ite->next() ); + for ( SMDS_NodeIteratorPtr ite = smDS->GetNodes(); ite->more(); ) + elems.push_back( ite->next() ); + smDS->Clear(); + + // compute the mesh on the FACE + sm->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE ); + sm->ComputeStateEngine( SMESH_subMesh::COMPUTE_SUBMESH ); + + // re-fill proxy sub-meshes of the FACE + for ( size_t i = 0 ; i < _sdVec.size(); ++i ) + if (( psm = _sdVec[i]._proxyMesh->getFaceSubM( F ))) + for ( SMDS_ElemIteratorPtr ite = smDS->GetElements(); ite->more(); ) + psm->AddElement( ite->next() ); + + // re-fill smDS + for ( size_t i = 0; i < elems.size(); ++i ) + smDS->AddElement( elems[i] ); + + if ( sm->GetComputeState() != SMESH_subMesh::COMPUTE_OK ) + return error( errMsg ); + + } // end of re-meshing in case of failed smoothing + else + { + // No wrongly shaped faces remain; final smooth. Set node XYZ. + bool isStructuredFixed = false; + if ( SMESH_2D_Algo* algo = dynamic_cast( sm->GetAlgo() )) + isStructuredFixed = algo->FixInternalNodes( *data._proxyMesh, F ); + if ( !isStructuredFixed ) + { + if ( isConcaveFace ) // fix narrow faces by swapping diagonals + fixBadFaces( F, helper, /*is2D=*/false, ++shriStep ); + + for ( int st = 3; st; --st ) + { + switch( st ) { + case 1: smoothType = _SmoothNode::LAPLACIAN; break; + case 2: smoothType = _SmoothNode::LAPLACIAN; break; + case 3: smoothType = _SmoothNode::ANGULAR; break; + } + dumpFunction(SMESH_Comment("shrinkFace")<first<<"_st"<<++smooStep); // debug + for ( size_t i = 0; i < nodesToSmooth.size(); ++i ) + { + nodesToSmooth[i].Smooth( nbBad,surface,helper,refSign, + smoothType,/*set3D=*/st==1 ); + } + dumpFunctionEnd(); + } + } + if ( !getMeshDS()->IsEmbeddedMode() ) + // Log node movement for ( size_t i = 0; i < nodesToSmooth.size(); ++i ) { - nodesToSmooth[i].Smooth( badNb,surface,helper,refSign, - smoothType,/*set3D=*/st==1 ); + SMESH_TNodeXYZ p ( nodesToSmooth[i]._node ); + getMeshDS()->MoveNode( nodesToSmooth[i]._node, p.X(), p.Y(), p.Z() ); } - dumpFunctionEnd(); - } } + // Set an event listener to clear FACE sub-mesh together with SOLID sub-mesh VISCOUS_3D::ToClearSubWithMain( sm, data._solid ); - if ( !getMeshDS()->IsEmbeddedMode() ) - // Log node movement - for ( size_t i = 0; i < nodesToSmooth.size(); ++i ) - { - SMESH_TNodeXYZ p ( nodesToSmooth[i]._node ); - getMeshDS()->MoveNode( nodesToSmooth[i]._node, p.X(), p.Y(), p.Z() ); - } - } // loop on FACES to srink mesh on @@ -6910,6 +9872,11 @@ bool _ViscousBuilder::prepareEdgeToShrink( _LayerEdge& edge, if ( eos.SWOLType() == TopAbs_FACE ) { + if ( tgtNode->GetPosition()->GetDim() != 2 ) // not inflated edge + { + edge._pos.clear(); + return srcNode == tgtNode; + } gp_XY srcUV ( edge._pos[0].X(), edge._pos[0].Y() ); //helper.GetNodeUV( F, srcNode ); gp_XY tgtUV = edge.LastUV( TopoDS::Face( eos._sWOL ), eos ); //helper.GetNodeUV( F, tgtNode ); gp_Vec2d uvDir( srcUV, tgtUV ); @@ -6928,6 +9895,11 @@ bool _ViscousBuilder::prepareEdgeToShrink( _LayerEdge& edge, } else // _sWOL is TopAbs_EDGE { + if ( tgtNode->GetPosition()->GetDim() != 1 ) // not inflated edge + { + edge._pos.clear(); + return srcNode == tgtNode; + } const TopoDS_Edge& E = TopoDS::Edge( eos._sWOL ); SMESHDS_SubMesh* edgeSM = getMeshDS()->MeshElements( E ); if ( !edgeSM || edgeSM->NbElements() == 0 ) @@ -7256,6 +10228,7 @@ bool _LayerEdge::SetNewLength2d( Handle(Geom_Surface)& surface, dumpMove( tgtNode ); #endif } + return true; } @@ -7266,7 +10239,7 @@ bool _LayerEdge::SetNewLength2d( Handle(Geom_Surface)& surface, */ //================================================================================ -bool _SmoothNode::Smooth(int& badNb, +bool _SmoothNode::Smooth(int& nbBad, Handle(Geom_Surface)& surface, SMESH_MesherHelper& helper, const double refSign, @@ -7347,7 +10320,7 @@ bool _SmoothNode::Smooth(int& badNb, if ( nbOkAfter < nbOkBefore ) { - badNb += _simplices.size() - nbOkBefore; + nbBad += _simplices.size() - nbOkBefore; return false; } @@ -7365,7 +10338,7 @@ bool _SmoothNode::Smooth(int& badNb, dumpMove( _node ); } - badNb += _simplices.size() - nbOkAfter; + nbBad += _simplices.size() - nbOkAfter; return ( (tgtUV-newPos).SquareModulus() > 1e-10 ); } @@ -7441,13 +10414,22 @@ _SolidData::~_SolidData() for ( ; n2e != _n2eMap.end(); ++n2e ) { _LayerEdge* & e = n2e->second; - if ( e && e->_2neibors ) + if ( e ) + { + delete e->_curvature; + if ( e->_2neibors ) + delete e->_2neibors->_plnNorm; delete e->_2neibors; + } delete e; - e = NULL; + e = 0; } _n2eMap.clear(); + + delete _helper; + _helper = 0; } + //================================================================================ /*! * \brief Keep a _LayerEdge inflated along the EDGE @@ -7481,8 +10463,8 @@ void _Shrinker1D::AddEdge( const _LayerEdge* e, // Update _nodes - const SMDS_MeshNode* tgtNode0 = _edges[0] ? _edges[0]->_nodes.back() : 0; - const SMDS_MeshNode* tgtNode1 = _edges[1] ? _edges[1]->_nodes.back() : 0; + const SMDS_MeshNode* tgtNode0 = TgtNode( 0 ); + const SMDS_MeshNode* tgtNode1 = TgtNode( 1 ); if ( _nodes.empty() ) { @@ -7514,7 +10496,7 @@ void _Shrinker1D::AddEdge( const _LayerEdge* e, else { // remove target node of the _LayerEdge from _nodes - int nbFound = 0; + size_t nbFound = 0; for ( size_t i = 0; i < _nodes.size(); ++i ) if ( !_nodes[i] || _nodes[i] == tgtNode0 || _nodes[i] == tgtNode1 ) _nodes[i] = 0, nbFound++; diff --git a/src/StdMeshers/StdMeshers_ViscousLayers2D.cxx b/src/StdMeshers/StdMeshers_ViscousLayers2D.cxx index 585bcaf71..4e78b7157 100644 --- a/src/StdMeshers/StdMeshers_ViscousLayers2D.cxx +++ b/src/StdMeshers/StdMeshers_ViscousLayers2D.cxx @@ -113,6 +113,7 @@ namespace VISCOUS_2D //virtual int NbElements() const { return _elements.size()+1; } virtual int NbNodes() const { return Max( 0, _uvPtStructVec.size()-2 ); } void SetUVPtStructVec(UVPtStructVec& vec) { _uvPtStructVec.swap( vec ); } + UVPtStructVec& GetUVPtStructVec() { return _uvPtStructVec; } }; _ProxyMeshOfFace(const SMESH_Mesh& mesh): SMESH_ProxyMesh(mesh) {} _EdgeSubMesh* GetEdgeSubMesh(int ID) { return (_EdgeSubMesh*) getProxySubMesh(ID); } @@ -299,6 +300,8 @@ namespace VISCOUS_2D double _D; // _vec1.Crossed( _vec2 ) double _param1, _param2; // intersection param on _seg1 and _seg2 + _SegmentIntersection(): _param1(0), _param2(0), _D(0) {} + bool Compute(const _Segment& seg1, const _Segment& seg2, bool seg2IsRay = false ) { // !!! If seg2IsRay, returns true at any _param2 !!! @@ -515,29 +518,53 @@ SMESH_ProxyMesh::Ptr StdMeshers_ViscousLayers2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Face& theFace) { - SMESH_ProxyMesh::Ptr pm; - + using namespace VISCOUS_2D; vector< const StdMeshers_ViscousLayers2D* > hyps; vector< TopoDS_Shape > hypShapes; - if ( VISCOUS_2D::findHyps( theMesh, theFace, hyps, hypShapes )) + + SMESH_ProxyMesh::Ptr pm = _ProxyMeshHolder::FindProxyMeshOfFace( theFace, theMesh ); + if ( !pm ) { - VISCOUS_2D::_ViscousBuilder2D builder( theMesh, theFace, hyps, hypShapes ); - pm = builder.Compute(); - SMESH_ComputeErrorPtr error = builder.GetError(); - if ( error && !error->IsOK() ) - theMesh.GetSubMesh( theFace )->GetComputeError() = error; - else if ( !pm ) + if ( findHyps( theMesh, theFace, hyps, hypShapes )) + { + VISCOUS_2D::_ViscousBuilder2D builder( theMesh, theFace, hyps, hypShapes ); + pm = builder.Compute(); + SMESH_ComputeErrorPtr error = builder.GetError(); + if ( error && !error->IsOK() ) + theMesh.GetSubMesh( theFace )->GetComputeError() = error; + else if ( !pm ) + pm.reset( new SMESH_ProxyMesh( theMesh )); + if ( getenv("__ONLY__VL2D__")) + pm.reset(); + } + else + { pm.reset( new SMESH_ProxyMesh( theMesh )); - if ( getenv("__ONLY__VL2D__")) - pm.reset(); - } - else - { - pm.reset( new SMESH_ProxyMesh( theMesh )); + } } return pm; } // -------------------------------------------------------------------------------- +void StdMeshers_ViscousLayers2D::SetProxyMeshOfEdge( const StdMeshers_FaceSide& edgeNodes ) +{ + using namespace VISCOUS_2D; + SMESH_ProxyMesh::Ptr pm = + _ProxyMeshHolder::FindProxyMeshOfFace( edgeNodes.Face(), *edgeNodes.GetMesh() ); + if ( !pm ) { + _ProxyMeshOfFace* proxyMeshOfFace = new _ProxyMeshOfFace( *edgeNodes.GetMesh() ); + pm.reset( proxyMeshOfFace ); + new _ProxyMeshHolder( edgeNodes.Face(), pm ); + } + _ProxyMeshOfFace* proxyMeshOfFace = static_cast<_ProxyMeshOfFace*>( pm.get() ); + _ProxyMeshOfFace::_EdgeSubMesh* sm = proxyMeshOfFace->GetEdgeSubMesh( edgeNodes.EdgeID(0) ); + sm->GetUVPtStructVec() = edgeNodes.GetUVPtStruct(); +} +// -------------------------------------------------------------------------------- +bool StdMeshers_ViscousLayers2D::HasProxyMesh( const TopoDS_Face& face, SMESH_Mesh& mesh ) +{ + return VISCOUS_2D::_ProxyMeshHolder::FindProxyMeshOfFace( face, mesh ); +} +// -------------------------------------------------------------------------------- SMESH_ComputeErrorPtr StdMeshers_ViscousLayers2D::CheckHypothesis(SMESH_Mesh& theMesh, const TopoDS_Shape& theShape, @@ -1794,7 +1821,7 @@ bool _ViscousBuilder2D::shrink() // x-x-x-x-----x-----x---- // | | | | e1 e2 e3 - int isRShrinkedForAdjacent; + int isRShrinkedForAdjacent = 0; UVPtStructVec nodeDataForAdjacent; for ( int isR = 0; isR < 2; ++isR ) { diff --git a/src/StdMeshers/StdMeshers_ViscousLayers2D.hxx b/src/StdMeshers/StdMeshers_ViscousLayers2D.hxx index 4c885e4d6..cff610b17 100644 --- a/src/StdMeshers/StdMeshers_ViscousLayers2D.hxx +++ b/src/StdMeshers/StdMeshers_ViscousLayers2D.hxx @@ -27,6 +27,7 @@ #include "StdMeshers_ViscousLayers.hxx" class TopoDS_Face; +class StdMeshers_FaceSide; /*! * \brief Hypothesis defining parameters of viscous layers @@ -72,6 +73,9 @@ public: static const char* GetHypType() { return "ViscousLayers2D"; } + static void SetProxyMeshOfEdge( const StdMeshers_FaceSide& edgeNodes ); + static bool HasProxyMesh( const TopoDS_Face& face, SMESH_Mesh& theMesh ); + private: }; diff --git a/src/StdMeshersGUI/StdMeshersGUI_DistrPreview.cxx b/src/StdMeshersGUI/StdMeshersGUI_DistrPreview.cxx index 8b1aa911b..e6aaa2889 100644 --- a/src/StdMeshersGUI/StdMeshersGUI_DistrPreview.cxx +++ b/src/StdMeshersGUI/StdMeshersGUI_DistrPreview.cxx @@ -293,7 +293,7 @@ void StdMeshersGUI_DistrPreview::update() int size = graph.length()/2; double* x = new double[size], *y = new double[size]; - double min_x, max_x, min_y, max_y; + double min_x = 0, max_x = 0, min_y = 0, max_y = 0; for( int i=0; iclearSelected(); - TColStd_MapOfInteger aIndexes; + myPreviewActor->HighlightAll( false ); QList selItems = myListWidget->selectedItems(); QListWidgetItem* anItem; foreach(anItem, selItems) myPreviewActor->HighlightID( anItem->text().toInt() ); + if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) + aViewWindow->Repaint(); + // update remove button myRemoveButton->setEnabled( selItems.size() > 0 ); diff --git a/src/StdMeshers_I/StdMeshers_ViscousLayers_i.cxx b/src/StdMeshers_I/StdMeshers_ViscousLayers_i.cxx index cf988542e..ee39c26da 100644 --- a/src/StdMeshers_I/StdMeshers_ViscousLayers_i.cxx +++ b/src/StdMeshers_I/StdMeshers_ViscousLayers_i.cxx @@ -53,7 +53,6 @@ StdMeshers_ViscousLayers_i::StdMeshers_ViscousLayers_i( PortableServer::POA_ptr : SALOME::GenericObj_i( thePOA ), SMESH_Hypothesis_i( thePOA ) { - MESSAGE( "StdMeshers_ViscousLayers_i::StdMeshers_ViscousLayers_i" ); myBaseImpl = new ::StdMeshers_ViscousLayers( theGenImpl->GetANewId(), theStudyId, theGenImpl ); @@ -69,7 +68,6 @@ StdMeshers_ViscousLayers_i::StdMeshers_ViscousLayers_i( PortableServer::POA_ptr StdMeshers_ViscousLayers_i::~StdMeshers_ViscousLayers_i() { - MESSAGE( "StdMeshers_ViscousLayers_i::~StdMeshers_ViscousLayers_i" ); } //================================================================================ @@ -265,7 +263,6 @@ void StdMeshers_ViscousLayers_i::SetMethod( ::StdMeshers::VLExtrusionMethod how ::StdMeshers_ViscousLayers* StdMeshers_ViscousLayers_i::GetImpl() { - MESSAGE( "StdMeshers_ViscousLayers_i::GetImpl" ); return ( ::StdMeshers_ViscousLayers* )myBaseImpl; } diff --git a/src/StdMeshers_I/StdMeshers_i.cxx b/src/StdMeshers_I/StdMeshers_i.cxx index 2401d69dd..b94ca0a0f 100644 --- a/src/StdMeshers_I/StdMeshers_i.cxx +++ b/src/StdMeshers_I/StdMeshers_i.cxx @@ -134,8 +134,6 @@ extern "C" STDMESHERS_I_EXPORT GenericHypothesisCreator_i* GetHypothesisCreator (const char* aHypName) { - MESSAGE("Get HypothesisCreator for " << aHypName); - GenericHypothesisCreator_i* aCreator = 0; // Hypotheses diff --git a/src/Tools/MeshCut/MeshCut_DC.cxx b/src/Tools/MeshCut/MeshCut_DC.cxx index ccc45655a..1639f0bdc 100644 --- a/src/Tools/MeshCut/MeshCut_DC.cxx +++ b/src/Tools/MeshCut/MeshCut_DC.cxx @@ -72,13 +72,13 @@ int main(int argc, char *argv[]) debug = false; string ficMEDin; string ficMEDout; - float xNormal; - float yNormal; - float zNormal; - float xm; - float ym; - float zm; - float tolerance; + float xNormal = 0; + float yNormal = 0; + float zNormal = 0; + float xm = 0; + float ym = 0; + float zm = 0; + float tolerance = 0; try { if (argc != 13) diff --git a/src/Tools/MeshCut/MeshCut_Fonctions.cxx b/src/Tools/MeshCut/MeshCut_Fonctions.cxx index bd6a8df02..f55361325 100644 --- a/src/Tools/MeshCut/MeshCut_Fonctions.cxx +++ b/src/Tools/MeshCut/MeshCut_Fonctions.cxx @@ -84,7 +84,7 @@ int MESHCUT::positionNoeudPlan(int indiceNoeud) int MESHCUT::intersectionSegmentPlan(int it4, int na) { - int ngA, ngB; // Numéros des noeuds extrémités AB + int ngA = -1, ngB = -1; // Numéros des noeuds extrémités AB float lambda, ps; //, ab; // ab = longueur AB float A[3], B[3]; diff --git a/src/Tools/MeshCut/MeshCut_Maillage.cxx b/src/Tools/MeshCut/MeshCut_Maillage.cxx index fd6ceabb0..1c7726730 100644 --- a/src/Tools/MeshCut/MeshCut_Maillage.cxx +++ b/src/Tools/MeshCut/MeshCut_Maillage.cxx @@ -204,7 +204,7 @@ float Maillage::distanceNoeudMaille(int ngnoeud, int imaille, TYPE_MAILLE tm) int Maillage::noeudVoisin(int ngnoeud, int imaille, TYPE_MAILLE tm) { float x, y, z; - int ngv; + int ngv = -1; float x0 = XX[ngnoeud - 1]; float y0 = YY[ngnoeud - 1]; float z0 = ZZ[ngnoeud - 1]; @@ -557,13 +557,13 @@ void Maillage::inputMED(std::string fichierMED) ostringstream OSCOORD; med_int nnoe = 0; // Nbre de noeuds - med_float *coo1; // Table des coordonnées + med_float *coo1 = 0; // Table des coordonnées // char nomcoo[mdim * MED_SNAME_SIZE + 1]; // Table des noms des coordonnées // char unicoo[mdim * MED_SNAME_SIZE + 1]; // Table des unités des coordonnées - char *nomnoe; + char *nomnoe = 0; - med_int *numnoe; - med_int *nufano; + med_int *numnoe = 0; + med_int *nufano = 0; // med_grid_type rep; // med_bool inonoe, inunoe; // med_int profil[2] = { 2, 3 }; @@ -1133,7 +1133,7 @@ void Maillage::outputMED(std::string fichierMED) // float x, y, z; med_int nnoe = nombreNoeudsMaillage; // Nombre de noeuds - med_float *coo; // Table des coordonnées + med_float *coo = 0; // Table des coordonnées // Noms des coordonnées (variable nomcoo) char* nomcoo = new char[mdim * MED_SNAME_SIZE + 1]; @@ -1169,9 +1169,9 @@ void Maillage::outputMED(std::string fichierMED) // Tables des noms, numeros, numeros de familles des noeuds // autant d'elements que de noeuds - les noms ont pout longueur MED_SNAME_SIZE - char *nomnoe; + char *nomnoe = 0; med_int *numnoe = NULL; - med_int *nufano; + med_int *nufano = NULL; med_bool inonoe = MED_FALSE; med_bool inunoe = MED_FALSE; @@ -1580,7 +1580,7 @@ int Maillage::NGLOBAL(TYPE_MAILLE typeMaille, int nlocal) TYPE_MAILLE Maillage::TYPE(int nglobal) { // Attention, les num. globaux commencent à 1, les num. locaux à 0 - TYPE_MAILLE resultat; + TYPE_MAILLE resultat = (TYPE_MAILLE)-1; int cpt = 0; for (int itm = (int) POI1; itm <= (int) HEXA20; itm++) { diff --git a/src/Tools/MeshCut/MeshCut_Utils.cxx b/src/Tools/MeshCut/MeshCut_Utils.cxx index 26c1995d5..b17e2b4d7 100644 --- a/src/Tools/MeshCut/MeshCut_Utils.cxx +++ b/src/Tools/MeshCut/MeshCut_Utils.cxx @@ -534,7 +534,7 @@ int MESHCUT::copieFichier(std::string source, std::string cible) med_geometry_type MESHCUT::InstanceMGE(TYPE_MAILLE TYPE) { - med_geometry_type typeBanaliseMED; + med_geometry_type typeBanaliseMED = MED_NONE; switch (TYPE) { diff --git a/src/Tools/blocFissure/doc/conf.py.in b/src/Tools/blocFissure/doc/conf.py.in index 47bfec558..72abf4e5f 100644 --- a/src/Tools/blocFissure/doc/conf.py.in +++ b/src/Tools/blocFissure/doc/conf.py.in @@ -83,7 +83,8 @@ pygments_style = 'sphinx' # The style sheet to use for HTML and HTML Help pages. A file of that name # must exist either in Sphinx' static/ path, or in one of the custom paths # given in html_static_path. -html_style = 'default' +#html_style = 'default' +html_theme = 'default' # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". diff --git a/src/Tools/blocFissure/doc/faq.rst b/src/Tools/blocFissure/doc/faq.rst new file mode 100755 index 000000000..03e5ff06c --- /dev/null +++ b/src/Tools/blocFissure/doc/faq.rst @@ -0,0 +1,19 @@ +.. _faq: + +####################### +FAQ +####################### + + - Does Bloc Fissure works on a 2D mesh ? + +No, Bloc Fissure works only for 3D meshes. However, the user can extrude the 2D mesh to a 3D mesh, insert a crack and then extract a surface containing the crack. + + - Can I insert a crack in a symmetry plan ? + +No, the user must insert the crack without using the symmetry plan passing through the crack lips. + + - I can't have Bloc Fissure working, it raises a pure python error, what can I do ? + +Bloc Fissure has some error messages for the most commonly encountered misuses. If the program raises a pure python error, it means that this error is rare or has not been encountered by the programmers yet. + +Still, either the case can't be treated using Bloc Fissure or the insertion procedure was not fully respected. In the first case, use Zcracks (soon available). In the second case, see the :ref:`tutorial `. \ No newline at end of file diff --git a/src/Tools/blocFissure/doc/gui.rst b/src/Tools/blocFissure/doc/gui.rst new file mode 100755 index 000000000..af0815088 --- /dev/null +++ b/src/Tools/blocFissure/doc/gui.rst @@ -0,0 +1,79 @@ +.. _gui: + +With GUI +===================================== + +To make the use of « Bloc Fissure » easier, a Graphical User Interface (GUI) was developed. +Inputs are similar to those of :ref:`script mode