From 401b2a2e54af16513f98bf23584a7f69ab8a2956 Mon Sep 17 00:00:00 2001 From: eap Date: Thu, 24 Jan 2019 18:28:24 +0300 Subject: [PATCH] 23620: EDF 10301 - Completing Extrusion along a path Add scale factors to Extrusion along line Add angles to Extrusion along path --- doc/salome/examples/modifying_meshes_ex22.py | 15 +- doc/salome/examples/modifying_meshes_ex23.py | 55 +- .../SMESH/images/extrusion_along_path_dlg.png | Bin 44946 -> 46531 bytes .../gui/SMESH/images/extrusionalongaline1.png | Bin 45079 -> 48507 bytes doc/salome/gui/SMESH/input/extrusion.rst | 14 +- .../gui/SMESH/input/extrusion_along_path.rst | 12 +- idl/SMESH_MeshEditor.idl | 34 +- src/SMESH/SMESH_MeshEditor.cxx | 1113 ++++++----------- src/SMESH/SMESH_MeshEditor.hxx | 110 +- src/SMESH/SMESH_MesherHelper.cxx | 13 +- src/SMESH/SMESH_MesherHelper.hxx | 10 +- src/SMESH/SMESH_Pattern.cxx | 1 + src/SMESHDS/SMESHDS_Mesh.cxx | 2 +- .../SMESHGUI_ExtrusionAlongPathDlg.cxx | 186 ++- src/SMESHGUI/SMESHGUI_ExtrusionAlongPathDlg.h | 11 + src/SMESHGUI/SMESHGUI_ExtrusionDlg.cxx | 167 ++- src/SMESHGUI/SMESHGUI_ExtrusionDlg.h | 15 +- src/SMESHGUI/SMESH_msg_en.ts | 62 +- src/SMESHUtils/SMESH_Delaunay.hxx | 4 +- src/SMESHUtils/SMESH_MeshAlgos.cxx | 2 +- src/SMESH_I/SMESH_MeshEditor_i.cxx | 148 ++- src/SMESH_I/SMESH_MeshEditor_i.hxx | 38 +- src/SMESH_SWIG/smeshBuilder.py | 126 +- src/StdMeshers/StdMeshers_FaceSide.cxx | 5 +- src/StdMeshers/StdMeshers_Import_1D.cxx | 1 + src/StdMeshers/StdMeshers_Import_1D2D.cxx | 1 + src/StdMeshers/StdMeshers_Prism_3D.cxx | 1 + src/StdMeshers/StdMeshers_ProjectionUtils.cxx | 1 + src/StdMeshers/StdMeshers_Projection_2D.cxx | 1 + .../StdMeshers_SegmentLengthAroundVertex.cxx | 1 + src/StdMeshers/StdMeshers_ViscousLayers.cxx | 1 + src/StdMeshers/StdMeshers_ViscousLayers2D.cxx | 1 + 32 files changed, 1071 insertions(+), 1080 deletions(-) diff --git a/doc/salome/examples/modifying_meshes_ex22.py b/doc/salome/examples/modifying_meshes_ex22.py index d9e1f97d9..fe99d13e3 100644 --- a/doc/salome/examples/modifying_meshes_ex22.py +++ b/doc/salome/examples/modifying_meshes_ex22.py @@ -1,5 +1,7 @@ # Extrusion +# There is a series of Extrusion Along Line methods added at different times; +# a fully functional method is ExtrusionSweepObjects() import salome, math salome.salome_init() @@ -48,22 +50,13 @@ stepVector = [0.,0.,1.] mesh.ExtrusionSweepObject1D( obj, stepVector, nbSteps ) # extrude a group -lineExtruded = None -for g in mesh.GetGroups( SMESH.FACE ): - if g.GetName() == "line_extruded": - lineExtruded = g - break -obj = lineExtruded +obj = mesh.GetGroupByName( "line_extruded", SMESH.FACE )[0] stepVector = [0,-5.,0.] nbSteps = 1 mesh.ExtrusionSweepObject( obj, stepVector, nbSteps ) # extrude all nodes and triangle faces of the disk quarter, applying a scale factor -diskGroup = None -for g in mesh.GetGroups( SMESH.FACE ): - if g.GetName() == "line_rotated": - diskGroup = g - break +diskGroup = mesh.GetGroupByName( "line_rotated", SMESH.FACE )[0] crit = [ smesh.GetCriterion( SMESH.FACE, SMESH.FT_ElemGeomType,'=',SMESH.Geom_TRIANGLE ), smesh.GetCriterion( SMESH.FACE, SMESH.FT_BelongToMeshGroup,'=', diskGroup )] trianglesFilter = smesh.GetFilterFromCriteria( crit ) diff --git a/doc/salome/examples/modifying_meshes_ex23.py b/doc/salome/examples/modifying_meshes_ex23.py index 65b57ff36..d7f413440 100644 --- a/doc/salome/examples/modifying_meshes_ex23.py +++ b/doc/salome/examples/modifying_meshes_ex23.py @@ -19,7 +19,7 @@ iv = 1 vertices = [] for point in points: vert = geompy.MakeVertex(point[0], point[1], 0) - geompy.addToStudy(vert, "Vertex_" + repr(iv)) + #geompy.addToStudy(vert, "Vertex_" + repr(iv)) vertices.append(vert) iv += 1 pass @@ -97,8 +97,8 @@ Edge_Circle_mesh = Mesh1D(Edge_Circle , 8, "Edge_Circle" , smesh_builder=sme # IDsOfElements, PathMesh, PathShape, NodeStart, # HasAngles, Angles, HasRefPoint, RefPoint refPoint = SMESH.PointStruct(0, 0, 0) -a10 = 10.0*math.pi/180.0 -a45 = 45.0*math.pi/180.0 +a10 = math.radians( 10.0 ) +a45 = math.radians( 45.0 ) # 1. Extrusion of two mesh edges along a straight path error = quad_1.ExtrusionAlongPath([1,2], Edge_straight_mesh, Edge_straight, 1, @@ -128,4 +128,53 @@ error = quad_6.ExtrusionAlongPath(ff_6 , Edge_Circle_mesh, Edge_Circle, 1, error = quad_7.ExtrusionAlongPath(ff_7, Edge_Circle_mesh, Edge_Circle, 1, 1, [a45, -a45, a45, -a45, a45, -a45, a45, -a45], 0, refPoint) + + +# Make the same meshes using a fully functional method ExtrusionAlongPathObjects() having +# the following arguments: +# Nodes, Edges, Faces, PathObject, PathShape=None, +# NodeStart=1, HasAngles=False, Angles=[], LinearVariation=False, +# HasRefPoint=False, RefPoint=[0,0,0], MakeGroups=False, +# ScaleFactors=[], ScalesVariation=False + +quad_1 = MakeQuadMesh2("quad_1", smesh_builder=smesh)[0] +quad_2 = MakeQuadMesh2("quad_2", smesh_builder=smesh)[0] +quad_3 = MakeQuadMesh2("quad_3", smesh_builder=smesh)[0] +quad_4 = MakeQuadMesh2("quad_4", smesh_builder=smesh)[0] +quad_5 = MakeQuadMesh2("quad_5", smesh_builder=smesh)[0] +quad_6 = MakeQuadMesh2("quad_6", smesh_builder=smesh)[0] +quad_7 = MakeQuadMesh2("quad_7", smesh_builder=smesh)[0] + +# 1. Extrusion of two mesh edges along a straight path +nn, ee, ff = [], [1,2], [] +error = quad_1.ExtrusionAlongPathObjects( nn, ee, ff, Edge_straight_mesh ) + +# 2. Extrusion of one mesh edge along a curved path +nn, ee, ff = [], [2], [] +error = quad_2.ExtrusionAlongPathObjects( nn, ee, ff, Edge_bezierrr_mesh ) + +# 3. Extrusion of one mesh edge along a curved path with usage of angles +error = quad_3.ExtrusionAlongPathObjects( nn, ee, ff, Edge_bezierrr_mesh, + Angles=[a45, a45, a45, 0, -a45, -a45, -a45]) + +# 4. Extrusion of one mesh edge along the path, which is a part of a meshed wire +nn, ee, ff = [], [4], [] +error = quad_4.ExtrusionAlongPathObjects( nn, ee, ff, Wire_polyline_mesh, Wire_polyline_edges[0], + Angles=[a10, a10, a10]) + +# 5. Extrusion of two mesh faces along the path, which is a part of a meshed wire +nn, ee, ff = [], [], quad_5 +error = quad_5.ExtrusionAlongPathObjects( nn, ee, ff, Wire_polyline_mesh, Wire_polyline_edges[2], + NodeStart=4 ) + +# 6. Extrusion of two mesh faces along a closed path +nn, ee, ff = [], [], quad_6 +error = quad_6.ExtrusionAlongPathObjects( nn, ee, ff, Edge_Circle_mesh ) + +# 7. Extrusion of two mesh faces along a closed path with usage of angles +nn, ee, ff = [], [], quad_7 +error = quad_7.ExtrusionAlongPathObjects( nn, ee, ff, Edge_Circle_mesh, Edge_Circle, + Angles=[a45, -a45, a45, -a45, a45, -a45, a45, -a45]) + + salome.sg.updateObjBrowser() diff --git a/doc/salome/gui/SMESH/images/extrusion_along_path_dlg.png b/doc/salome/gui/SMESH/images/extrusion_along_path_dlg.png index bdc1eff88c7f175904f644fd8bcd23f1d2dba8ea..98e362f388837641fa0a85dbae8fb0897715334c 100644 GIT binary patch literal 46531 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 literal 44946 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 literal 45079 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 f9)Ul_2)teF>_extruded" and "_top". For example if a selected quadrangle is included in *g_Faces* group (see figures below) then result hexahedra will be included in *g_Faces_extruded* group and a quadrangle created at the "top" of extruded mesh will be included in *g_Faces_top group*. .. image:: ../images/extrusion_groups.png diff --git a/doc/salome/gui/SMESH/input/extrusion_along_path.rst b/doc/salome/gui/SMESH/input/extrusion_along_path.rst index 71851c8ef..70fb0cb2f 100644 --- a/doc/salome/gui/SMESH/input/extrusion_along_path.rst +++ b/doc/salome/gui/SMESH/input/extrusion_along_path.rst @@ -123,7 +123,7 @@ Extrusion of 2d elements along a closed path * **Start node** - the start node of the Path. It is used to define the direction of extrusion. - * If you activate **Generate Groups** check-box, the **result elements** created from **selected elements** contained in groups will be included into new groups named by pattern "_extruded" and "_top". For example if a selected quadrangle is included in *g_Faces* group (see figures below) then result hexahedra will be included in *g_Faces_extruded* group and a quadrangle created at the "top" of extruded mesh will be included in *g_Faces_top group*. + * If you activate **Generate groups** check-box, the *result elements* created from *selected elements* contained in groups will be included into new groups named by pattern "_extruded" and "_top". For example if a selected quadrangle is included in *g_Faces* group (see figures below) then result hexahedra will be included in *g_Faces_extruded* group and a quadrangle created at the "top" of extruded mesh will be included in *g_Faces_top group*. .. image:: ../images/extrusion_groups.png :align: center @@ -138,16 +138,18 @@ Extrusion of 2d elements along a closed path #. There are two optional parameters, which can be very useful: - * If the path of extrusion is curvilinear, at each iteration the extruded elements are rotated to keep its initial angularity to the curve. By default, the **Base Point** around which the elements are rotated is the mass center of the elements (note that it can differ from the gravity center computed by *Geometry* module for the underlying shape), however, you can specify any point as the **Base Point** and the elements will be rotated with respect to this point. Note that only the displacement of the **Base Point** exactly equals to the path, and all other extruded elements simply keep their position relatively to the **Base Point** at each iteration. + * If the path of extrusion is curvilinear, at each iteration the extruded elements are rotated to keep its initial angularity to the curve. By default, the **Base point** around which the elements are rotated is the mass center of the elements (note that it can differ from the gravity center computed by *Geometry* module for the underlying shape), however, you can specify any point as the **Base point** and the elements will be rotated with respect to this point. Note that only the displacement of the **Base point** exactly equals to the path, and all other extruded elements simply keep their position relatively to the **Base point** at each iteration. .. |add| image:: ../images/add.png .. |rem| image:: ../images/remove.png - * The elements can also be rotated around the path to get the resulting mesh in a helical fashion. You can set the values of angles at the right, add them to the list of angles at the left by pressing the *"Add"* button |add| and remove them from the list by pressing the *"Remove"* button |rem|. + * The elements can also be rotated around the path with rotaion center at the **Base point** to get the resulting mesh in a helical fashion. You can set the values of angles at the right, add them to **Rotation angles** list at the left by pressing the *"Add"* button |add| and remove them from the list by pressing the *"Remove"* button |rem|. + **Linear variation of angles** option allows defining the angle of gradual rotation for the whole path. At each step the elements will be rotated by *( angle / nb. of steps )*. - **Linear variation of the angles** option allows defining the angle of gradual rotation for the whole path. At each step the elements will be rotated by *( angle / nb. of steps )*. - + * Each of optional **Scale factors** in the list is applied to nodes of a corresponding extrusion step unless **Linear variation of factors** is checked, is which case the scale factors are spread over all extrusion steps. **Base point** serves as a scaling canter. + * *"Add"* button |add| adds a scale factor to the list. + * *"Remove"* button |rem| removes selected scale factors from the list. #. Click **Apply** or **Apply and Close** button to confirm the operation. Mesh edges will be extruded into faces, faces into volumes. The external surface of the resulting 3d mesh (if faces have been extruded) is covered with faces, and corners with edges. If the path is closed, the resulting mesh can contain duplicated nodes and faces, because no sewing is done. diff --git a/idl/SMESH_MeshEditor.idl b/idl/SMESH_MeshEditor.idl index 482f8e9b6..83ed605fa 100644 --- a/idl/SMESH_MeshEditor.idl +++ b/idl/SMESH_MeshEditor.idl @@ -510,13 +510,21 @@ module SMESH /*! * \brief Generate dim+1 elements by extrusion of elements along vector - * \param nodes - nodes to extrude: a list including groups, sub-meshes or a mesh - * \param edges - edges to extrude: a list including groups, sub-meshes or a mesh - * \param faces - faces to extrude: a list including groups, sub-meshes or a mesh - * \param stepVector - vector giving direction and distance of an extrusion step - * \param nbOfSteps - number of elements to generate from one element + * \param nodes - nodes to extrude: a list including groups, sub-meshes or a mesh. + * \param edges - edges to extrude: a list including groups, sub-meshes or a mesh. + * \param faces - faces to extrude: a list including groups, sub-meshes or a mesh. + * \param stepVector - vector giving direction and distance of an extrusion step. + * \param nbOfSteps - number of elements to generate from one element. * \param toMakeGroups - if true, new elements will be included into new groups * corresponding to groups the input elements included in. + * \param scaleFactors - optional scale factors to apply during extrusion; it's + * usage depends on \a scalesVariation parameter. + * \param scalesVariation - if \c True, \a scaleFactors are spread over all \a NbOfSteps, + otherwise \a scaleFactors[i] is applied to nodes at the i-th extrusion step. + * \param angles - optional rotation angles to apply during extrusion; it's + * usage depends on \a anglesVariation parameter. + * \param anglesVariation - if \c True, \a angles are spread over all \a NbOfSteps, + otherwise \a angle[i] is applied to nodes at the i-th extrusion step. * \return ListOfGroups - new groups created if \a toMakeGroups is true */ ListOfGroups ExtrusionSweepObjects(in ListOfIDSources nodes, @@ -524,10 +532,12 @@ module SMESH in ListOfIDSources faces, in DirStruct stepVector, in long nbOfSteps, + in boolean toMakeGroups, in double_array scaleFactors, - in boolean linearVariation, + in boolean scaleVariation, in double_array basePoint, - in boolean toMakeGroups) + in double_array angles, + in boolean angleVariation) raises (SALOME::SALOME_Exception); /*! Generates new elements by extrusion along the normal to a discretized surface or wire @@ -569,18 +579,20 @@ module SMESH EXTR_CANT_GET_TANGENT }; - ListOfGroups ExtrusionAlongPathObjects(in ListOfIDSources Nodes, - in ListOfIDSources Edges, - in ListOfIDSources Faces, + ListOfGroups ExtrusionAlongPathObjects(in ListOfIDSources Nodes, + in ListOfIDSources Edges, + in ListOfIDSources Faces, in SMESH_IDSource Path, in GEOM::GEOM_Object PathShape, in long NodeStart, in boolean HasAngles, in double_array Angles, - in boolean LinearVariation, + in boolean AnglesVariation, in boolean HasRefPoint, in PointStruct RefPoint, in boolean MakeGroups, + in double_array ScaleFactors, + in boolean ScaleVariation, out Extrusion_Error Error) raises (SALOME::SALOME_Exception); diff --git a/src/SMESH/SMESH_MeshEditor.cxx b/src/SMESH/SMESH_MeshEditor.cxx index 81db6b65f..69cb3e94b 100644 --- a/src/SMESH/SMESH_MeshEditor.cxx +++ b/src/SMESH/SMESH_MeshEditor.cxx @@ -606,25 +606,6 @@ static void shiftNodesQuadTria(vector< const SMDS_MeshNode* >& aNodes) aNodes[5] = nd2; } -//======================================================================= -//function : nbEdgeConnectivity -//purpose : return number of the edges connected with the theNode. -// if theEdges has connections with the other type of the -// elements, return -1 -//======================================================================= - -static int nbEdgeConnectivity(const SMDS_MeshNode* theNode) -{ - // SMDS_ElemIteratorPtr elemIt = theNode->GetInverseElementIterator(); - // int nb=0; - // while(elemIt->more()) { - // elemIt->next(); - // nb++; - // } - // return nb; - return theNode->NbInverseElements(); -} - //======================================================================= //function : getNodesFromTwoTria //purpose : @@ -5183,6 +5164,7 @@ SMESH_MeshEditor::RotationSweep(TIDSortedElemSet theElemSets[2], SMESH_MeshEditor::ExtrusParam::ExtrusParam( const gp_Vec& theStep, const int theNbSteps, const std::list& theScales, + const std::list& theAngles, const gp_XYZ* theBasePoint, const int theFlags, const double theTolerance): @@ -5197,32 +5179,52 @@ SMESH_MeshEditor::ExtrusParam::ExtrusParam( const gp_Vec& theStep, for (int i=1; i<=theNbSteps; i++ ) mySteps->Append( stepSize ); - int nbScales = theScales.size(); - if ( nbScales > 0 ) + if ( !theScales.empty() ) { - if ( IsLinearVariation() && nbScales < theNbSteps ) + if ( IsScaleVariation() && (int)theScales.size() < theNbSteps ) + linearScaleVariation( theNbSteps, const_cast< std::list& >( theScales )); + + // add medium scales + std::list::const_iterator s2 = theScales.begin(), s1 = s2++; + myScales.reserve( theNbSteps * 2 ); + myScales.push_back( 0.5 * ( *s1 + 1. )); + myScales.push_back( *s1 ); + for ( ; s2 != theScales.end(); s1 = s2++ ) { - myScales.reserve( theNbSteps ); - std::list::const_iterator scale = theScales.begin(); - double prevScale = 1.0; - for ( int iSc = 1; scale != theScales.end(); ++scale, ++iSc ) - { - int iStep = int( iSc / double( nbScales ) * theNbSteps + 0.5 ); - int stDelta = Max( 1, iStep - myScales.size()); - double scDelta = ( *scale - prevScale ) / stDelta; - for ( int iStep = 0; iStep < stDelta; ++iStep ) - { - myScales.push_back( prevScale + scDelta ); - prevScale = myScales.back(); - } - prevScale = *scale; - } + myScales.push_back( 0.5 * ( *s1 + *s2 )); + myScales.push_back( *s2 ); } - else + } + + if ( !theAngles.empty() ) + { + std::list& angles = const_cast< std::list& >( theAngles ); + if ( IsAngleVariation() && (int)theAngles.size() < theNbSteps ) + linearAngleVariation( theNbSteps, angles ); + + // accumulate angles + double angle = 0; + int nbAngles = 0; + std::list::iterator a1 = angles.begin(), a2; + for ( ; a1 != angles.end(); ++a1, ++nbAngles ) + { + angle += *a1; + *a1 = angle; + } + while ( nbAngles++ < theNbSteps ) + angles.push_back( angles.back() ); + + // add medium angles + a2 = angles.begin(), a1 = a2++; + myAngles.push_back( 0.5 * *a1 ); + myAngles.push_back( *a1 ); + for ( ; a2 != angles.end(); a1 = a2++ ) { - myScales.assign( theScales.begin(), theScales.end() ); + myAngles.push_back( 0.5 * ( *a1 + *a2 )); + myAngles.push_back( *a2 ); } } + if ( theBasePoint ) { myBaseP = *theBasePoint; @@ -5293,6 +5295,41 @@ SMESH_MeshEditor::ExtrusParam::ExtrusParam( const double theStepSize, } } +//======================================================================= +//function : ExtrusParam +//purpose : for extrusion along path +//======================================================================= + +SMESH_MeshEditor::ExtrusParam::ExtrusParam( const std::vector< PathPoint >& thePoints, + const gp_Pnt* theBasePoint, + const std::list& theScales, + const bool theMakeGroups ) + : myBaseP( Precision::Infinite(), 0, 0 ), + myFlags( EXTRUSION_FLAG_BOUNDARY | ( theMakeGroups ? EXTRUSION_FLAG_GROUPS : 0 )), + myPathPoints( thePoints ) +{ + if ( theBasePoint ) + { + myBaseP = theBasePoint->XYZ(); + } + + if ( !theScales.empty() ) + { + // add medium scales + std::list::const_iterator s2 = theScales.begin(), s1 = s2++; + myScales.reserve( thePoints.size() * 2 ); + myScales.push_back( 0.5 * ( 1. + *s1 )); + myScales.push_back( *s1 ); + for ( ; s2 != theScales.end(); s1 = s2++ ) + { + myScales.push_back( 0.5 * ( *s1 + *s2 )); + myScales.push_back( *s2 ); + } + } + + myMakeNodesFun = & SMESH_MeshEditor::ExtrusParam::makeNodesAlongTrack; +} + //======================================================================= //function : ExtrusParam::SetElementsToUse //purpose : stores elements to use for extrusion by normal, depending on @@ -5398,38 +5435,37 @@ makeNodesByDir( SMESHDS_Mesh* mesh, newNodes.push_back( newNode ); } - if ( !myScales.empty() ) + if ( !myScales.empty() || !myAngles.empty() ) { - if ( makeMediumNodes && myMediumScales.empty() ) - { - myMediumScales.resize( myScales.size() ); - double prevFactor = 1.; - for ( size_t i = 0; i < myScales.size(); ++i ) - { - myMediumScales[i] = 0.5 * ( prevFactor + myScales[i] ); - prevFactor = myScales[i]; - } - } - typedef std::vector::iterator ScaleIt; - ScaleIt scales[] = { myScales.begin(), myMediumScales.begin() }; - - size_t iSc = 0, nbScales = myScales.size() + myMediumScales.size(); + gp_XYZ center = myBaseP; + gp_Ax1 ratationAxis( center, myDir ); + gp_Trsf rotation; - gp_XYZ center = myBaseP; std::list::iterator nIt = newNodes.begin(); - size_t iN = 0; - for ( beginStepIter( makeMediumNodes ); moreSteps() && ( iN < nbScales ); ++nIt, ++iN ) + size_t i = !makeMediumNodes; + for ( beginStepIter( makeMediumNodes ); + moreSteps(); + ++nIt, i += 1 + !makeMediumNodes ) { center += myDir.XYZ() * nextStep(); - iSc += int( makeMediumNodes ); - ScaleIt& scale = scales[ iSc % 2 ]; - gp_XYZ xyz = SMESH_NodeXYZ( *nIt ); - xyz = ( *scale * ( xyz - center )) + center; - mesh->MoveNode( *nIt, xyz.X(), xyz.Y(), xyz.Z() ); - - ++scale; + bool moved = false; + if ( i < myScales.size() ) + { + xyz = ( myScales[i] * ( xyz - center )) + center; + moved = true; + } + if ( !myAngles.empty() ) + { + rotation.SetRotation( ratationAxis, myAngles[i] ); + rotation.Transforms( xyz ); + moved = true; + } + if ( moved ) + mesh->MoveNode( *nIt, xyz.X(), xyz.Y(), xyz.Z() ); + else + break; } } return nbNodes; @@ -5596,6 +5632,100 @@ makeNodesByNormal1D( SMESHDS_Mesh* mesh, return 0; } +//======================================================================= +//function : ExtrusParam::makeNodesAlongTrack +//purpose : create nodes for extrusion along path +//======================================================================= + +int SMESH_MeshEditor::ExtrusParam:: +makeNodesAlongTrack( SMESHDS_Mesh* mesh, + const SMDS_MeshNode* srcNode, + std::list & newNodes, + const bool makeMediumNodes) +{ + const Standard_Real aTolAng=1.e-4; + + gp_Pnt aV0x = myBaseP; + gp_Pnt aPN0 = SMESH_NodeXYZ( srcNode ); + + const PathPoint& aPP0 = myPathPoints[0]; + gp_Pnt aP0x = aPP0.myPnt; + gp_Dir aDT0x= aPP0.myTgt; + + std::vector< gp_Pnt > centers; + centers.reserve( NbSteps() * 2 ); + + gp_Trsf aTrsf, aTrsfRot, aTrsfRotT1T0; + + for ( size_t j = 1; j < myPathPoints.size(); ++j ) + { + const PathPoint& aPP = myPathPoints[j]; + const gp_Pnt& aP1x = aPP.myPnt; + const gp_Dir& aDT1x = aPP.myTgt; + + // Translation + gp_Vec aV01x( aP0x, aP1x ); + aTrsf.SetTranslation( aV01x ); + gp_Pnt aV1x = aV0x.Transformed( aTrsf ); + gp_Pnt aPN1 = aPN0.Transformed( aTrsf ); + + // rotation 1 [ T1,T0 ] + Standard_Real aAngleT1T0 = -aDT1x.Angle( aDT0x ); + if ( fabs( aAngleT1T0 ) > aTolAng ) + { + gp_Dir aDT1T0 = aDT1x ^ aDT0x; + aTrsfRotT1T0.SetRotation( gp_Ax1( aV1x, aDT1T0 ), aAngleT1T0 ); + + aPN1 = aPN1.Transformed( aTrsfRotT1T0 ); + } + + // rotation 2 + if ( aPP.myAngle != 0. ) + { + aTrsfRot.SetRotation( gp_Ax1( aV1x, aDT1x ), aPP.myAngle ); + aPN1 = aPN1.Transformed( aTrsfRot ); + } + + // make new node + if ( makeMediumNodes ) + { + // create additional node + gp_XYZ midP = 0.5 * ( aPN1.XYZ() + aPN0.XYZ() ); + const SMDS_MeshNode* newNode = mesh->AddNode( midP.X(), midP.Y(), midP.Z() ); + newNodes.push_back( newNode ); + + } + const SMDS_MeshNode* newNode = mesh->AddNode( aPN1.X(), aPN1.Y(), aPN1.Z() ); + newNodes.push_back( newNode ); + + centers.push_back( 0.5 * ( aV0x.XYZ() + aV1x.XYZ() )); + centers.push_back( aV1x ); + + aPN0 = aPN1; + aP0x = aP1x; + aV0x = aV1x; + aDT0x = aDT1x; + } + + // scale + if ( !myScales.empty() ) + { + gp_Trsf aTrsfScale; + std::list::iterator node = newNodes.begin(); + for ( size_t i = !makeMediumNodes; + i < myScales.size() && node != newNodes.end(); + i += ( 1 + !makeMediumNodes ), ++node ) + { + aTrsfScale.SetScale( centers[ i ], myScales[ i ] ); + gp_Pnt aN = SMESH_NodeXYZ( *node ); + gp_Pnt aP = aN.Transformed( aTrsfScale ); + mesh->MoveNode( *node, aP.X(), aP.Y(), aP.Z() ); + } + } + + return myPathPoints.size() + makeMediumNodes * ( myPathPoints.size() - 2 ); +} + //======================================================================= //function : ExtrusionSweep //purpose : @@ -5609,10 +5739,31 @@ SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet theElems[2], const int theFlags, const double theTolerance) { - ExtrusParam aParams( theStep, theNbSteps, std::list(), 0, theFlags, theTolerance ); + std::list dummy; + ExtrusParam aParams( theStep, theNbSteps, dummy, dummy, 0, + theFlags, theTolerance ); return ExtrusionSweep( theElems, aParams, newElemsMap ); } +namespace +{ + +//======================================================================= +//function : getOriFactor +//purpose : Return -1 or 1 depending on if order of given nodes corresponds to +// edge curve orientation +//======================================================================= + + double getOriFactor( const TopoDS_Edge& edge, + const SMDS_MeshNode* n1, + const SMDS_MeshNode* n2, + SMESH_MesherHelper& helper) + { + double u1 = helper.GetNodeU( edge, n1, n2 ); + double u2 = helper.GetNodeU( edge, n2, n1 ); + return u1 < u2 ? 1. : -1.; + } +} //======================================================================= //function : ExtrusionSweep @@ -5661,11 +5812,11 @@ SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet theElemSets[2], newNodesItVec.reserve( nbNodes ); // loop on elem nodes - SMDS_ElemIteratorPtr itN = elem->nodesIterator(); + SMDS_NodeIteratorPtr itN = elem->nodeIterator(); while ( itN->more() ) { // check if a node has been already sweeped - const SMDS_MeshNode* node = cast2Node( itN->next() ); + const SMDS_MeshNode* node = itN->next(); TNodeOfNodeListMap::iterator nIt = mapNewNodes.insert( make_pair( node, list() )).first; list& listNewNodes = nIt->second; @@ -5726,726 +5877,183 @@ SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet theElemSets[2], //======================================================================= SMESH_MeshEditor::Extrusion_Error SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet theElements[2], - SMESH_subMesh* theTrack, + SMESH_Mesh* theTrackMesh, + SMDS_ElemIteratorPtr theTrackIterator, const SMDS_MeshNode* theN1, - const bool theHasAngles, - list& theAngles, - const bool theLinearVariation, - const bool theHasRefPoint, - const gp_Pnt& theRefPoint, + std::list& theAngles, + const bool theAngleVariation, + std::list& theScales, + const bool theScaleVariation, + const gp_Pnt* theRefPoint, const bool theMakeGroups) { ClearLastCreated(); - int aNbE; - std::list aPrms; - TIDSortedElemSet::iterator itElem; - - gp_XYZ aGC; - TopoDS_Edge aTrackEdge; - TopoDS_Vertex aV1, aV2; - - SMDS_ElemIteratorPtr aItE; - SMDS_NodeIteratorPtr aItN; - SMDSAbs_ElementType aTypeE; - - TNodeOfNodeListMap mapNewNodes; - // 1. Check data - aNbE = theElements[0].size() + theElements[1].size(); - // nothing to do - if ( !aNbE ) + if ( theElements[0].empty() && theElements[1].empty() ) return EXTR_NO_ELEMENTS; - // 1.1 Track Pattern - ASSERT( theTrack ); - - SMESHDS_SubMesh* pSubMeshDS = theTrack->GetSubMeshDS(); - if ( !pSubMeshDS ) - return ExtrusionAlongTrack( theElements, theTrack->GetFather(), theN1, - theHasAngles, theAngles, theLinearVariation, - theHasRefPoint, theRefPoint, theMakeGroups ); - - aItE = pSubMeshDS->GetElements(); - while ( aItE->more() ) { - const SMDS_MeshElement* pE = aItE->next(); - aTypeE = pE->GetType(); - // Pattern must contain links only - if ( aTypeE != SMDSAbs_Edge ) - return EXTR_PATH_NOT_EDGE; - } - - list fullList; - - const TopoDS_Shape& aS = theTrack->GetSubShape(); - // Sub-shape for the Pattern must be an Edge or Wire - if( aS.ShapeType() == TopAbs_EDGE ) { - aTrackEdge = TopoDS::Edge( aS ); - // the Edge must not be degenerated - if ( SMESH_Algo::isDegenerated( aTrackEdge ) ) - return EXTR_BAD_PATH_SHAPE; - TopExp::Vertices( aTrackEdge, aV1, aV2 ); - aItN = theTrack->GetFather()->GetSubMesh( aV1 )->GetSubMeshDS()->GetNodes(); - const SMDS_MeshNode* aN1 = aItN->next(); - aItN = theTrack->GetFather()->GetSubMesh( aV2 )->GetSubMeshDS()->GetNodes(); - const SMDS_MeshNode* aN2 = aItN->next(); - // starting node must be aN1 or aN2 - if ( !( aN1 == theN1 || aN2 == theN1 ) ) - return EXTR_BAD_STARTING_NODE; - aItN = pSubMeshDS->GetNodes(); - while ( aItN->more() ) { - const SMDS_MeshNode* pNode = aItN->next(); - SMDS_EdgePositionPtr pEPos = pNode->GetPosition(); - double aT = pEPos->GetUParameter(); - aPrms.push_back( aT ); - } - //Extrusion_Error err = - makeEdgePathPoints(aPrms, aTrackEdge, (aN1==theN1), fullList); - } else if( aS.ShapeType() == TopAbs_WIRE ) { - list< SMESH_subMesh* > LSM; - TopTools_SequenceOfShape Edges; - SMESH_subMeshIteratorPtr itSM = theTrack->getDependsOnIterator(false,true); - while(itSM->more()) { - SMESH_subMesh* SM = itSM->next(); - LSM.push_back(SM); - const TopoDS_Shape& aS = SM->GetSubShape(); - Edges.Append(aS); - } - list< list > LLPPs; - int startNid = theN1->GetID(); - TColStd_MapOfInteger UsedNums; - - int NbEdges = Edges.Length(); - int i = 1; - for(; i<=NbEdges; i++) { - int k = 0; - list< SMESH_subMesh* >::iterator itLSM = LSM.begin(); - for(; itLSM!=LSM.end(); itLSM++) { - k++; - if(UsedNums.Contains(k)) continue; - aTrackEdge = TopoDS::Edge( Edges.Value(k) ); - SMESH_subMesh* locTrack = *itLSM; - SMESHDS_SubMesh* locMeshDS = locTrack->GetSubMeshDS(); - TopExp::Vertices( aTrackEdge, aV1, aV2 ); - aItN = locTrack->GetFather()->GetSubMesh(aV1)->GetSubMeshDS()->GetNodes(); - const SMDS_MeshNode* aN1 = aItN->next(); - aItN = locTrack->GetFather()->GetSubMesh(aV2)->GetSubMeshDS()->GetNodes(); - const SMDS_MeshNode* aN2 = aItN->next(); - // starting node must be aN1 or aN2 - if ( !( aN1->GetID() == startNid || aN2->GetID() == startNid ) ) continue; - // 2. Collect parameters on the track edge - aPrms.clear(); - aItN = locMeshDS->GetNodes(); - while ( aItN->more() ) { - const SMDS_MeshNode* pNode = aItN->next(); - SMDS_EdgePositionPtr pEPos = pNode->GetPosition(); - double aT = pEPos->GetUParameter(); - aPrms.push_back( aT ); - } - list LPP; - //Extrusion_Error err = - makeEdgePathPoints(aPrms, aTrackEdge,(aN1->GetID()==startNid), LPP); - LLPPs.push_back(LPP); - UsedNums.Add(k); - // update startN for search following edge - if( aN1->GetID() == startNid ) startNid = aN2->GetID(); - else startNid = aN1->GetID(); - break; - } - } - list< list >::iterator itLLPP = LLPPs.begin(); - list firstList = *itLLPP; - list::iterator itPP = firstList.begin(); - for(; itPP!=firstList.end(); itPP++) { - fullList.push_back( *itPP ); - } - SMESH_MeshEditor_PathPoint PP1 = fullList.back(); - fullList.pop_back(); - itLLPP++; - for(; itLLPP!=LLPPs.end(); itLLPP++) { - list currList = *itLLPP; - itPP = currList.begin(); - SMESH_MeshEditor_PathPoint PP2 = currList.front(); - gp_Dir D1 = PP1.Tangent(); - gp_Dir D2 = PP2.Tangent(); - gp_Dir Dnew( gp_Vec( (D1.X()+D2.X())/2, (D1.Y()+D2.Y())/2, - (D1.Z()+D2.Z())/2 ) ); - PP1.SetTangent(Dnew); - fullList.push_back(PP1); - itPP++; - for(; itPP!=firstList.end(); itPP++) { - fullList.push_back( *itPP ); - } - PP1 = fullList.back(); - fullList.pop_back(); - } - // if wire not closed - fullList.push_back(PP1); - // else ??? - } - else { - return EXTR_BAD_PATH_SHAPE; - } - - return makeExtrElements(theElements, fullList, theHasAngles, theAngles, theLinearVariation, - theHasRefPoint, theRefPoint, theMakeGroups); -} - - -//======================================================================= -//function : ExtrusionAlongTrack -//purpose : -//======================================================================= -SMESH_MeshEditor::Extrusion_Error -SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet theElements[2], - SMESH_Mesh* theTrack, - const SMDS_MeshNode* theN1, - const bool theHasAngles, - list& theAngles, - const bool theLinearVariation, - const bool theHasRefPoint, - const gp_Pnt& theRefPoint, - const bool theMakeGroups) -{ - ClearLastCreated(); - - int aNbE; - std::list aPrms; - TIDSortedElemSet::iterator itElem; - - gp_XYZ aGC; - TopoDS_Edge aTrackEdge; - TopoDS_Vertex aV1, aV2; - - SMDS_ElemIteratorPtr aItE; - SMDS_NodeIteratorPtr aItN; - SMDSAbs_ElementType aTypeE; + ASSERT( theTrackMesh ); + if ( ! theTrackIterator || !theTrackIterator->more() ) + return EXTR_NO_ELEMENTS; - TNodeOfNodeListMap mapNewNodes; + // 2. Get ordered nodes + SMESH_MeshAlgos::TElemGroupVector branchEdges; + SMESH_MeshAlgos::TNodeGroupVector branchNods; + SMESH_MeshAlgos::Get1DBranches( theTrackIterator, branchEdges, branchNods, theN1 ); + if ( branchEdges.empty() ) + return EXTR_PATH_NOT_EDGE; - // 1. Check data - aNbE = theElements[0].size() + theElements[1].size(); - // nothing to do - if ( !aNbE ) - return EXTR_NO_ELEMENTS; + if ( branchEdges.size() > 1 ) + return EXTR_BAD_PATH_SHAPE; - // 1.1 Track Pattern - ASSERT( theTrack ); - - SMESHDS_Mesh* pMeshDS = theTrack->GetMeshDS(); - - aItE = pMeshDS->elementsIterator(); - while ( aItE->more() ) { - const SMDS_MeshElement* pE = aItE->next(); - aTypeE = pE->GetType(); - // Pattern must contain links only - if ( aTypeE != SMDSAbs_Edge ) - return EXTR_PATH_NOT_EDGE; - } - - list fullList; - - const TopoDS_Shape& aS = theTrack->GetShapeToMesh(); - - if ( !theTrack->HasShapeToMesh() ) { - //Mesh without shape - const SMDS_MeshNode* currentNode = NULL; - const SMDS_MeshNode* prevNode = theN1; - std::vector aNodesList; - aNodesList.push_back(theN1); - int nbEdges = 0, conn=0; - const SMDS_MeshElement* prevElem = NULL; - const SMDS_MeshElement* currentElem = NULL; - int totalNbEdges = theTrack->NbEdges(); - SMDS_ElemIteratorPtr nIt; - - //check start node - if( !theTrack->GetMeshDS()->Contains( theN1 )) { - return EXTR_BAD_STARTING_NODE; - } - - conn = nbEdgeConnectivity(theN1); - if( conn != 1 ) - return EXTR_PATH_NOT_EDGE; - - aItE = theN1->GetInverseElementIterator(); - prevElem = aItE->next(); - currentElem = prevElem; - //Get all nodes - if(totalNbEdges == 1 ) { - nIt = currentElem->nodesIterator(); - currentNode = static_cast(nIt->next()); - if(currentNode == prevNode) - currentNode = static_cast(nIt->next()); - aNodesList.push_back(currentNode); - } else { - nIt = currentElem->nodesIterator(); - while( nIt->more() ) { - currentNode = static_cast(nIt->next()); - if(currentNode == prevNode) - currentNode = static_cast(nIt->next()); - aNodesList.push_back(currentNode); - - //case of the closed mesh - if(currentNode == theN1) { - nbEdges++; - break; - } + std::vector< const SMDS_MeshNode* >& pathNodes = branchNods[0]; + std::vector< const SMDS_MeshElement* >& pathEdges = branchEdges[0]; + if ( pathNodes[0] != theN1 && pathNodes[1] != theN1 ) + return EXTR_BAD_STARTING_NODE; - conn = nbEdgeConnectivity(currentNode); - if(conn > 2) { - return EXTR_PATH_NOT_EDGE; - }else if( conn == 1 && nbEdges > 0 ) { - //End of the path - nbEdges++; - break; - }else { - prevNode = currentNode; - aItE = currentNode->GetInverseElementIterator(); - currentElem = aItE->next(); - if( currentElem == prevElem) - currentElem = aItE->next(); - nIt = currentElem->nodesIterator(); - prevElem = currentElem; - nbEdges++; - } - } - } - - if(nbEdges != totalNbEdges) - return EXTR_PATH_NOT_EDGE; - - TopTools_SequenceOfShape Edges; - list< list > LLPPs; - int startNid = theN1->GetID(); - for ( size_t i = 1; i < aNodesList.size(); i++ ) - { - gp_Pnt p1 = SMESH_NodeXYZ( aNodesList[i-1] ); - gp_Pnt p2 = SMESH_NodeXYZ( aNodesList[i] ); - TopoDS_Edge e = BRepBuilderAPI_MakeEdge( p1, p2 ); - list LPP; - aPrms.clear(); - makeEdgePathPoints(aPrms, e, (aNodesList[i-1]->GetID()==startNid), LPP); - LLPPs.push_back(LPP); - if ( aNodesList[i-1]->GetID() == startNid ) startNid = aNodesList[i ]->GetID(); - else startNid = aNodesList[i-1]->GetID(); - } - - list< list >::iterator itLLPP = LLPPs.begin(); - list firstList = *itLLPP; - list::iterator itPP = firstList.begin(); - for(; itPP!=firstList.end(); itPP++) { - fullList.push_back( *itPP ); - } - - SMESH_MeshEditor_PathPoint PP1 = fullList.back(); - SMESH_MeshEditor_PathPoint PP2; - fullList.pop_back(); - itLLPP++; - for(; itLLPP!=LLPPs.end(); itLLPP++) { - list currList = *itLLPP; - itPP = currList.begin(); - PP2 = currList.front(); - gp_Dir D1 = PP1.Tangent(); - gp_Dir D2 = PP2.Tangent(); - gp_Dir Dnew( 0.5 * ( D1.XYZ() + D2.XYZ() )); - PP1.SetTangent(Dnew); - fullList.push_back(PP1); - itPP++; - for(; itPP!=currList.end(); itPP++) { - fullList.push_back( *itPP ); - } - PP1 = fullList.back(); - fullList.pop_back(); - } - fullList.push_back(PP1); - - } // Sub-shape for the Pattern must be an Edge or Wire - else if ( aS.ShapeType() == TopAbs_EDGE ) - { - aTrackEdge = TopoDS::Edge( aS ); - // the Edge must not be degenerated - if ( SMESH_Algo::isDegenerated( aTrackEdge ) ) - return EXTR_BAD_PATH_SHAPE; - TopExp::Vertices( aTrackEdge, aV1, aV2 ); - const SMDS_MeshNode* aN1 = SMESH_Algo::VertexNode( aV1, pMeshDS ); - const SMDS_MeshNode* aN2 = SMESH_Algo::VertexNode( aV2, pMeshDS ); - // starting node must be aN1 or aN2 - if ( !( aN1 == theN1 || aN2 == theN1 ) ) - return EXTR_BAD_STARTING_NODE; - aItN = pMeshDS->nodesIterator(); - while ( aItN->more() ) { - const SMDS_MeshNode* pNode = aItN->next(); - if( pNode==aN1 || pNode==aN2 ) continue; - SMDS_EdgePositionPtr pEPos = pNode->GetPosition(); - double aT = pEPos->GetUParameter(); - aPrms.push_back( aT ); - } - //Extrusion_Error err = - makeEdgePathPoints(aPrms, aTrackEdge, (aN1==theN1), fullList); - } - else if( aS.ShapeType() == TopAbs_WIRE ) { - list< SMESH_subMesh* > LSM; - TopTools_SequenceOfShape Edges; - TopExp_Explorer eExp(aS, TopAbs_EDGE); - for(; eExp.More(); eExp.Next()) { - TopoDS_Edge E = TopoDS::Edge( eExp.Current() ); - if( SMESH_Algo::isDegenerated(E) ) continue; - SMESH_subMesh* SM = theTrack->GetSubMesh(E); - if(SM) { - LSM.push_back(SM); - Edges.Append(E); - } - } - list< list > LLPPs; - TopoDS_Vertex aVprev; - TColStd_MapOfInteger UsedNums; - int NbEdges = Edges.Length(); - int i = 1; - for(; i<=NbEdges; i++) { - int k = 0; - list< SMESH_subMesh* >::iterator itLSM = LSM.begin(); - for(; itLSM!=LSM.end(); itLSM++) { - k++; - if(UsedNums.Contains(k)) continue; - aTrackEdge = TopoDS::Edge( Edges.Value(k) ); - SMESH_subMesh* locTrack = *itLSM; - SMESHDS_SubMesh* locMeshDS = locTrack->GetSubMeshDS(); - TopExp::Vertices( aTrackEdge, aV1, aV2 ); - bool aN1isOK = false, aN2isOK = false; - if ( aVprev.IsNull() ) { - // if previous vertex is not yet defined, it means that we in the beginning of wire - // and we have to find initial vertex corresponding to starting node theN1 - const SMDS_MeshNode* aN1 = SMESH_Algo::VertexNode( aV1, pMeshDS ); - const SMDS_MeshNode* aN2 = SMESH_Algo::VertexNode( aV2, pMeshDS ); - // starting node must be aN1 or aN2 - aN1isOK = ( aN1 && aN1 == theN1 ); - aN2isOK = ( aN2 && aN2 == theN1 ); - } - else { - // we have specified ending vertex of the previous edge on the previous iteration - // and we have just to check that it corresponds to any vertex in current segment - aN1isOK = aVprev.IsSame( aV1 ); - aN2isOK = aVprev.IsSame( aV2 ); - } - if ( !aN1isOK && !aN2isOK ) continue; - // 2. Collect parameters on the track edge - aPrms.clear(); - aItN = locMeshDS->GetNodes(); - while ( aItN->more() ) { - const SMDS_MeshNode* pNode = aItN->next(); - SMDS_EdgePositionPtr pEPos = pNode->GetPosition(); - double aT = pEPos->GetUParameter(); - aPrms.push_back( aT ); - } - list LPP; - //Extrusion_Error err = - makeEdgePathPoints(aPrms, aTrackEdge, aN1isOK, LPP); - LLPPs.push_back(LPP); - UsedNums.Add(k); - // update startN for search following edge - if ( aN1isOK ) aVprev = aV2; - else aVprev = aV1; - break; + if ( theTrackMesh->NbEdges( ORDER_QUADRATIC ) > 0 ) + { + // add medium nodes to pathNodes + std::vector< const SMDS_MeshNode* > pathNodes2; + std::vector< const SMDS_MeshElement* > pathEdges2; + pathNodes2.reserve( pathNodes.size() * 2 ); + pathEdges2.reserve( pathEdges.size() * 2 ); + for ( size_t i = 0; i < pathEdges.size(); ++i ) + { + pathNodes2.push_back( pathNodes[i] ); + pathEdges2.push_back( pathEdges[i] ); + if ( pathEdges[i]->IsQuadratic() ) + { + pathNodes2.push_back( pathEdges[i]->GetNode(2) ); + pathEdges2.push_back( pathEdges[i] ); } } - list< list >::iterator itLLPP = LLPPs.begin(); - list& firstList = *itLLPP; - fullList.splice( fullList.end(), firstList ); - - SMESH_MeshEditor_PathPoint PP1 = fullList.back(); - fullList.pop_back(); - itLLPP++; - for(; itLLPP!=LLPPs.end(); itLLPP++) { - list& currList = *itLLPP; - SMESH_MeshEditor_PathPoint PP2 = currList.front(); - gp_Dir D1 = PP1.Tangent(); - gp_Dir D2 = PP2.Tangent(); - gp_Dir Dnew( D1.XYZ() + D2.XYZ() ); - PP1.SetTangent(Dnew); - fullList.push_back(PP1); - fullList.splice( fullList.end(), currList, ++currList.begin(), currList.end() ); - PP1 = fullList.back(); - fullList.pop_back(); - } - // if wire not closed - fullList.push_back(PP1); - // else ??? - } - else { - return EXTR_BAD_PATH_SHAPE; + pathNodes2.push_back( pathNodes.back() ); + pathEdges.swap( pathEdges2 ); + pathNodes.swap( pathNodes2 ); } - return makeExtrElements(theElements, fullList, theHasAngles, theAngles, theLinearVariation, - theHasRefPoint, theRefPoint, theMakeGroups); -} + // 3. Get path data at pathNodes + std::vector< ExtrusParam::PathPoint > points( pathNodes.size() ); -//======================================================================= -//function : makeEdgePathPoints -//purpose : auxiliary for ExtrusionAlongTrack -//======================================================================= -SMESH_MeshEditor::Extrusion_Error -SMESH_MeshEditor::makeEdgePathPoints(std::list& aPrms, - const TopoDS_Edge& aTrackEdge, - bool FirstIsStart, - list& LPP) -{ - Standard_Real aTx1, aTx2, aL2, aTolVec, aTolVec2; - aTolVec=1.e-7; - aTolVec2=aTolVec*aTolVec; - double aT1, aT2; - TopoDS_Vertex aV1, aV2; - TopExp::Vertices( aTrackEdge, aV1, aV2 ); - aT1=BRep_Tool::Parameter( aV1, aTrackEdge ); - aT2=BRep_Tool::Parameter( aV2, aTrackEdge ); - // 2. Collect parameters on the track edge - aPrms.push_front( aT1 ); - aPrms.push_back( aT2 ); - // sort parameters - aPrms.sort(); - if( FirstIsStart ) { - if ( aT1 > aT2 ) { - aPrms.reverse(); - } - } - else { - if ( aT2 > aT1 ) { - aPrms.reverse(); - } - } - // 3. Path Points - SMESH_MeshEditor_PathPoint aPP; - Handle(Geom_Curve) aC3D = BRep_Tool::Curve( aTrackEdge, aTx1, aTx2 ); - std::list::iterator aItD = aPrms.begin(); - for(; aItD != aPrms.end(); ++aItD) { - double aT = *aItD; - gp_Pnt aP3D; - gp_Vec aVec; - aC3D->D1( aT, aP3D, aVec ); - aL2 = aVec.SquareMagnitude(); - if ( aL2 < aTolVec2 ) - return EXTR_CANT_GET_TANGENT; - gp_Dir aTgt( FirstIsStart ? aVec : -aVec ); - aPP.SetPnt( aP3D ); - aPP.SetTangent( aTgt ); - aPP.SetParameter( aT ); - LPP.push_back(aPP); - } - return EXTR_OK; -} + if ( theAngleVariation ) + linearAngleVariation( points.size()-1, theAngles ); + if ( theScaleVariation ) + linearScaleVariation( points.size()-1, theScales ); + theAngles.push_front( 0 ); // for the 1st point that is not transformed + std::list::iterator angle = theAngles.begin(); -//======================================================================= -//function : makeExtrElements -//purpose : auxiliary for ExtrusionAlongTrack -//======================================================================= -SMESH_MeshEditor::Extrusion_Error -SMESH_MeshEditor::makeExtrElements(TIDSortedElemSet theElemSets[2], - list& fullList, - const bool theHasAngles, - list& theAngles, - const bool theLinearVariation, - const bool theHasRefPoint, - const gp_Pnt& theRefPoint, - const bool theMakeGroups) -{ - const int aNbTP = fullList.size(); + SMESHDS_Mesh* pathMeshDS = theTrackMesh->GetMeshDS(); - // Angles - if( theHasAngles && !theAngles.empty() && theLinearVariation ) - linearAngleVariation(aNbTP-1, theAngles); + std::map< int, double > edgeID2OriFactor; // orientation of EDGEs + std::map< int, double >::iterator id2factor; + SMESH_MesherHelper pathHelper( *theTrackMesh ); + gp_Pnt p; gp_Vec tangent; + const double tol2 = gp::Resolution() * gp::Resolution(); - // fill vector of path points with angles - vector aPPs; - list::iterator itPP = fullList.begin(); - list::iterator itAngles = theAngles.begin(); - aPPs.push_back( *itPP++ ); - for( ; itPP != fullList.end(); itPP++) { - aPPs.push_back( *itPP ); - if ( theHasAngles && itAngles != theAngles.end() ) - aPPs.back().SetAngle( *itAngles++ ); - } + for ( size_t i = 0; i < pathNodes.size(); ++i ) + { + ExtrusParam::PathPoint & point = points[ i ]; - TNodeOfNodeListMap mapNewNodes; - TElemOfVecOfNnlmiMap mapElemNewNodes; - TTElemOfElemListMap newElemsMap; - TIDSortedElemSet::iterator itElem; - // source elements for each generated one - SMESH_SequenceOfElemPtr srcElems, srcNodes; + point.myPnt = SMESH_NodeXYZ( pathNodes[ i ]); - // 3. Center of rotation aV0 - gp_Pnt aV0 = theRefPoint; - if ( !theHasRefPoint ) - { - gp_XYZ aGC( 0.,0.,0. ); - TIDSortedElemSet newNodes; + if ( angle != theAngles.end() ) + point.myAngle = *angle++; - for ( int is2ndSet = 0; is2ndSet < 2; ++is2ndSet ) + tangent.SetCoord( 0,0,0 ); + const int shapeID = pathNodes[ i ]->GetShapeID(); + const TopoDS_Shape& shape = pathMeshDS->IndexToShape( shapeID ); + TopAbs_ShapeEnum shapeType = shape.IsNull() ? TopAbs_SHAPE : shape.ShapeType(); + switch ( shapeType ) + { + case TopAbs_EDGE: { - TIDSortedElemSet& theElements = theElemSets[ is2ndSet ]; - itElem = theElements.begin(); - for ( ; itElem != theElements.end(); itElem++ ) + TopoDS_Edge edge = TopoDS::Edge( shape ); + id2factor = edgeID2OriFactor.insert( std::make_pair( shapeID, 0 )).first; + if ( id2factor->second == 0 ) { - const SMDS_MeshElement* elem = *itElem; - SMDS_ElemIteratorPtr itN = elem->nodesIterator(); - while ( itN->more() ) { - const SMDS_MeshElement* node = itN->next(); - if ( newNodes.insert( node ).second ) - aGC += SMESH_NodeXYZ( node ); - } + if ( i ) id2factor->second = getOriFactor( edge, pathNodes[i-1], pathNodes[i], pathHelper ); + else id2factor->second = getOriFactor( edge, pathNodes[i], pathNodes[i+1], pathHelper ); } + double u = pathHelper.GetNodeU( edge, pathNodes[i] ), u0, u1; + Handle(Geom_Curve) curve = BRep_Tool::Curve( edge, u0, u1 ); + curve->D1( u, p, tangent ); + tangent *= id2factor->second; + break; } - aGC /= newNodes.size(); - aV0.SetXYZ( aGC ); - } // if (!theHasRefPoint) { - - // 4. Processing the elements - SMESHDS_Mesh* aMesh = GetMeshDS(); - list emptyList; - - setElemsFirst( theElemSets ); - for ( int is2ndSet = 0; is2ndSet < 2; ++is2ndSet ) - { - TIDSortedElemSet& theElements = theElemSets[ is2ndSet ]; - for ( itElem = theElements.begin(); itElem != theElements.end(); itElem++ ) + case TopAbs_VERTEX: { - const SMDS_MeshElement* elem = *itElem; - - vector & newNodesItVec = mapElemNewNodes[ elem ]; - newNodesItVec.reserve( elem->NbNodes() ); - - // loop on elem nodes - int nodeIndex = -1; - SMDS_ElemIteratorPtr itN = elem->nodesIterator(); - while ( itN->more() ) + int nbEdges = 0; + PShapeIteratorPtr shapeIt = pathHelper.GetAncestors( shape, *theTrackMesh, TopAbs_EDGE ); + while ( const TopoDS_Shape* edgePtr = shapeIt->next() ) { - ++nodeIndex; - // check if a node has been already processed - const SMDS_MeshNode* node = cast2Node( itN->next() ); - TNodeOfNodeListMap::iterator nIt = mapNewNodes.insert( make_pair( node, emptyList )).first; - list& listNewNodes = nIt->second; - if ( listNewNodes.empty() ) + int edgeID = pathMeshDS->ShapeToIndex( *edgePtr ); + for ( int di = -1; di <= 0; ++di ) { - // make new nodes - Standard_Real aAngle1x, aAngleT1T0, aTolAng; - gp_Pnt aP0x, aP1x, aPN0, aPN1, aV0x, aV1x; - gp_Ax1 anAx1, anAxT1T0; - gp_Dir aDT1x, aDT0x, aDT1T0; - - aTolAng=1.e-4; - - aV0x = aV0; - aPN0 = SMESH_NodeXYZ( node ); - - const SMESH_MeshEditor_PathPoint& aPP0 = aPPs[0]; - aP0x = aPP0.Pnt(); - aDT0x= aPP0.Tangent(); - - for ( int j = 1; j < aNbTP; ++j ) { - const SMESH_MeshEditor_PathPoint& aPP1 = aPPs[j]; - aP1x = aPP1.Pnt(); - aDT1x = aPP1.Tangent(); - aAngle1x = aPP1.Angle(); - - gp_Trsf aTrsf, aTrsfRot, aTrsfRotT1T0; - // Translation - gp_Vec aV01x( aP0x, aP1x ); - aTrsf.SetTranslation( aV01x ); - - // translated point - aV1x = aV0x.Transformed( aTrsf ); - aPN1 = aPN0.Transformed( aTrsf ); - - // rotation 1 [ T1,T0 ] - aAngleT1T0=-aDT1x.Angle( aDT0x ); - if (fabs(aAngleT1T0) > aTolAng) + size_t j = i + di; + if ( j < pathEdges.size() && edgeID == pathEdges[ j ]->GetShapeID() ) + { + TopoDS_Edge edge = TopoDS::Edge( *edgePtr ); + id2factor = edgeID2OriFactor.insert( std::make_pair( edgeID, 0 )).first; + if ( id2factor->second == 0 ) { - aDT1T0=aDT1x^aDT0x; - anAxT1T0.SetLocation( aV1x ); - anAxT1T0.SetDirection( aDT1T0 ); - aTrsfRotT1T0.SetRotation( anAxT1T0, aAngleT1T0 ); - - aPN1 = aPN1.Transformed( aTrsfRotT1T0 ); - } - - // rotation 2 - if ( theHasAngles ) { - anAx1.SetLocation( aV1x ); - anAx1.SetDirection( aDT1x ); - aTrsfRot.SetRotation( anAx1, aAngle1x ); - - aPN1 = aPN1.Transformed( aTrsfRot ); + if ( j < i ) + id2factor->second = getOriFactor( edge, pathNodes[i-1], pathNodes[i], pathHelper ); + else + id2factor->second = getOriFactor( edge, pathNodes[i], pathNodes[i+1], pathHelper ); } - - // make new node - if ( elem->IsQuadratic() && !elem->IsMediumNode(node) ) + double u = pathHelper.GetNodeU( edge, pathNodes[i] ), u0, u1; + Handle(Geom_Curve) curve = BRep_Tool::Curve( edge, u0, u1 ); + gp_Vec du; + curve->D1( u, p, du ); + double size2 = du.SquareMagnitude(); + if ( du.SquareMagnitude() > tol2 ) { - // create additional node - gp_XYZ midP = 0.5 * ( aPN1.XYZ() + aPN0.XYZ() ); - const SMDS_MeshNode* newNode = aMesh->AddNode( midP.X(), midP.Y(), midP.Z() ); - myLastCreatedNodes.push_back(newNode); - srcNodes.push_back( node ); - listNewNodes.push_back( newNode ); + tangent += du.Divided( Sqrt( size2 )) * id2factor->second; + nbEdges++; } - const SMDS_MeshNode* newNode = aMesh->AddNode( aPN1.X(), aPN1.Y(), aPN1.Z() ); - myLastCreatedNodes.push_back(newNode); - srcNodes.push_back( node ); - listNewNodes.push_back( newNode ); - - aPN0 = aPN1; - aP0x = aP1x; - aV0x = aV1x; - aDT0x = aDT1x; + break; } } - else if( elem->IsQuadratic() && !elem->IsMediumNode(node) ) + } + if ( nbEdges > 0 ) + break; + } + default: + { + for ( int di = -1; di <= 1; di += 2 ) + { + size_t j = i + di; + if ( j < pathNodes.size() ) { - // if current elem is quadratic and current node is not medium - // we have to check - may be it is needed to insert additional nodes - list< const SMDS_MeshNode* > & listNewNodes = nIt->second; - if ((int) listNewNodes.size() == aNbTP-1 ) - { - vector aNodes(2*(aNbTP-1)); - gp_XYZ P(node->X(), node->Y(), node->Z()); - list< const SMDS_MeshNode* >::iterator it = listNewNodes.begin(); - int i; - for(i=0; iX() + P.X() )/2.; - double y = ( N->Y() + P.Y() )/2.; - double z = ( N->Z() + P.Z() )/2.; - const SMDS_MeshNode* newN = aMesh->AddNode(x,y,z); - srcNodes.push_back( node ); - myLastCreatedNodes.push_back(newN); - aNodes[2*i] = newN; - aNodes[2*i+1] = N; - P = gp_XYZ(N->X(),N->Y(),N->Z()); - } - listNewNodes.clear(); - for(i=0; i<2*(aNbTP-1); i++) { - listNewNodes.push_back(aNodes[i]); - } - } + gp_Vec dir( point.myPnt, SMESH_NodeXYZ( pathNodes[ j ])); + double size2 = dir.SquareMagnitude(); + if ( size2 > tol2 ) + tangent += dir.Divided( Sqrt( size2 )) * di; } - - newNodesItVec.push_back( nIt ); } - - // make new elements - sweepElement( elem, newNodesItVec, newElemsMap[elem], aNbTP-1, srcElems ); } - } + } // switch ( shapeType ) - makeWalls( mapNewNodes, newElemsMap, mapElemNewNodes, theElemSets[0], aNbTP-1, srcElems ); + if ( tangent.SquareMagnitude() < tol2 ) + return EXTR_CANT_GET_TANGENT; - if ( theMakeGroups ) - generateGroups( srcNodes, srcElems, "extruded"); + point.myTgt = tangent; + + } // loop on pathNodes + + + ExtrusParam nodeMaker( points, theRefPoint, theScales, theMakeGroups ); + TTElemOfElemListMap newElemsMap; + + ExtrusionSweep( theElements, nodeMaker, newElemsMap ); return EXTR_OK; } - //======================================================================= //function : linearAngleVariation //purpose : spread values over nbSteps @@ -6490,6 +6098,33 @@ void SMESH_MeshEditor::linearAngleVariation(const int nbSteps, } } +//======================================================================= +//function : linearScaleVariation +//purpose : spread values over nbSteps +//======================================================================= + +void SMESH_MeshEditor::linearScaleVariation(const int theNbSteps, + std::list& theScales) +{ + int nbScales = theScales.size(); + std::vector myScales; + myScales.reserve( theNbSteps ); + std::list::const_iterator scale = theScales.begin(); + double prevScale = 1.0; + for ( int iSc = 1; scale != theScales.end(); ++scale, ++iSc ) + { + int iStep = int( iSc / double( nbScales ) * theNbSteps + 0.5 ); + int stDelta = Max( 1, iStep - myScales.size()); + double scDelta = ( *scale - prevScale ) / stDelta; + for ( int iStep = 0; iStep < stDelta; ++iStep ) + { + myScales.push_back( prevScale + scDelta ); + prevScale = myScales.back(); + } + prevScale = *scale; + } + theScales.assign( myScales.begin(), myScales.end() ); +} //================================================================================ /*! diff --git a/src/SMESH/SMESH_MeshEditor.hxx b/src/SMESH/SMESH_MeshEditor.hxx index 221a78d46..de89a3c4e 100644 --- a/src/SMESH/SMESH_MeshEditor.hxx +++ b/src/SMESH/SMESH_MeshEditor.hxx @@ -297,6 +297,7 @@ public: * USE_INPUT_ELEMS_ONLY: to use only input elements to compute extrusion direction * for ExtrusionByNormal() * SCALE_LINEAR_VARIATION: to make linear variation of scale factors + * ANGLE_LINEAR_VARIATION: to make linear variation of angles */ enum ExtrusionFlags { EXTRUSION_FLAG_BOUNDARY = 0x01, @@ -304,7 +305,8 @@ public: EXTRUSION_FLAG_GROUPS = 0x04, EXTRUSION_FLAG_BY_AVG_NORMAL = 0x08, EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY = 0x10, - EXTRUSION_FLAG_SCALE_LINEAR_VARIATION = 0x20 + EXTRUSION_FLAG_SCALE_LINEAR_VARIATION = 0x20, + EXTRUSION_FLAG_ANGLE_LINEAR_VARIATION = 0x40 }; /*! @@ -312,24 +314,20 @@ public: */ class SMESH_EXPORT ExtrusParam { - gp_Dir myDir; // direction of extrusion - Handle(TColStd_HSequenceOfReal) mySteps; // magnitudes for each step - std::vector myScales, myMediumScales;// scale factors - gp_XYZ myBaseP; // scaling center - SMESH_SequenceOfNode myNodes; // nodes for using in sewing - int myFlags; // see ExtrusionFlags - double myTolerance; // tolerance for sewing nodes - const TIDSortedElemSet* myElemsToUse; // elements to use for extrusion by normal - - int (ExtrusParam::*myMakeNodesFun)(SMESHDS_Mesh* mesh, - const SMDS_MeshNode* srcNode, - std::list & newNodes, - const bool makeMediumNodes); - public: + //! Point on extrusion path + struct PathPoint + { + gp_Pnt myPnt; + gp_Dir myTgt; + double myAngle, myScale; + PathPoint(): myPnt(99., 99., 99.), myTgt(1.,0.,0.), myAngle(0), myScale(0) {} + }; + ExtrusParam( const gp_Vec& theStep, const int theNbSteps, const std::list& theScales, + const std::list& theAngles, const gp_XYZ* theBaseP, const int theFlags = 0, const double theTolerance = 1e-6); @@ -341,15 +339,21 @@ public: const int theNbSteps, const int theFlags, const int theDim); // for extrusion by normal + ExtrusParam( const std::vector< PathPoint >& thePoints, + const gp_Pnt* theBaseP, + const std::list& theScales, + const bool theMakeGroups); // for extrusion along path SMESH_SequenceOfNode& ChangeNodes() { return myNodes; } int& Flags() { return myFlags; } bool ToMakeBoundary() const { return myFlags & EXTRUSION_FLAG_BOUNDARY; } bool ToMakeGroups() const { return myFlags & EXTRUSION_FLAG_GROUPS; } bool ToUseInpElemsOnly() const { return myFlags & EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY; } - bool IsLinearVariation() const { return myFlags & EXTRUSION_FLAG_SCALE_LINEAR_VARIATION; } - int NbSteps() const { return mySteps->Length(); } - + bool IsScaleVariation() const { return myFlags & EXTRUSION_FLAG_SCALE_LINEAR_VARIATION; } + bool IsAngleVariation() const { return myFlags & EXTRUSION_FLAG_ANGLE_LINEAR_VARIATION; } + int NbSteps() const { + return mySteps.IsNull() ? myPathPoints.size() - 1: mySteps->Length(); + } // stores elements to use for extrusion by normal, depending on // state of EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY flag; // define myBaseP for scaling @@ -365,6 +369,20 @@ public: } private: + gp_Dir myDir; // direction of extrusion + Handle(TColStd_HSequenceOfReal) mySteps; // magnitudes for each step + std::vector myScales;// scale factors + std::vector myAngles;// angles + gp_XYZ myBaseP; // scaling/rotation center + SMESH_SequenceOfNode myNodes; // nodes for using in sewing + int myFlags; // see ExtrusionFlags + double myTolerance; // tolerance for sewing nodes + const TIDSortedElemSet* myElemsToUse; // elements to use for extrusion by normal + std::vector< PathPoint > myPathPoints; // points along a path + int (ExtrusParam::* myMakeNodesFun)(SMESHDS_Mesh*, // function of extrusion method + const SMDS_MeshNode*, + std::list &, + const bool); int makeNodesByDir( SMESHDS_Mesh* mesh, const SMDS_MeshNode* srcNode, std::list & newNodes, @@ -381,6 +399,10 @@ public: const SMDS_MeshNode* srcNode, std::list & newNodes, const bool makeMediumNodes); + int makeNodesAlongTrack( SMESHDS_Mesh* mesh, + const SMDS_MeshNode* srcNode, + std::list & newNodes, + const bool makeMediumNodes); // step iteration void beginStepIter( bool withMediumNodes ); bool moreSteps(); @@ -438,24 +460,16 @@ public: }; Extrusion_Error ExtrusionAlongTrack (TIDSortedElemSet theElements[2], - SMESH_subMesh* theTrackPattern, + SMESH_Mesh* theTrackMesh, + SMDS_ElemIteratorPtr theTrackIterator, const SMDS_MeshNode* theNodeStart, - const bool theHasAngles, std::list& theAngles, - const bool theLinearVariation, - const bool theHasRefPoint, - const gp_Pnt& theRefPoint, + const bool theAngleVariation, + std::list& theScales, + const bool theScaleVariation, + const gp_Pnt* theRefPoint, const bool theMakeGroups); - Extrusion_Error ExtrusionAlongTrack (TIDSortedElemSet theElements[2], - SMESH_Mesh* theTrackPattern, - const SMDS_MeshNode* theNodeStart, - const bool theHasAngles, - std::list& theAngles, - const bool theLinearVariation, - const bool theHasRefPoint, - const gp_Pnt& theRefPoint, - const bool theMakeGroups); - // Generate new elements by extrusion of theElements along path given by theTrackPattern, + // Generate new elements by extrusion of theElements along path given by theTrackIterator, // theHasAngles are the rotation angles, base point can be given by theRefPoint PGroupIDs Transform (TIDSortedElemSet & theElements, @@ -791,36 +805,10 @@ public: const int nbSteps, SMESH_SequenceOfElemPtr& srcElements); - struct SMESH_MeshEditor_PathPoint - { - gp_Pnt myPnt; - gp_Dir myTgt; - double myAngle, myPrm; - - SMESH_MeshEditor_PathPoint(): myPnt(99., 99., 99.), myTgt(1.,0.,0.), myAngle(0), myPrm(0) {} - void SetPnt (const gp_Pnt& aP3D) { myPnt =aP3D; } - void SetTangent (const gp_Dir& aTgt) { myTgt =aTgt; } - void SetAngle (const double& aBeta) { myAngle=aBeta; } - void SetParameter(const double& aPrm) { myPrm =aPrm; } - const gp_Pnt& Pnt ()const { return myPnt; } - const gp_Dir& Tangent ()const { return myTgt; } - double Angle ()const { return myAngle; } - double Parameter ()const { return myPrm; } - }; - Extrusion_Error makeEdgePathPoints(std::list& aPrms, - const TopoDS_Edge& aTrackEdge, - bool aFirstIsStart, - std::list& aLPP); - Extrusion_Error makeExtrElements(TIDSortedElemSet theElements[2], - std::list& theFullList, - const bool theHasAngles, - std::list& theAngles, - const bool theLinearVariation, - const bool theHasRefPoint, - const gp_Pnt& theRefPoint, - const bool theMakeGroups); static void linearAngleVariation(const int NbSteps, std::list& theAngles); + static void linearScaleVariation(const int NbSteps, + std::list& theScales); bool doubleNodes( SMESHDS_Mesh* theMeshDS, const TIDSortedElemSet& theElems, diff --git a/src/SMESH/SMESH_MesherHelper.cxx b/src/SMESH/SMESH_MesherHelper.cxx index 5925964b0..eb859d61e 100644 --- a/src/SMESH/SMESH_MesherHelper.cxx +++ b/src/SMESH/SMESH_MesherHelper.cxx @@ -36,6 +36,7 @@ #include "SMESH_HypoFilter.hxx" #include "SMESH_Mesh.hxx" #include "SMESH_MeshAlgos.hxx" +#include "SMESH_MeshEditor.hxx" #include "SMESH_ProxyMesh.hxx" #include "SMESH_subMesh.hxx" @@ -73,7 +74,7 @@ using namespace std; namespace { - inline SMESH_TNodeXYZ XYZ(const SMDS_MeshNode* n) { return SMESH_TNodeXYZ(n); } + inline SMESH_NodeXYZ XYZ(const SMDS_MeshNode* n) { return SMESH_NodeXYZ(n); } enum { U_periodic = 1, V_periodic = 2 }; } @@ -1035,6 +1036,16 @@ double SMESH_MesherHelper::GetNodeU(const TopoDS_Edge& E, int vertexID = n->getshapeId(); const TopoDS_Vertex& V = TopoDS::Vertex(meshDS->IndexToShape(vertexID)); param = BRep_Tool::Parameter( V, E ); + + if ( inEdgeNode ) + { + BRepAdaptor_Curve curve( E ); + if ( curve.IsPeriodic() ) + { + double uInEdge = GetNodeU( E, inEdgeNode ); + param += ShapeAnalysis::AdjustByPeriod( param, uInEdge, curve.Period() ); + } + } } } if ( check ) diff --git a/src/SMESH/SMESH_MesherHelper.hxx b/src/SMESH/SMESH_MesherHelper.hxx index 3b516baa0..8c9aea094 100644 --- a/src/SMESH/SMESH_MesherHelper.hxx +++ b/src/SMESH/SMESH_MesherHelper.hxx @@ -29,7 +29,8 @@ #include "SMESH_SMESH.hxx" -#include "SMESH_MeshEditor.hxx" // needed for many meshers +#include "SMESH_ComputeError.hxx" +#include "SMESH_TypeDefs.hxx" #include #include @@ -44,8 +45,15 @@ class GeomAPI_ProjectPointOnCurve; class GeomAPI_ProjectPointOnSurf; class SMDS_MeshNode; class SMESHDS_Hypothesis; +class SMESHDS_Mesh; +class SMESHDS_SubMesh; class SMESH_Gen; +class SMESH_Mesh; class SMESH_ProxyMesh; +class SMESH_subMesh; +class TopoDS_Edge; +class TopoDS_Face; +class TopoDS_Vertex; typedef std::map TLinkNodeMap; typedef std::map::iterator ItTLinkNode; diff --git a/src/SMESH/SMESH_Pattern.cxx b/src/SMESH/SMESH_Pattern.cxx index f032ae475..e069d62b6 100644 --- a/src/SMESH/SMESH_Pattern.cxx +++ b/src/SMESH/SMESH_Pattern.cxx @@ -38,6 +38,7 @@ #include "SMESH_Block.hxx" #include "SMESH_Mesh.hxx" #include "SMESH_MeshAlgos.hxx" +#include "SMESH_MeshEditor.hxx" #include "SMESH_MesherHelper.hxx" #include "SMESH_subMesh.hxx" diff --git a/src/SMESHDS/SMESHDS_Mesh.cxx b/src/SMESHDS/SMESHDS_Mesh.cxx index 7a8714424..3a641ec74 100644 --- a/src/SMESHDS/SMESHDS_Mesh.cxx +++ b/src/SMESHDS/SMESHDS_Mesh.cxx @@ -1202,7 +1202,7 @@ bool SMESHDS_Mesh::IsGroupOfSubShapes (const TopoDS_Shape& theShape) const return true; for ( TopoDS_Iterator it( theShape ); it.More(); it.Next() ) - if (IsGroupOfSubShapes( it.Value() )) + if ( IsGroupOfSubShapes( it.Value() )) return true; return false; diff --git a/src/SMESHGUI/SMESHGUI_ExtrusionAlongPathDlg.cxx b/src/SMESHGUI/SMESHGUI_ExtrusionAlongPathDlg.cxx index f6b5f80bf..866dd1ad2 100644 --- a/src/SMESHGUI/SMESHGUI_ExtrusionAlongPathDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_ExtrusionAlongPathDlg.cxx @@ -200,6 +200,7 @@ SMESHGUI_ExtrusionAlongPathDlg::SMESHGUI_ExtrusionAlongPathDlg( SMESHGUI* theMod BasePointGrpLayout->addWidget(ZLab); BasePointGrpLayout->addWidget(ZSpin); + // Angles AnglesGrp = new QGroupBox(tr("SMESH_ANGLES"), GroupArguments); AnglesGrp->setCheckable(true); AnglesGrp->setChecked(false); @@ -219,15 +220,42 @@ SMESHGUI_ExtrusionAlongPathDlg::SMESHGUI_ExtrusionAlongPathDlg( SMESHGUI* theMod LinearAnglesCheck = new QCheckBox(tr("LINEAR_ANGLES"), AnglesGrp); - // layouting AnglesGrpLayout->addWidget(AnglesList, 0, 0, 4, 1); AnglesGrpLayout->addWidget(AddAngleButton, 0, 1); AnglesGrpLayout->addWidget(RemoveAngleButton, 2, 1); AnglesGrpLayout->addWidget(AngleSpin, 0, 2); - AnglesGrpLayout->addWidget(LinearAnglesCheck, 4, 0); + AnglesGrpLayout->addWidget(LinearAnglesCheck, 4, 0, 1, 3); AnglesGrpLayout->setRowMinimumHeight(1, 10); AnglesGrpLayout->setRowStretch(3, 10); + // Scales + ScalesGrp = new QGroupBox(tr("SMESH_SCALES"), GroupArguments); + ScalesGrp->setCheckable(true); + ScalesGrp->setChecked(false); + QGridLayout* ScalesGrpLayout = new QGridLayout(ScalesGrp); + ScalesGrpLayout->setSpacing(SPACING); ScalesGrpLayout->setMargin(MARGIN); + + ScalesList = new QListWidget(ScalesGrp); + ScalesList->setSelectionMode(QListWidget::ExtendedSelection); + + AddScaleButton = new QToolButton(ScalesGrp); + AddScaleButton->setIcon(addImage); + + RemoveScaleButton = new QToolButton(ScalesGrp); + RemoveScaleButton->setIcon(removeImage); + + ScaleSpin = new SMESHGUI_SpinBox(ScalesGrp); + + LinearScalesCheck = new QCheckBox(tr("LINEAR_SCALES"), ScalesGrp); + + ScalesGrpLayout->addWidget(ScalesList, 0, 0, 4, 1); + ScalesGrpLayout->addWidget(AddScaleButton, 0, 1); + ScalesGrpLayout->addWidget(RemoveScaleButton, 2, 1); + ScalesGrpLayout->addWidget(ScaleSpin, 0, 2); + ScalesGrpLayout->addWidget(LinearScalesCheck, 4, 0, 1, 3); + ScalesGrpLayout->setRowMinimumHeight(1, 10); + ScalesGrpLayout->setRowStretch(3, 10); + // CheckBox for groups generation MakeGroupsCheck = new QCheckBox(tr("SMESH_MAKE_GROUPS"), GroupArguments); MakeGroupsCheck->setChecked(true); @@ -236,10 +264,11 @@ SMESHGUI_ExtrusionAlongPathDlg::SMESHGUI_ExtrusionAlongPathDlg( SMESHGUI* theMod myPreviewCheckBox = new QCheckBox(tr("PREVIEW"), GroupArguments); // layouting - GroupArgumentsLayout->addWidget(SelectorWdg, 0, 0); - GroupArgumentsLayout->addWidget(PathGrp, 1, 0); - GroupArgumentsLayout->addWidget(BasePointGrp, 2, 0); + GroupArgumentsLayout->addWidget(SelectorWdg, 0, 0, 1, 2); + GroupArgumentsLayout->addWidget(PathGrp, 1, 0, 1, 2); + GroupArgumentsLayout->addWidget(BasePointGrp, 2, 0, 1, 2); GroupArgumentsLayout->addWidget(AnglesGrp, 3, 0); + GroupArgumentsLayout->addWidget(ScalesGrp, 3, 1); GroupArgumentsLayout->addWidget(myPreviewCheckBox, 4, 0); GroupArgumentsLayout->addWidget(MakeGroupsCheck, 5, 0); @@ -282,12 +311,13 @@ SMESHGUI_ExtrusionAlongPathDlg::SMESHGUI_ExtrusionAlongPathDlg( SMESHGUI* theMod YSpin->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision"); ZSpin->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision"); AngleSpin->RangeStepAndValidator(-180.0, 180.0, 5.0, "angle_precision"); + ScaleSpin->RangeStepAndValidator(COORD_MIN, COORD_MAX, 1.0, "length_precision"); - mySelector = (SMESH::GetViewWindow( mySMESHGUI ))->GetSelector(); + mySelector = SMESH::GetViewWindow( mySMESHGUI )->GetSelector(); mySMESHGUI->SetActiveDialogBox(this); - myPathMeshFilter = new SMESH_TypeFilter(SMESH::MESHorSUBMESH); + myPathMeshFilter = new SMESH_TypeFilter(SMESH::IDSOURCE_EDGE); myHelpFileName = "extrusion_along_path.html"; @@ -302,6 +332,8 @@ SMESHGUI_ExtrusionAlongPathDlg::SMESHGUI_ExtrusionAlongPathDlg( SMESHGUI* theMod connect(AddAngleButton, SIGNAL(clicked()), this, SLOT(OnAngleAdded())); connect(RemoveAngleButton, SIGNAL(clicked()), this, SLOT(OnAngleRemoved())); + connect(AddScaleButton, SIGNAL(clicked()), this, SLOT(OnAngleAdded())); + connect(RemoveScaleButton, SIGNAL(clicked()), this, SLOT(OnAngleRemoved())); connect(SelectPathMeshButton, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument())); connect(SelectStartPointButton, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument())); @@ -324,19 +356,27 @@ SMESHGUI_ExtrusionAlongPathDlg::SMESHGUI_ExtrusionAlongPathDlg( SMESHGUI* theMod connect(ZSpin, SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation())); connect(AddAngleButton, SIGNAL(clicked()), this, SLOT(toDisplaySimulation())); connect(RemoveAngleButton, SIGNAL(clicked()), this, SLOT(toDisplaySimulation())); - //connect(LinearAnglesCheck, SIGNAL(toggled(bool)), SLOT(onSelectMesh())); + connect(AddScaleButton, SIGNAL(clicked()), this, SLOT(toDisplaySimulation())); + connect(RemoveScaleButton, SIGNAL(clicked()), this, SLOT(toDisplaySimulation())); + connect(LinearScalesCheck, SIGNAL(toggled(bool)), this, SLOT(toDisplaySimulation())); + connect(LinearAnglesCheck, SIGNAL(toggled(bool)), this, SLOT(toDisplaySimulation())); + connect(ScalesGrp, SIGNAL(toggled(bool)), this, SLOT(toDisplaySimulation())); + connect(AnglesGrp, SIGNAL(toggled(bool)), this, SLOT(toDisplaySimulation())); //To Connect preview check box connectPreviewControl(); AnglesList ->installEventFilter(this); + ScalesList ->installEventFilter(this); StartPointLineEdit->installEventFilter(this); XSpin->editor() ->installEventFilter(this); YSpin->editor() ->installEventFilter(this); ZSpin->editor() ->installEventFilter(this); CheckIsEnable(); + + resize( minimumSizeHint() ); } //================================================================================= @@ -369,6 +409,7 @@ void SMESHGUI_ExtrusionAlongPathDlg::Init (bool ResetControls) ZSpin->SetValue(0.0); AngleSpin->SetValue(45); + ScaleSpin->SetValue(2); myPreviewCheckBox->setChecked(false); onDisplaySimulation(false); } @@ -416,12 +457,10 @@ bool SMESHGUI_ExtrusionAlongPathDlg::ClickOnApply() QStringList aParameters; //get angles - SMESH::double_array_var anAngles = getAngles(); - + SMESH::double_array_var anAngles = getAngles(); for (int i = 0; i < myAnglesList.count(); i++) aParameters << AnglesList->item(i)->text(); - // get base point SMESH::PointStruct aBasePoint; if (BasePointGrp->isChecked()) { @@ -433,6 +472,11 @@ bool SMESHGUI_ExtrusionAlongPathDlg::ClickOnApply() aParameters << YSpin->text(); aParameters << ZSpin->text(); + //get scales + SMESH::double_array_var aScales = getScales(); + for (int i = 0; i < myScalesList.count(); i++) + aParameters << ScalesList->item(i)->text(); + bool meshHadNewTypeBefore = true; int maxSelType = 0; const bool makeGroups = ( MakeGroupsCheck->isEnabled() && MakeGroupsCheck->isChecked() ); @@ -464,8 +508,8 @@ bool SMESHGUI_ExtrusionAlongPathDlg::ClickOnApply() GEOM::GEOM_Object::_nil(), aNodeStart, AnglesGrp->isChecked(), anAngles, LinearAnglesCheck->isChecked(), - BasePointGrp->isChecked(), aBasePoint, - makeGroups, retVal ); + BasePointGrp->isChecked(), aBasePoint, makeGroups, + aScales, LinearScalesCheck->isChecked(), retVal ); wc.suspend(); switch (retVal) { @@ -911,17 +955,34 @@ void SMESHGUI_ExtrusionAlongPathDlg::enterEvent (QEvent*) //======================================================================= void SMESHGUI_ExtrusionAlongPathDlg::OnAngleAdded() { - QString msg; - if( !AngleSpin->isValid( msg, true ) ) { - QString str( tr( "SMESH_INCORRECT_INPUT" ) ); - if ( !msg.isEmpty() ) - str += "\n" + msg; - SUIT_MessageBox::critical( this, tr( "SMESH_ERROR" ), str ); - return; + if ( sender() == AddAngleButton ) + { + QString msg; + if( !AngleSpin->isValid( msg, true ) ) { + QString str( tr( "SMESH_INCORRECT_INPUT" ) ); + if ( !msg.isEmpty() ) + str += "\n" + msg; + SUIT_MessageBox::critical( this, tr( "SMESH_ERROR" ), str ); + return; + } + AnglesList->addItem(AngleSpin->text()); + myAnglesList.append(AngleSpin->GetValue()); } - AnglesList->addItem(AngleSpin->text()); - myAnglesList.append(AngleSpin->GetValue()); - + + if ( sender() == AddScaleButton ) + { + QString msg; + if( !ScaleSpin->isValid( msg, true ) ) { + QString str( tr( "SMESH_INCORRECT_INPUT" ) ); + if ( !msg.isEmpty() ) + str += "\n" + msg; + SUIT_MessageBox::critical( this, tr( "SMESH_ERROR" ), str ); + return; + } + ScalesList->addItem(ScaleSpin->text()); + myScalesList.append(ScaleSpin->GetValue()); + } + updateLinearAngles(); } @@ -931,10 +992,23 @@ void SMESHGUI_ExtrusionAlongPathDlg::OnAngleAdded() //======================================================================= void SMESHGUI_ExtrusionAlongPathDlg::OnAngleRemoved() { - QList aList = AnglesList->selectedItems(); + QListWidget* widget; + QList* list; + if ( sender() == RemoveScaleButton ) + { + widget = ScalesList; + list = & myScalesList; + } + else + { + widget = AnglesList; + list = & myAnglesList; + } + + QList aList = widget->selectedItems(); QListWidgetItem* anItem; foreach(anItem, aList) { - myAnglesList.removeAt(AnglesList->row(anItem)); + list->removeAt( widget->row( anItem )); delete anItem; } @@ -951,7 +1025,11 @@ bool SMESHGUI_ExtrusionAlongPathDlg::eventFilter (QObject* object, QEvent* event QKeyEvent* ke = (QKeyEvent*)event; if (object == AnglesList) { if (ke->key() == Qt::Key_Delete) - OnAngleRemoved(); + RemoveAngleButton->click(); + } + if (object == ScalesList) { + if (ke->key() == Qt::Key_Delete) + RemoveScaleButton->click(); } } else if (event->type() == QEvent::FocusIn) { @@ -1023,6 +1101,19 @@ void SMESHGUI_ExtrusionAlongPathDlg::updateLinearAngles() if( !enableLinear ) LinearAnglesCheck->setChecked( false ); LinearAnglesCheck->setEnabled( enableLinear ); + + enableLinear = true; + for( int row = 0, nbRows = ScalesList->count(); row < nbRows; row++ ) { + if( QListWidgetItem* anItem = ScalesList->item( row ) ) { + enableLinear = false; + anItem->text().toDouble(&enableLinear); + if( !enableLinear ) + break; + } + } + if( !enableLinear ) + LinearScalesCheck->setChecked( false ); + LinearScalesCheck->setEnabled( enableLinear ); } //================================================================================= @@ -1074,9 +1165,10 @@ void SMESHGUI_ExtrusionAlongPathDlg::onDisplaySimulation( bool toDisplayPreview if ( myPreviewCheckBox->isChecked() && toDisplayPreview ) { if ( SelectorWdg->IsAnythingSelected() && isValid() && isValuesValid()) { - // get angles + // get angles and scales SMESH::double_array_var anAngles = getAngles(); - + SMESH::double_array_var aScales = getScales(); + // get base point SMESH::PointStruct aBasePoint; if (BasePointGrp->isChecked()) { @@ -1107,7 +1199,9 @@ void SMESHGUI_ExtrusionAlongPathDlg::onDisplaySimulation( bool toDisplayPreview aNodeStart, AnglesGrp->isChecked(), anAngles, LinearAnglesCheck->isChecked(), BasePointGrp->isChecked(), aBasePoint, - makeGroups, retVal ); + makeGroups, + aScales, LinearScalesCheck->isChecked(), + retVal); if( retVal == SMESH::SMESH_MeshEditor::EXTR_OK ) { @@ -1133,18 +1227,36 @@ void SMESHGUI_ExtrusionAlongPathDlg::onDisplaySimulation( bool toDisplayPreview } } +//======================================================================= +//function : getAngles +//purpose : return CORBA array of angles +//======================================================================= + SMESH::double_array_var SMESHGUI_ExtrusionAlongPathDlg::getAngles() { SMESH::double_array_var anAngles = new SMESH::double_array; - if (AnglesGrp->isChecked()) + if ( AnglesGrp->isChecked() ) { - anAngles->length(myAnglesList.count()); - int j = 0; - for (int i = 0; i < myAnglesList.count(); i++) { - double angle = myAnglesList[i]; - anAngles[ j++ ] = angle*M_PI/180.; - } - anAngles->length(j); + anAngles->length( myAnglesList.count() ); + for (int i = 0; i < myAnglesList.count(); i++) + anAngles[ i ] = myAnglesList[ i ] * M_PI / 180.; } return anAngles; } + +//======================================================================= +//function : getScales +//purpose : return CORBA array of scale factors +//======================================================================= + +SMESH::double_array_var SMESHGUI_ExtrusionAlongPathDlg::getScales() +{ + SMESH::double_array_var anScales = new SMESH::double_array; + if ( ScalesGrp->isChecked() ) + { + anScales->length( myScalesList.count() ); + for (int i = 0; i < myScalesList.count(); i++) + anScales[ i ] = myScalesList[ i ]; + } + return anScales; +} diff --git a/src/SMESHGUI/SMESHGUI_ExtrusionAlongPathDlg.h b/src/SMESHGUI/SMESHGUI_ExtrusionAlongPathDlg.h index 18cd048ae..2bd6f1d21 100644 --- a/src/SMESHGUI/SMESHGUI_ExtrusionAlongPathDlg.h +++ b/src/SMESHGUI/SMESHGUI_ExtrusionAlongPathDlg.h @@ -82,6 +82,7 @@ private: bool isValuesValid(); SMESH::double_array_var getAngles(); + SMESH::double_array_var getScales(); void updateLinearAngles(); @@ -94,6 +95,7 @@ private: SMESH::SMESH_IDSource_var myPath; SUIT_SelectionFilter* myPathMeshFilter; QList myAnglesList; + QList myScalesList; // widgets SMESHGUI_3TypesSelector* SelectorWdg; @@ -103,12 +105,21 @@ private: QLineEdit* PathMeshLineEdit; QPushButton* SelectStartPointButton; QLineEdit* StartPointLineEdit; + QCheckBox* LinearAnglesCheck; QGroupBox* AnglesGrp; QListWidget* AnglesList; QToolButton* AddAngleButton; QToolButton* RemoveAngleButton; SMESHGUI_SpinBox* AngleSpin; + + QCheckBox* LinearScalesCheck; + QGroupBox* ScalesGrp; + QListWidget* ScalesList; + QToolButton* AddScaleButton; + QToolButton* RemoveScaleButton; + SMESHGUI_SpinBox* ScaleSpin; + QGroupBox* BasePointGrp; QPushButton* SelectBasePointButton; SMESHGUI_SpinBox* XSpin; diff --git a/src/SMESHGUI/SMESHGUI_ExtrusionDlg.cxx b/src/SMESHGUI/SMESHGUI_ExtrusionDlg.cxx index d17be56aa..ad1bb208b 100644 --- a/src/SMESHGUI/SMESHGUI_ExtrusionDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_ExtrusionDlg.cxx @@ -709,6 +709,8 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule) // Scales ScalesGrp = new QGroupBox(tr("SMESH_SCALES"), GroupArguments); + ScalesGrp->setCheckable(true); + ScalesGrp->setChecked(false); QGridLayout* ScalesGrpLayout = new QGridLayout( ScalesGrp ); ScalesGrpLayout->setSpacing(SPACING); ScalesGrpLayout->setMargin(MARGIN); @@ -730,10 +732,40 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule) ScalesGrpLayout->addWidget(AddScaleButton, 0, 1); ScalesGrpLayout->addWidget(RemoveScaleButton, 2, 1); ScalesGrpLayout->addWidget(ScaleSpin, 0, 2); - ScalesGrpLayout->addWidget(LinearScalesCheck, 4, 0); + ScalesGrpLayout->addWidget(LinearScalesCheck, 4, 0, 1, 3); ScalesGrpLayout->setRowMinimumHeight(1, 10); ScalesGrpLayout->setRowStretch(3, 10); + // Angles + + AnglesGrp = new QGroupBox(tr("SMESH_ANGLES"), GroupArguments); + AnglesGrp->setCheckable(true); + AnglesGrp->setChecked(false); + QGridLayout* AnglesGrpLayout = new QGridLayout( AnglesGrp ); + AnglesGrpLayout->setSpacing(SPACING); AnglesGrpLayout->setMargin(MARGIN); + + AnglesList = new QListWidget( AnglesGrp ); + AnglesList->setSelectionMode(QListWidget::ExtendedSelection); + + AddAngleButton = new QToolButton( AnglesGrp ); + AddAngleButton->setIcon( addImage ); + + RemoveAngleButton = new QToolButton( AnglesGrp ); + RemoveAngleButton->setIcon( removeImage ); + + AngleSpin = new SMESHGUI_SpinBox( AnglesGrp ); + AngleSpin->SetValue(10); + + LinearAnglesCheck = new QCheckBox(tr("LINEAR_ANGLES"), AnglesGrp ); + + AnglesGrpLayout->addWidget(AnglesList, 0, 0, 4, 1); + AnglesGrpLayout->addWidget(AddAngleButton, 0, 1); + AnglesGrpLayout->addWidget(RemoveAngleButton, 2, 1); + AnglesGrpLayout->addWidget(AngleSpin, 0, 2); + AnglesGrpLayout->addWidget(LinearAnglesCheck, 4, 0, 1, 3); + AnglesGrpLayout->setRowMinimumHeight(1, 10); + AnglesGrpLayout->setRowStretch(3, 10); + // layouting GroupArgumentsLayout->addWidget(SelectorWdg, 0, 0, 1, 9); GroupArgumentsLayout->addWidget(ExtrMethod_RBut0, 1, 0, 1, 3); @@ -761,7 +793,8 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule) GroupArgumentsLayout->addWidget(ByAverageNormalCheck, 6, 0, 1, 4); GroupArgumentsLayout->addWidget(UseInputElemsOnlyCheck, 6, 4, 1, 4); GroupArgumentsLayout->addWidget(BasePointGrp, 7, 0, 1, 9); - GroupArgumentsLayout->addWidget(ScalesGrp, 8, 0, 1, 9); + GroupArgumentsLayout->addWidget(ScalesGrp, 8, 0, 1, 4); + GroupArgumentsLayout->addWidget(AnglesGrp, 8, 5, 1, 4); GroupArgumentsLayout->addWidget(myPreviewCheckBox, 9, 0, 1, 8); GroupArgumentsLayout->addWidget(MakeGroupsCheck, 10,0, 1, 8); GroupArgumentsLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding), 10, 0); @@ -810,12 +843,13 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule) BasePoint_YSpin->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision"); BasePoint_ZSpin->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision"); ScaleSpin->RangeStepAndValidator (COORD_MIN, COORD_MAX, 1.0, "length_precision"); + AngleSpin->RangeStepAndValidator (-180.0, 180.0, 5.0, "angle_precision"); ExtrMethod_RBut0->setChecked(true); UseInputElemsOnlyCheck->setChecked(true); MakeGroupsCheck->setChecked(true); - mySelector = (SMESH::GetViewWindow( mySMESHGUI ))->GetSelector(); + mySelector = SMESH::GetViewWindow( mySMESHGUI )->GetSelector(); mySMESHGUI->SetActiveDialogBox(this); @@ -844,6 +878,8 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule) connect(AddScaleButton, SIGNAL(clicked()), this, SLOT(OnScaleAdded())); connect(RemoveScaleButton, SIGNAL(clicked()), this, SLOT(OnScaleRemoved())); + connect(AddAngleButton, SIGNAL(clicked()), this, SLOT(OnScaleAdded())); + connect(RemoveAngleButton, SIGNAL(clicked()), this, SLOT(OnScaleRemoved())); connect(SelectVectorButton, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument())); connect(SelectBasePointButton,SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument())); @@ -871,10 +907,15 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule) connect(AddScaleButton, SIGNAL(clicked()), this, SLOT(toDisplaySimulation())); connect(RemoveScaleButton, SIGNAL(clicked()), this, SLOT(toDisplaySimulation())); connect(LinearScalesCheck, SIGNAL(toggled(bool)), this, SLOT(toDisplaySimulation())); + connect(AddAngleButton, SIGNAL(clicked()), this, SLOT(toDisplaySimulation())); + connect(RemoveAngleButton, SIGNAL(clicked()), this, SLOT(toDisplaySimulation())); + connect(LinearAnglesCheck, SIGNAL(toggled(bool)), this, SLOT(toDisplaySimulation())); connect(BasePointGrp, SIGNAL(toggled(bool)), this, SLOT(toDisplaySimulation())); connect(BasePoint_XSpin, SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation())); connect(BasePoint_YSpin, SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation())); connect(BasePoint_ZSpin, SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation())); + connect(ScalesGrp, SIGNAL(toggled(bool)), this, SLOT(toDisplaySimulation())); + connect(AnglesGrp, SIGNAL(toggled(bool)), this, SLOT(toDisplaySimulation())); //To Connect preview check box connectPreviewControl(); @@ -964,14 +1005,26 @@ bool SMESHGUI_ExtrusionDlg::isValuesValid() //purpose : return 3 scaling parameters //======================================================================= -bool SMESHGUI_ExtrusionDlg::getScaleParams( SMESH::double_array*& scales, - SMESH::double_array*& basePoint ) +void SMESHGUI_ExtrusionDlg::getScaleParams( SMESH::double_array*& scales, + SMESH::double_array*& basePoint, + bool & scalesVariation, + SMESH::double_array*& angles, + bool & anglesVariation ) { scales = new SMESH::double_array; - scales->length( myScalesList.count() ); - for ( int i = 0; i < myScalesList.count(); ++i ) - (*scales)[i] = myScalesList[i]; - + if ( ScalesGrp->isChecked() ) + { + scales->length( myScalesList.count() ); + for ( int i = 0; i < myScalesList.count(); ++i ) + (*scales)[i] = myScalesList[i]; + } + angles = new SMESH::double_array; + if ( AnglesGrp->isChecked() ) + { + angles->length( myAnglesList.count() ); + for ( int i = 0; i < myAnglesList.count(); ++i ) + (*angles)[i] = myAnglesList[i]*M_PI/180.; + } basePoint = new SMESH::double_array; if ( BasePointGrp->isChecked() ) { @@ -981,7 +1034,8 @@ bool SMESHGUI_ExtrusionDlg::getScaleParams( SMESH::double_array*& scales, (*basePoint)[2] = BasePoint_ZSpin->GetValue(); } - return ( scales->length() > 0 && LinearScalesCheck->isChecked() ); + scalesVariation = ( scales->length() > 0 && LinearScalesCheck->isChecked() ); + anglesVariation = ( angles->length() > 0 && LinearAnglesCheck->isChecked() ); } //================================================================================= @@ -1074,6 +1128,7 @@ void SMESHGUI_ExtrusionDlg::ClickOnRadio() BasePointGrp->setEnabled( !ExtrMethod_RBut2->isChecked() ); ScalesGrp ->setEnabled( !ExtrMethod_RBut2->isChecked() ); + AnglesGrp ->setEnabled( !ExtrMethod_RBut2->isChecked() ); CheckIsEnable(); @@ -1126,13 +1181,11 @@ bool SMESHGUI_ExtrusionDlg::ClickOnApply() long aNbSteps = (long)SpinBox_NbSteps->value(); aParameters << SpinBox_NbSteps->text(); - SMESH::double_array_var scales = new SMESH::double_array; - scales->length( myScalesList.count() ); for (int i = 0; i < myScalesList.count(); i++) - { - scales[i] = myScalesList[i]; aParameters << ScalesList->item(i)->text(); - } + + for (int i = 0; i < myAnglesList.count(); i++) + aParameters << AnglesList->item(i)->text(); bool meshHadNewTypeBefore = true; int maxSelType = 0; @@ -1175,12 +1228,14 @@ bool SMESHGUI_ExtrusionDlg::ClickOnApply() } else { - SMESH::double_array_var scales, basePoint; - bool linVariation = getScaleParams( scales.out(), basePoint.out() ); + SMESH::double_array_var scales, basePoint, angles; + bool scalesVariation, anglesVariation; + getScaleParams( scales.out(), basePoint.out(), scalesVariation, + angles.out(), anglesVariation ); groups = meshEditor->ExtrusionSweepObjects( nodes, edges, faces, - aVector, aNbSteps, - scales, linVariation, basePoint, - makeGroups ); + aVector, aNbSteps, makeGroups, + scales, scalesVariation, basePoint, + angles, anglesVariation ); } } catch (...) { @@ -1565,12 +1620,14 @@ void SMESHGUI_ExtrusionDlg::onDisplaySimulation( bool toDisplayPreview ) } else { - SMESH::double_array_var scales, basePoint; - bool linVariation = getScaleParams( scales.out(), basePoint.out() ); + SMESH::double_array_var scales, basePoint, angles; + bool scalesVariation, anglesVariation; + getScaleParams( scales.out(), basePoint.out(), scalesVariation, + angles.out(), anglesVariation ); groups = meshEditor->ExtrusionSweepObjects( nodes, edges, faces, - aVector, aNbSteps, - scales, linVariation, basePoint, - makeGroups ); + aVector, aNbSteps, makeGroups, + scales, scalesVariation, basePoint, + angles, anglesVariation ); } SMESH::MeshPreviewStruct_var aMeshPreviewStruct = meshEditor->GetPreviewData(); mySimulation->SetData(aMeshPreviewStruct); @@ -1614,35 +1671,65 @@ void SMESHGUI_ExtrusionDlg::getExtrusionVector(SMESH::DirStruct& aVector) //======================================================================= // function : OnScaleAdded() -// purpose : Called when user adds Scale to the list +// purpose : Called when user adds Scale or Angle to the list //======================================================================= void SMESHGUI_ExtrusionDlg::OnScaleAdded() { - QString msg; - if( !ScaleSpin->isValid( msg, true ) ) { - QString str( tr( "SMESH_INCORRECT_INPUT" ) ); - if ( !msg.isEmpty() ) - str += "\n" + msg; - SUIT_MessageBox::critical( this, tr( "SMESH_ERROR" ), str ); - return; + if ( sender() == AddScaleButton ) + { + QString msg; + if( !ScaleSpin->isValid( msg, true ) ) { + QString str( tr( "SMESH_INCORRECT_INPUT" ) ); + if ( !msg.isEmpty() ) + str += "\n" + msg; + SUIT_MessageBox::critical( this, tr( "SMESH_ERROR" ), str ); + return; + } + ScalesList->addItem(ScaleSpin->text()); + myScalesList.append(ScaleSpin->GetValue()); + } + + if ( sender() == AddAngleButton ) + { + QString msg; + if( !AngleSpin->isValid( msg, true ) ) { + QString str( tr( "SMESH_INCORRECT_INPUT" ) ); + if ( !msg.isEmpty() ) + str += "\n" + msg; + SUIT_MessageBox::critical( this, tr( "SMESH_ERROR" ), str ); + return; + } + AnglesList->addItem(AngleSpin->text()); + myAnglesList.append(AngleSpin->GetValue()); } - ScalesList->addItem(ScaleSpin->text()); - myScalesList.append(ScaleSpin->GetValue()); } //======================================================================= // function : OnScaleRemoved() -// purpose : Called when user removes Scale(s) from the list +// purpose : Called when user removes Scales or Angles from the list //======================================================================= void SMESHGUI_ExtrusionDlg::OnScaleRemoved() { - QList aList = ScalesList->selectedItems(); + QListWidget* widget; + QList* list; + if ( sender() == RemoveScaleButton ) + { + widget = ScalesList; + list = & myScalesList; + } + else + { + widget = AnglesList; + list = & myAnglesList; + } + + QList aList = widget->selectedItems(); QListWidgetItem* anItem; int row = 0; foreach(anItem, aList) { - row = ScalesList->row(anItem); - myScalesList.removeAt(row); + row = widget->row(anItem); + list->removeAt(row); delete anItem; } - ScalesList->setCurrentRow( row, QItemSelectionModel::Select ); + widget->setCurrentRow( row, QItemSelectionModel::Select ); } diff --git a/src/SMESHGUI/SMESHGUI_ExtrusionDlg.h b/src/SMESHGUI/SMESHGUI_ExtrusionDlg.h index b539eee98..1b1c21100 100644 --- a/src/SMESHGUI/SMESHGUI_ExtrusionDlg.h +++ b/src/SMESHGUI/SMESHGUI_ExtrusionDlg.h @@ -145,8 +145,11 @@ private: void getExtrusionVector(SMESH::DirStruct& aVector); void extrusionByNormal(SMESH::SMESH_MeshEditor_ptr meshEditor, const bool makeGroups=false); - bool getScaleParams( SMESH::double_array*& scales, - SMESH::double_array*& basePoint ); + void getScaleParams( SMESH::double_array*& scales, + SMESH::double_array*& basePoint, + bool & scalesVariation, + SMESH::double_array*& angles, + bool & anglesVariation); bool isValid(); bool isValuesValid(); @@ -154,6 +157,7 @@ private: LightApp_SelectionMgr* mySelectionMgr; /* User shape selection */ SVTK_Selector* mySelector; QList myScalesList; + QList myAnglesList; // widgets SMESHGUI_3TypesSelector* SelectorWdg; @@ -198,6 +202,13 @@ private: SMESHGUI_SpinBox* ScaleSpin; QCheckBox* LinearScalesCheck; + QGroupBox* AnglesGrp; + QListWidget* AnglesList; + QToolButton* AddAngleButton; + QToolButton* RemoveAngleButton; + SMESHGUI_SpinBox* AngleSpin; + QCheckBox* LinearAnglesCheck; + QGroupBox* GroupButtons; QPushButton* buttonOk; QPushButton* buttonCancel; diff --git a/src/SMESHGUI/SMESH_msg_en.ts b/src/SMESHGUI/SMESH_msg_en.ts index 222fa1e06..ac6bcd036 100644 --- a/src/SMESHGUI/SMESH_msg_en.ts +++ b/src/SMESHGUI/SMESH_msg_en.ts @@ -1847,15 +1847,15 @@ Do you want to continue? SMESH_EXTRUSION_TO_DISTANCE - Extrusion To Distance + Extrusion to distance SMESH_EXTRUSION_ALONG_VECTOR - Extrusion Along Vector + Extrusion along vector SMESH_EXTRUSION_BY_NORMAL - Extrusion By Normal + Extrusion by normal SMESH_FACE @@ -5517,18 +5517,6 @@ Please select a group and try again CANT_GET_TANGENT Can't get tangent for one of the path nodes - - EXTRUSION_0D - Extrusion of 0D elements - - - EXTRUSION_1D - Extrusion of 1D elements - - - EXTRUSION_2D - Extrusion of 2D elements - EXTRUSION_ALONG_PATH Extrusion along a path @@ -5539,7 +5527,7 @@ Please select a group and try again LINEAR_ANGLES - Linear variation of the angles + Linear variation of angles NO_ELEMENTS_SELECTED @@ -5551,11 +5539,19 @@ Please select a group and try again SMESH_ANGLES - Rotation Angles + Rotation angles SMESH_BASE_POINT - Base Point + Base point + + + SMESH_SCALES + Scale factors + + + LINEAR_SCALES + Linear variation of factors SMESH_PATH @@ -5575,11 +5571,11 @@ Please select a group and try again SMESH_USE_ANGLES - Use Angles + Use angles SMESH_USE_BASE_POINT - Use Base Point + Use base point WRONG_ANGLES_NUMBER @@ -5588,18 +5584,6 @@ Please select a group and try again SMESHGUI_ExtrusionDlg - - EXTRUSION_0D - Extrusion of nodes - - - EXTRUSION_1D - Extrusion of 1D elements - - - EXTRUSION_2D - Extrusion of 2D elements - EXTRUSION_ALONG_LINE Extrusion along a line @@ -5614,15 +5598,23 @@ Please select a group and try again SMESH_SCALES - Scale Factors + Scale factors LINEAR_SCALES - Linear Variation of Scale Factors + Linear variation of factors BASE_POINT - Scaling Center + Base point + + + LINEAR_ANGLES + Linear variation of angles + + + SMESH_ANGLES + Rotation angles diff --git a/src/SMESHUtils/SMESH_Delaunay.hxx b/src/SMESHUtils/SMESH_Delaunay.hxx index 71707118b..8c1960011 100644 --- a/src/SMESHUtils/SMESH_Delaunay.hxx +++ b/src/SMESHUtils/SMESH_Delaunay.hxx @@ -79,8 +79,8 @@ class SMESHUtils_EXPORT SMESH_Delaunay // return UV of the i-th source boundary node (zero based) gp_XY GetBndUV(const int iNode) const; - // return scale factor to convert real UV to/from UV used for Delauney meshing: - // delauney_UV = real_UV * scale + // return scale factor to convert real UV to/from UV used for Delaunay meshing: + // delaunay_UV = real_UV * scale const gp_XY& GetScale() const { return _scale; } void ToPython() const; diff --git a/src/SMESHUtils/SMESH_MeshAlgos.cxx b/src/SMESHUtils/SMESH_MeshAlgos.cxx index 6cd891ccc..52d7d5415 100644 --- a/src/SMESHUtils/SMESH_MeshAlgos.cxx +++ b/src/SMESHUtils/SMESH_MeshAlgos.cxx @@ -1764,7 +1764,7 @@ double SMESH_MeshAlgos::GetDistance( const SMDS_MeshVolume* volume, !vTool.GetFaceBaryCenter( iF, bc[0], bc[1], bc[2] )) continue; gp_XYZ bcp = point.XYZ() - gp_XYZ( bc[0], bc[1], bc[2] ); - if ( gp_XYZ( n[0], n[1], n[2] ) * bcp < 1e-6 ) + if ( gp_XYZ( n[0], n[1], n[2] ) * bcp < -1e-12 ) continue; // find distance to a facet diff --git a/src/SMESH_I/SMESH_MeshEditor_i.cxx b/src/SMESH_I/SMESH_MeshEditor_i.cxx index b03eca37d..7ef847bf0 100644 --- a/src/SMESH_I/SMESH_MeshEditor_i.cxx +++ b/src/SMESH_I/SMESH_MeshEditor_i.cxx @@ -2496,7 +2496,8 @@ namespace MeshEditor_I bool myIsExtrusionByNormal; static int makeFlags( CORBA::Boolean MakeGroups, - CORBA::Boolean LinearVariation = false, + CORBA::Boolean ScaleVariation = false, + CORBA::Boolean AngleVariation = false, CORBA::Boolean ByAverageNormal = false, CORBA::Boolean UseInputElemsOnly = false, CORBA::Long Flags = 0, @@ -2505,7 +2506,8 @@ namespace MeshEditor_I if ( MakeGroups ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS; if ( ByAverageNormal ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BY_AVG_NORMAL; if ( UseInputElemsOnly) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY; - if ( LinearVariation ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_SCALE_LINEAR_VARIATION; + if ( ScaleVariation ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_SCALE_LINEAR_VARIATION; + if ( AngleVariation ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_ANGLE_LINEAR_VARIATION; if ( MakeBoundary ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY; return Flags; } @@ -2513,7 +2515,9 @@ namespace MeshEditor_I ExtrusionParams(const SMESH::DirStruct & theDir, CORBA::Long theNbOfSteps, const SMESH::double_array & theScaleFactors, - CORBA::Boolean theLinearVariation, + CORBA::Boolean theScaleVariation, + const SMESH::double_array & theAngles, + CORBA::Boolean theAngleVariation, const SMESH::double_array & theBasePoint, CORBA::Boolean theMakeGroups): ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x, @@ -2521,8 +2525,9 @@ namespace MeshEditor_I theDir.PS.z ), theNbOfSteps, toList( theScaleFactors ), + toList( theAngles ), TBasePoint( theBasePoint ), - makeFlags( theMakeGroups, theLinearVariation )), + makeFlags( theMakeGroups, theScaleVariation, theAngleVariation )), myIsExtrusionByNormal( false ) { } @@ -2537,8 +2542,9 @@ namespace MeshEditor_I theDir.PS.z ), theNbOfSteps, std::list(), + std::list(), 0, - makeFlags( theMakeGroups, false, false, false, + makeFlags( theMakeGroups, false, false, false, false, theExtrFlags, false ), theSewTolerance ), myIsExtrusionByNormal( false ) @@ -2553,7 +2559,7 @@ namespace MeshEditor_I CORBA::Boolean theMakeGroups ): ::SMESH_MeshEditor::ExtrusParam ( theStepSize, theNbOfSteps, - makeFlags( theMakeGroups, false, + makeFlags( theMakeGroups, false, false, theByAverageNormal, theUseInputElemsOnly ), theDim), myIsExtrusionByNormal( true ) @@ -2565,8 +2571,6 @@ namespace MeshEditor_I Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS); } - private: - static std::list toList( const SMESH::double_array & theScaleFactors ) { std::list scales; @@ -2575,6 +2579,8 @@ namespace MeshEditor_I return scales; } + private: + // structure used to convert SMESH::double_array to gp_XYZ* struct TBasePoint { @@ -2613,17 +2619,19 @@ SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNode const SMESH::ListOfIDSources & theFaces, const SMESH::DirStruct & theStepVector, CORBA::Long theNbOfSteps, + CORBA::Boolean theToMakeGroups, const SMESH::double_array & theScaleFactors, - CORBA::Boolean theLinearVariation, + CORBA::Boolean theScalesVariation, const SMESH::double_array & theBasePoint, - CORBA::Boolean theToMakeGroups) + const SMESH::double_array & theAngles, + CORBA::Boolean theAnglesVariation) throw (SALOME::SALOME_Exception) { SMESH_TRY; initData(); - ExtrusionParams params( theStepVector, theNbOfSteps, theScaleFactors, - theLinearVariation, theBasePoint, theToMakeGroups ); + ExtrusionParams params( theStepVector, theNbOfSteps, theScaleFactors, theScalesVariation, + theAngles, theAnglesVariation, theBasePoint, theToMakeGroups ); TIDSortedElemSet elemsNodes[2]; for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) { @@ -2664,12 +2672,17 @@ SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNode { dumpGroupsList( aPythonDump, aGroups ); aPythonDump << this<< ".ExtrusionSweepObjects( " - << theNodes << ", " - << theEdges << ", " - << theFaces << ", " - << theStepVector << ", " - << TVar( theNbOfSteps ) << ", " - << theToMakeGroups << " )"; + << theNodes << ", " + << theEdges << ", " + << theFaces << ", " + << theStepVector << ", " + << TVar( theNbOfSteps ) << ", " + << theToMakeGroups << ", " + << TVar( theScaleFactors ) << ", " + << theScalesVariation << ", " + << TVar( theBasePoint ) << ", " + << TVar( theAngles ) << ", " + << theAnglesVariation << " )"; } else { @@ -2847,15 +2860,17 @@ SMESH::ListOfGroups* SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & theNodes, const SMESH::ListOfIDSources & theEdges, const SMESH::ListOfIDSources & theFaces, - SMESH::SMESH_IDSource_ptr thePathMesh, + SMESH::SMESH_IDSource_ptr thePathObject, GEOM::GEOM_Object_ptr thePathShape, CORBA::Long theNodeStart, CORBA::Boolean theHasAngles, const SMESH::double_array & theAngles, - CORBA::Boolean theLinearVariation, + CORBA::Boolean theAnglesVariation, CORBA::Boolean theHasRefPoint, const SMESH::PointStruct & theRefPoint, bool theMakeGroups, + const SMESH::double_array & theScaleFactors, + CORBA::Boolean theScalesVariation, SMESH::SMESH_MeshEditor::Extrusion_Error& theError) throw (SALOME::SALOME_Exception) { @@ -2865,45 +2880,58 @@ SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & the SMESH::ListOfGroups_var aGroups = new SMESH::ListOfGroups; theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE; - if ( thePathMesh->_is_nil() ) + if ( thePathObject->_is_nil() ) return aGroups._retn(); - // get a sub-mesh - SMESH_subMesh* aSubMesh = 0; - SMESH_Mesh_i* aMeshImp = SMESH::DownCast( thePathMesh ); - if ( thePathShape->_is_nil() ) + + SMDS_ElemIteratorPtr pathEdgesIterator; + + SMESH_Mesh_i* aMeshImp = SMESH::DownCast( thePathObject ); + if ( !CORBA::is_nil( thePathShape ) && aMeshImp ) { - // thePathMesh should be either a sub-mesh or a mesh with 1D elements only - if ( SMESH_subMesh_i* sm = SMESH::DownCast( thePathMesh )) + // get a sub-mesh of thePathShape + TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape ); + SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape ); + if ( !aSubMesh ) + return aGroups._retn(); + + if ( !aSubMesh->GetSubMeshDS() ) { - SMESH::SMESH_Mesh_var mesh = thePathMesh->GetMesh(); - aMeshImp = SMESH::DownCast( mesh ); - if ( !aMeshImp ) return aGroups._retn(); - aSubMesh = aMeshImp->GetImpl().GetSubMeshContaining( sm->GetId() ); - if ( !aSubMesh ) return aGroups._retn(); + SMESHDS_Mesh * meshDS = aMeshImp->GetImpl().GetMeshDS(); + meshDS->AddCompoundSubmesh( aShape, TopAbs_EDGE ); + if ( !aSubMesh->GetSubMeshDS() ) + return aGroups._retn(); } - else if ( !aMeshImp || - aMeshImp->NbEdges() != aMeshImp->NbElements() ) - { + theError = SMESH::SMESH_MeshEditor::EXTR_PATH_NOT_EDGE; + pathEdgesIterator = aSubMesh->GetSubMeshDS()->GetElements(); + if ( !pathEdgesIterator->more() || + pathEdgesIterator->next()->GetType() != SMDSAbs_Edge ) return aGroups._retn(); - } + + pathEdgesIterator = aSubMesh->GetSubMeshDS()->GetElements(); } else { - if ( !aMeshImp ) return aGroups._retn(); - TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape ); - aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape ); - if ( !aSubMesh /*|| !aSubMesh->GetSubMeshDS()*/ ) + theError = SMESH::SMESH_MeshEditor::EXTR_PATH_NOT_EDGE; + prepareIdSource( thePathObject ); + pathEdgesIterator = SMESH_Mesh_i::GetElements( thePathObject, SMESH::EDGE ); + if ( !pathEdgesIterator || !pathEdgesIterator->more() ) return aGroups._retn(); } - SMDS_MeshNode* nodeStart = - (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(theNodeStart); - if ( !nodeStart ) { - theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE; - return aGroups._retn(); + if ( !aMeshImp ) + { + SMESH::SMESH_Mesh_var pathMesh = thePathObject->GetMesh(); + aMeshImp = SMESH::DownCast( pathMesh ); } + + theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE; + const SMDS_MeshNode* nodeStart = aMeshImp->GetImpl().GetMeshDS()->FindNode( theNodeStart ); + if ( !nodeStart ) + return aGroups._retn(); + + TIDSortedElemSet elemsNodes[2]; for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) { if ( SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE )) @@ -2914,12 +2942,11 @@ SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & the for ( int i = 0, nb = theFaces.length(); i < nb; ++i ) idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face ); - list angles; - for ( CORBA::ULong i = 0; i < theAngles.length(); i++ ) { - angles.push_back( theAngles[i] ); - } + list angles = ExtrusionParams::toList( theAngles ); + list scales = ExtrusionParams::toList( theScaleFactors ); gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z ); + const gp_Pnt *refPntPtr = theHasRefPoint ? &refPnt : 0; int nbOldGroups = myMesh->NbGroup(); @@ -2934,15 +2961,12 @@ SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & the theMakeGroups = false; } - ::SMESH_MeshEditor::Extrusion_Error error; - if ( !aSubMesh ) - error = getEditor().ExtrusionAlongTrack( workElements, &(aMeshImp->GetImpl()), nodeStart, - theHasAngles, angles, theLinearVariation, - theHasRefPoint, refPnt, theMakeGroups ); - else - error = getEditor().ExtrusionAlongTrack( workElements, aSubMesh, nodeStart, - theHasAngles, angles, theLinearVariation, - theHasRefPoint, refPnt, theMakeGroups ); + ::SMESH_MeshEditor::Extrusion_Error error = + getEditor().ExtrusionAlongTrack( workElements, + &(aMeshImp->GetImpl()), pathEdgesIterator, nodeStart, + angles, theAnglesVariation, + scales, theScalesVariation, + refPntPtr, theMakeGroups ); declareMeshModified( /*isReComputeSafe=*/true ); theError = convExtrError( error ); @@ -2964,18 +2988,20 @@ SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & the << theNodes << ", " << theEdges << ", " << theFaces << ", " - << thePathMesh << ", " + << thePathObject << ", " << thePathShape << ", " << theNodeStart << ", " << theHasAngles << ", " << TVar( theAngles ) << ", " - << theLinearVariation << ", " + << theAnglesVariation << ", " << theHasRefPoint << ", " << "SMESH.PointStruct( " << TVar( theHasRefPoint ? theRefPoint.x : 0 ) << ", " << TVar( theHasRefPoint ? theRefPoint.y : 0 ) << ", " << TVar( theHasRefPoint ? theRefPoint.z : 0 ) << " ), " - << theMakeGroups << " )"; + << theMakeGroups << ", " + << TVar( theScaleFactors ) << ", " + << theScalesVariation << " )"; } else { diff --git a/src/SMESH_I/SMESH_MeshEditor_i.hxx b/src/SMESH_I/SMESH_MeshEditor_i.hxx index d8c46a64f..016f00055 100644 --- a/src/SMESH_I/SMESH_MeshEditor_i.hxx +++ b/src/SMESH_I/SMESH_MeshEditor_i.hxx @@ -322,25 +322,27 @@ public: void RenumberNodes() throw (SALOME::SALOME_Exception); void RenumberElements() throw (SALOME::SALOME_Exception); - SMESH::ListOfGroups* RotationSweepObjects(const SMESH::ListOfIDSources & nodes, - const SMESH::ListOfIDSources & edges, - const SMESH::ListOfIDSources & faces, + SMESH::ListOfGroups* RotationSweepObjects(const SMESH::ListOfIDSources & Nodes, + const SMESH::ListOfIDSources & Edges, + const SMESH::ListOfIDSources & Faces, const SMESH::AxisStruct & Axis, CORBA::Double AngleInRadians, CORBA::Long NbOfSteps, CORBA::Double Tolerance, - CORBA::Boolean toMakeGroups) + CORBA::Boolean ToMakeGroups) throw (SALOME::SALOME_Exception); - SMESH::ListOfGroups* ExtrusionSweepObjects(const SMESH::ListOfIDSources & nodes, - const SMESH::ListOfIDSources & edges, - const SMESH::ListOfIDSources & faces, - const SMESH::DirStruct & stepVector, - CORBA::Long nbOfSteps, - const SMESH::double_array & theScaleFactors, - CORBA::Boolean theLinearVariation, - const SMESH::double_array & theBasePoint, - CORBA::Boolean toMakeGroups) + SMESH::ListOfGroups* ExtrusionSweepObjects(const SMESH::ListOfIDSources & Nodes, + const SMESH::ListOfIDSources & Edges, + const SMESH::ListOfIDSources & Faces, + const SMESH::DirStruct & StepVector, + CORBA::Long NbOfSteps, + CORBA::Boolean ToMakeGroups, + const SMESH::double_array & ScaleFactors, + CORBA::Boolean ScalesVariation, + const SMESH::double_array & BasePoint, + const SMESH::double_array & Angles, + CORBA::Boolean AnglesVariation) throw (SALOME::SALOME_Exception); SMESH::ListOfGroups* ExtrusionByNormal(const SMESH::ListOfIDSources& objects, @@ -360,18 +362,20 @@ public: throw (SALOME::SALOME_Exception); SMESH::ListOfGroups* - ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & nodes, - const SMESH::ListOfIDSources & edges, - const SMESH::ListOfIDSources & faces, + ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & Nodes, + const SMESH::ListOfIDSources & Edges, + const SMESH::ListOfIDSources & Faces, SMESH::SMESH_IDSource_ptr PathMesh, GEOM::GEOM_Object_ptr PathShape, CORBA::Long NodeStart, CORBA::Boolean HasAngles, const SMESH::double_array & Angles, - CORBA::Boolean LinearVariation, + CORBA::Boolean AnglesVariation, CORBA::Boolean HasRefPoint, const SMESH::PointStruct & RefPoint, bool MakeGroups, + const SMESH::double_array & ScaleFactors, + CORBA::Boolean ScalesVariation, SMESH::SMESH_MeshEditor::Extrusion_Error& Error) throw (SALOME::SALOME_Exception); diff --git a/src/SMESH_SWIG/smeshBuilder.py b/src/SMESH_SWIG/smeshBuilder.py index 20b7bc038..f3e83622c 100755 --- a/src/SMESH_SWIG/smeshBuilder.py +++ b/src/SMESH_SWIG/smeshBuilder.py @@ -752,26 +752,28 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ): """ if not meshes: return None - for i,m in enumerate(meshes): - if isinstance(m, Mesh): + if not isinstance( meshes, list ): + meshes = [ meshes ] + for i,m in enumerate( meshes ): + if isinstance( m, Mesh ): meshes[i] = m.GetMesh() - mergeTolerance,Parameters,hasVars = ParseParameters(mergeTolerance) + mergeTolerance,Parameters,hasVars = ParseParameters( mergeTolerance ) if hasattr(meshes[0], "SetParameters"): - meshes[0].SetParameters(Parameters) + meshes[0].SetParameters( Parameters ) else: - meshes[0].GetMesh().SetParameters(Parameters) + meshes[0].GetMesh().SetParameters( Parameters ) if isinstance( meshToAppendTo, Mesh ): meshToAppendTo = meshToAppendTo.GetMesh() if allGroups: aSmeshMesh = SMESH._objref_SMESH_Gen.ConcatenateWithGroups( self,meshes,uniteIdenticalGroups,mergeNodesAndElements, - mergeTolerance,meshToAppendTo) + mergeTolerance,meshToAppendTo ) else: aSmeshMesh = SMESH._objref_SMESH_Gen.Concatenate( self,meshes,uniteIdenticalGroups,mergeNodesAndElements, - mergeTolerance,meshToAppendTo) + mergeTolerance,meshToAppendTo ) - aMesh = Mesh(self, self.geompyD, aSmeshMesh, name=name) + aMesh = Mesh( self, self.geompyD, aSmeshMesh, name=name ) return aMesh def CopyMesh( self, meshPart, meshName, toCopyGroups=False, toKeepIDs=False): @@ -2501,6 +2503,25 @@ class Mesh(metaclass = MeshMeta): minor = -1 # invoke engine's function self.mesh.ExportMED(fileName, auto_groups, minor, overwrite, autoDimension) + return + + + def Append(self, meshes, uniteIdenticalGroups = True, + mergeNodesAndElements = False, mergeTolerance = 1e-5, allGroups = False): + """ + Append given meshes into this mesh. + All groups of input meshes will be created in this mesh. + + Parameters: + meshes: :class:`meshes, sub-meshes, groups or filters ` to append + uniteIdenticalGroups: if True, groups with same names are united, else they are renamed + mergeNodesAndElements: if True, equal nodes and elements are merged + mergeTolerance: tolerance for merging nodes + allGroups: forces creation of groups corresponding to every input mesh + """ + self.smeshpyD.Concatenate( meshes, uniteIdenticalGroups, + mergeNodesAndElements, mergeTolerance, allGroups, + meshToAppendTo = self.GetMesh() ) # Operations with groups: # ---------------------- @@ -5340,7 +5361,8 @@ class Mesh(metaclass = MeshMeta): NbOfSteps, Tolerance, MakeGroups, TotalAngle) def ExtrusionSweepObjects(self, nodes, edges, faces, StepVector, NbOfSteps, MakeGroups=False, - scaleFactors=[], linearVariation=False, basePoint=[] ): + scaleFactors=[], linearVariation=False, basePoint=[], + angles=[], anglesVariation=False): """ Generate new elements by extrusion of the given elements and nodes @@ -5354,15 +5376,19 @@ class Mesh(metaclass = MeshMeta): NbOfSteps: the number of steps MakeGroups: forces the generation of new groups from existing ones scaleFactors: optional scale factors to apply during extrusion - linearVariation: if *True*, scaleFactors are spread over all *scaleFactors*, - else scaleFactors[i] is applied to nodes at the i-th extrusion step - basePoint: optional scaling center; if not provided, a gravity center of + linearVariation: if *True*, *scaleFactors* are spread over all *NbOfSteps*, + else *scaleFactors* [i] is applied to nodes at the i-th extrusion step + basePoint: optional scaling and rotation center; if not provided, a gravity center of nodes and elements being extruded is used as the scaling center. It can be either - a list of tree components of the point or - a node ID or - a GEOM point + angles: list of angles in radians. Nodes at each extrusion step are rotated + around *basePoint*, additionally to previous steps. + anglesVariation: forces the computation of rotation angles as linear + variation of the given *angles* along path steps Returns: the list of created :class:`groups ` if *MakeGroups* == True, empty list otherwise @@ -5387,13 +5413,17 @@ class Mesh(metaclass = MeshMeta): basePoint = self.geompyD.PointCoordinates( basePoint ) NbOfSteps,Parameters,hasVars = ParseParameters(NbOfSteps) - Parameters = StepVector.PS.parameters + var_separator + Parameters + scaleFactors,scaleParameters,hasVars = ParseParameters(scaleFactors) + angles,angleParameters,hasVars = ParseAngles(angles) + Parameters = StepVector.PS.parameters + var_separator + \ + Parameters + var_separator + \ + scaleParameters + var_separator + angleParameters self.mesh.SetParameters(Parameters) return self.editor.ExtrusionSweepObjects( nodes, edges, faces, - StepVector, NbOfSteps, + StepVector, NbOfSteps, MakeGroups, scaleFactors, linearVariation, basePoint, - MakeGroups) + angles, anglesVariation ) def ExtrusionSweep(self, IDsOfElements, StepVector, NbOfSteps, MakeGroups=False, IsNodes = False): @@ -5555,9 +5585,10 @@ class Mesh(metaclass = MeshMeta): return self.editor.AdvancedExtrusion(IDsOfElements, StepVector, NbOfSteps, ExtrFlags, SewTolerance, MakeGroups) - def ExtrusionAlongPathObjects(self, Nodes, Edges, Faces, PathMesh, PathShape=None, + def ExtrusionAlongPathObjects(self, Nodes, Edges, Faces, PathObject, PathShape=None, NodeStart=1, HasAngles=False, Angles=[], LinearVariation=False, - HasRefPoint=False, RefPoint=[0,0,0], MakeGroups=False): + HasRefPoint=False, RefPoint=[0,0,0], MakeGroups=False, + ScaleFactors=[], ScalesVariation=False): """ Generate new elements by extrusion of the given elements and nodes along the path. The path of extrusion must be a meshed edge. @@ -5566,20 +5597,22 @@ class Mesh(metaclass = MeshMeta): Nodes: nodes to extrude: a list including ids, :class:`a mesh, sub-meshes, groups or filters ` Edges: edges to extrude: a list including ids, :class:`a mesh, sub-meshes, groups or filters ` Faces: faces to extrude: a list including ids, :class:`a mesh, sub-meshes, groups or filters ` - PathMesh: 1D mesh or 1D sub-mesh, along which proceeds the extrusion - PathShape: shape (edge) defines the sub-mesh of PathMesh if PathMesh - contains not only path segments, else it can be None + PathObject: :class:`mesh, sub-mesh, group or filter ` containing edges along which proceeds the extrusion + PathShape: optional shape (edge or wire) which defines the sub-mesh of the mesh defined by *PathObject* if the mesh contains not only path segments, else it can be None NodeStart: the first or the last node on the path. Defines the direction of extrusion - HasAngles: allows the shape to be rotated around the path - to get the resulting mesh in a helical fashion - Angles: list of angles + HasAngles: not used obsolete + Angles: list of angles in radians. Nodes at each extrusion step are rotated + around *basePoint*, additionally to previous steps. LinearVariation: forces the computation of rotation angles as linear variation of the given Angles along path steps HasRefPoint: allows using the reference point - RefPoint: the reference point around which the shape is rotated (the mass center of the - shape by default). The User can specify any point as the Reference Point. + RefPoint: optional scaling and rotation center (mass center of the extruded + elements by default). The User can specify any point as the Reference Point. *RefPoint* can be either GEOM Vertex, [x,y,z] or :class:`SMESH.PointStruct` MakeGroups: forces the generation of new groups from existing ones + ScaleFactors: optional scale factors to apply during extrusion + ScalesVariation: if *True*, *scaleFactors* are spread over all *NbOfSteps*, + else *scaleFactors* [i] is applied to nodes at the i-th extrusion step Returns: list of created :class:`groups ` and @@ -5597,15 +5630,18 @@ class Mesh(metaclass = MeshMeta): if isinstance( RefPoint, list ): if not RefPoint: RefPoint = [0,0,0] RefPoint = SMESH.PointStruct( *RefPoint ) - if isinstance( PathMesh, Mesh ): - PathMesh = PathMesh.GetMesh() + if isinstance( PathObject, Mesh ): + PathObject = PathObject.GetMesh() Angles,AnglesParameters,hasVars = ParseAngles(Angles) - Parameters = AnglesParameters + var_separator + RefPoint.parameters + ScaleFactors,ScalesParameters,hasVars = ParseParameters(ScaleFactors) + Parameters = AnglesParameters + var_separator + \ + RefPoint.parameters + var_separator + ScalesParameters self.mesh.SetParameters(Parameters) return self.editor.ExtrusionAlongPathObjects(Nodes, Edges, Faces, - PathMesh, PathShape, NodeStart, + PathObject, PathShape, NodeStart, HasAngles, Angles, LinearVariation, - HasRefPoint, RefPoint, MakeGroups) + HasRefPoint, RefPoint, MakeGroups, + ScaleFactors, ScalesVariation) def ExtrusionAlongPathX(self, Base, Path, NodeStart, HasAngles=False, Angles=[], LinearVariation=False, @@ -5619,9 +5655,9 @@ class Mesh(metaclass = MeshMeta): Base: :class:`mesh, sub-mesh, group, filter `, or list of ids of elements for extrusion Path: 1D mesh or 1D sub-mesh, along which proceeds the extrusion NodeStart: the start node from Path. Defines the direction of extrusion - HasAngles: allows the shape to be rotated around the path - to get the resulting mesh in a helical fashion - Angles: list of angles in radians + HasAngles: not used obsolete + Angles: list of angles in radians. Nodes at each extrusion step are rotated + around *basePoint*, additionally to previous steps. LinearVariation: forces the computation of rotation angles as linear variation of the given Angles along path steps HasRefPoint: allows using the reference point @@ -5662,9 +5698,9 @@ class Mesh(metaclass = MeshMeta): PathMesh: mesh containing a 1D sub-mesh on the edge, along which proceeds the extrusion PathShape: shape (edge) defines the sub-mesh for the path NodeStart: the first or the last node on the edge. Defines the direction of extrusion - HasAngles: allows the shape to be rotated around the path - to get the resulting mesh in a helical fashion - Angles: list of angles in radians + HasAngles: not used obsolete + Angles: list of angles in radians. Nodes at each extrusion step are rotated + around *basePoint*, additionally to previous steps. HasRefPoint: allows using the reference point RefPoint: the reference point around which the shape is rotated (the mass center of the shape by default). The User can specify any point as the Reference Point. @@ -5703,9 +5739,9 @@ class Mesh(metaclass = MeshMeta): PathMesh: mesh containing a 1D sub-mesh on the edge, along which the extrusion proceeds PathShape: shape (edge) defines the sub-mesh for the path NodeStart: the first or the last node on the edge. Defines the direction of extrusion - HasAngles: allows the shape to be rotated around the path - to get the resulting mesh in a helical fashion - Angles: list of angles + HasAngles: not used obsolete + Angles: list of angles in radians. Nodes at each extrusion step are rotated + around *basePoint*, additionally to previous steps. HasRefPoint: allows using the reference point RefPoint: the reference point around which the shape is rotated (the mass center of the shape by default). The User can specify any point as the Reference Point. @@ -5741,9 +5777,9 @@ class Mesh(metaclass = MeshMeta): PathMesh: mesh containing a 1D sub-mesh on the edge, along which the extrusion proceeds PathShape: shape (edge) defines the sub-mesh for the path NodeStart: the first or the last node on the edge. Defines the direction of extrusion - HasAngles: allows the shape to be rotated around the path - to get the resulting mesh in a helical fashion - Angles: list of angles + HasAngles: not used obsolete + Angles: list of angles in radians. Nodes at each extrusion step are rotated + around *basePoint*, additionally to previous steps. HasRefPoint: allows using the reference point RefPoint: the reference point around which the shape is rotated (the mass center of the shape by default). The User can specify any point as the Reference Point. @@ -5779,9 +5815,9 @@ class Mesh(metaclass = MeshMeta): PathMesh: mesh containing a 1D sub-mesh on the edge, along which the extrusion proceeds PathShape: shape (edge) defines the sub-mesh for the path NodeStart: the first or the last node on the edge. Defines the direction of extrusion - HasAngles: allows the shape to be rotated around the path - to get the resulting mesh in a helical fashion - Angles: list of angles + HasAngles: not used obsolete + Angles: list of angles in radians. Nodes at each extrusion step are rotated + around *basePoint*, additionally to previous steps. HasRefPoint: allows using the reference point RefPoint: the reference point around which the shape is rotated (the mass center of the shape by default). The User can specify any point as the Reference Point. diff --git a/src/StdMeshers/StdMeshers_FaceSide.cxx b/src/StdMeshers/StdMeshers_FaceSide.cxx index 0b6848622..2f312a6f4 100644 --- a/src/StdMeshers/StdMeshers_FaceSide.cxx +++ b/src/StdMeshers/StdMeshers_FaceSide.cxx @@ -32,10 +32,11 @@ #include "SMESHDS_Mesh.hxx" #include "SMESHDS_SubMesh.hxx" #include "SMESH_Algo.hxx" +#include "SMESH_Block.hxx" +#include "SMESH_ComputeError.hxx" #include "SMESH_Mesh.hxx" +#include "SMESH_MeshEditor.hxx" #include "SMESH_MesherHelper.hxx" -#include "SMESH_ComputeError.hxx" -#include "SMESH_Block.hxx" #include #include diff --git a/src/StdMeshers/StdMeshers_Import_1D.cxx b/src/StdMeshers/StdMeshers_Import_1D.cxx index a313cd6a3..0d8466ccc 100644 --- a/src/StdMeshers/StdMeshers_Import_1D.cxx +++ b/src/StdMeshers/StdMeshers_Import_1D.cxx @@ -36,6 +36,7 @@ #include "SMESH_Group.hxx" #include "SMESH_HypoFilter.hxx" #include "SMESH_Mesh.hxx" +#include "SMESH_MeshEditor.hxx" #include "SMESH_MesherHelper.hxx" #include "SMESH_subMesh.hxx" #include "SMESH_subMeshEventListener.hxx" diff --git a/src/StdMeshers/StdMeshers_Import_1D2D.cxx b/src/StdMeshers/StdMeshers_Import_1D2D.cxx index f0d4925c8..1ab0f6753 100644 --- a/src/StdMeshers/StdMeshers_Import_1D2D.cxx +++ b/src/StdMeshers/StdMeshers_Import_1D2D.cxx @@ -40,6 +40,7 @@ #include "SMESH_Mesh.hxx" #include "SMESH_MesherHelper.hxx" #include "SMESH_OctreeNode.hxx" +#include "SMESH_MeshEditor.hxx" #include "SMESH_subMesh.hxx" #include "Utils_SALOME_Exception.hxx" diff --git a/src/StdMeshers/StdMeshers_Prism_3D.cxx b/src/StdMeshers/StdMeshers_Prism_3D.cxx index 4c82b5271..cb11b0613 100644 --- a/src/StdMeshers/StdMeshers_Prism_3D.cxx +++ b/src/StdMeshers/StdMeshers_Prism_3D.cxx @@ -33,6 +33,7 @@ #include "SMESH_Comment.hxx" #include "SMESH_Gen.hxx" #include "SMESH_HypoFilter.hxx" +#include "SMESH_MeshEditor.hxx" #include "SMESH_MesherHelper.hxx" #include "StdMeshers_FaceSide.hxx" #include "StdMeshers_ProjectionSource1D.hxx" diff --git a/src/StdMeshers/StdMeshers_ProjectionUtils.cxx b/src/StdMeshers/StdMeshers_ProjectionUtils.cxx index 9425e9a17..ec175baf0 100644 --- a/src/StdMeshers/StdMeshers_ProjectionUtils.cxx +++ b/src/StdMeshers/StdMeshers_ProjectionUtils.cxx @@ -37,6 +37,7 @@ #include "SMESH_Hypothesis.hxx" #include "SMESH_Mesh.hxx" #include "SMESH_MeshAlgos.hxx" +#include "SMESH_MeshEditor.hxx" #include "SMESH_MesherHelper.hxx" #include "SMESH_subMesh.hxx" #include "SMESH_subMeshEventListener.hxx" diff --git a/src/StdMeshers/StdMeshers_Projection_2D.cxx b/src/StdMeshers/StdMeshers_Projection_2D.cxx index d9b01603c..79fb6f05e 100644 --- a/src/StdMeshers/StdMeshers_Projection_2D.cxx +++ b/src/StdMeshers/StdMeshers_Projection_2D.cxx @@ -42,6 +42,7 @@ #include "SMESH_Gen.hxx" #include "SMESH_Mesh.hxx" #include "SMESH_MeshAlgos.hxx" +#include "SMESH_MeshEditor.hxx" #include "SMESH_MesherHelper.hxx" #include "SMESH_Pattern.hxx" #include "SMESH_subMesh.hxx" diff --git a/src/StdMeshers/StdMeshers_SegmentLengthAroundVertex.cxx b/src/StdMeshers/StdMeshers_SegmentLengthAroundVertex.cxx index e221883ec..0ccb2aa87 100644 --- a/src/StdMeshers/StdMeshers_SegmentLengthAroundVertex.cxx +++ b/src/StdMeshers/StdMeshers_SegmentLengthAroundVertex.cxx @@ -31,6 +31,7 @@ #include "SMDS_MeshNode.hxx" #include "SMESHDS_Mesh.hxx" #include "SMESHDS_SubMesh.hxx" +#include "SMESH_MeshEditor.hxx" #include "SMESH_MesherHelper.hxx" #include "utilities.h" diff --git a/src/StdMeshers/StdMeshers_ViscousLayers.cxx b/src/StdMeshers/StdMeshers_ViscousLayers.cxx index a384191b2..62488c6d6 100644 --- a/src/StdMeshers/StdMeshers_ViscousLayers.cxx +++ b/src/StdMeshers/StdMeshers_ViscousLayers.cxx @@ -43,6 +43,7 @@ #include "SMESH_MesherHelper.hxx" #include "SMESH_ProxyMesh.hxx" #include "SMESH_subMesh.hxx" +#include "SMESH_MeshEditor.hxx" #include "SMESH_subMeshEventListener.hxx" #include "StdMeshers_FaceSide.hxx" #include "StdMeshers_ViscousLayers2D.hxx" diff --git a/src/StdMeshers/StdMeshers_ViscousLayers2D.cxx b/src/StdMeshers/StdMeshers_ViscousLayers2D.cxx index f759c4ba0..53118b73f 100644 --- a/src/StdMeshers/StdMeshers_ViscousLayers2D.cxx +++ b/src/StdMeshers/StdMeshers_ViscousLayers2D.cxx @@ -38,6 +38,7 @@ #include "SMESH_Group.hxx" #include "SMESH_HypoFilter.hxx" #include "SMESH_Mesh.hxx" +#include "SMESH_MeshEditor.hxx" #include "SMESH_MesherHelper.hxx" #include "SMESH_ProxyMesh.hxx" #include "SMESH_Quadtree.hxx" -- 2.39.2