X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FSMESH%2FSMESH_MeshEditor.cxx;h=08cc1d9c2338fe8f628a01af17d75fa9593bd045;hp=350fcd60f6f40b794f4687fbcb20050a5120e8d8;hb=52d825495306f72048c8754aa5c86c6a390f8262;hpb=943d6263fe9817091118f5f41659ca2790ac2475 diff --git a/src/SMESH/SMESH_MeshEditor.cxx b/src/SMESH/SMESH_MeshEditor.cxx index 350fcd60f..08cc1d9c2 100644 --- a/src/SMESH/SMESH_MeshEditor.cxx +++ b/src/SMESH/SMESH_MeshEditor.cxx @@ -518,14 +518,12 @@ int SMESH_MeshEditor::FindShape (const SMDS_MeshElement * theElem) } else { - const map& id2sm = GetMeshDS()->SubMeshes(); - map::const_iterator id_sm = id2sm.begin(); - for ( ; id_sm != id2sm.end(); ++id_sm ) - if ( id_sm->second->Contains( theElem )) - return id_sm->first; + SMESHDS_SubMeshIteratorPtr smIt = GetMeshDS()->SubMeshes(); + while ( const SMESHDS_SubMesh* sm = smIt->next() ) + if ( sm->Contains( theElem )) + return sm->GetID(); } - //MESSAGE ("::FindShape() - SHAPE NOT FOUND") return 0; } @@ -1174,7 +1172,7 @@ int SMESH_MeshEditor::Reorient2D (TIDSortedElemSet & theFaces, avoidSet.clear(); avoidSet.insert(theFace); - NLink link( theFace->GetNode( 0 ), 0 ); + NLink link( theFace->GetNode( 0 ), (SMDS_MeshNode *) 0 ); const int nbNodes = theFace->NbCornerNodes(); for ( int i = 0; i < nbNodes; ++i ) // loop on links of theFace @@ -1245,6 +1243,92 @@ int SMESH_MeshEditor::Reorient2D (TIDSortedElemSet & theFaces, return nbReori; } +//================================================================================ +/*! + * \brief Reorient faces basing on orientation of adjacent volumes. + * \param theFaces - faces to reorient. If empty, all mesh faces are treated. + * \param theVolumes - reference volumes. + * \param theOutsideNormal - to orient faces to have their normal + * pointing either \a outside or \a inside the adjacent volumes. + * \return number of reoriented faces. + */ +//================================================================================ + +int SMESH_MeshEditor::Reorient2DBy3D (TIDSortedElemSet & theFaces, + TIDSortedElemSet & theVolumes, + const bool theOutsideNormal) +{ + int nbReori = 0; + + SMDS_ElemIteratorPtr faceIt; + if ( theFaces.empty() ) + faceIt = GetMeshDS()->elementsIterator( SMDSAbs_Face ); + else + faceIt = elemSetIterator( theFaces ); + + vector< const SMDS_MeshNode* > faceNodes; + TIDSortedElemSet checkedVolumes; + set< const SMDS_MeshNode* > faceNodesSet; + SMDS_VolumeTool volumeTool; + + while ( faceIt->more() ) // loop on given faces + { + const SMDS_MeshElement* face = faceIt->next(); + if ( face->GetType() != SMDSAbs_Face ) + continue; + + const int nbCornersNodes = face->NbCornerNodes(); + faceNodes.assign( face->begin_nodes(), face->end_nodes() ); + + checkedVolumes.clear(); + SMDS_ElemIteratorPtr vIt = faceNodes[ 0 ]->GetInverseElementIterator( SMDSAbs_Volume ); + while ( vIt->more() ) + { + const SMDS_MeshElement* volume = vIt->next(); + + if ( !checkedVolumes.insert( volume ).second ) + continue; + if ( !theVolumes.empty() && !theVolumes.count( volume )) + continue; + + // is volume adjacent? + bool allNodesCommon = true; + for ( int iN = 1; iN < nbCornersNodes && allNodesCommon; ++iN ) + allNodesCommon = ( volume->GetNodeIndex( faceNodes[ iN ]) > -1 ); + if ( !allNodesCommon ) + continue; + + // get nodes of a corresponding volume facet + faceNodesSet.clear(); + faceNodesSet.insert( faceNodes.begin(), faceNodes.end() ); + volumeTool.Set( volume ); + int facetID = volumeTool.GetFaceIndex( faceNodesSet ); + if ( facetID < 0 ) continue; + volumeTool.SetExternalNormal(); + const SMDS_MeshNode** facetNodes = volumeTool.GetFaceNodes( facetID ); + + // compare order of faceNodes and facetNodes + const int iQ = 1 + ( nbCornersNodes < faceNodes.size() ); + int iNN[2]; + for ( int i = 0; i < 2; ++i ) + { + const SMDS_MeshNode* n = facetNodes[ i*iQ ]; + for ( int iN = 0; iN < nbCornersNodes; ++iN ) + if ( faceNodes[ iN ] == n ) + { + iNN[ i ] = iN; + break; + } + } + bool isOutside = Abs( iNN[0]-iNN[1] ) == 1 ? iNN[0] < iNN[1] : iNN[0] > iNN[1]; + if ( isOutside != theOutsideNormal ) + nbReori += Reorient( face ); + } + } // loop on given faces + + return nbReori; +} + //======================================================================= //function : getBadRate //purpose : @@ -1615,7 +1699,7 @@ namespace }; const int theHexTo4Prisms_FB[6*4+1] = // front-back { - 0, 3, 8, 1, 2, 9, 3, 7, 8, 2, 6, 9, 7, 4, 8, 6, 5, 9, 4, 0, 8, 5, 1, 9, -1 + 0, 3, 9, 1, 2, 8, 3, 7, 9, 2, 6, 8, 7, 4, 9, 6, 5, 8, 4, 0, 9, 5, 1, 8, -1 }; const int theHexTo2Prisms_BT_1[6*2+1] = @@ -3617,13 +3701,8 @@ static bool getClosestUV (Extrema_GenExtPS& projector, if ( projector.IsDone() ) { double u, v, minVal = DBL_MAX; for ( int i = projector.NbExt(); i > 0; i-- ) -#if OCC_VERSION_LARGE > 0x06040000 // Porting to OCCT6.5.1 if ( projector.SquareDistance( i ) < minVal ) { minVal = projector.SquareDistance( i ); -#else - if ( projector.Value( i ) < minVal ) { - minVal = projector.Value( i ); -#endif projector.Point( i ).Parameter( u, v ); } result.SetCoord( u, v ); @@ -6428,7 +6507,7 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems, if ( ( theMakeGroups && theCopy ) || ( theMakeGroups && theTargetMesh ) ) - newGroupIDs = generateGroups( srcNodes, srcElems, groupPostfix, theTargetMesh ); + newGroupIDs = generateGroups( srcNodes, srcElems, groupPostfix, theTargetMesh, false ); return newGroupIDs; } @@ -6436,9 +6515,11 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems, //======================================================================= /*! * \brief Create groups of elements made during transformation - * \param nodeGens - nodes making corresponding myLastCreatedNodes - * \param elemGens - elements making corresponding myLastCreatedElems - * \param postfix - to append to names of new groups + * \param nodeGens - nodes making corresponding myLastCreatedNodes + * \param elemGens - elements making corresponding myLastCreatedElems + * \param postfix - to append to names of new groups + * \param targetMesh - mesh to create groups in + * \param topPresent - is there "top" elements that are created by sweeping */ //======================================================================= @@ -6446,14 +6527,17 @@ SMESH_MeshEditor::PGroupIDs SMESH_MeshEditor::generateGroups(const SMESH_SequenceOfElemPtr& nodeGens, const SMESH_SequenceOfElemPtr& elemGens, const std::string& postfix, - SMESH_Mesh* targetMesh) + SMESH_Mesh* targetMesh, + const bool topPresent) { PGroupIDs newGroupIDs( new list ); SMESH_Mesh* mesh = targetMesh ? targetMesh : GetMesh(); // Sort existing groups by types and collect their names - // to store an old group and a generated new ones + // containers to store an old group and generated new ones; + // 1st new group is for result elems of different type than a source one; + // 2nd new group is for same type result elems ("top" group at extrusion) using boost::tuple; using boost::make_tuple; typedef tuple< SMESHDS_GroupBase*, SMESHDS_Group*, SMESHDS_Group* > TOldNewGroup; @@ -6483,6 +6567,7 @@ SMESH_MeshEditor::generateGroups(const SMESH_SequenceOfElemPtr& nodeGens, // Loop on nodes and elements to add them in new groups + vector< const SMDS_MeshElement* > resultElems; for ( int isNodes = 0; isNodes < 2; ++isNodes ) { const SMESH_SequenceOfElemPtr& gens = isNodes ? nodeGens : elemGens; @@ -6505,7 +6590,7 @@ SMESH_MeshEditor::generateGroups(const SMESH_SequenceOfElemPtr& nodeGens, continue; } // collect all elements made by the iElem-th sourceElem - list< const SMDS_MeshElement* > resultElems; + resultElems.clear(); if ( const SMDS_MeshElement* resElem = elems( iElem )) if ( resElem != sourceElem ) resultElems.push_back( resElem ); @@ -6514,25 +6599,23 @@ SMESH_MeshEditor::generateGroups(const SMESH_SequenceOfElemPtr& nodeGens, if ( resElem != sourceElem ) resultElems.push_back( resElem ); - // there must be a top element const SMDS_MeshElement* topElem = 0; - if ( isNodes ) + if ( isNodes ) // there must be a top element { topElem = resultElems.back(); resultElems.pop_back(); } else { - list< const SMDS_MeshElement* >::reverse_iterator resElemIt = resultElems.rbegin(); + vector< const SMDS_MeshElement* >::reverse_iterator resElemIt = resultElems.rbegin(); for ( ; resElemIt != resultElems.rend() ; ++resElemIt ) if ( (*resElemIt)->GetType() == sourceElem->GetType() ) { topElem = *resElemIt; - resultElems.erase( --(resElemIt.base()) ); // erase *resElemIt + *resElemIt = 0; // erase *resElemIt break; } } - // add resultElems to groups originted from ones the sourceElem belongs to list< TOldNewGroup >::iterator gOldNew, gLast = groupsOldNew.end(); for ( gOldNew = groupsOldNew.begin(); gOldNew != gLast; ++gOldNew ) @@ -6542,16 +6625,17 @@ SMESH_MeshEditor::generateGroups(const SMESH_SequenceOfElemPtr& nodeGens, { // fill in a new group SMDS_MeshGroup & newGroup = gOldNew->get<1>()->SMDSGroup(); - list< const SMDS_MeshElement* >::iterator resLast = resultElems.end(), resElemIt; + vector< const SMDS_MeshElement* >::iterator resLast = resultElems.end(), resElemIt; for ( resElemIt = resultElems.begin(); resElemIt != resLast; ++resElemIt ) - newGroup.Add( *resElemIt ); + if ( *resElemIt ) + newGroup.Add( *resElemIt ); // fill a "top" group if ( topElem ) { SMDS_MeshGroup & newTopGroup = gOldNew->get<2>()->SMDSGroup(); newTopGroup.Add( topElem ); - } + } } } } // loop on created elements @@ -6565,7 +6649,6 @@ SMESH_MeshEditor::generateGroups(const SMESH_SequenceOfElemPtr& nodeGens, SMESHDS_GroupBase* oldGroupDS = orderedOldNewGroups[i]->get<0>(); SMESHDS_Group* newGroups[2] = { orderedOldNewGroups[i]->get<1>(), orderedOldNewGroups[i]->get<2>() }; - const int nbNewGroups = !newGroups[0]->IsEmpty() + !newGroups[1]->IsEmpty(); for ( int is2nd = 0; is2nd < 2; ++is2nd ) { SMESHDS_Group* newGroupDS = newGroups[ is2nd ]; @@ -6579,11 +6662,21 @@ SMESH_MeshEditor::generateGroups(const SMESH_SequenceOfElemPtr& nodeGens, newGroupDS->SetType( newGroupDS->GetElements()->next()->GetType() ); // make a name - const bool isTop = ( nbNewGroups == 2 && + const bool isTop = ( topPresent && newGroupDS->GetType() == oldGroupDS->GetType() && is2nd ); string name = oldGroupDS->GetStoreName(); + { // remove trailing whitespaces (issue 22599) + size_t size = name.size(); + while ( size > 1 && isspace( name[ size-1 ])) + --size; + if ( size != name.size() ) + { + name.resize( size ); + oldGroupDS->SetStoreName( name.c_str() ); + } + } if ( !targetMesh ) { string suffix = ( isTop ? "top": postfix.c_str() ); name += "_"; @@ -8751,6 +8844,7 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d, const bool theT aHelper.SetIsQuadratic( true ); aHelper.SetIsBiQuadratic( theToBiQuad ); aHelper.SetElementsOnShape(true); + aHelper.ToFixNodeParameters( true ); // convert elements assigned to sub-meshes int nbCheckedElems = 0; @@ -10298,15 +10392,12 @@ namespace { } void Perform(const gp_Pnt& aPnt, double theTol) { + theTol *= theTol; _state = TopAbs_OUT; _extremum.Perform(aPnt); if ( _extremum.IsDone() ) for ( int iSol = 1; iSol <= _extremum.NbExt() && _state == TopAbs_OUT; ++iSol) -#if OCC_VERSION_LARGE > 0x06040000 // Porting to OCCT6.5.1 _state = ( _extremum.SquareDistance(iSol) <= theTol ? TopAbs_IN : TopAbs_OUT ); -#else - _state = ( _extremum.Value(iSol) <= theTol ? TopAbs_IN : TopAbs_OUT ); -#endif } TopAbs_State State() const { @@ -10563,7 +10654,12 @@ double SMESH_MeshEditor::OrientedAngle(const gp_Pnt& p0, const gp_Pnt& p1, const gp_Vec v2(p0, g2); gp_Vec n1 = vref.Crossed(v1); gp_Vec n2 = vref.Crossed(v2); - return n2.AngleWithRef(n1, vref); + try { + return n2.AngleWithRef(n1, vref); + } + catch ( Standard_Failure ) { + } + return Max( v1.Magnitude(), v2.Magnitude() ); } /*! @@ -10576,13 +10672,16 @@ double SMESH_MeshEditor::OrientedAngle(const gp_Pnt& p0, const gp_Pnt& p1, const * If there is no shared faces between the group #n and the group #p in the list, the group j_n_p is not created. * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation). * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples". - * @param theElems - list of groups of volumes, where a group of volume is a set of - * SMDS_MeshElements sorted by Id. - * @param createJointElems - if TRUE, create the elements - * @return TRUE if operation has been completed successfully, FALSE otherwise + * \param theElems - list of groups of volumes, where a group of volume is a set of + * SMDS_MeshElements sorted by Id. + * \param createJointElems - if TRUE, create the elements + * \param onAllBoundaries - if TRUE, the nodes and elements are also created on + * the boundary between \a theDomains and the rest mesh + * \return TRUE if operation has been completed successfully, FALSE otherwise */ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector& theElems, - bool createJointElems) + bool createJointElems, + bool onAllBoundaries) { MESSAGE("----------------------------------------------"); MESSAGE("SMESH_MeshEditor::doubleNodesOnGroupBoundaries"); @@ -10611,15 +10710,20 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector volume to modify) @@ -10648,7 +10752,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vectorgetVtkId(); @@ -10661,26 +10765,30 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vectorfromVtkToSmds(neighborsVtkIds[n]); const SMDS_MeshElement* elem = meshDS->FindElement(smdsId); - if (! domain.count(elem)) // neighbor is in another domain : face is shared + if (elem && ! domain.count(elem)) // neighbor is in another domain : face is shared { bool ok = false ; - for (int idombis = 0; idombis < theElems.size(); idombis++) // check if the neighbor belongs to another domain of the list + for (int idombis = 0; idombis < theElems.size() && !ok; idombis++) // check if the neighbor belongs to another domain of the list { // MESSAGE("Domain " << idombis); const TIDSortedElemSet& domainbis = theElems[idombis]; if ( domainbis.count(elem)) ok = true ; // neighbor is in a correct domain : face is kept } - if ( ok ) // the characteristics of the face is stored + if ( ok || onAllBoundaries ) // the characteristics of the face is stored { DownIdType face(downIds[n], downTypes[n]); - if (!faceDomains.count(face)) - faceDomains[face] = emptyMap; // create an empty entry for face if (!faceDomains[face].count(idom)) { faceDomains[face][idom] = vtkId; // volume associated to face in this domain celldom[vtkId] = idom; //MESSAGE(" cell with a border " << vtkId << " domain " << idom); } + if ( !ok ) + { + theRestDomElems.insert( elem ); + faceDomains[face][iRestDom] = neighborsVtkIds[n]; + celldom[neighborsVtkIds[n]] = iRestDom; + } } } } @@ -10694,14 +10802,14 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector domvol = itface->second; + const std::map& domvol = itface->second; if (!domvol.count(idomain)) continue; DownIdType face = itface->first; @@ -10730,8 +10838,6 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector > mutipleNodesToFace; // nodes multi domains with domain order to transform in Face (junction between 3 or more 2D domains) MESSAGE(".. Duplication of the nodes"); - for (int idomain = 0; idomain < theElems.size(); idomain++) + for (int idomain = idom0; idomain < nbDomains; idomain++) { itface = faceDomains.begin(); for (; itface != faceDomains.end(); ++itface) { - std::map domvol = itface->second; + const std::map& domvol = itface->second; if (!domvol.count(idomain)) continue; DownIdType face = itface->first; @@ -10770,15 +10876,12 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector::iterator itdom = domvol.begin(); + std::map::const_iterator itdom = domvol.begin(); for (; itdom != domvol.end(); ++itdom) { int idom = itdom->first; @@ -10816,7 +10919,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vectorfromVtkToSmds(vtkVolIds[ivol]); SMDS_MeshElement* elem = (SMDS_MeshElement*)meshDS->FindElement(smdsId); - if (theElems[idom].count(elem)) + if (domain.count(elem)) { SMDS_VtkVolume* svol = dynamic_cast(elem); domvol[idom] = svol; @@ -11070,7 +11174,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector >::const_iterator itnod = nodeDomains.begin(); for (; itnod != nodeDomains.end(); ++itnod)