From cf9144672986f830048c7db40ea7e04d56a0aedd Mon Sep 17 00:00:00 2001 From: Christophe Bourcier Date: Wed, 10 Dec 2014 15:05:43 +0100 Subject: [PATCH] Some work for MG-CADSurf 1.3: - new option volume_gradation - add description of advanced options in the doc - set some options as deprecated (in the doc only, since they still work) - add tests on proximity and remove tiny edges --- .../gui/BLSURFPLUGIN/input/blsurf_hypo.doc | 93 +++++++++++---- src/BLSURFPlugin/BLSURFPlugin_Hypothesis.cxx | 1 + tests/test_proximity.py | 92 +++++++++++++++ tests/test_remove_tiny_edges.py | 110 ++++++++++++++++++ 4 files changed, 275 insertions(+), 21 deletions(-) create mode 100644 tests/test_proximity.py create mode 100644 tests/test_remove_tiny_edges.py diff --git a/doc/salome/gui/BLSURFPLUGIN/input/blsurf_hypo.doc b/doc/salome/gui/BLSURFPLUGIN/input/blsurf_hypo.doc index 6f32daf..30fe89a 100644 --- a/doc/salome/gui/BLSURFPLUGIN/input/blsurf_hypo.doc +++ b/doc/salome/gui/BLSURFPLUGIN/input/blsurf_hypo.doc @@ -104,41 +104,90 @@ possible to input the value of the option and edit it later. - Clear option - removes the option selected in the table. -The following MG-CADSurf options are commonly usable: +The following advanced MG-CADSurf options can be used: + +- \b volume_gradation (real) - Controls the mesh volume gradation, which can improve the shape quality of a +volume mesh built afterward, specially in thin volume areas. +The volume gradation parameter must be greater than 1, and should be greater or equal to the value of the classic +surface gradation (at the risk of increasing the time of convergence of the gradation process). +The closer it is to 1, the smoother the final volume mesh you will build should be. + +- \b correct_surface_intersections (bool) - If this option is deactivated, MeshGems-CADSurf will not correct +surface intersections. This particularly useful if you don't want volume filling in a later stage, or if you want to fix the +intersections in an other way (using MeshGems Cleaner for instance). +By default this option is 1. + +- \b surface_intersections_processing_max_cost (real) - If correct_surface_intersections = 1, this +parameter gives the time the user is ready to spend in the intersection prevention process. For example, +if set to 3, MeshGems-CADSurf will not spend more time in the intersection removal process than +3 times the time required to mesh without processing the intersections. + +- \b create_tag_on_collision (bool) - If this option is activated, MeshGems-CADSurf will create new tags to +describe tag collisions (when it locally changes the topology, depending on the patch independent +options). When this option is not activated, only one tag is preserved while the other one is dropped. +By default this option is 1. + +- \b debug (bool) - If debug = 1, MeshGems-CADSurf will be very verbose and will output some intermediate files +in the working directory. This option is meant to communicate with Distene support mainly. +By default this option is 0. + +- \b enforce_cad_edge_sizes (bool) - Relaxes the given sizemap constraint around CAD edges to allow a better +element quality and a better geometric approximation. It is only useful in combination with the gradation option. +By default this option is 0. + +- \b rectify_jacobian (bool) - The quadratic elements generation is a processing of the MeshGems-CADSurf +meshing process which inserts the extra nodes on the CAD. This parameter determines whether +MeshGems-CADSurf will try to correct or not all the elements of the surface mesh with negative +Jacobians by moving the internal nodes of the mesh. +By default this option is 1. -- \b frontal (integer) +- \b jacobian_rectification_respect_geometry (bool) - This parameter determines whether or not the geometry accuracy +is more important than the negative Jacobian correction. When this parameter is set to 0, +MeshGems-CADSurf is allowed to lose the CAD-mesh associativity in order to correct the last negative Jacobians. +By default this option is 1. - - 1 - the mesh generator inserts points with an advancing front method. +- \b respect_geometry (bool) - This patch independent option can be deactivated to allow MeshGems-CADSurf +to lower the geometry accuracy in its patch independent process. +By default this option is 1. - - 0 - it inserts them with an algebraic method (on internal edges). This method is - slightly faster but generates less regular meshes. +- \b max_number_of_points_per_patch (int) - This parameter controls the maximum amount of points MeshGems-CADSurf +is allowed to generate on a single CAD patch. For an automatic gestion of the memory, one can set this parameter to ”0”. +By default this option is 100000. - \n Default is 1. +- \b periodic_tolerance (double) - This parameter defines the maximum size difference between two periodic edges +and also the maximum distance error between two periodic entities. +By default this option is diag/100. -- \anchor blsurf_hinterpol_flag \b hinterpol_flag (integer) - determines the computation of an -interpolated value v between two points P1 and P2 on a -curve. Let h1 be the value at point P1, h2 be the value at point -P2, and t be a parameter varying from 0 to 1 when moving from P1 -to P2. +- \b required_entities (char) - The required entities control the correction operations. Accepted values for this parameter are: - - 0 - the interpolation is linear: \f$v = h1 + t (h2 - h1 )\f$ + - respect : MeshGems-CADSurf is not allowed to alter any required entity, even for correction purposes, + - ignore : MeshGems-CADSurf will ignore the required entities in its processing, + - clear : MeshGems-CADSurf will clear any required status for the entities. There will not be any entity marked as required in the generated mesh. - - 1 - the interpolation is geometric: \f$v = h1 \times \left( \frac{h1}{h2} \right)^{t}\f$ + \n By default this option is "respect". - - 2 - the interpolation is sinusoidal: \f$v = \frac{h1+h2}{2} + \frac{h1-h2}{2 \cdot \cos(\pi \cdot t)}\f$ +- \b tags (char) - The tag (attribute) system controls the optimisation process. Accepted values for this parameter are: - \n Default is 0. + - respect : the CAD tags will be preserved and unaltered by the optimisation operations, + - ignore : the CAD tags will be ignored by the optimisation operations but they will still be present inthe output mesh, + - clear : MeshGems-CADSurf will clear any tag on any entity and optimise accordingly. There will not be any tag in the generated mesh. -- \anchor blsurf_hmean_flag \b hmean_flag (integer) - determines the computation of the average of several -values: + \n By default this option is "respect". - - -1 - the minimum is computed. + +\b Remark: To set boolean options, you have to type 0 or 1. - - 0 or 2 - the arithmetic average is computed. - - 1 - the geometric average is computed. - \n Default is 0. +The following MG-CADSurf options are deprecated (since MeshGems 1.3) and will be removed in the next version of Salome: + +- frontal +- hinterpol_flag +- hmean_flag +- prox_nb_layer +- prox_ratio +- proximity. + The following PreCAD options are commonly usable. @@ -425,4 +474,6 @@ Sample TUI Script of the definition of MG-CADSurf periodicity \ref tui_blsurf_pe \ref blsurf_top "Back to top" +For more information on MeshGems-CADSurf, you can read its documentation at $MESHGEMS_ROOT_DIR/Docs/mg-cadsurf_user_manual.pdf + */ diff --git a/src/BLSURFPlugin/BLSURFPlugin_Hypothesis.cxx b/src/BLSURFPlugin/BLSURFPlugin_Hypothesis.cxx index 608168e..8e59d5b 100644 --- a/src/BLSURFPlugin/BLSURFPlugin_Hypothesis.cxx +++ b/src/BLSURFPlugin/BLSURFPlugin_Hypothesis.cxx @@ -108,6 +108,7 @@ BLSURFPlugin_Hypothesis::BLSURFPlugin_Hypothesis(int hypId, int studyId, SMESH_G const char* doubleOptionNames[] = { "surface_intersections_processing_max_cost",// default = 15 "periodic_tolerance", // default = diag/100 "prox_ratio", + "volume_gradation" "" // mark of end }; const char* charOptionNames[] = { "required_entities", // default = "respect" diff --git a/tests/test_proximity.py b/tests/test_proximity.py new file mode 100644 index 0000000..730f382 --- /dev/null +++ b/tests/test_proximity.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- + +import sys +import salome + +salome.salome_init() +theStudy = salome.myStudy + +### +### GEOM component +### + +import GEOM +from salome.geom import geomBuilder +import math +import SALOMEDS + + +geompy = geomBuilder.New(theStudy) + +# Create a box +box = geompy.MakeBoxDXDYDZ(100, 100, 100) + +# Create a sphere near the sides of the box +sphere_tmp = geompy.MakeSphereR(5) +sphere = geompy.MakeTranslation(sphere_tmp, 6, 6, 50) + +part = geompy.MakePartition([box, sphere]) +geompy.addToStudy( box, 'box' ) +geompy.addToStudy( sphere, 'sphere' ) +geompy.addToStudy( part, 'part' ) + +# Create the groups of faces +box_faces = geompy.GetShapesOnBox(box, part, geompy.ShapeType["FACE"], GEOM.ST_ON) +gr_box_faces = geompy.CreateGroup(part, geompy.ShapeType["FACE"]) +geompy.UnionList(gr_box_faces, box_faces) +geompy.addToStudyInFather(part, gr_box_faces, "box_faces") + +all_faces = geompy.SubShapeAll(part, geompy.ShapeType["FACE"]) +gr_all_faces = geompy.CreateGroup(part, geompy.ShapeType["FACE"]) +geompy.UnionList(gr_all_faces, all_faces) + +gr_spheres_faces = geompy.CutGroups(gr_all_faces, gr_box_faces) +geompy.addToStudyInFather(part, gr_spheres_faces, "spheres_faces") + +### +### SMESH component +### + +import SMESH, SALOMEDS +from salome.smesh import smeshBuilder + +smesh = smeshBuilder.New(theStudy) +Mesh_1 = smesh.Mesh(part, "Mesh_part") +BLSURF = Mesh_1.Triangle(algo=smeshBuilder.BLSURF) +BLSURF_Parameters_1 = BLSURF.Parameters() +BLSURF_Parameters_1.SetGradation( 1.2 ) +BLSURF_Parameters_1.SetGeometricMesh( 1 ) +BLSURF_Parameters_1.SetPhySize( 20 ) +#BLSURF_Parameters_1.SetMinSize( 0.1 ) +BLSURF_Parameters_1.SetMaxSize( 20 ) +BLSURF_Parameters_1.SetAngleMesh( 8 ) + +# Old way to set proximity (Mesh Gems 1.1) +#BLSURF_Parameters_1.SetOptionValue( 'proximity', '1' ) +#BLSURF_Parameters_1.SetOptionValue( 'prox_ratio', '1.2' ) +#BLSURF_Parameters_1.SetOptionValue( 'prox_nb_layer', '3' ) + +# New way to set proximity (Mesh Gems >= 1.3) +BLSURF_Parameters_1.SetOptionValue( "volume_gradation", "1.2" ) + +isDone = Mesh_1.Compute() +if not isDone: + raise Exception("Compute mesh ended in error") + +# Create the groups on the mesh +gr_mesh_box = Mesh_1.Group(gr_box_faces) +gr_mesh_spheres = Mesh_1.Group(gr_spheres_faces) + +# Check the minimal area of the box faces to check the proximity +box_ids = gr_mesh_box.GetIDs() +box_areas = [Mesh_1.GetArea(i) for i in box_ids] + +min_area = min(box_areas) + +print "min_area: ", min_area + +if min_area > 1: + raise Exception("Wrong minimal area on box. Proximity has not worked.") + +if salome.sg.hasDesktop(): + salome.sg.updateObjBrowser(1) diff --git a/tests/test_remove_tiny_edges.py b/tests/test_remove_tiny_edges.py new file mode 100644 index 0000000..403f40d --- /dev/null +++ b/tests/test_remove_tiny_edges.py @@ -0,0 +1,110 @@ +# -*- coding: utf-8 -*- + +import salome + +import GEOM +from salome.geom import geomBuilder +geompy = geomBuilder.New(salome.myStudy) + +import math + +tiny_edge_length = 0.1 + +O = geompy.MakeVertex(0, 0, 0) +OX = geompy.MakeVectorDXDYDZ(1, 0, 0) +OY = geompy.MakeVectorDXDYDZ(0, 1, 0) +OZ = geompy.MakeVectorDXDYDZ(0, 0, 1) + +Face_1 = geompy.MakeFaceHW(10, 10, 1) +geomObj_1 = geompy.MakeMarker(0, 0, 0, 1, 0, 0, 0, 1, 0) +Sketch_1 = geompy.MakeSketcherOnPlane("Sketcher:F -2.5209155082703 -1.4416453838348:TT -1.1105282306671 -2.9872753620148:TT 0.76354801654816 -2.3303825855255:TT 1.9614112377167 -3.0838770866394:TT 3.8354876041412 -1.2677619457245:TT 4.2218952178955 0.644955098629:TT 3.2751967906952 2.5576722621918:TT 0.58966463804245 3.5430111885071:TT -3.7380990982056 3.2338852882385:TT -4.433632850647 0.85747921466827:WW", Face_1 ) +vertices = geompy.ExtractShapes(Sketch_1, geompy.ShapeType["VERTEX"], True) +Curve_1 = geompy.MakeInterpol(vertices, True, True) + +p_small = geompy.MakeVertexOnCurve(Curve_1, 0.001) +geompy.addToStudy(p_small, "p_small") + +part = geompy.MakePartition([Face_1], [Curve_1, p_small], Limit=geompy.ShapeType["FACE"]) +geompy.addToStudy(part, "part") + +Vx = geompy.MakeVectorDXDYDZ(1, 0, 0) +Vy = geompy.MakeVectorDXDYDZ(0, 1, 0) +Vz = geompy.MakeVectorDXDYDZ(0, 0, 1) + +p1 = geompy.MakeVertex(-5, -5, 0) +p2 = geompy.MakeVertex(5, 5, 0) +left_edges = geompy.GetShapesOnPlaneWithLocation(part, geompy.ShapeType["EDGE"], Vx, p1, GEOM.ST_ON) +left = geompy.CreateGroup(part, geompy.ShapeType["EDGE"]) +geompy.UnionList(left, left_edges) +geompy.addToStudyInFather(part, left, "left") + +right_edges = geompy.GetShapesOnPlaneWithLocation(part, geompy.ShapeType["EDGE"], Vx, p2, GEOM.ST_ON) +right = geompy.CreateGroup(part, geompy.ShapeType["EDGE"]) +geompy.UnionList(right, right_edges) +geompy.addToStudyInFather(part, right, "right") + +bottom_edges = geompy.GetShapesOnPlaneWithLocation(part, geompy.ShapeType["EDGE"], Vy, p1, GEOM.ST_ON) +bottom = geompy.CreateGroup(part, geompy.ShapeType["EDGE"]) +geompy.UnionList(bottom, bottom_edges) +geompy.addToStudyInFather(part, bottom, "bottom") + +top_edges = geompy.GetShapesOnPlaneWithLocation(part, geompy.ShapeType["EDGE"], Vy, p2, GEOM.ST_ON) +top = geompy.CreateGroup(part, geompy.ShapeType["EDGE"]) +geompy.UnionList(top, top_edges) +geompy.addToStudyInFather(part, top, "top") + +faces = geompy.SubShapeAll(part, geompy.ShapeType["FACE"]) +sub_shapes = [] +for i, face in enumerate(faces): + geompy.addToStudyInFather(part, face, "face_%i"%(i+1)) + sub_shapes.append(face) + +# Mesh +# ==== + +import SMESH +from salome.smesh import smeshBuilder +smesh = smeshBuilder.New(salome.myStudy) + +Mesh = smesh.Mesh(part, "Mesh") + +algo2d = Mesh.Triangle(algo=smeshBuilder.BLSURF) +params = algo2d.Parameters() +params.SetVerbosity(1) +#algo2d.SetTopology(smesh.PreCAD) +params.SetGeometricMesh( 1 ) +params.SetAngleMesh( 4 ) +params.SetPhySize( 8 ) +#algo2d.SetGradation(1.05) +#params.SetQuadAllowed( True ) +params.SetQuadraticMesh( True ) +params.SetRemoveTinyEdges( True ) +params.SetTinyEdgeLength( tiny_edge_length ) +#params.SetOptionValue( 'rectify_jacobian', '0' ) + +Mesh.Compute() + +for sub_shape in sub_shapes: + Mesh.Group(sub_shape) + +x0, y0, z0 = geompy.PointCoordinates(p_small) +node = Mesh.FindNodeClosestTo(x0, y0, z0) + +elems = Mesh.GetNodeInverseElements(node) + +edges_length = [] +for elem in elems: + if Mesh.GetElementType(elem, True) == SMESH.EDGE: + edge_length = Mesh.GetLength(elem) + edges_length.append(edge_length) + +min_length = min(edges_length) +x1, y1, z1 = Mesh.GetNodeXYZ(node) + +print min_length + +if min_length