1 // Copyright (C) 2007-2008 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 // SMESH SMESH_I : idl implementation based on 'SMESH' unit's calsses
23 // File : SMESH_MeshEditor.hxx
24 // Created : Mon Apr 12 14:56:19 2004
25 // Author : Edward AGAPOV (eap)
28 #ifndef SMESH_MeshEditor_HeaderFile
29 #define SMESH_MeshEditor_HeaderFile
31 #include "SMESH_SMESH.hxx"
33 #include "SMDS_MeshElement.hxx"
34 #include "SMESH_Controls.hxx"
35 #include "SMESH_Mesh.hxx"
36 #include "SMESH_SequenceOfElemPtr.hxx"
37 #include "SMESH_SequenceOfNode.hxx"
39 #include <TColStd_HSequenceOfReal.hxx>
50 class SMESH_MesherHelper;
53 typedef std::map<const SMDS_MeshElement*,
54 std::list<const SMDS_MeshElement*> > TElemOfElemListMap;
55 typedef std::map<const SMDS_MeshNode*, const SMDS_MeshNode*> TNodeNodeMap;
57 //!< Set of elements sorted by ID, to be used to assure predictability of edition
58 typedef std::set< const SMDS_MeshElement*, TIDCompare > TIDSortedElemSet;
60 typedef pair< const SMDS_MeshNode*, const SMDS_MeshNode* > NLink;
63 //=======================================================================
65 * \brief A sorted pair of nodes
67 //=======================================================================
69 struct SMESH_TLink: public NLink
71 SMESH_TLink(const SMDS_MeshNode* n1, const SMDS_MeshNode* n2 ):NLink( n1, n2 )
72 { if ( n1->GetID() < n2->GetID() ) std::swap( first, second ); }
73 SMESH_TLink(const NLink& link ):NLink( link )
74 { if ( first->GetID() < second->GetID() ) std::swap( first, second ); }
77 // ============================================================
79 * \brief Searcher for the node closest to point
81 // ============================================================
83 struct SMESH_NodeSearcher
85 virtual const SMDS_MeshNode* FindClosestTo( const gp_Pnt& pnt ) = 0;
88 // ============================================================
90 * \brief Editor of a mesh
92 // ============================================================
94 class SMESH_EXPORT SMESH_MeshEditor {
98 SMESH_MeshEditor( SMESH_Mesh* theMesh );
103 SMDS_MeshElement* AddElement(const std::vector<const SMDS_MeshNode*> & nodes,
104 const SMDSAbs_ElementType type,
110 SMDS_MeshElement* AddElement(const std::vector<int> & nodeIDs,
111 const SMDSAbs_ElementType type,
115 bool Remove (const std::list< int >& theElemIDs, const bool isNodes);
116 // Remove a node or an element.
117 // Modify a compute state of sub-meshes which become empty
119 bool InverseDiag (const SMDS_MeshElement * theTria1,
120 const SMDS_MeshElement * theTria2 );
121 // Replace two neighbour triangles with ones built on the same 4 nodes
122 // but having other common link.
123 // Return False if args are improper
125 bool InverseDiag (const SMDS_MeshNode * theNode1,
126 const SMDS_MeshNode * theNode2 );
127 // Replace two neighbour triangles sharing theNode1-theNode2 link
128 // with ones built on the same 4 nodes but having other common link.
129 // Return false if proper faces not found
131 bool DeleteDiag (const SMDS_MeshNode * theNode1,
132 const SMDS_MeshNode * theNode2 );
133 // Replace two neighbour triangles sharing theNode1-theNode2 link
134 // with a quadrangle built on the same 4 nodes.
135 // Return false if proper faces not found
137 bool Reorient (const SMDS_MeshElement * theElement);
138 // Reverse theElement orientation
142 * \brief Fuse neighbour triangles into quadrangles.
143 * \param theElems - The triangles to be fused.
144 * \param theCriterion - Is used to choose a neighbour to fuse with.
145 * \param theMaxAngle - Is a max angle between element normals at which fusion
146 * is still performed; theMaxAngle is mesured in radians.
147 * \retval bool - Success or not.
149 bool TriToQuad (TIDSortedElemSet & theElems,
150 SMESH::Controls::NumericalFunctorPtr theCriterion,
151 const double theMaxAngle);
154 * \brief Split quadrangles into triangles.
155 * \param theElems - The faces to be splitted.
156 * \param theCriterion - Is used to choose a diagonal for splitting.
157 * \retval bool - Success or not.
159 bool QuadToTri (TIDSortedElemSet & theElems,
160 SMESH::Controls::NumericalFunctorPtr theCriterion);
163 * \brief Split quadrangles into triangles.
164 * \param theElems - The faces to be splitted.
165 * \param the13Diag - Is used to choose a diagonal for splitting.
166 * \retval bool - Success or not.
168 bool QuadToTri (TIDSortedElemSet & theElems,
169 const bool the13Diag);
172 * \brief Find better diagonal for splitting.
173 * \param theQuad - The face to find better splitting of.
174 * \param theCriterion - Is used to choose a diagonal for splitting.
175 * \retval int - 1 for 1-3 diagonal, 2 for 2-4, -1 - for errors.
177 int BestSplit (const SMDS_MeshElement* theQuad,
178 SMESH::Controls::NumericalFunctorPtr theCriterion);
181 enum SmoothMethod { LAPLACIAN = 0, CENTROIDAL };
183 void Smooth (TIDSortedElemSet & theElements,
184 std::set<const SMDS_MeshNode*> & theFixedNodes,
185 const SmoothMethod theSmoothMethod,
186 const int theNbIterations,
187 double theTgtAspectRatio = 1.0,
188 const bool the2D = true);
189 // Smooth theElements using theSmoothMethod during theNbIterations
190 // or until a worst element has aspect ratio <= theTgtAspectRatio.
191 // Aspect Ratio varies in range [1.0, inf].
192 // If theElements is empty, the whole mesh is smoothed.
193 // theFixedNodes contains additionally fixed nodes. Nodes built
194 // on edges and boundary nodes are always fixed.
195 // If the2D, smoothing is performed using UV parameters of nodes
196 // on geometrical faces
198 typedef std::auto_ptr< std::list<int> > PGroupIDs;
200 PGroupIDs RotationSweep (TIDSortedElemSet & theElements,
201 const gp_Ax1& theAxis,
202 const double theAngle,
203 const int theNbSteps,
204 const double theToler,
205 const bool theMakeGroups,
206 const bool theMakeWalls=true);
207 // Generate new elements by rotation of theElements around theAxis
208 // by theAngle by theNbSteps
211 * Auxilary flag for advanced extrusion.
212 * BOUNDARY: create or not boundary for result of extrusion
213 * SEW: try to use existing nodes or create new nodes in any case
215 enum ExtrusionFlags {
216 EXTRUSION_FLAG_BOUNDARY = 0x01,
217 EXTRUSION_FLAG_SEW = 0x02
221 * special structire for control of extrusion functionality
224 gp_Dir myDir; // direction of extrusion
225 Handle(TColStd_HSequenceOfReal) mySteps; // magnitudes for each step
226 SMESH_SequenceOfNode myNodes; // nodes for using in sewing
230 * Create new node in the mesh with given coordinates
231 * (auxilary for advanced extrusion)
233 const SMDS_MeshNode* CreateNode(const double x,
236 const double tolnode,
237 SMESH_SequenceOfNode& aNodes);
240 * Generate new elements by extrusion of theElements
241 * It is a method used in .idl file. All functionality
242 * is implemented in the next method (see below) which
243 * is used in the cuurent method.
244 * param theElems - list of elements for extrusion
245 * param newElemsMap returns history of extrusion
246 * param theFlags set flags for performing extrusion (see description
247 * of enum ExtrusionFlags for additional information)
248 * param theTolerance - uses for comparing locations of nodes if flag
249 * EXTRUSION_FLAG_SEW is set
251 PGroupIDs ExtrusionSweep (TIDSortedElemSet & theElems,
252 const gp_Vec& theStep,
253 const int theNbSteps,
254 TElemOfElemListMap& newElemsMap,
255 const bool theMakeGroups,
256 const int theFlags = EXTRUSION_FLAG_BOUNDARY,
257 const double theTolerance = 1.e-6);
260 * Generate new elements by extrusion of theElements
261 * param theElems - list of elements for extrusion
262 * param newElemsMap returns history of extrusion
263 * param theFlags set flags for performing extrusion (see description
264 * of enum ExtrusionFlags for additional information)
265 * param theTolerance - uses for comparing locations of nodes if flag
266 * EXTRUSION_FLAG_SEW is set
267 * param theParams - special structure for manage of extrusion
269 PGroupIDs ExtrusionSweep (TIDSortedElemSet & theElems,
270 ExtrusParam& theParams,
271 TElemOfElemListMap& newElemsMap,
272 const bool theMakeGroups,
274 const double theTolerance);
277 // Generate new elements by extrusion of theElements
278 // by theStep by theNbSteps
280 enum Extrusion_Error {
285 EXTR_BAD_STARTING_NODE,
286 EXTR_BAD_ANGLES_NUMBER,
287 EXTR_CANT_GET_TANGENT
290 Extrusion_Error ExtrusionAlongTrack (TIDSortedElemSet & theElements,
291 SMESH_subMesh* theTrackPattern,
292 const SMDS_MeshNode* theNodeStart,
293 const bool theHasAngles,
294 std::list<double>& theAngles,
295 const bool theHasRefPoint,
296 const gp_Pnt& theRefPoint,
297 const bool theMakeGroups);
298 // Generate new elements by extrusion of theElements along path given by theTrackPattern,
299 // theHasAngles are the rotation angles, base point can be given by theRefPoint
301 PGroupIDs Transform (TIDSortedElemSet & theElements,
302 const gp_Trsf& theTrsf,
304 const bool theMakeGroups,
305 SMESH_Mesh* theTargetMesh=0);
306 // Move or copy theElements applying theTrsf to their nodes
308 typedef std::list< std::list< const SMDS_MeshNode* > > TListOfListOfNodes;
310 void FindCoincidentNodes (std::set<const SMDS_MeshNode*> & theNodes,
311 const double theTolerance,
312 TListOfListOfNodes & theGroupsOfNodes);
313 // Return list of group of nodes close to each other within theTolerance.
314 // Search among theNodes or in the whole mesh if theNodes is empty.
317 * \brief Return SMESH_NodeSearcher
319 SMESH_NodeSearcher* GetNodeSearcher();
321 int SimplifyFace (const std::vector<const SMDS_MeshNode *> faceNodes,
322 std::vector<const SMDS_MeshNode *>& poly_nodes,
323 std::vector<int>& quantities) const;
324 // Split face, defined by <faceNodes>, into several faces by repeating nodes.
325 // Is used by MergeNodes()
327 void MergeNodes (TListOfListOfNodes & theNodeGroups);
328 // In each group, the cdr of nodes are substituted by the first one
331 typedef std::list< std::list< int > > TListOfListOfElementsID;
333 void FindEqualElements(std::set<const SMDS_MeshElement*> & theElements,
334 TListOfListOfElementsID & theGroupsOfElementsID);
335 // Return list of group of elements build on the same nodes.
336 // Search among theElements or in the whole mesh if theElements is empty.
338 void MergeElements(TListOfListOfElementsID & theGroupsOfElementsID);
339 // In each group remove all but first of elements.
341 void MergeEqualElements();
342 // Remove all but one of elements built on the same nodes.
343 // Return nb of successfully merged groups.
345 static bool CheckFreeBorderNodes(const SMDS_MeshNode* theNode1,
346 const SMDS_MeshNode* theNode2,
347 const SMDS_MeshNode* theNode3 = 0);
348 // Return true if the three nodes are on a free border
350 static bool FindFreeBorder (const SMDS_MeshNode* theFirstNode,
351 const SMDS_MeshNode* theSecondNode,
352 const SMDS_MeshNode* theLastNode,
353 std::list< const SMDS_MeshNode* > & theNodes,
354 std::list< const SMDS_MeshElement* >& theFaces);
355 // Return nodes and faces of a free border if found
359 // for SewFreeBorder()
360 SEW_BORDER1_NOT_FOUND,
361 SEW_BORDER2_NOT_FOUND,
362 SEW_BOTH_BORDERS_NOT_FOUND,
364 SEW_VOLUMES_TO_SPLIT,
365 // for SewSideElements()
366 SEW_DIFF_NB_OF_ELEMENTS,
367 SEW_TOPO_DIFF_SETS_OF_ELEMENTS,
374 Sew_Error SewFreeBorder (const SMDS_MeshNode* theBorderFirstNode,
375 const SMDS_MeshNode* theBorderSecondNode,
376 const SMDS_MeshNode* theBorderLastNode,
377 const SMDS_MeshNode* theSide2FirstNode,
378 const SMDS_MeshNode* theSide2SecondNode,
379 const SMDS_MeshNode* theSide2ThirdNode = 0,
380 const bool theSide2IsFreeBorder = true,
381 const bool toCreatePolygons = false,
382 const bool toCreatePolyedrs = false);
383 // Sew the free border to the side2 by replacing nodes in
384 // elements on the free border with nodes of the elements
385 // of the side 2. If nb of links in the free border and
386 // between theSide2FirstNode and theSide2LastNode are different,
387 // additional nodes are inserted on a link provided that no
388 // volume elements share the splitted link.
389 // The side 2 is a free border if theSide2IsFreeBorder == true.
390 // Sewing is peformed between the given first, second and last
391 // nodes on the sides.
392 // theBorderFirstNode is merged with theSide2FirstNode.
393 // if (!theSide2IsFreeBorder) then theSide2SecondNode gives
394 // the last node on the side 2, which will be merged with
395 // theBorderLastNode.
396 // if (theSide2IsFreeBorder) then theSide2SecondNode will
397 // be merged with theBorderSecondNode.
398 // if (theSide2IsFreeBorder && theSide2ThirdNode == 0) then
399 // the 2 free borders are sewn link by link and no additional
400 // nodes are inserted.
401 // Return false, if sewing failed.
403 Sew_Error SewSideElements (TIDSortedElemSet& theSide1,
404 TIDSortedElemSet& theSide2,
405 const SMDS_MeshNode* theFirstNode1ToMerge,
406 const SMDS_MeshNode* theFirstNode2ToMerge,
407 const SMDS_MeshNode* theSecondNode1ToMerge,
408 const SMDS_MeshNode* theSecondNode2ToMerge);
409 // Sew two sides of a mesh. Nodes belonging to theSide1 are
410 // merged with nodes of elements of theSide2.
411 // Number of elements in theSide1 and in theSide2 must be
412 // equal and they should have similar node connectivity.
413 // The nodes to merge should belong to side s borders and
414 // the first node should be linked to the second.
416 void InsertNodesIntoLink(const SMDS_MeshElement* theFace,
417 const SMDS_MeshNode* theBetweenNode1,
418 const SMDS_MeshNode* theBetweenNode2,
419 std::list<const SMDS_MeshNode*>& theNodesToInsert,
420 const bool toCreatePoly = false);
421 // insert theNodesToInsert into theFace between theBetweenNode1 and theBetweenNode2.
422 // If toCreatePoly is true, replace theFace by polygon, else split theFace.
424 void UpdateVolumes (const SMDS_MeshNode* theBetweenNode1,
425 const SMDS_MeshNode* theBetweenNode2,
426 std::list<const SMDS_MeshNode*>& theNodesToInsert);
427 // insert theNodesToInsert into all volumes, containing link
428 // theBetweenNode1 - theBetweenNode2, between theBetweenNode1 and theBetweenNode2.
430 void ConvertToQuadratic(const bool theForce3d);
431 //converts all mesh to quadratic one, deletes old elements, replacing
432 //them with quadratic ones with the same id.
434 bool ConvertFromQuadratic();
435 //converts all mesh from quadratic to ordinary ones, deletes old quadratic elements, replacing
436 //them with ordinary mesh elements with the same id.
439 // static int SortQuadNodes (const SMDS_Mesh * theMesh,
440 // int theNodeIds[] );
441 // // Set 4 nodes of a quadrangle face in a good order.
442 // // Swap 1<->2 or 2<->3 nodes and correspondingly return
445 // static bool SortHexaNodes (const SMDS_Mesh * theMesh,
446 // int theNodeIds[] );
447 // // Set 8 nodes of a hexahedron in a good order.
448 // // Return success status
450 static void AddToSameGroups (const SMDS_MeshElement* elemToAdd,
451 const SMDS_MeshElement* elemInGroups,
452 SMESHDS_Mesh * aMesh);
453 // Add elemToAdd to the all groups the elemInGroups belongs to
455 static void RemoveElemFromGroups (const SMDS_MeshElement* element,
456 SMESHDS_Mesh * aMesh);
457 // remove element from the all groups
459 static void ReplaceElemInGroups (const SMDS_MeshElement* elemToRm,
460 const SMDS_MeshElement* elemToAdd,
461 SMESHDS_Mesh * aMesh);
462 // replace elemToRm by elemToAdd in the all groups
465 * \brief Return nodes linked to the given one in elements of the type
467 static void GetLinkedNodes( const SMDS_MeshNode* node,
468 TIDSortedElemSet & linkedNodes,
469 SMDSAbs_ElementType type = SMDSAbs_All );
471 static const SMDS_MeshElement*
472 FindFaceInSet(const SMDS_MeshNode* n1,
473 const SMDS_MeshNode* n2,
474 const TIDSortedElemSet& elemSet,
475 const TIDSortedElemSet& avoidSet);
476 // Return a face having linked nodes n1 and n2 and which is
477 // - not in avoidSet,
478 // - in elemSet provided that !elemSet.empty()
481 * \brief Find corresponding nodes in two sets of faces
482 * \param theSide1 - first face set
483 * \param theSide2 - second first face
484 * \param theFirstNode1 - a boundary node of set 1
485 * \param theFirstNode2 - a node of set 2 corresponding to theFirstNode1
486 * \param theSecondNode1 - a boundary node of set 1 linked with theFirstNode1
487 * \param theSecondNode2 - a node of set 2 corresponding to theSecondNode1
488 * \param nReplaceMap - output map of corresponding nodes
489 * \retval Sew_Error - is a success or not
491 static Sew_Error FindMatchingNodes(std::set<const SMDS_MeshElement*>& theSide1,
492 std::set<const SMDS_MeshElement*>& theSide2,
493 const SMDS_MeshNode* theFirstNode1,
494 const SMDS_MeshNode* theFirstNode2,
495 const SMDS_MeshNode* theSecondNode1,
496 const SMDS_MeshNode* theSecondNode2,
497 TNodeNodeMap & nReplaceMap);
500 * \brief Returns true if given node is medium
501 * \param n - node to check
502 * \param typeToCheck - type of elements containing the node to ask about node status
503 * \retval bool - check result
505 static bool IsMedium(const SMDS_MeshNode* node,
506 const SMDSAbs_ElementType typeToCheck = SMDSAbs_All);
508 int FindShape (const SMDS_MeshElement * theElem);
509 // Return an index of the shape theElem is on
510 // or zero if a shape not found
512 SMESH_Mesh * GetMesh() { return myMesh; }
514 SMESHDS_Mesh * GetMeshDS() { return myMesh->GetMeshDS(); }
516 const SMESH_SequenceOfElemPtr& GetLastCreatedNodes() const { return myLastCreatedNodes; }
518 const SMESH_SequenceOfElemPtr& GetLastCreatedElems() const { return myLastCreatedElems; }
520 bool DoubleNodes( const std::list< int >& theListOfNodes,
521 const std::list< int >& theListOfModifiedElems );
526 * \brief Convert elements contained in a submesh to quadratic
527 * \retval int - nb of checked elements
529 int convertElemToQuadratic(SMESHDS_SubMesh * theSm,
530 SMESH_MesherHelper& theHelper,
531 const bool theForce3d);
534 * \brief Convert quadratic elements to linear ones and remove quadratic nodes
535 * \retval int - nb of checked elements
537 int removeQuadElem( SMESHDS_SubMesh * theSm,
538 SMDS_ElemIteratorPtr theItr,
539 const int theShapeID);
541 * \brief Create groups of elements made during transformation
542 * \param nodeGens - nodes making corresponding myLastCreatedNodes
543 * \param elemGens - elements making corresponding myLastCreatedElems
544 * \param postfix - to append to names of new groups
546 PGroupIDs generateGroups(const SMESH_SequenceOfElemPtr& nodeGens,
547 const SMESH_SequenceOfElemPtr& elemGens,
548 const std::string& postfix,
549 SMESH_Mesh* targetMesh=0);
552 typedef std::map<const SMDS_MeshNode*, std::list<const SMDS_MeshNode*> > TNodeOfNodeListMap;
553 typedef TNodeOfNodeListMap::iterator TNodeOfNodeListMapItr;
554 typedef std::vector<TNodeOfNodeListMapItr> TVecOfNnlmiMap;
555 typedef std::map<const SMDS_MeshElement*, TVecOfNnlmiMap > TElemOfVecOfNnlmiMap;
558 * \brief Create elements by sweeping an element
559 * \param elem - element to sweep
560 * \param newNodesItVec - nodes generated from each node of the element
561 * \param newElems - generated elements
562 * \param nbSteps - number of sweeping steps
563 * \param srcElements - to append elem for each generated element
565 void sweepElement(const SMDS_MeshElement* elem,
566 const std::vector<TNodeOfNodeListMapItr> & newNodesItVec,
567 std::list<const SMDS_MeshElement*>& newElems,
569 SMESH_SequenceOfElemPtr& srcElements);
572 * \brief Create 1D and 2D elements around swept elements
573 * \param mapNewNodes - source nodes and ones generated from them
574 * \param newElemsMap - source elements and ones generated from them
575 * \param elemNewNodesMap - nodes generated from each node of each element
576 * \param elemSet - all swept elements
577 * \param nbSteps - number of sweeping steps
578 * \param srcElements - to append elem for each generated element
580 void makeWalls (TNodeOfNodeListMap & mapNewNodes,
581 TElemOfElemListMap & newElemsMap,
582 TElemOfVecOfNnlmiMap & elemNewNodesMap,
583 TIDSortedElemSet& elemSet,
585 SMESH_SequenceOfElemPtr& srcElements);
591 * Sequence for keeping nodes created during last operation
593 SMESH_SequenceOfElemPtr myLastCreatedNodes;
596 * Sequence for keeping elements created during last operation
598 SMESH_SequenceOfElemPtr myLastCreatedElems;