# Add Node
-
import salome
salome.salome_init()
-import GEOM
-from salome.geom import geomBuilder
-geompy = geomBuilder.New(salome.myStudy)
-import SMESH, SALOMEDS
from salome.smesh import smeshBuilder
smesh = smeshBuilder.New(salome.myStudy)
-import salome_notebook
mesh = smesh.Mesh()
# Add 0D Element
-
import salome
salome.salome_init()
-import GEOM
-from salome.geom import geomBuilder
-geompy = geomBuilder.New(salome.myStudy)
-import SMESH, SALOMEDS
from salome.smesh import smeshBuilder
smesh = smeshBuilder.New(salome.myStudy)
-import salome_notebook
mesh = smesh.Mesh()
import salome
salome.salome_init()
-import GEOM
+
from salome.geom import geomBuilder
geompy = geomBuilder.New(salome.myStudy)
import SMESH, SALOMEDS
from salome.smesh import smeshBuilder
smesh = smeshBuilder.New(salome.myStudy)
-import salome_notebook
# create a geometry
import salome
salome.salome_init()
-import GEOM
-from salome.geom import geomBuilder
-geompy = geomBuilder.New(salome.myStudy)
import SMESH, SALOMEDS
from salome.smesh import smeshBuilder
smesh = smeshBuilder.New(salome.myStudy)
-import salome_notebook
# create an empty mesh structure
import salome
salome.salome_init()
-import GEOM
-from salome.geom import geomBuilder
-geompy = geomBuilder.New(salome.myStudy)
-import SMESH, SALOMEDS
from salome.smesh import smeshBuilder
smesh = smeshBuilder.New(salome.myStudy)
-import salome_notebook
import math
pass
# Create a polyhedral volume (12-hedron with pentagonal faces)
-mesh.GetMeshEditor().AddPolyhedralVolume([dd[0], dd[1], dd[2], dd[3], dd[4], # top
- dd[0], cc[0], bb[1], cc[1], dd[1], # -
- dd[1], cc[1], bb[2], cc[2], dd[2], # -
- dd[2], cc[2], bb[3], cc[3], dd[3], # - below top
- dd[3], cc[3], bb[4], cc[4], dd[4], # -
- dd[4], cc[4], bb[0], cc[0], dd[0], # -
- aa[4], bb[4], cc[4], bb[0], aa[0], # .
- aa[3], bb[3], cc[3], bb[4], aa[4], # .
- aa[2], bb[2], cc[2], bb[3], aa[3], # . above bottom
- aa[1], bb[1], cc[1], bb[2], aa[2], # .
- aa[0], bb[0], cc[0], bb[1], aa[1], # .
- aa[0], aa[1], aa[2], aa[3], aa[4]], # bottom
- [5,5,5,5,5,5,5,5,5,5,5,5])
-
-salome.sg.updateObjBrowser(1)
+mesh.AddPolyhedralVolume([dd[0], dd[1], dd[2], dd[3], dd[4], # top
+ dd[0], cc[0], bb[1], cc[1], dd[1], # -
+ dd[1], cc[1], bb[2], cc[2], dd[2], # -
+ dd[2], cc[2], bb[3], cc[3], dd[3], # - below top
+ dd[3], cc[3], bb[4], cc[4], dd[4], # -
+ dd[4], cc[4], bb[0], cc[0], dd[0], # -
+ aa[4], bb[4], cc[4], bb[0], aa[0], # .
+ aa[3], bb[3], cc[3], bb[4], aa[4], # .
+ aa[2], bb[2], cc[2], bb[3], aa[3], # . above bottom
+ aa[1], bb[1], cc[1], bb[2], aa[2], # .
+ aa[0], bb[0], cc[0], bb[1], aa[1], # .
+ aa[0], aa[1], aa[2], aa[3], aa[4]], # bottom
+ [5,5,5,5,5,5,5,5,5,5,5,5])
+
+if salome.sg.hasDesktop():
+ salome.sg.updateObjBrowser(1)
import salome
salome.salome_init()
-import GEOM
+
from salome.geom import geomBuilder
geompy = geomBuilder.New(salome.myStudy)
import SMESH, SALOMEDS
from salome.smesh import smeshBuilder
smesh = smeshBuilder.New(salome.myStudy)
-import salome_notebook
box = geompy.MakeBoxDXDYDZ(200, 200, 200)
mesh.Quadrangle()
mesh.Compute()
-# find node at (0,0,0)
+# find node at (0,0,0) which is located on a geom vertex
node000 = None
for vId in geompy.SubShapeAllIDs( box, geompy.ShapeType["VERTEX"]):
if node000: break
if not node000:
raise "node000 not found"
-# find node000 using the tested function
+# find node000 using a dedicated function
n = mesh.FindNodeClosestTo( -1,-1,-1 )
if not n == node000:
raise "FindNodeClosestTo() returns " + str( n ) + " != " + str( node000 )
\page display_mode_page Display Mode
-\n By default your objects are represented as set in \b Preferences.
+\n By default your objects are represented as set in
+\ref mesh_preferences_page "Preferences".
\n However, right-clicking on the mesh in the <b>Object Browser</b>,
and selecting <b>Display Mode</b>, you can display your mesh as:
\image html image55.gif Shrink
-*/
\ No newline at end of file
+*/
If you try to export a group, the warning will be shown:
\image html meshexportgroupwarning.png
<ul>
- <li><b>Don't show this warning anymore</b> check-box specifies show or
- not the warning. If checked, the warning will not be shown anymore in
- the similar situation </li>
+ <li><b>Don't show this warning anymore</b> check-box allows to
+ switch off the warning. You can re-activate the warning in
+ \ref group_export_warning_pref "Preferences".</li>
</ul>
There are additional parameters available at export to MED and SAUV format files.
<ul>
- <li><b>Automatically create groups</b> check-box specifies whether to
+ <li>
+\anchor export_auto_groups
+ <b>Automatically create groups</b> check-box specifies whether to
create groups of all mesh entities of available dimensions or
- not. If checked, the created groups have names like "Group_On_All_Nodes",
- "Group_On_All_Faces", etc.</li>
+ not. The created groups have names like "Group_On_All_Nodes",
+ "Group_On_All_Faces", etc. A default state of this check-box can be
+ set in \ref export_auto_groups_pref "Preferences". </li>
<li><b>Automatically define space dimension</b> check-box specifies
whether to define space dimension for export by mesh configuration
or not. Usually the mesh is exported as a mesh in 3D space, just as
\image html pref21.png
- <b>Automatic Update</b>
- - If you toggle <b>Automatic Update</b> checkbox, the model in your
- viewer will be automatically updated when you make changes in it, depending on
+ - <b>Automatic Update</b> - if activated, the mesh in your
+ viewer will be automatically updated after it's computation, depending on
values of additional preferences specified below.
- <b>Size limit (elements)</b> - allows specifying the maximum
number of elements in the resulting mesh for which the automatic updating
of the presentation is performed. This option affects only
- <b>Compute</b> operation. Zero value means "no limit". Default value
- is 500 000 mesh elements.
- - <b>Incremental limit check</b> - when this control is switched on,
+ \ref compute_anchor "Compute" operation. Zero value means "no
+ limit". Default value is 500 000 mesh elements.
+ - <b>Incremental limit check</b> - if activated,
the mesh size limit check is not applied to the total number of
elements in the resulting mesh, it is applied iteratively to each entity type
in the following order: 0D elements, edges, faces, volumes, balls.
this type are shown, otherwise the user is warned that some entities are not shown.
- <b>Quality Controls</b>
- - If you toggle <b>Display entity</b>, both faces and edges of an
- object will be displayed in the viewer by default.
- - If you toggle <b>Use precision</b> checkbox, you can display numbers in
- <b>Quality Control</b> diagrams at the necessary level of precision.
- - <b>Number of digits after point</b> - defines precision for
- <b>Quality Controls</b>. By default, numbers in <b>Quality Control</b>
- diagrams are presented as integers.
- - <b>Double nodes tolerance</b> defines the maximal distance between two
- mesh nodes, at which they are considered coincident by <b>Double nodes</b>
- quality control.
+ - <b>Display entity</b> - if activated, only currently
+ \ref quality_page "controlled" entities are displayed in the
+ viewer and other entities are temporarily hidden. For example if you
+ activate \ref length_page "Length" quality control, which controls
+ the length of mesh segments, then only mesh segments are
+ displayed and faces and volumes are hidden.
+ - <b>Use precision</b> - if activated, all quality controls
+ will be computed at precision defined by <b>Number of digits after
+ point</b> - as integers by default.
+ - <b>Double nodes tolerance</b> - defines the maximal distance between two
+ mesh nodes, at which they are considered coincident by
+ \ref double_nodes_control_page "Double nodes" quality control.
- <b>Display mode</b>
- <b>Default display mode</b> - allows to set Wireframe, Shading, Nodes or Shrink
- presentation mode as default.
+ \ref display_mode_page "presentation mode" as default.
+\anchor quadratic_2d_mode_pref
- <b>Representation of the 2D quadratic elements</b>
- - <b>Default mode of the 2D quadratic elements</b> combo-box - allows
- to select lines or arcs for representation of quadratic elements as default.
+ - <b>Default mode of the 2D quadratic elements</b> - allows to
+ select either \a Lines or \a Arcs as a default
+ \ref quadratic_2d_mode "representation" of 1D and 2D
+ \ref adding_quadratic_elements_page "quadratic elements".
- <b>Maximum Angle</b> - maximum deviation angle used by the
application to build arcs.
- <b>Mesh export</b>
- - If you toggle <b>Automatically create groups for MED export</b> check-box,
- this operation will be carried out automatically.
- - <b>Show warning when exporting group</b> check-box - allows defining the
- behavior of the warning when exporting a group.
+\anchor export_auto_groups_pref
+ - <b>Automatically create groups for MED export</b> - defines a
+ default state of a corresponding check-box in \ref export_auto_groups
+ "MED Export" dialog.
+\anchor group_export_warning_pref
+ - <b>Show warning when exporting group</b> - if activated, a warning is
+ displayed when exporting a group.
- <b>Mesh computation</b>
- <b>Show a computation result notification</b> combo-box allows to
<h3>Removing Orphan Nodes</h3>
\tui_script{modifying_meshes_ex13.py}
-<br>
-\section tui_renumbering_nodes_and_elements Renumbering Nodes and Elements
-\tui_script{modifying_meshes_ex14.py}
-
<br>
\section tui_moving_nodes Moving Nodes
\tui_script{modifying_meshes_ex15.py}
<li>\subpage display_mode_page "Display Mode" - allows to select between
Wireframe, Shading and Nodes presentation.</li>
<li>\subpage display_entity_page "Display Entity" - allows to display
-entities by types (Faces, Edges, Volumes etc.).</li>
+ entities by types (Faces, Edges, Volumes etc.).</li>
+\anchor quadratic_2d_mode
<li><b>2D Quadratic</b> - allows to select between the representation
-of quadratic edges as broken <b>lines</b> or as <b>arcs</b></li>
+ of quadratic edges as broken \b lines or as \b arcs. A default
+ representation can be set in \ref quadratic_2d_mode_pref "Preferences".
+ Arc representation applies to 1D and 2D elements only.
+</li>
<li><b>Orientation of faces</b> - shows vectors of orientation of
faces of the selected mesh. The orientation vector is shown for each 2D mesh element
and for each free face of a 3D mesh element. the vector direction is calculated by
#include "utilities.h"
+using SMESHUtils::ControlPnt;
+
extern "C"
{
#include "libmesh5.h"
}}}}
-Control_Pnt::Control_Pnt(): gp_Pnt()
-{
- size=0;
-}
-Control_Pnt::Control_Pnt( const gp_Pnt& aPnt,
- double theSize): gp_Pnt( aPnt )
-{
- size=theSize;
-}
-Control_Pnt::Control_Pnt(double theX,
- double theY,
- double theZ): gp_Pnt(theX, theY, theZ)
-{
- size=0;
-}
-Control_Pnt::Control_Pnt(double theX,
- double theY,
- double theZ,
- double theSize): gp_Pnt(theX, theY, theZ)
-{
- size=theSize;
-}
-
DriverGMF_Write::DriverGMF_Write():
Driver_SMESHDS_Mesh(), _exportRequiredGroups( true )
{
return DRS_OK;
}
-Driver_Mesh::Status DriverGMF_Write::PerformSizeMap( const std::vector<Control_Pnt>& points )
+Driver_Mesh::Status DriverGMF_Write::PerformSizeMap( const std::vector<ControlPnt>& points )
{
// const int dim = 3, version = sizeof(long) == 4 ? 2 : 3;
const int dim = 3, version = 2; // Version 3 not supported by mg-hexa
GmfSetKwd(solFileID, GmfSolAtVertices, pointsNumber, 1, TypTab);
// Read the control points information from the vector and write it into the files
- std::vector<Control_Pnt>::const_iterator points_it;
+ std::vector<ControlPnt>::const_iterator points_it;
for (points_it = points.begin(); points_it != points.end(); points_it++ )
{
GmfSetLin( verticesFileID, GmfVertices, points_it->X(), points_it->Y(), points_it->Z(), 0 );
#include "Driver_SMESHDS_Mesh.h"
#include "SMDSAbs_ElementType.hxx"
#include "SMDS_ElemIterator.hxx"
-
-#include <gp_Pnt.hxx>
-
-/*!
- * \brief Class for storing control points for writing GMF size maps
- */
-class MESHDriverGMF_EXPORT Control_Pnt : public gp_Pnt
-{
-public:
- Control_Pnt();
- Control_Pnt(const gp_Pnt& aPnt, double theSize);
- Control_Pnt(double x, double y, double z);
- Control_Pnt(double x, double y, double z, double size);
-
- double Size() const { return size; };
- void SetSize( double theSize ) { size = theSize; };
-
-private:
- double size;
-};
+#include "SMESH_ControlPnt.hxx"
/*!
* \brief Driver Writing a mesh into a GMF file.
virtual Status Perform();
// Size Maps
- Status PerformSizeMap( const std::vector<Control_Pnt>& points );
+ Status PerformSizeMap( const std::vector<SMESHUtils::ControlPnt>& points );
void SetSizeMapPrefix( std::string prefix )
{
myVerticesFile = prefix + ".mesh";
template< class VECT > // interlacedIDs[i] = smdsIDs[ indices[ i ]]
static void applyInterlace( const std::vector<int>& interlace, VECT & data)
{
- if ( interlace.empty() ) return;
+ if ( interlace.size() < data.size() ) return;
VECT tmpData( data.size() );
for ( size_t i = 0; i < data.size(); ++i )
tmpData[i] = data[ interlace[i] ];
template< class VECT > // interlacedIDs[ indices[ i ]] = smdsIDs[i]
static void applyInterlaceRev( const std::vector<int>& interlace, VECT & data)
{
- if ( interlace.empty() ) return;
+ if ( interlace.size() < data.size() ) return;
VECT tmpData( data.size() );
for ( size_t i = 0; i < data.size(); ++i )
tmpData[ interlace[i] ] = data[i];
if (ReverseOrDulicate && ReverseOrDulicate->isChecked())
{
const std::vector<int>& i = SMDS_MeshCell::reverseSmdsOrder( myGeomType );
- if ( i.empty() ) // polygon
+ if ( i.size() != anIds.size() ) // polygon
std::reverse( anIds.begin(), anIds.end() );
else
SMDS_MeshCell::applyInterlace( i, anIds );
SMESH_TryCatch.hxx
SMESH_MeshAlgos.hxx
SMESH_MAT2d.hxx
+ SMESH_ControlPnt.hxx
)
# --- sources ---
SMESH_MeshAlgos.cxx
SMESH_MAT2d.cxx
SMESH_FreeBorders.cxx
+ SMESH_ControlPnt.cxx
)
# --- rules ---
--- /dev/null
+// Copyright (C) 2007-2016 CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// Author : Lioka RAZAFINDRAZAKA (CEA)
+
+#include "SMESH_ControlPnt.hxx"
+
+#include <BRepBndLib.hxx>
+#include <BRepMesh_IncrementalMesh.hxx>
+#include <BRep_Tool.hxx>
+#include <Bnd_Box.hxx>
+#include <GCPnts_UniformAbscissa.hxx>
+#include <GeomAdaptor_Curve.hxx>
+#include <Geom_Curve.hxx>
+#include <IntCurvesFace_Intersector.hxx>
+#include <Poly_Array1OfTriangle.hxx>
+#include <Poly_Triangle.hxx>
+#include <Poly_Triangulation.hxx>
+#include <Precision.hxx>
+#include <TColgp_Array1OfPnt.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopLoc_Location.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS_Iterator.hxx>
+#include <TopoDS_Solid.hxx>
+#include <gp_Ax3.hxx>
+#include <gp_Dir.hxx>
+#include <gp_Lin.hxx>
+#include <gp_Trsf.hxx>
+#include <gp_Vec.hxx>
+
+#include <set>
+
+namespace SMESHUtils
+{
+ // Some functions for surface sampling
+ void subdivideTriangle( const gp_Pnt& p1,
+ const gp_Pnt& p2,
+ const gp_Pnt& p3,
+ const double& theSize,
+ std::vector<ControlPnt>& thePoints );
+
+ std::vector<gp_Pnt> computePointsForSplitting( const gp_Pnt& p1,
+ const gp_Pnt& p2,
+ const gp_Pnt& p3 );
+ gp_Pnt tangencyPoint(const gp_Pnt& p1,
+ const gp_Pnt& p2,
+ const gp_Pnt& Center);
+
+}
+
+//================================================================================
+/*!
+ * \brief Fills a vector of points from which a size map input file can be written
+ */
+//================================================================================
+
+void SMESHUtils::createControlPoints( const TopoDS_Shape& theShape,
+ const double& theSize,
+ std::vector<ControlPnt>& thePoints )
+{
+ if ( theShape.ShapeType() == TopAbs_VERTEX )
+ {
+ gp_Pnt aPnt = BRep_Tool::Pnt( TopoDS::Vertex(theShape) );
+ ControlPnt aControlPnt( aPnt, theSize );
+ thePoints.push_back( aControlPnt );
+ }
+ if ( theShape.ShapeType() == TopAbs_EDGE )
+ {
+ createPointsSampleFromEdge( TopoDS::Edge( theShape ), theSize, thePoints );
+ }
+ else if ( theShape.ShapeType() == TopAbs_WIRE )
+ {
+ TopExp_Explorer Ex;
+ for (Ex.Init(theShape,TopAbs_EDGE); Ex.More(); Ex.Next())
+ {
+ createPointsSampleFromEdge( TopoDS::Edge( Ex.Current() ), theSize, thePoints );
+ }
+ }
+ else if ( theShape.ShapeType() == TopAbs_FACE )
+ {
+ createPointsSampleFromFace( TopoDS::Face( theShape ), theSize, thePoints );
+ }
+ else if ( theShape.ShapeType() == TopAbs_SOLID )
+ {
+ createPointsSampleFromSolid( TopoDS::Solid( theShape ), theSize, thePoints );
+ }
+ else if ( theShape.ShapeType() == TopAbs_COMPOUND )
+ {
+ TopoDS_Iterator it( theShape );
+ for(; it.More(); it.Next())
+ {
+ createControlPoints( it.Value(), theSize, thePoints );
+ }
+ }
+}
+
+//================================================================================
+/*!
+ * \brief Fills a vector of points with point samples approximately
+ * \brief spaced with a given size
+ */
+//================================================================================
+
+void SMESHUtils::createPointsSampleFromEdge( const TopoDS_Edge& theEdge,
+ const double& theSize,
+ std::vector<ControlPnt>& thePoints )
+{
+ double step = theSize;
+ double first, last;
+ Handle( Geom_Curve ) aCurve = BRep_Tool::Curve( theEdge, first, last );
+ GeomAdaptor_Curve C ( aCurve );
+ GCPnts_UniformAbscissa DiscretisationAlgo(C, step , first, last, Precision::Confusion());
+ int nbPoints = DiscretisationAlgo.NbPoints();
+
+ ControlPnt aPnt;
+ aPnt.SetSize(theSize);
+
+ for ( int i = 1; i <= nbPoints; i++ )
+ {
+ double param = DiscretisationAlgo.Parameter( i );
+ aCurve->D0( param, aPnt );
+ thePoints.push_back( aPnt );
+ }
+}
+
+//================================================================================
+/*!
+ * \brief Fills a vector of points with point samples approximately
+ * \brief spaced with a given size
+ */
+//================================================================================
+
+void SMESHUtils::createPointsSampleFromFace( const TopoDS_Face& theFace,
+ const double& theSize,
+ std::vector<ControlPnt>& thePoints )
+{
+ BRepMesh_IncrementalMesh M(theFace, 0.01, Standard_True);
+ TopLoc_Location aLocation;
+
+ // Triangulate the face
+ Handle(Poly_Triangulation) aTri = BRep_Tool::Triangulation (theFace, aLocation);
+
+ // Get the transformation associated to the face location
+ gp_Trsf aTrsf = aLocation.Transformation();
+
+ // Get triangles
+ int nbTriangles = aTri->NbTriangles();
+ Poly_Array1OfTriangle triangles(1,nbTriangles);
+ triangles=aTri->Triangles();
+
+ // GetNodes
+ int nbNodes = aTri->NbNodes();
+ TColgp_Array1OfPnt nodes(1,nbNodes);
+ nodes = aTri->Nodes();
+
+ // Iterate on triangles and subdivide them
+ for(int i=1; i<=nbTriangles; i++)
+ {
+ Poly_Triangle aTriangle = triangles.Value(i);
+ gp_Pnt p1 = nodes.Value(aTriangle.Value(1));
+ gp_Pnt p2 = nodes.Value(aTriangle.Value(2));
+ gp_Pnt p3 = nodes.Value(aTriangle.Value(3));
+
+ p1.Transform(aTrsf);
+ p2.Transform(aTrsf);
+ p3.Transform(aTrsf);
+
+ subdivideTriangle(p1, p2, p3, theSize, thePoints);
+ }
+}
+
+//================================================================================
+/*!
+ * \brief Fills a vector of points with point samples approximately
+ * \brief spaced with a given size
+ */
+//================================================================================
+
+void SMESHUtils::createPointsSampleFromSolid( const TopoDS_Solid& theSolid,
+ const double& theSize,
+ std::vector<ControlPnt>& thePoints )
+{
+ // Compute the bounding box
+ double Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
+ Bnd_Box B;
+ BRepBndLib::Add(theSolid, B);
+ B.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
+
+ // Create the points
+ double step = theSize;
+
+ for ( double x=Xmin; x-Xmax<Precision::Confusion(); x=x+step )
+ {
+ for ( double y=Ymin; y-Ymax<Precision::Confusion(); y=y+step )
+ {
+ // Step1 : generate the Zmin -> Zmax line
+ gp_Pnt startPnt(x, y, Zmin);
+ gp_Pnt endPnt(x, y, Zmax);
+ gp_Vec aVec(startPnt, endPnt);
+ gp_Lin aLine(startPnt, aVec);
+ double endParam = Zmax - Zmin;
+
+ // Step2 : for each face of theSolid:
+ std::set<double> intersections;
+ std::set<double>::iterator it = intersections.begin();
+
+ TopExp_Explorer Ex;
+ for (Ex.Init(theSolid,TopAbs_FACE); Ex.More(); Ex.Next())
+ {
+ // check if there is an intersection
+ IntCurvesFace_Intersector anIntersector(TopoDS::Face(Ex.Current()), Precision::Confusion());
+ anIntersector.Perform(aLine, 0, endParam);
+
+ // get the intersection's parameter and store it
+ int nbPoints = anIntersector.NbPnt();
+ for(int i = 0 ; i < nbPoints ; i++ )
+ {
+ it = intersections.insert( it, anIntersector.WParameter(i+1) );
+ }
+ }
+ // Step3 : go through the line chunk by chunk
+ if ( intersections.begin() != intersections.end() )
+ {
+ std::set<double>::iterator intersectionsIterator=intersections.begin();
+ double first = *intersectionsIterator;
+ intersectionsIterator++;
+ bool innerPoints = true;
+ for ( ; intersectionsIterator!=intersections.end() ; intersectionsIterator++ )
+ {
+ double second = *intersectionsIterator;
+ if ( innerPoints )
+ {
+ // If the last chunk was outside of the shape or this is the first chunk
+ // add the points in the range [first, second] to the points vector
+ double localStep = (second -first) / ceil( (second - first) / step );
+ for ( double z = Zmin + first; z < Zmin + second; z = z + localStep )
+ {
+ thePoints.push_back(ControlPnt( x, y, z, theSize ));
+ }
+ thePoints.push_back(ControlPnt( x, y, Zmin + second, theSize ));
+ }
+ first = second;
+ innerPoints = !innerPoints;
+ }
+ }
+ }
+ }
+}
+
+//================================================================================
+/*!
+ * \brief Subdivides a triangle until it reaches a certain size (recursive function)
+ */
+//================================================================================
+
+void SMESHUtils::subdivideTriangle( const gp_Pnt& p1,
+ const gp_Pnt& p2,
+ const gp_Pnt& p3,
+ const double& theSize,
+ std::vector<ControlPnt>& thePoints)
+{
+ // Size threshold to stop subdividing
+ // This value ensures that two control points are distant no more than 2*theSize
+ // as shown below
+ //
+ // The greater distance D of the mass center M to each Edge is 1/3 * Median
+ // and Median < sqrt(3/4) * a where a is the greater side (by using Apollonius' thorem).
+ // So D < 1/3 * sqrt(3/4) * a and if a < sqrt(3) * S then D < S/2
+ // and the distance between two mass centers of two neighbouring triangles
+ // sharing an edge is < 2 * 1/2 * S = S
+ // If the traingles share a Vertex and no Edge the distance of the mass centers
+ // to the Vertices is 2*D < S so the mass centers are distant of less than 2*S
+
+ double threshold = sqrt( 3. ) * theSize;
+
+ if ( (p1.Distance(p2) > threshold ||
+ p2.Distance(p3) > threshold ||
+ p3.Distance(p1) > threshold))
+ {
+ std::vector<gp_Pnt> midPoints = computePointsForSplitting(p1, p2, p3);
+
+ subdivideTriangle( midPoints[0], midPoints[1], midPoints[2], theSize, thePoints );
+ subdivideTriangle( midPoints[0], p2, midPoints[1], theSize, thePoints );
+ subdivideTriangle( midPoints[2], midPoints[1], p3, theSize, thePoints );
+ subdivideTriangle( p1, midPoints[0], midPoints[2], theSize, thePoints );
+ }
+ else
+ {
+ double x = (p1.X() + p2.X() + p3.X()) / 3 ;
+ double y = (p1.Y() + p2.Y() + p3.Y()) / 3 ;
+ double z = (p1.Z() + p2.Z() + p3.Z()) / 3 ;
+
+ ControlPnt massCenter( x ,y ,z, theSize );
+ thePoints.push_back( massCenter );
+ }
+}
+
+//================================================================================
+/*!
+ * \brief Returns the appropriate points for splitting a triangle
+ * \brief the tangency points of the incircle are used in order to have mostly
+ * \brief well-shaped sub-triangles
+ */
+//================================================================================
+
+std::vector<gp_Pnt> SMESHUtils::computePointsForSplitting( const gp_Pnt& p1,
+ const gp_Pnt& p2,
+ const gp_Pnt& p3 )
+{
+ std::vector<gp_Pnt> midPoints;
+ //Change coordinates
+ gp_Trsf Trsf_1; // Identity transformation
+ gp_Ax3 reference_system(gp::Origin(), gp::DZ(), gp::DX()); // OXY
+
+ gp_Vec Vx(p1, p3);
+ gp_Vec Vaux(p1, p2);
+ gp_Dir Dx(Vx);
+ gp_Dir Daux(Vaux);
+ gp_Dir Dz = Dx.Crossed(Daux);
+ gp_Ax3 current_system(p1, Dz, Dx);
+
+ Trsf_1.SetTransformation( reference_system, current_system );
+
+ gp_Pnt A = p1.Transformed(Trsf_1);
+ gp_Pnt B = p2.Transformed(Trsf_1);
+ gp_Pnt C = p3.Transformed(Trsf_1);
+
+ double a = B.Distance(C) ;
+ double b = A.Distance(C) ;
+ double c = B.Distance(A) ;
+
+ // Incenter coordinates
+ // see http://mathworld.wolfram.com/Incenter.html
+ double Xi = ( b*B.X() + c*C.X() ) / ( a + b + c );
+ double Yi = ( b*B.Y() ) / ( a + b + c );
+ gp_Pnt Center(Xi, Yi, 0);
+
+ // Calculate the tangency points of the incircle
+ gp_Pnt T1 = tangencyPoint( A, B, Center);
+ gp_Pnt T2 = tangencyPoint( B, C, Center);
+ gp_Pnt T3 = tangencyPoint( C, A, Center);
+
+ gp_Pnt p1_2 = T1.Transformed(Trsf_1.Inverted());
+ gp_Pnt p2_3 = T2.Transformed(Trsf_1.Inverted());
+ gp_Pnt p3_1 = T3.Transformed(Trsf_1.Inverted());
+
+ midPoints.push_back(p1_2);
+ midPoints.push_back(p2_3);
+ midPoints.push_back(p3_1);
+
+ return midPoints;
+}
+
+//================================================================================
+/*!
+ * \brief Computes the tangency points of the circle of center Center with
+ * \brief the straight line (p1 p2)
+ */
+//================================================================================
+
+gp_Pnt SMESHUtils::tangencyPoint(const gp_Pnt& p1,
+ const gp_Pnt& p2,
+ const gp_Pnt& Center)
+{
+ double Xt = 0;
+ double Yt = 0;
+
+ // The tangency point is the intersection of the straight line (p1 p2)
+ // and the straight line (Center T) which is orthogonal to (p1 p2)
+ if ( fabs(p1.X() - p2.X()) <= Precision::Confusion() )
+ {
+ Xt=p1.X(); // T is on (p1 p2)
+ Yt=Center.Y(); // (Center T) is orthogonal to (p1 p2)
+ }
+ else if ( fabs(p1.Y() - p2.Y()) <= Precision::Confusion() )
+ {
+ Yt=p1.Y(); // T is on (p1 p2)
+ Xt=Center.X(); // (Center T) is orthogonal to (p1 p2)
+ }
+ else
+ {
+ // First straight line coefficients (equation y=a*x+b)
+ double a = (p2.Y() - p1.Y()) / (p2.X() - p1.X()) ;
+ double b = p1.Y() - a*p1.X(); // p1 is on this straight line
+
+ // Second straight line coefficients (equation y=c*x+d)
+ double c = -1 / a; // The 2 lines are orthogonal
+ double d = Center.Y() - c*Center.X(); // Center is on this straight line
+
+ Xt = (d - b) / (a - c);
+ Yt = a*Xt + b;
+ }
+
+ return gp_Pnt( Xt, Yt, 0 );
+}
--- /dev/null
+// Copyright (C) 2007-2016 CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// Author : Lioka RAZAFINDRAZAKA (CEA)
+
+#ifndef SMESH_CONTROLPNT_H
+#define SMESH_CONTROLPNT_H
+
+#include "SMESH_Utils.hxx"
+
+#include <gp_Pnt.hxx>
+
+class TopoDS_Shape;
+class TopoDS_Edge ;
+class TopoDS_Face ;
+class TopoDS_Solid;
+
+#include <vector>
+
+namespace SMESHUtils
+{
+ /*!
+ * \brief Control point: coordinates and element size at these coordinates
+ */
+ struct SMESHUtils_EXPORT ControlPnt : public gp_Pnt
+ {
+ ControlPnt()
+ : gp_Pnt(), size(0) {}
+ ControlPnt( const gp_Pnt& aPnt, double theSize)
+ : gp_Pnt( aPnt ), size( theSize ) {}
+ ControlPnt(double theX,double theY,double theZ)
+ : gp_Pnt(theX, theY, theZ), size(0) {}
+ ControlPnt(double theX,double theY,double theZ, double theSize)
+ : gp_Pnt(theX, theY, theZ), size( theSize ) {}
+
+ double Size() const { return size; };
+ void SetSize( double theSize ) { size = theSize; };
+
+ double size;
+ };
+
+ // Functions to get sample point from shapes
+ void createControlPoints( const TopoDS_Shape& theShape,
+ const double& theSize,
+ std::vector< ControlPnt >& thePoints );
+
+ void createPointsSampleFromEdge( const TopoDS_Edge& theEdge,
+ const double& theSize,
+ std::vector<ControlPnt>& thePoints );
+
+ void createPointsSampleFromFace( const TopoDS_Face& theFace,
+ const double& theSize,
+ std::vector<ControlPnt>& thePoints );
+
+ void createPointsSampleFromSolid( const TopoDS_Solid& theSolid,
+ const double& theSize,
+ std::vector<ControlPnt>& thePoints );
+
+}
+#endif
size_t TPythonDump::myCounter = 0;
const char theNotPublishedObjectName[] = "__NOT__Published__Object__";
- TVar::TVar(CORBA::Double value):myVals(1) { myVals[0] = SMESH_Comment(value); }
- TVar::TVar(CORBA::Long value):myVals(1) { myVals[0] = SMESH_Comment(value); }
- TVar::TVar(CORBA::Short value):myVals(1) { myVals[0] = SMESH_Comment(value); }
- TVar::TVar(const SMESH::double_array& value):myVals(value.length())
+ TVar::TVar(CORBA::Double value):myVals(1), myIsList(false) { myVals[0] = SMESH_Comment(value); }
+ TVar::TVar(CORBA::Long value):myVals(1), myIsList(false) { myVals[0] = SMESH_Comment(value); }
+ TVar::TVar(CORBA::Short value):myVals(1), myIsList(false) { myVals[0] = SMESH_Comment(value); }
+ TVar::TVar(const SMESH::double_array& value):myVals(value.length()), myIsList(true)
{
for ( size_t i = 0; i < value.length(); i++)
myVals[i] = SMESH_Comment(value[i]);
operator<<(const TVar& theVarValue)
{
const std::vector< int >& varIDs = SMESH_Gen_i::GetSMESHGen()->GetLastParamIndices();
- if ( theVarValue.myVals.size() != 1 )
+ if ( theVarValue.myIsList )
{
myStream << "[ ";
for ( size_t i = 1; i <= theVarValue.myVals.size(); ++i )
struct SMESH_I_EXPORT TVar
{
std::vector< std::string > myVals;
+ bool myIsList;
TVar(CORBA::Double value);
TVar(CORBA::Long value);
TVar(CORBA::Short value);
## Finds groups of ajacent nodes within Tolerance.
# @param Tolerance the value of tolerance
- # @param SubMeshOrGroup SubMesh or Group
+ # @param SubMeshOrGroup SubMesh, Group or Filter
# @param exceptNodes list of either SubMeshes, Groups or node IDs to exclude from search
# @param SeparateCornerAndMediumNodes if @c True, in quadratic mesh puts
# corner and medium nodes in separate groups thus preventing
StdMeshers_MEFISTO_2D::StdMeshers_MEFISTO_2D(int hypId, int studyId, SMESH_Gen * gen):
SMESH_2D_Algo(hypId, studyId, gen)
{
- MESSAGE("StdMeshers_MEFISTO_2D::StdMeshers_MEFISTO_2D");
_name = "MEFISTO_2D";
_shapeType = (1 << TopAbs_FACE);
_compatibleHypothesis.push_back("MaxElementArea");
StdMeshers_MEFISTO_2D::~StdMeshers_MEFISTO_2D()
{
- MESSAGE("StdMeshers_MEFISTO_2D::~StdMeshers_MEFISTO_2D");
}
//=============================================================================
bool StdMeshers_MEFISTO_2D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape)
{
- MESSAGE("StdMeshers_MEFISTO_2D::Compute");
-
TopoDS_Face F = TopoDS::Face(aShape.Oriented(TopAbs_FORWARD));
// helper builds quadratic mesh if necessary
if (ierr == 0)
{
- MESSAGE("... End Triangulation Generated Triangle Number " << nbt);
- MESSAGE(" Node Number " << nbst);
StoreResult(nbst, uvst, nbt, nust, mefistoToDS, scalex, scaley);
isOk = true;
}
const TopoDS_Shape & aShape,
MapShapeNbElems& aResMap)
{
- MESSAGE("StdMeshers_MEFISTO_2D::Evaluate");
-
TopoDS_Face F = TopoDS::Face(aShape.Oriented(TopAbs_FORWARD));
double aLen = 0.0;
}
deviation2sideInd.insert( make_pair( devia, iS ));
}
+ double maxDevi = deviation2sideInd.rbegin()->first;
+ if ( maxDevi < 1e-7 && sides.size() == 3 )
+ {
+ // a triangle FACE; use a side with the most outstanding length as an elliptic one
+ deviation2sideInd.clear();
+ multimap< double, int > len2sideInd;
+ for ( size_t iS = 0; iS < sides.size(); ++iS )
+ len2sideInd.insert( make_pair( sides[iS]->Length(), iS ));
+
+ multimap< double, int >::iterator l2i = len2sideInd.begin();
+ double len0 = l2i->first;
+ double len1 = (++l2i)->first;
+ double len2 = (++l2i)->first;
+ if ( len1 - len0 > len2 - len1 )
+ deviation2sideInd.insert( make_pair( 0., len2sideInd.begin()->second ));
+ else
+ deviation2sideInd.insert( make_pair( 0., len2sideInd.rbegin()->second ));
+ }
int iCirc = deviation2sideInd.rbegin()->second;
aCircSide = sides[ iCirc ];
case FIXED_POINTS_1D:
{
const std::vector<double>& aPnts = _fpHyp->GetPoints();
- const std::vector<int>& nbsegs = _fpHyp->GetNbSegments();
+ std::vector<int> nbsegs = _fpHyp->GetNbSegments();
+ if ( theReverse )
+ std::reverse( nbsegs.begin(), nbsegs.end() );
// sort normalized params, taking into account theReverse
TColStd_SequenceOfReal Params;
{
list< double > params;
bool reversed = false;
- if ( theMesh.GetShapeToMesh().ShapeType() >= TopAbs_WIRE ) {
+ if ( theMesh.GetShapeToMesh().ShapeType() >= TopAbs_WIRE && _revEdgesIDs.empty() ) {
// if the shape to mesh is WIRE or EDGE
reversed = ( EE.Orientation() == TopAbs_REVERSED );
}