# the gradation to its maximum
algo2d.SetGradation( 2.5 )
+# -----------------------
+# Adding enforced meshes
+# -----------------------
+
+# create 1D mesh
+OZ = geompy.MakeVectorDXDYDZ(0, 0, 1)
+circle_1 = geompy.MakeCircle( geompy.MakeVertex( 100, 75, 200 ), OZ, 50 )
+circle_2 = geompy.MakeCircle( geompy.MakeVertex( 100, 150, 200 ), OZ, 70 )
+circles = geompy.MakeCompound([ circle_1, circle_2 ], theName="circles")
+mesh_1D = smesh.Mesh( circles, "enforced circles" )
+mesh_1D.Segment().LocalLength( 7 )
+mesh_1D.Compute()
+
+# Add enforced mesh
+algo2d.SetEnforcedMeshes([
+ smeshBuilder.MG_EnforcedMesh1D( mesh_1D, "Enforced edges")])
+
+# -----------------
# compute the mesh
+# -----------------
+
cadsurfMesh.Compute()
-# ---------------------------------------------------------------
+
+# ================================================================
# blsurf_construct_mesh_internal_vertices Using internal vertices
-# ---------------------------------------------------------------
+# ================================================================
# Creating a geometry containing internal vertices
Face_3 = geompy.MakeFaceHW(1, 1, 1)
\ref blsurf_top "Back to top"
+\section blsurf_enforced_meshes Enforced Meshes
+
+\image html blsurf_enforced_meshes.png
+
+MG-CADSurf algorithm can be forced by other 1D meshes, sub-meshes or
+groups. 1D meshes are allowed to pass over face boundaries and to
+intersect other enforced meshes.
+If a group name is given, the enforced 1D elements will be added to the group.
+If the group does not exist, it is created.
+
+\sa Sample TUI Script of the \ref tui_blsurf "creation of a MG-CADSurf hypothesis", including enforced meshes.
+
+\ref blsurf_top "Back to top"
+
+
\section blsurf_periodicity Periodicity
\subsection periodicity_introduction Introduction
#ifndef _SMESH_BLSURFALGORITHM_IDL_
#define _SMESH_BLSURFALGORITHM_IDL_
-#include "SMESH_Hypothesis.idl"
#include "GEOM_Gen.idl"
#include "SALOME_Exception.idl"
+#include "SMESH_Hypothesis.idl"
+#include "SMESH_Mesh.idl"
/*!
* BLSURFPlugin: interfaces to BLSURF related hypotheses and algorithms
{
typedef sequence<string> string_array;
+ // Enforced 1D Mesh
+ struct MG_EnforcedMesh1D
+ {
+ SMESH::SMESH_IDSource mesh; // mesh, group or sub-mesh
+ string groupName; // optional name of a group to add mesh edges to
+ };
+ typedef sequence< MG_EnforcedMesh1D > EnforcedMeshesList;
+
// Enforced vertex name
typedef string TEnfName;
// Entry
typedef sequence<TEntry> TEntryList;
// Group name
typedef string TEnfGroupName;
-
+
// Coordinates of enforced vertex
typedef sequence<double,3> TEnfVertexCoords;
// List of coords
typedef sequence<TEnfVertexCoords> TEnfVertexCoordsList;
-
+
// Enforced vertex
struct TEnfVertex {
TEnfName name;
double GetVolumeProximityRatio();
/*!
- *Set verbosity level in the range 0 to 100.
+ * Set verbosity level in the range 0 to 100.
*/
void SetVerbosity(in short theVal) raises (SALOME::SALOME_Exception);
short GetVerbosity();
+ /*!
+ * Set/Get enforced 1D meshes
+ */
+ void SetEnforcedMeshes( in EnforcedMeshesList enforcedMeshes );
+ EnforcedMeshesList GetEnforcedMeshes();
+
/*!
* Set enforce_cad_edge_sizes parameter
*
noBLSURFPlugin = 0
try:
import BLSURFPlugin
+ from BLSURFPlugin import MG_EnforcedMesh1D
+
except ImportError:
noBLSURFPlugin = 1
pass
def GetInternalEnforcedVertexAllFacesGroup(self):
return self.Parameters().GetInternalEnforcedVertexAllFacesGroup()
+ #-----------------------------------------
+ # Enforced mesh
+ #-----------------------------------------
+
+ ## Set enforced 1D meshes
+ # @param enfMeshes : list of smeshBuilder.MG_EnforcedMesh1D structures
+ #
+ # Example: cadsurf.SetEnforcedMeshes([ smeshBuilder.MG_EnforcedMesh1D( mesh1D, "Group 1D")]
+ def SetEnforcedMeshes( self, enfMeshes ):
+ from salome.smesh.smeshBuilder import Mesh
+ for em in enfMeshes:
+ if isinstance( em.mesh, Mesh ):
+ em.mesh = em.mesh.GetMesh()
+ return self.Parameters().SetEnforcedMeshes( enfMeshes )
+
#-----------------------------------------
# Attractors
#-----------------------------------------
// ---
#include "BLSURFPlugin_BLSURF.hxx"
-#include "BLSURFPlugin_Hypothesis.hxx"
+
#include "BLSURFPlugin_Attractor.hxx"
+#include "BLSURFPlugin_EnforcedMesh1D.hxx"
+#include "BLSURFPlugin_Hypothesis.hxx"
extern "C"{
#include <meshgems/meshgems.h>
#include <meshgems/cadsurf.h>
}
-#include <structmember.h>
-
-
-#include <Basics_Utils.hxx>
-
#include <SMDS_EdgePosition.hxx>
#include <SMESHDS_Group.hxx>
+#include <SMESH_File.hxx>
#include <SMESH_Gen.hxx>
#include <SMESH_Group.hxx>
#include <SMESH_Mesh.hxx>
#include <SMESH_MesherHelper.hxx>
#include <StdMeshers_FaceSide.hxx>
#include <StdMeshers_ViscousLayers2D.hxx>
-#include <SMESH_File.hxx>
+#include <Basics_Utils.hxx>
#include <utilities.h>
+#include <cstdlib>
#include <limits>
#include <list>
-#include <vector>
#include <set>
-#include <cstdlib>
+#include <vector>
+
+#include <structmember.h> // python
// OPENCASCADE includes
#include <BRepBndLib.hxx>
status_t size_on_edge(integer edge_id, real t, real *size, void *user_data);
status_t size_on_vertex(integer vertex_id, real *size, void *user_data);
-typedef struct {
- gp_XY uv;
- gp_XYZ xyz;
-} projectionPoint;
-
/////////////////////////////////////////////////////////
-projectionPoint getProjectionPoint(TopoDS_Face& theFace, const gp_Pnt& thePoint)
+BLSURFPlugin_BLSURF::projectionPoint
+BLSURFPlugin_BLSURF::getProjectionPoint(TopoDS_Face& theFace,
+ const gp_Pnt& thePoint,
+ const bool theAllowStateON)
{
projectionPoint myPoint;
{
if ( !foundFace.IsNull() )
return myPoint; // thePoint seems to be TopAbs_ON
- foundFace = face;
- myPoint.uv = uv.XY();
- myPoint.xyz = surface->Value( uv ).XYZ();
+ foundFace = face;
+ myPoint.uv = uv.XY();
+ myPoint.xyz = surface->Value( uv ).XYZ();
+ myPoint.state = FC.State();
// break;
}
- if ( FC.State() == TopAbs_ON )
+ if ( FC.State() == TopAbs_ON && !theAllowStateON )
return myPoint;
}
}
const TopoDS_Face& face = d2f->second.first;
const gp_Pnt2d & uv = d2f->second.second;
BRepClass_FaceClassifier FC( face, uv, Precision::Confusion());
- if ( FC.State() == TopAbs_IN )
+ if (( FC.State() == TopAbs_IN ) ||
+ ( FC.State() == TopAbs_ON && theAllowStateON ))
{
- foundFace = face;
- myPoint.uv = uv.XY();
- myPoint.xyz = theHelper->GetSurface( face )->Value( uv ).XYZ();
- break;
+ foundFace = face;
+ myPoint.uv = uv.XY();
+ myPoint.xyz = theHelper->GetSurface( face )->Value( uv ).XYZ();
+ myPoint.state = FC.State();
+ if ( FC.State() == TopAbs_IN )
+ break;
}
}
}
// "getProjectionPoint: can't find a face by a vertex");
theFace = TopoDS::Face( foundFace );
}
- else
+ else // !theFace.IsNull()
{
Handle(Geom_Surface) surface = BRep_Tool::Surface( theFace );
GeomAPI_ProjectPointOnSurf projector( thePoint, surface );
Standard_Real u,v;
projector.LowerDistanceParameters(u,v);
- myPoint.uv = gp_XY(u,v);
- gp_Pnt aPnt = projector.NearestPoint();
- myPoint.xyz = gp_XYZ(aPnt.X(),aPnt.Y(),aPnt.Z());
+ myPoint.uv = gp_XY(u,v);
+ myPoint.xyz = projector.NearestPoint().XYZ();
BRepClass_FaceClassifier FC( theFace, myPoint.uv, Precision::Confusion());
- if ( FC.State() != TopAbs_IN )
+ myPoint.state = FC.State();
+
+ if (( FC.State() != TopAbs_IN ) &&
+ ( FC.State() != TopAbs_ON || !theAllowStateON ))
theFace.Nullify();
}
/////////////////////////////////////////////////////////
TopoDS_Shape BLSURFPlugin_BLSURF::entryToShape(std::string entry)
{
- GEOM::GEOM_Object_var aGeomObj;
- TopoDS_Shape S = TopoDS_Shape();
- SALOMEDS::SObject_var aSObj = SMESH_Gen_i::GetSMESHGen()->getStudyServant()->FindObjectID( entry.c_str() );
- if (!aSObj->_is_nil()) {
- CORBA::Object_var obj = aSObj->GetObject();
- aGeomObj = GEOM::GEOM_Object::_narrow(obj);
- aSObj->UnRegister();
- }
- if ( !aGeomObj->_is_nil() )
- S = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( aGeomObj.in() );
+ GEOM::GEOM_Object_var aGeomObj = SMESH_Gen_i::GetSMESHGen()->GetGeomObjectByEntry( entry );
+ TopoDS_Shape S = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( aGeomObj );
return S;
}
BLSURFPlugin_Hypothesis::TEnfVertexCoords enf_coords, coords, s_coords;
// Find the face and get the (u,v) values of the enforced vertex on the face
- projectionPoint myPoint = getProjectionPoint(faceShape,aPnt);
+ BLSURFPlugin_BLSURF::projectionPoint myPoint =
+ BLSURFPlugin_BLSURF::getProjectionPoint(faceShape,aPnt);
if ( faceShape.IsNull() )
return;
// xa
pos1 = AttractorFunction.find(sep);
if (pos1!=string::npos)
- xa = atof(AttractorFunction.substr(10, pos1-10).c_str());
+ xa = atof(AttractorFunction.substr(10, pos1-10).c_str());
// ya
pos2 = AttractorFunction.find(sep, pos1+1);
if (pos2!=string::npos) {
- ya = atof(AttractorFunction.substr(pos1+1, pos2-pos1-1).c_str());
- pos1 = pos2;
+ ya = atof(AttractorFunction.substr(pos1+1, pos2-pos1-1).c_str());
+ pos1 = pos2;
}
// za
pos2 = AttractorFunction.find(sep, pos1+1);
if (pos2!=string::npos) {
- za = atof(AttractorFunction.substr(pos1+1, pos2-pos1-1).c_str());
- pos1 = pos2;
+ za = atof(AttractorFunction.substr(pos1+1, pos2-pos1-1).c_str());
+ pos1 = pos2;
}
// a
pos2 = AttractorFunction.find(sep, pos1+1);
if (pos2!=string::npos) {
- a = atof(AttractorFunction.substr(pos1+1, pos2-pos1-1).c_str());
- pos1 = pos2;
+ a = atof(AttractorFunction.substr(pos1+1, pos2-pos1-1).c_str());
+ pos1 = pos2;
}
// b
pos2 = AttractorFunction.find(sep, pos1+1);
if (pos2!=string::npos) {
- b = atof(AttractorFunction.substr(pos1+1, pos2-pos1-1).c_str());
- pos1 = pos2;
+ b = atof(AttractorFunction.substr(pos1+1, pos2-pos1-1).c_str());
+ pos1 = pos2;
}
// createNode
pos2 = AttractorFunction.find(sep, pos1+1);
// d
pos2 = AttractorFunction.find(")");
if (pos2!=string::npos) {
- d = atof(AttractorFunction.substr(pos1+1, pos2-pos1-1).c_str());
+ d = atof(AttractorFunction.substr(pos1+1, pos2-pos1-1).c_str());
}
// Get the (u,v) values of the attractor on the face
- projectionPoint myPoint = getProjectionPoint(TopoDS::Face(GeomShape),gp_Pnt(xa,ya,za));
- gp_XY uvPoint = myPoint.uv;
- gp_XYZ xyzPoint = myPoint.xyz;
+ BLSURFPlugin_BLSURF::projectionPoint myPoint =
+ BLSURFPlugin_BLSURF::getProjectionPoint(TopoDS::Face(GeomShape),gp_Pnt(xa,ya,za));
+ gp_XY uvPoint = myPoint.uv;
+ gp_XYZ xyzPoint = myPoint.xyz;
Standard_Real u0 = uvPoint.X();
Standard_Real v0 = uvPoint.Y();
Standard_Real x0 = xyzPoint.X();
SMESHDS_Mesh* meshDS = aMesh.GetMeshDS();
SMESH_MesherHelper helper( aMesh ), helperWithShape( aMesh );
- myHelper = theHelper = & helperWithShape;
+ theHelper = & helperWithShape;
// do not call helper.IsQuadraticSubMesh() because sub-meshes
// may be cleaned and helper.myTLinkNodeMap gets invalid in such a case
bool haveQuadraticSubMesh = helperWithShape.IsQuadraticSubMesh( aShape );
+ haveQuadraticSubMesh = haveQuadraticSubMesh || (_hypothesis && _hypothesis->GetQuadraticMesh());
+ helper.SetIsQuadratic( haveQuadraticSubMesh );
+ helperWithShape.SetIsQuadratic( haveQuadraticSubMesh );
+
bool quadraticSubMeshAndViscousLayer = false;
bool needMerge = false;
typedef set< SMESHDS_SubMesh*, ShapeTypeCompare > TSubMeshSet;
TopTools_IndexedDataMapOfShapeListOfShape e2ffmap;
TopExp::MapShapesAndAncestors( aShape, TopAbs_EDGE, TopAbs_FACE, e2ffmap );
+ BLSURFPlugin_EnforcedMesh1D enforcedMesh( helperWithShape, _hypothesis );
+
// Issue 0019864. On DebianSarge, FE signals do not obey to OSD::SetSignal(false)
#ifndef WIN32
feclearexcept( FE_ALL_EXCEPT );
SetParameters(_hypothesis, css, aShape);
- haveQuadraticSubMesh = haveQuadraticSubMesh || (_hypothesis != NULL && _hypothesis->GetQuadraticMesh());
- helper.SetIsQuadratic( haveQuadraticSubMesh );
-
// To remove as soon as quadratic mesh is allowed - BEGIN
// GDD: Viscous layer is not allowed with quadratic mesh
if (_haveViscousLayers && haveQuadraticSubMesh ) {
{
TopoDS_Face f = TopoDS::Face(face_iter.Current());
- SMESH_subMesh* fSM = aMesh.GetSubMesh( f );
- if ( !fSM->IsEmpty() ) continue; // skip already meshed FACE with viscous layers
+ //SMESH_subMesh* fSM = aMesh.GetSubMesh( f );
+ //if ( !fSM->IsEmpty() ) continue; // skip already meshed FACE with viscous layers
// make INTERNAL face oriented FORWARD (issue 0020993)
if (f.Orientation() != TopAbs_FORWARD && f.Orientation() != TopAbs_REVERSED )
}
// Specific size map = Attractor
- std::map<int,std::vector<double> >::iterator attractor_iter = FaceId2AttractorCoords.begin();
-
- for (; attractor_iter != FaceId2AttractorCoords.end(); ++attractor_iter) {
- if (attractor_iter->first == faceKey)
+ std::map<int,std::vector<double> >::iterator attractor_iter =
+ FaceId2AttractorCoords.find( faceKey );
+ if (attractor_iter != FaceId2AttractorCoords.end() )
+ {
+ double * xyzCoords = & attractor_iter->second[2];
+ gp_Pnt P(xyzCoords[0],xyzCoords[1],xyzCoords[2]);
+ BRepClass_FaceClassifier scl(f,P,1e-7);
+ TopAbs_State result = scl.State();
+ if ( result == TopAbs_OUT )
+ MESSAGE("Point is out of face: node is not created");
+ if ( result == TopAbs_UNKNOWN )
+ MESSAGE("Point position on face is unknown: node is not created");
+ if ( result == TopAbs_ON )
+ MESSAGE("Point is on border of face: node is not created");
+ if ( result == TopAbs_IN )
{
- double xyzCoords[3] = {attractor_iter->second[2],
- attractor_iter->second[3],
- attractor_iter->second[4]};
-
- gp_Pnt P(xyzCoords[0],xyzCoords[1],xyzCoords[2]);
- BRepClass_FaceClassifier scl(f,P,1e-7);
- scl.Perform(f, P, 1e-7);
- TopAbs_State result = scl.State();
- if ( result == TopAbs_OUT )
- MESSAGE("Point is out of face: node is not created");
- if ( result == TopAbs_UNKNOWN )
- MESSAGE("Point position on face is unknown: node is not created");
- if ( result == TopAbs_ON )
- MESSAGE("Point is on border of face: node is not created");
- if ( result == TopAbs_IN )
- {
- // Point is inside face and not on border
- double uvCoords[2] = {attractor_iter->second[0],attractor_iter->second[1]};
- ienf++;
- cad_point_t* point_p = cad_point_new(fce, ienf, uvCoords);
- cad_point_set_tag(point_p, ienf);
- }
- FaceId2AttractorCoords.erase(faceKey);
+ // Point is inside face and not on border
+ double * uvCoords = & attractor_iter->second[0];
+ ienf++;
+ cad_point_t* point_p = cad_point_new(fce, ienf, uvCoords);
+ cad_point_set_tag(point_p, ienf);
}
+ FaceId2AttractorCoords.erase(faceKey);
}
// -----------------
EDGES
now create the edges associated to this face
*****************************************************************************************/
- int edgeKey = -1;
- for (TopExp_Explorer edge_iter(f,TopAbs_EDGE);edge_iter.More();edge_iter.Next())
+
+ std::vector< TopoDS_Edge > edges;
+ for ( TopExp_Explorer edge_iter( f, TopAbs_EDGE ); edge_iter.More(); edge_iter.Next() )
{
- TopoDS_Edge e = TopoDS::Edge(edge_iter.Current());
- int ic = emap.FindIndex(e);
- if (ic <= 0)
- ic = emap.Add(e);
+ const TopoDS_Edge& e = TopoDS::Edge( edge_iter.Current() );
+ if ( !enforcedMesh.GetSplitsOfEdge( e, edges, emap ))
+ edges.push_back( e );
+ }
+ for ( const TopoDS_Edge& e : edges )
+ {
+ int ic = emap.Add(e);
double tmin,tmax;
curves.push_back(BRep_Tool::CurveOnSurface(e, f, tmin, tmax));
- if (HasSizeMapOnEdge){
- edgeKey = EdgesWithSizeMap.FindIndex(e);
+ if ( HasSizeMapOnEdge )
+ {
+ int edgeKey = EdgesWithSizeMap.FindIndex(e);
if (EdgeId2SizeMap.find(edgeKey)!=EdgeId2SizeMap.end())
{
theSizeMapStr = EdgeId2SizeMap[edgeKey];
The following call sets it to the same value as the edge_id : */
// IMP23368. Do not set tag to an EDGE shared by FACEs of a hyper-patch
bool isInHyperPatch = false;
+ if ( e2ffmap.Contains( e )) // not there for a part of EDGE divided by enforced segments
{
std::set< int > faceTags, faceIDs;
TopTools_ListIteratorOfListOfShape fIt( e2ffmap.FindFromKey( e ));
if ( !isInHyperPatch )
cad_edge_set_tag(edg, ic);
- /* by default, an edge does not necessalry appear in the resulting mesh,
+ /* by default, an edge does not necessarily appear in the resulting mesh,
unless the following property is set :
*/
cad_edge_set_property(edg, EDGE_PROPERTY_SOFT_REQUIRED);
for ( int iN = 0; iN < nbNodes; ++iN )
{
const UVPtStruct& nData = nodeDataVec[ iN ];
- double t = nData.param;
- real uv[2] = { nData.u, nData.v };
- SMESH_TNodeXYZ nXYZ( nData.node );
+ double t = nData.param;
+ real uv[2] = { nData.u, nData.v };
+ SMESH_TNodeXYZ nXYZ = nData.node;
// cout << "\tt = " << t
// << "\t uv = ( " << uv[0] << ","<< uv[1] << " ) "
// << "\t u = " << nData.param
*****************************************************************************************/
int npts = 0;
- int ip1, ip2, *ip;
- gp_Pnt2d e0 = curves.back()->Value(tmin);
- gp_Pnt ee0 = surfaces.back()->Value(e0.X(), e0.Y());
- Standard_Real d1=0,d2=0;
-
- int vertexKey = -1;
- for (TopExp_Explorer ex_edge(e ,TopAbs_VERTEX); ex_edge.More(); ex_edge.Next()) {
- TopoDS_Vertex v = TopoDS::Vertex(ex_edge.Current());
- ++npts;
- if (npts == 1){
- ip = &ip1;
- d1 = ee0.SquareDistance(BRep_Tool::Pnt(v));
- } else {
- ip = &ip2;
- d2 = ee0.SquareDistance(BRep_Tool::Pnt(v));
- }
- *ip = pmap.FindIndex(v);
- if(*ip <= 0) {
- *ip = pmap.Add(v);
- // SMESH_subMesh* sm = aMesh.GetSubMesh(v);
- // if ( sm->IsMeshComputed() )
- // edgeSubmeshes.insert( sm->GetSubMeshDS() );
- }
+ int ip[2];
+ double d[2];
+ gp_Pnt2d uv0 = curves.back()->Value(tmin);
+ gp_Pnt p0 = surfaces.back()->Value( uv0.X(), uv0.Y() );
-// std::string aFileName = "fmap_vertex_";
-// aFileName.append(val_to_string(*ip));
-// aFileName.append(".brep");
-// BRepTools::Write(v,aFileName.c_str());
+ for (TopExp_Explorer ex_edge(e ,TopAbs_VERTEX); ex_edge.More(); ex_edge.Next())
+ {
+ const TopoDS_Vertex& v = TopoDS::Vertex(ex_edge.Current());
+ ip[ npts ] = pmap.Add(v);
+ d [ npts ] = p0.SquareDistance(BRep_Tool::Pnt(v));
+ ++npts;
- if (HasSizeMapOnVertex){
- vertexKey = VerticesWithSizeMap.FindIndex(v);
- if (VertexId2SizeMap.find(vertexKey)!=VertexId2SizeMap.end()){
+ if (HasSizeMapOnVertex)
+ {
+ int vertexKey = VerticesWithSizeMap.FindIndex(v);
+ if (VertexId2SizeMap.find(vertexKey)!=VertexId2SizeMap.end())
+ {
theSizeMapStr = VertexId2SizeMap[vertexKey];
if (theSizeMapStr.find(bad_end) == (theSizeMapStr.size()-bad_end.size()-1))
continue;
PyGILState_Release(gstate);
}
}
- }
- if (npts != 2) {
- // should not happen
+ } // loop on vertices
+
+ if (npts != 2) { // should not happen
MESSAGE("An edge does not have 2 extremities.");
- } else {
- if (d1 < d2) {
- // This defines the curves extremity connectivity
- cad_edge_set_extremities(edg, ip1, ip2);
- /* set the tag (color) to the same value as the extremity id : */
- cad_edge_set_extremities_tag(edg, ip1, ip2);
- }
- else {
- cad_edge_set_extremities(edg, ip2, ip1);
- cad_edge_set_extremities_tag(edg, ip2, ip1);
- }
+ continue;
}
+
+ if ( d[0] > d[1] )
+ std::swap( ip[0], ip[1] );
+
+ // This defines the curves extremity connectivity
+ cad_edge_set_extremities (edg, ip[0], ip[1]);
+ /* set the tag (color) to the same value as the extremity id : */
+ cad_edge_set_extremities_tag(edg, ip[0], ip[1]);
+
} // for edge
+
+ // ==============================
+ // Add segments of enforced mesh
+ // ==============================
+
+ if ( enforcedMesh.HasSegmentsOnFace( f ))
+ {
+ BLSURFPlugin_EnforcedMesh1D::Segmemnt seg;
+ while ( enforcedMesh.NextSegment( seg, pmap ))
+ {
+ curves.push_back( seg._pcurve );
+
+ cad_edge_t *edg = cad_edge_new( fce, seg._tag, seg._u[0], seg._u[1],
+ curv_fun,seg._pcurve.get());
+ cad_edge_set_tag( edg, seg._tag );
+
+ cad_edge_set_property( edg, EDGE_PROPERTY_SOFT_REQUIRED );
+ cad_edge_set_property( edg, EDGE_PROPERTY_INTERNAL );
+
+ cad_edge_set_extremities ( edg, seg._vTag[0], seg._vTag[1]);
+ cad_edge_set_extremities_tag( edg, seg._vTag[0], seg._vTag[1]);
+
+ dcad_edge_discretization_t *dedge;
+ dcad_get_edge_discretization( dcad, edg, &dedge );
+ dcad_edge_discretization_set_vertex_count( dedge, 2 );
+
+ dcad_edge_discretization_set_vertex_coordinates( dedge, 1,
+ seg._u [0],
+ &seg._uv[0].ChangeCoord(1),
+ seg._xyz[0].ChangeData() );
+ dcad_edge_discretization_set_vertex_coordinates( dedge, 2,
+ seg._u [1],
+ &seg._uv[1].ChangeCoord(1),
+ seg._xyz[1].ChangeData() );
+
+ dcad_edge_discretization_set_vertex_tag( dedge, 1, seg._vTag[0] );
+ dcad_edge_discretization_set_vertex_tag( dedge, 2, seg._vTag[1] );
+
+ dcad_edge_discretization_set_property(dedge, DISTENE_DCAD_PROPERTY_REQUIRED);
+ }
+ }
+
+
} //for face
///////////////////////
// set_param(css, "max_size", val_to_string( minFaceSize * 5 ).c_str());
}
- // TODO: be able to use a mesh in input.
- // See imsh usage in Products/templates/mg-cadsurf_template_common.cpp
- // => cadsurf_set_mesh
-
// Use the original dcad
cadsurf_set_dcad(css, dcad);
std::string GMFFileName = BLSURFPlugin_Hypothesis::GetDefaultGMFFile();
if (_hypothesis)
GMFFileName = _hypothesis->GetGMFFile();
- if (GMFFileName != "") {
+ if (GMFFileName != "")
+ {
bool asciiFound = (GMFFileName.find(".mesh", GMFFileName.length()-5) != std::string::npos);
bool binaryFound = (GMFFileName.find(".meshb",GMFFileName.length()-6) != std::string::npos);
if (!asciiFound && !binaryFound)
integer *evedg, *evtri, *evquad, *tags_buff, type;
real xyz[3];
- mesh_get_vertex_count(msh, &nv);
- mesh_get_edge_count(msh, &ne);
- mesh_get_triangle_count(msh, &nt);
+ mesh_get_vertex_count (msh, &nv);
+ mesh_get_edge_count (msh, &ne);
+ mesh_get_triangle_count (msh, &nt);
mesh_get_quadrangle_count(msh, &nq);
evedg = (integer *)mesh_calloc_generic_buffer(msh);
std::vector<const SMDS_MeshNode*> nodes(nv+1);
std::vector<bool> tags(nv+1);
+ BLSURFPlugin_Hypothesis::TEnfVertexCoords projVertex;
+
/* enumerated vertices */
- for(int iv=1;iv<=nv;iv++) {
+ for ( int iv = 1; iv <= nv; iv++ )
+ {
mesh_get_vertex_coordinates(msh, iv, xyz);
mesh_get_vertex_tag(msh, iv, &tag);
// Issue 0020656. Use vertex coordinates
nodes[iv] = NULL;
- if ( tag > 0 && tag <= pmap.Extent() ) {
- TopoDS_Vertex v = TopoDS::Vertex(pmap(tag));
- double tol = BRep_Tool::Tolerance( v );
- gp_Pnt p = BRep_Tool::Pnt( v );
- if ( p.IsEqual( gp_Pnt( xyz[0], xyz[1], xyz[2]), 1e3*tol))
- xyz[0] = p.X(), xyz[1] = p.Y(), xyz[2] = p.Z();
- else
- tag = 0; // enforced or attracted vertex
- nodes[iv] = SMESH_Algo::VertexNode( v, meshDS );
+ if ( tag > 0 )
+ {
+ if ( tag <= pmap.Extent() )
+ {
+ TopoDS_Vertex v = TopoDS::Vertex(pmap(tag));
+ double tol = BRep_Tool::Tolerance( v );
+ gp_Pnt p = BRep_Tool::Pnt( v );
+ if ( p.IsEqual( gp_Pnt( xyz[0], xyz[1], xyz[2]), 1e3*tol))
+ xyz[0] = p.X(), xyz[1] = p.Y(), xyz[2] = p.Z();
+ else
+ tag = 0; // enforced or attracted vertex
+ nodes[iv] = SMESH_Algo::VertexNode( v, meshDS );
+ }
+ if ( !nodes[iv] && ( nodes[iv] = enforcedMesh.GetNodeByTag( tag, pmap )))
+ {
+ continue;
+ }
}
if ( !nodes[iv] )
nodes[iv] = meshDS->AddNode(xyz[0], xyz[1], xyz[2]);
// Create group of enforced vertices if requested
- BLSURFPlugin_Hypothesis::TEnfVertexCoords projVertex;
- projVertex.clear();
- projVertex.push_back((double)xyz[0]);
- projVertex.push_back((double)xyz[1]);
- projVertex.push_back((double)xyz[2]);
- std::map< BLSURFPlugin_Hypothesis::TEnfVertexCoords, BLSURFPlugin_Hypothesis::TEnfVertexList >::const_iterator enfCoordsIt = EnfVertexCoords2EnfVertexList.find(projVertex);
+ projVertex.assign( xyz, xyz + 3 );
+ auto enfCoordsIt = EnfVertexCoords2EnfVertexList.find( projVertex );
if (enfCoordsIt != EnfVertexCoords2EnfVertexList.end())
{
- BLSURFPlugin_Hypothesis::TEnfVertexList::const_iterator enfListIt = enfCoordsIt->second.begin();
- BLSURFPlugin_Hypothesis::TEnfVertex *currentEnfVertex;
- for (; enfListIt != enfCoordsIt->second.end(); ++enfListIt) {
- currentEnfVertex = (*enfListIt);
- if (currentEnfVertex->grpName != "") {
- bool groupDone = false;
- SMESH_Mesh::GroupIteratorPtr grIt = aMesh.GetGroups();
- while (grIt->more()) {
+ for ( BLSURFPlugin_Hypothesis::TEnfVertex *currentEnfVertex : enfCoordsIt->second )
+ if (currentEnfVertex->grpName != "")
+ {
+ SMDS_MeshGroup* groupDS = nullptr;
+ for ( SMESH_Mesh::GroupIteratorPtr grIt = aMesh.GetGroups(); grIt->more() && !groupDS; )
+ {
SMESH_Group * group = grIt->next();
- if ( !group ) continue;
- SMESHDS_GroupBase* groupDS = group->GetGroupDS();
- if ( !groupDS ) continue;
- if ( groupDS->GetType()==SMDSAbs_Node && currentEnfVertex->grpName.compare(group->GetName())==0) {
- SMESHDS_Group* aGroupDS = static_cast<SMESHDS_Group*>( groupDS );
- aGroupDS->SMDSGroup().Add(nodes[iv]);
- // How can I inform the hypothesis ?
- // _hypothesis->AddEnfVertexNodeID(currentEnfVertex->grpName,nodes[iv]->GetID());
- groupDone = true;
- break;
- }
+ SMESHDS_Group * grp = dynamic_cast< SMESHDS_Group* >( group->GetGroupDS() );
+ if ( grp &&
+ grp->GetType() == SMDSAbs_Node &&
+ currentEnfVertex->grpName == group->GetName() )
+ groupDS = &grp->SMDSGroup();
}
- if (!groupDone)
+ if ( !groupDS )
{
- SMESH_Group* aGroup = aMesh.AddGroup( SMDSAbs_Node, currentEnfVertex->grpName.c_str() );
- aGroup->SetName( currentEnfVertex->grpName.c_str() );
- SMESHDS_Group* aGroupDS = static_cast<SMESHDS_Group*>( aGroup->GetGroupDS() );
- aGroupDS->SMDSGroup().Add(nodes[iv]);
- groupDone = true;
+ SMESH_Group * group = aMesh.AddGroup( SMDSAbs_Node, currentEnfVertex->grpName.c_str() );
+ SMESHDS_Group * grp = static_cast< SMESHDS_Group* >( group->GetGroupDS() );
+ groupDS = &grp->SMDSGroup();
}
- if (!groupDone)
- throw SALOME_Exception(LOCALIZED("An enforced vertex node was not added to a group"));
+ groupDS->Add( nodes[iv] );
}
- else
- MESSAGE("Group name is empty: '"<<currentEnfVertex->grpName<<"' => group is not created");
- }
}
// internal points are tagged to zero
- if(tag > 0 && tag <= pmap.Extent() ){
+ if ( tag > 0 && tag <= pmap.Extent() )
+ {
meshDS->SetNodeOnVertex(nodes[iv], TopoDS::Vertex(pmap(tag)));
tags[iv] = false;
- } else {
+ }
+ else
+ {
tags[iv] = true;
}
}
/* enumerate edges */
- for(int it=1;it<=ne;it++) {
+ for ( int it = 1; it <= ne; it++ )
+ {
SMDS_MeshEdge* edg;
mesh_get_edge_vertices(msh, it, vtx);
mesh_get_edge_extra_vertices(msh, it, &type, evedg);
// Get the initial tags corresponding to the output tag and redefine the tag as
// the last of the two initial tags (else the output tag is out of emap and hasn't any meaning)
mesh_get_composite_tag_definition(msh, tag, &nb_tag, tags_buff);
- if(nb_tag > 1)
- tag=tags_buff[nb_tag-1];
+ if ( nb_tag > 1 )
+ tag = tags_buff[ nb_tag-1 ];
if ( tag < 1 || tag > emap.Extent() )
{
- std::cerr << "MG-CADSurf BUG:::: Edge tag " << tag
- << " does not point to a CAD edge (nb edges " << emap.Extent() << ")" << std::endl;
+ if ( !enforcedMesh.IsSegmentTag( tag )) // it's a false INTERNAL EDGE of enforced mesh
+ {
+ std::cerr << "MG-CADSurf BUG:::: Edge tag " << tag
+ << " does not point to a CAD edge (nb edges " << emap.Extent() << ")"
+ << std::endl;
+ }
continue;
}
+ if ( meshDS->ShapeToIndex( emap( tag )) == 0 )
+ tag = enforcedMesh.GetTagOfSplitEdge( tag );
+
if (tags[vtx[0]]) {
Set_NodeOnEdge(meshDS, nodes[vtx[0]], emap(tag));
tags[vtx[0]] = false;
*/
status_t curv_fun(real t, real *uv, real *dt, real *dtt, void *user_data)
{
- /* t is given. It contains the t (time) 1D parametric coordintaes
- of the point PreCAD/MG-CADSurf is querying on the curve */
+ /* t is given. It contains the 1D parametric coordintaes
+ of the point MG-CADSurf is querying on the curve */
- /* user_data identifies the edge PreCAD/MG-CADSurf is querying
- * (see cad_edge_new later in this example) */
- const Geom2d_Curve*pargeo = (const Geom2d_Curve*) user_data;
+ /* user_data identifies the edge MG-CADSurf is querying */
+ const Geom2d_Curve* pargeo = (const Geom2d_Curve*) user_data;
- if (uv){
- /* MG-CADSurf is querying the function evaluation */
- gp_Pnt2d P;
- P=pargeo->Value(t);
+ if (uv) {
+ /* MG-CADSurf is querying the function evaluation */
+ gp_Pnt2d P = pargeo->Value(t);
uv[0]=P.X(); uv[1]=P.Y();
}
- if(dt) {
- /* query for the first order derivatives */
- gp_Vec2d V1;
- V1=pargeo->DN(t,1);
+ if (dt) {
+ /* query for the first order derivatives */
+ gp_Vec2d V1 = pargeo->DN(t,1);
dt[0]=V1.X(); dt[1]=V1.Y();
}
- if(dtt){
+ if (dtt) {
/* query for the second order derivatives */
- gp_Vec2d V2;
- V2=pargeo->DN(t,2);
+ gp_Vec2d V2 = pargeo->DN(t,2);
dtt[0]=V2.X(); dtt[1]=V2.Y();
}
typedef std::vector< TEdgePeriodicityIDs > TEdgesIDsPeriodicityVector;
typedef std::vector< TVertexPeriodicityIDs > TVerticesIDsPeriodicityVector;
+ // Point projection on FACE
+ typedef struct {
+ gp_XY uv;
+ gp_XYZ xyz;
+ TopAbs_State state;
+ } projectionPoint;
+
+ static projectionPoint getProjectionPoint(TopoDS_Face& theFace,
+ const gp_Pnt& thePoint,
+ const bool theAllowStateON=false);
protected:
private:
PyObject * main_mod;
PyObject * main_dict;
- SMESH_MesherHelper* myHelper;
volatile bool _compute_canceled;
};
--- /dev/null
+// Copyright (C) 2007-2021 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
+//
+// File : BLSURFPlugin_EnforcedMesh1D.cxx
+// Author : Edward AGAPOV (OCC)
+
+#include "BLSURFPlugin_EnforcedMesh1D.hxx"
+
+#include "BLSURFPlugin_BLSURF.hxx"
+
+#include <SMDS_IteratorOnIterators.hxx>
+#include <SMDS_MeshEdge.hxx>
+#include <SMDS_MeshGroup.hxx>
+#include <SMESHDS_Group.hxx>
+#include <SMESHDS_Mesh.hxx>
+#include <SMESH_Group.hxx>
+#include <SMESH_Mesh.hxx>
+#include <SMESH_MeshAlgos.hxx>
+#include <SMESH_MeshEditor.hxx>
+#include <SMESH_MesherHelper.hxx>
+#include <SMESH_TypeDefs.hxx>
+
+#include <BRepAdaptor_Curve.hxx>
+#include <BRepBuilderAPI_MakeVertex.hxx>
+#include <BRep_Tool.hxx>
+#include <Extrema_ExtCC.hxx>
+#include <Extrema_ExtElC.hxx>
+#include <Geom_Line.hxx>
+#include <ShapeAnalysis_Curve.hxx>
+#include <Geom2d_Line.hxx>
+
+// allow range iteration on NCollection_IndexedMap
+template < class IMAP >
+typename IMAP::const_iterator begin( const IMAP & m ) { return m.cbegin(); }
+template < class IMAP >
+typename IMAP::const_iterator end( const IMAP & m ) { return m.cend(); }
+
+
+namespace
+{
+ //================================================================================
+ /*!
+ * \brief Look for a node coincident with a given nodes among end nodes of a segment
+ * and among its internal nodes
+ * \param [in] p - the epoint
+ * \param [in] tol - 3D tolarace
+ * \param [in] segment - the segment
+ * \param [in] segInternalNodes - map of segment internal nodes
+ * \param [out] index - return index of found internal node; -1 if an end node is found
+ * \return const SMDS_MeshNode* - found node
+ */
+ //================================================================================
+
+ const SMDS_MeshNode* findNode( const gp_Pnt& p,
+ const double tol,
+ const SMDS_MeshElement* segment,
+ BLSURFPlugin_EnforcedMesh1D::TNodesOnSeg & segInternalNodes,
+ int & index )
+ {
+
+ SMESH_NodeXYZ node0 = segment->GetNode(0);
+ if ( p.IsEqual( node0, tol ))
+ return index = -1, node0.Node();
+ SMESH_NodeXYZ node1 = segment->GetNode(1);
+ if ( p.IsEqual( node1, tol ))
+ return index = -1, node1.Node();
+
+ auto seg2nodes = segInternalNodes.find( segment );
+ if ( seg2nodes != segInternalNodes.end() )
+ {
+ const std::vector< const SMDS_MeshNode* >& nodes = seg2nodes->second;
+ for ( size_t i = 0; i < nodes.size(); ++i )
+ if ( p.IsEqual( SMESH_NodeXYZ( nodes[i] ), tol ))
+ {
+ index = (int) i;
+ return nodes[i];
+ }
+ }
+ return nullptr;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Orient segments to correspond to order of nodes in a branch
+ * \param [in] braSegs - segments of the branch
+ * \param [in] braNodes - nodes of the branch
+ * \param [in] nodeIndex - index of a node of the branch
+ * \param [inout] mesh - mesh holding the nodes and segments
+ *
+ *
+ */
+ //================================================================================
+
+ void orientSegments( const std::vector< const SMDS_MeshElement* > & braSegs,
+ const std::vector< const SMDS_MeshNode* > & braNodes,
+ const size_t nodeIndex,
+ SMESH_Mesh* mesh )
+ {
+ const SMDS_MeshElement* toReverse[2] = { nullptr, nullptr };
+
+ if ( nodeIndex > 0 &&
+ braSegs[ nodeIndex - 1 ]->GetNode(1) != braNodes[ nodeIndex ])
+ toReverse[ 0 ] = braSegs[ nodeIndex - 1 ];
+
+ if ( nodeIndex < braSegs.size() &&
+ braSegs[ nodeIndex ]->GetNode(0) != braNodes[ nodeIndex ])
+ toReverse[ bool( toReverse[0]) ] = braSegs[ nodeIndex ];
+
+ if ( !toReverse[0] )
+ return;
+
+ SMESH_MeshEditor editor( mesh );
+ for ( int i = 0; i < 2; ++i )
+ if ( toReverse[ i ])
+ editor.Reorient( toReverse[ i ]);
+ }
+
+} // namespace
+
+//================================================================================
+/*!
+ * \brief Create enforced mesh segments in a mesh
+ * \param [in] helper - contains the mesh and the shape to compute
+ * \param [in] hyp - hypothesis containing data of enforced meshes
+ */
+//================================================================================
+
+BLSURFPlugin_EnforcedMesh1D::BLSURFPlugin_EnforcedMesh1D( SMESH_MesherHelper& helper,
+ const BLSURFPlugin_Hypothesis* hyp )
+ : _mesh ( helper.GetMesh() ),
+ _shape( helper.GetSubShape() ),
+ _helper( *_mesh ),
+ _isQuadratic( helper.GetIsQuadratic() )
+{
+ if ( !hyp || !_mesh || hyp->GetEnforcedMeshes().empty() )
+ return;
+
+ _tol = 2 * BRep_Tool::MaxTolerance( _shape, TopAbs_VERTEX );
+ _segTag = 1000 + helper.Count( _shape, TopAbs_EDGE, /*ignoreSame=*/false );
+ _segTag0 = _segTag;
+ _nodeTag0 = 1000 + helper.Count( _shape, TopAbs_VERTEX, /*ignoreSame=*/false );
+
+ for ( const BLSURFPlugin_Hypothesis::EnforcedMesh& enfMesh : hyp->GetEnforcedMeshes() )
+ {
+ copyEnforcedMesh( enfMesh, hyp, _shape );
+ }
+
+ for ( const SMDS_MeshElement* segment : _segmentsOnSeveralShapes )
+ {
+ splitSegmentOnSeveralShapes( segment );
+ }
+
+ for ( const TopoDS_Shape & face : _faces )
+ {
+ splitSelfIntersectingSegments( face );
+ }
+
+ for ( TEdge2Nodes::Iterator e2nn( _nodesOnEdge ); e2nn.More(); e2nn.Next() )
+ {
+ splitEdgeByNodes( e2nn.Key(), e2nn.Value() );
+ }
+}
+
+//================================================================================
+/*!
+ * \brief Convert enforced segments to quadratic
+ */
+//================================================================================
+
+BLSURFPlugin_EnforcedMesh1D::~BLSURFPlugin_EnforcedMesh1D()
+{
+ if ( !_isQuadratic )
+ return;
+
+ _helper.SetIsQuadratic( true );
+
+ SMESHDS_Mesh* meshDS = _mesh->GetMeshDS();
+ std::vector<const SMDS_MeshNode *> nodes(2);
+ std::vector<const SMDS_MeshElement *> trias;
+
+ SMDS_MeshGroup* group = nullptr;
+ if ( !_name2Group.empty() )
+ group = _name2Group.begin()->second;
+
+ for ( const TopoDS_Shape& f : _faces )
+ if ( HasSegmentsOnFace( TopoDS::Face( f )))
+ while ( _segIterator->more() )
+ {
+ const SMDS_MeshElement* segment = _segIterator->next();
+ if ( segment->GetType() != SMDSAbs_Edge )
+ break;
+
+ nodes[0] = segment->GetNode(0);
+ nodes[1] = segment->GetNode(1);
+ if ( meshDS->GetElementsByNodes( nodes, trias, SMDSAbs_Face ))
+ {
+ if ( !group || !group->Contains( segment ))
+ {
+ SMDS_MeshGroup* otherGroup = nullptr;
+ if ( _name2Group.size() > bool( group ))
+ for ( auto & n2g : _name2Group )
+ if ( n2g.second != group && n2g.second->Contains( segment ))
+ {
+ otherGroup = n2g.second;
+ break;
+ }
+ group = otherGroup;
+ }
+
+ _helper.AddTLinks( static_cast< const SMDS_MeshFace* >( trias[0] ));
+
+ meshDS->RemoveFreeElement( segment, meshDS->MeshElements( f ), /*fromGroup=*/false );
+
+ SMDS_MeshElement* quadSegment = _helper.AddEdge( nodes[0], nodes[1],
+ /*id=*/0, /*force3d=*/false );
+ if ( group && segment != quadSegment )
+ {
+ group->Remove( segment );
+ group->Add( quadSegment );
+ }
+ }
+ }
+ return;
+}
+
+//================================================================================
+/*!
+ * \brief Return EDGEs resulted from division of FACE boundary by enforced segments
+ * \param [in] edge - possibly divided EDGE
+ * \param [out] splits - split EDGEs
+ * \return bool - true if the EDGE is split
+ */
+//================================================================================
+
+bool BLSURFPlugin_EnforcedMesh1D::GetSplitsOfEdge( const TopoDS_Edge& edge,
+ std::vector< TopoDS_Edge > & splits,
+ TopTools_IndexedMapOfShape & edgeTags )
+{
+ std::vector< TopoDS_Edge > * splitsInMap = _edgeSplitsOfEdge.ChangeSeek( edge );
+ if ( !splitsInMap )
+ return false;
+
+ splits.insert( splits.end(), splitsInMap->begin(), splitsInMap->end() );
+
+ int eTag = edgeTags.Add( edge );
+
+ size_t index = splits.size() - 1;
+ for ( size_t i = 0; i < splitsInMap->size(); ++i, --index )
+ {
+ int splitTag = edgeTags.Add( splits[ index ]);
+ _splitTags2EdgeTag[ splitTag ] = eTag;
+
+ if ( edge.Orientation() == TopAbs_REVERSED )
+ splits[ index ].Reverse();
+ }
+
+ return true;
+}
+
+
+//================================================================================
+/*!
+ * \brief Add 1D elements to the mesh
+ */
+//================================================================================
+
+void BLSURFPlugin_EnforcedMesh1D::
+
+copyEnforcedMesh( const BLSURFPlugin_Hypothesis::EnforcedMesh& theEnfMesh,
+ const BLSURFPlugin_Hypothesis* theHyp,
+ const TopoDS_Shape& theShape)
+{
+ SMESH_Mesh* mesh1D;
+ SMDS_ElemIteratorPtr segIt = theHyp->GetEnforcedSegments( theEnfMesh, mesh1D );
+ if ( !segIt->more() )
+ return;
+
+ // setup predicates to detect nodes on FACE boundary
+ setupPredicates( theShape );
+
+ SMDS_MeshGroup* group = getGroup( theEnfMesh._groupName );
+ SMESHDS_Mesh* meshDS = _helper.GetMeshDS();
+
+ // get ordered nodes and segments of theEnfMesh
+ SMESH_MeshAlgos::TElemGroupVector edgeBranches;
+ SMESH_MeshAlgos::TNodeGroupVector nodeBranches;
+ SMESH_MeshAlgos::Get1DBranches( segIt, edgeBranches, nodeBranches );
+
+
+ // Copy nodes and segments from an enforced mesh to my mesh
+
+ TopoDS_Shape vertex, edge;
+
+ // first treat ends of branches that can be shared by branches
+ for ( size_t iB = 0; iB < nodeBranches.size(); ++iB )
+ {
+ std::vector< const SMDS_MeshNode* > & braNodes = nodeBranches[ iB ];
+ std::vector< const SMDS_MeshElement* > & braSegs = edgeBranches[ iB ];
+
+ for ( int isLast = 0; isLast < 2; ++isLast )
+ {
+ const SMDS_MeshNode* enfNode = isLast ? braNodes.back() : braNodes[0];
+ if ( meshDS->Contains( enfNode ))
+ continue; // already in my mesh
+
+ const SMDS_MeshNode* newNode = copyEnforcedNode( enfNode );
+ if ( !newNode )
+ orientSegments( braSegs, braNodes, isLast ? 0 : braNodes.size() - 1, mesh1D );
+
+ // replace enfNode at branch ends by newNode
+ SMESH_NodeXYZ enfPnt( newNode ? newNode : enfNode );
+ for ( std::vector< const SMDS_MeshNode* > & braNodes : nodeBranches )
+ {
+ for ( int isLast = 0; isLast < 2; ++isLast )
+ {
+ const SMDS_MeshNode* & endNode = isLast ? braNodes.back() : braNodes[0];
+ if ( endNode == enfNode || enfPnt.SquareDistance( endNode ) < _tol*_tol )
+ endNode = newNode;
+ }
+ }
+ continue;
+ } // loop on branch ends
+ } // loop on nodeBranches
+
+ // copy nodes and segments
+
+ for ( size_t iB = 0; iB < nodeBranches.size(); ++iB )
+ {
+ std::vector< const SMDS_MeshNode* > & braNodes = nodeBranches[ iB ];
+ std::vector< const SMDS_MeshElement* > & braSegs = edgeBranches[ iB ];
+
+ // copy nodes of the branch
+ for ( size_t i = 0; i < braNodes.size(); ++i )
+ {
+ const SMDS_MeshNode* & enfNode = braNodes[ i ];
+ const SMDS_MeshNode* newNode = copyEnforcedNode( enfNode );
+
+ if ( !newNode ) // orient segments to be able to get enforced not projected node
+ orientSegments( braSegs, braNodes, i, mesh1D );
+
+ enfNode = newNode;
+ }
+
+ // copy segments of the branch
+ for ( size_t i = 0; i < braSegs.size(); ++i )
+ {
+ //braSegs[ i ] = nullptr;
+
+ const SMDS_MeshNode* node0 = braNodes[ i ];
+ const SMDS_MeshNode* node1 = braNodes[ i + 1 ];
+ if ( !node0 && !node1 )
+ continue;
+
+ TopoDS_Shape shape0 = _helper.GetSubShapeByNode( node0, meshDS );
+ TopoDS_Shape shape1 = _helper.GetSubShapeByNode( node1, meshDS );
+ if ( shape0.IsNull() && shape1.IsNull() )
+ continue;
+
+ if ( !node0 && shape1.ShapeType() != TopAbs_FACE )
+ continue;
+ if ( !node1 && shape0.ShapeType() != TopAbs_FACE )
+ continue;
+
+ if ( !node0 || !node1 ) // create missing node at location of enforced node projected nowhere
+ {
+ SMESH_NodeXYZ pn = braSegs[i]->GetNode( !node1 );
+ ( node0 ? node1 : node0 ) = _helper.AddNode( pn->X(), pn->Y(), pn->Z() );
+ }
+
+ SMDS_MeshEdge* newSeg = _helper.AddEdge( node0, node1 );
+ if ( group )
+ group->Add( newSeg );
+ braSegs[ i ] = newSeg;
+
+ // check if the both nodes are on the same FACE
+ TopoDS_Shape face = shape0;
+ if ( !shape0.IsSame( shape1 ) && !shape0.IsNull() && !shape1.IsNull() )
+ {
+ if ( shape0.ShapeType() == TopAbs_FACE &&
+ _helper.IsSubShape( shape1, shape0 ))
+ {
+ face = shape0;
+ }
+ else if ( shape1.ShapeType() == TopAbs_FACE &&
+ _helper.IsSubShape( shape0, shape1 ))
+ {
+ face = shape1;
+ }
+ else // try to find a FACE by projecting a segment middle point
+ {
+ face.Nullify();
+ gp_Pnt middlePnt = 0.5 * ( SMESH_NodeXYZ( node0 ) + SMESH_NodeXYZ( node1 ));
+ //BLSURFPlugin_BLSURF::projectionPoint projPnt =
+ BLSURFPlugin_BLSURF::getProjectionPoint( TopoDS::Face( face ), middlePnt );
+
+ if ( !face.IsNull() &&
+ ( !_helper.IsSubShape( shape0, face ) ||
+ !_helper.IsSubShape( shape1, face ) ))
+ face.Nullify();
+ }
+ }
+ if ( !face.IsNull() && face.ShapeType() == TopAbs_FACE )
+ {
+ meshDS->SetMeshElementOnShape( newSeg, face );
+ _faces.Add( face );
+ }
+
+ if ( face.IsNull() || shape0.IsNull() || shape1.IsNull() )
+ {
+ _segmentsOnSeveralShapes.push_back( newSeg );
+ }
+
+ } // loop on branch segments
+ continue;
+ } // loop on branches
+
+ return;
+}
+
+//================================================================================
+/*!
+ * \brief Create a copy of a node of enforced mesh in my mesh
+ * \param [in] enfNode - enforced node
+ * \return const SMDS_MeshNode* - a node in my mesh
+ */
+//================================================================================
+
+const SMDS_MeshNode* BLSURFPlugin_EnforcedMesh1D::copyEnforcedNode( const SMDS_MeshNode* enfNode )
+{
+ SMESHDS_Mesh * meshDS = _helper.GetMeshDS();
+
+ if ( !enfNode || meshDS->Contains( enfNode ))
+ return enfNode; // already in my mesh
+
+ SMESH_NodeXYZ enfPnt = enfNode;
+
+ const SMDS_MeshNode* newNode = nullptr;
+
+ // check if enfNode is on VERTEX
+ TopoDS_Vertex vertex;
+ if ( _onVertexPredicate->IsSatisfy( enfNode, &vertex ))
+ {
+ _mesh->GetSubMesh( vertex )->ComputeStateEngine( SMESH_subMesh::COMPUTE );
+ newNode = SMESH_Algo::VertexNode( vertex, meshDS );
+ }
+
+ // check if enfNode is on EDGE
+ bool setNodeOnEdge = false;
+ TopoDS_Edge edge;
+ if ( !newNode )
+ {
+ setNodeOnEdge = _onEdgePredicate->IsSatisfy( enfNode, &edge );
+ if ( setNodeOnEdge )
+ {
+ newNode = findNodeOnEdge( enfPnt, edge );
+ setNodeOnEdge = !newNode;
+ }
+ }
+
+ // create a new node and set it on FACE
+ if ( !newNode )
+ {
+ TopoDS_Face face;
+ BLSURFPlugin_BLSURF::projectionPoint projPnt =
+ BLSURFPlugin_BLSURF::getProjectionPoint( face, enfPnt, /*allowStateON=*/true );
+ if ( face.IsNull() ) return newNode;
+
+ if ( projPnt.state == TopAbs_ON )
+ {
+ SMDS_MeshNode* projNode = const_cast< SMDS_MeshNode* >( enfNode );
+ projNode->setXYZ( projPnt.xyz.X(), projPnt.xyz.Y(), projPnt.xyz.Z() );
+ vertex.Nullify();
+ edge.Nullify();
+ if ( _onVertexPredicate->IsSatisfy( projNode, &vertex ))
+ {
+ _mesh->GetSubMesh( vertex )->ComputeStateEngine( SMESH_subMesh::COMPUTE );
+ newNode = SMESH_Algo::VertexNode( vertex, meshDS );
+ }
+ else if (( setNodeOnEdge = _onEdgePredicate->IsSatisfy( projNode, &edge )))
+ {
+ newNode = findNodeOnEdge( projPnt.xyz, edge );
+ setNodeOnEdge = !newNode;
+ }
+ projNode->setXYZ( enfPnt.X(), enfPnt.Y(), enfPnt.Z() );
+ }
+
+ if ( !newNode )
+ newNode = meshDS->AddNode( projPnt.xyz.X(), projPnt.xyz.Y(), projPnt.xyz.Z() );
+
+ if ( vertex.IsNull() && edge.IsNull() )
+ meshDS->SetNodeOnFace( newNode, face, projPnt.uv.X(), projPnt.uv.Y() );
+ }
+
+ // set the new node on EDGE
+ if ( newNode && setNodeOnEdge )
+ {
+ addNodeOnEdge( newNode, edge );
+ }
+
+ return newNode;
+}
+
+//================================================================================
+/*!
+ * \brief Split a segment whose nodes are on different FACEs into smaller parts
+ * lying each on one FACE
+ */
+//================================================================================
+
+void BLSURFPlugin_EnforcedMesh1D::splitSegmentOnSeveralShapes( const SMDS_MeshElement* segment )
+{
+ const SMDS_MeshNode* node0 = segment->GetNode(0);
+ const SMDS_MeshNode* node1 = segment->GetNode(1);
+ SMESHDS_Mesh * meshDS = _helper.GetMeshDS();
+
+ TopoDS_Shape shape0 = _helper.GetSubShapeByNode( node0, meshDS );
+ TopoDS_Shape shape1 = _helper.GetSubShapeByNode( node1, meshDS );
+
+ if ( shape0.IsNull() )
+ {
+ std::swap( node0, node1 );
+ shape0 = shape1;
+ shape1.Nullify();
+ }
+
+ gp_XYZ xyz0 = SMESH_NodeXYZ( node0 );
+ gp_XYZ xyz1 = SMESH_NodeXYZ( node1 );
+ gp_XYZ segDir = ( xyz1 - xyz0 ).Normalized();
+
+ //std::map< double, const SMDS_MeshNode* > mediumNodes; // nodes splitting the segment
+
+ while ( !shape0.IsSame( shape1 )) // move along the segment till shape1
+ {
+ if ( shape0.ShapeType() == TopAbs_FACE ) // make a node on an EDGE of the FACE
+ { // ----------------------------------
+ TopoDS_Edge edge;
+ double paramOnE;
+ gp_Pnt edgeIntPnt = getEdgeIntersection( shape0, xyz0, xyz1, edge, paramOnE );
+ if ( edge.IsNull() )
+ break;
+
+ // check if edgeIntPnt in on VERTEX
+ TopoDS_Vertex vertex;
+ for ( int iV = 0; iV < 2 && vertex.IsNull(); ++iV )
+ {
+ TopoDS_Vertex v = _helper.IthVertex( iV, edge );
+ if ( edgeIntPnt.SquareDistance( BRep_Tool::Pnt( v )) < _tol *_tol )
+ vertex = v;
+ }
+
+ // make a node on the EDGE
+ const SMDS_MeshNode* nodeOnEdge = nullptr;
+ if ( vertex.IsNull() )
+ {
+ nodeOnEdge = findNodeOnEdge( edgeIntPnt, edge );
+ if ( !nodeOnEdge )
+ {
+ if ( shape1.IsNull() && node1 )
+ {
+ nodeOnEdge = node1;
+ node1 = nullptr;
+ meshDS->MoveNode( nodeOnEdge, edgeIntPnt.X(), edgeIntPnt.Y(), edgeIntPnt.Z() );
+ }
+ else
+ {
+ nodeOnEdge = _helper.AddNode( edgeIntPnt.X(), edgeIntPnt.Y(), edgeIntPnt.Z() );
+ }
+ addNodeOnEdge( nodeOnEdge, edge, paramOnE );
+ }
+ }
+ else
+ {
+ _mesh->GetSubMesh( vertex )->ComputeStateEngine( SMESH_subMesh::COMPUTE );
+ nodeOnEdge = SMESH_Algo::VertexNode( vertex, meshDS );
+ }
+
+ // create a sub-segment
+ SMDS_MeshElement* newSeg = _helper.AddEdge( node0, nodeOnEdge );
+ meshDS->SetMeshElementOnShape( newSeg, shape0 );
+
+ SMESH_MeshEditor::AddToSameGroups( newSeg, segment, meshDS );
+
+ node0 = nodeOnEdge;
+ xyz0 = SMESH_NodeXYZ( node0 );
+ if ( vertex.IsNull() )
+ shape0 = edge;
+ else
+ shape0 = vertex;
+ }
+
+ else // shape0 is EDGE or VERTEX; look for the next FACE
+ { // ------------------------------------------------
+
+ if ( !shape1.IsNull() &&
+ shape1.ShapeType() == TopAbs_FACE &&
+ _helper.IsSubShape( shape0, shape1 )) // shape0 belongs to FACE shape1
+ {
+ SMDS_MeshElement* newSeg = _helper.AddEdge( node0, node1 );
+ SMESH_MeshEditor::AddToSameGroups( newSeg, segment, meshDS );
+ meshDS->SetMeshElementOnShape( newSeg, shape1 );
+ break;
+ }
+ // FACE search
+ TopoDS_Face face;
+ double shift = 10 * _tol;
+ for ( int nbAttemp = 0; face.IsNull() && nbAttemp < 10; ++nbAttemp )
+ {
+ xyz0 += segDir * shift;
+ shift *= 2;
+ BLSURFPlugin_BLSURF::getProjectionPoint( face, xyz0 );
+ }
+ if ( !face.IsNull() )
+ {
+ if ( _helper.IsSubShape( shape0, face ))
+ _faces.Add( face );
+ else
+ break;
+ shape0 = face;
+ }
+ else
+ {
+ break;
+ }
+ }
+ continue;
+ } //while ( !shape0.IsSame( shape1 ))
+
+ meshDS->RemoveFreeElement( segment, /*submesh=*/nullptr );
+}
+
+//================================================================================
+/*!
+ * \brief Find intersection of FACE EDGEs and a segment
+ * \param [in] theFace - the FACE
+ * \param [in] thePnt0 - first end of the segment
+ * \param [in] thePnt1 - last end of the segment
+ * \param [out] theFounfEdge - return the intersected EDGE
+ * \param [out] theParamOnEdge - return parameter of intersection point on EDGE
+ * \return gp_XYZ - point on an EDGE closest to the segment
+ */
+//================================================================================
+
+gp_Pnt BLSURFPlugin_EnforcedMesh1D::getEdgeIntersection( const TopoDS_Shape& theFaceOrEdge,
+ const gp_XYZ& thePnt0,
+ const gp_XYZ& thePnt1,
+ TopoDS_Edge & theFounfEdge,
+ double & theParamOnEdge)
+{
+ const double segLen = ( thePnt1 - thePnt0 ).Modulus();
+ const double maxSegDist2 = segLen * segLen * 0.5 * 0.5;
+
+ Handle(Geom_Line) segLine = new Geom_Line( thePnt0, thePnt1 - thePnt0 );
+ GeomAdaptor_Curve segLineAdpt( segLine, 0, segLen );
+
+ TopTools_MapOfShape edges;
+ double minParamOnSeg = segLen;
+ gp_Pnt foundPnt;
+ for ( TopExp_Explorer edgeExp( theFaceOrEdge, TopAbs_EDGE ); edgeExp.More(); edgeExp.Next() )
+ {
+ const TopoDS_Edge& edge = TopoDS::Edge( edgeExp.Current() );
+ if ( !edges.Add( edge ))
+ continue;
+
+ Extrema_ExtCC extrema( segLineAdpt, BRepAdaptor_Curve( edge ), _tol, _tol );
+
+ if ( extrema.IsDone() && !extrema.IsParallel() )
+ for ( int i = 1, nb = extrema.NbExt(); i <= nb; ++i )
+ if ( extrema.SquareDistance( i ) < maxSegDist2 )
+ {
+ Extrema_POnCurv pOnSeg, pOnEdge;
+ extrema.Points( i, pOnSeg, pOnEdge );
+ double paramOnSeg = pOnSeg.Parameter();
+ if ( 0 < paramOnSeg && paramOnSeg < minParamOnSeg )
+ {
+ minParamOnSeg = paramOnSeg;
+ foundPnt = pOnEdge.Value();
+ theFounfEdge = edge;
+ theParamOnEdge = pOnEdge.Parameter();
+ }
+ }
+ }
+ return foundPnt;
+}
+
+//================================================================================
+/*!
+ * \brief Split self-intersecting segments on a given FACE
+ */
+//================================================================================
+
+void BLSURFPlugin_EnforcedMesh1D::splitSelfIntersectingSegments( const TopoDS_Shape & theFace )
+{
+ const TopoDS_Face& face = TopoDS::Face( theFace );
+
+ SMESHDS_Mesh* meshDS = _helper.GetMeshDS();
+ SMESHDS_SubMesh* sm = meshDS->MeshElements( face );
+ if ( !sm || sm->NbElements() <= 1 )
+ return;
+
+ // get ordered nodes and segments on the face
+ SMESH_MeshAlgos::TElemGroupVector edgeBranches;
+ SMESH_MeshAlgos::TNodeGroupVector nodeBranches;
+ SMESH_MeshAlgos::Get1DBranches( sm->GetElements(), edgeBranches, nodeBranches );
+
+ // create element searcher
+ SMESH_ElementSearcher* elemSearcher;
+ SMESHUtils::Deleter< SMESH_ElementSearcher > elSearchdeleter;
+ std::vector< const SMDS_MeshElement* > foundElems;
+ {
+ std::vector< SMDS_ElemIteratorPtr > elemItVec;
+ for ( std::vector< const SMDS_MeshElement* > & braSegs : edgeBranches )
+ {
+ SMDS_ElemIteratorPtr segIt =
+ boost::make_shared< SMDS_ElementVectorIterator >( braSegs.begin(), braSegs.end() );
+ elemItVec.push_back( segIt );
+ }
+ typedef SMDS_IteratorOnIterators< const SMDS_MeshElement*,
+ std::vector< SMDS_ElemIteratorPtr > > TVecIterator;
+ SMDS_ElemIteratorPtr segIt = boost::make_shared< TVecIterator >( elemItVec );
+
+ elemSearcher = SMESH_MeshAlgos::GetElementSearcher( *meshDS, segIt, _tol );
+ elSearchdeleter._obj = elemSearcher;
+
+ // force usage of iterators before they die
+ elemSearcher->FindElementsByPoint( gp_Pnt( 0,0,1e+20), SMDSAbs_Edge, foundElems );
+ }
+
+
+ // Find intersecting segments
+
+ std::map< const SMDS_MeshElement* , std::vector< const SMDS_MeshNode* > > segInternalNodes;
+ SMESH_MeshEditor::TListOfListOfNodes nodeGroupsToMerge;
+
+ for ( std::vector< const SMDS_MeshElement* > & braSegs : edgeBranches )
+ {
+ braSegs.push_back( braSegs.back() );
+ const SMDS_MeshElement* prevSeg = nullptr;
+
+ for ( size_t i = 0, nb = braSegs.size() - 1; i < nb; ++i )
+ {
+ const SMDS_MeshElement* seg = braSegs[ i ];
+ const SMDS_MeshElement* nextSeg = braSegs[ i + 1 ];
+ const SMDS_MeshNode* node0 = seg->GetNode(0);
+ const SMDS_MeshNode* node1 = seg->GetNode(1);
+
+ gp_XYZ xyz0 = SMESH_NodeXYZ( node0 );
+ gp_XYZ xyz1 = SMESH_NodeXYZ( node1 );
+ gp_XYZ middlePnt = 0.5 * ( SMESH_NodeXYZ( node0 ) + SMESH_NodeXYZ( node1 ));
+ double segLen = ( xyz0 - xyz1 ).Modulus();
+
+ foundElems.clear();
+ elemSearcher->GetElementsInSphere( middlePnt, 0.5 * segLen + _tol, SMDSAbs_Edge, foundElems );
+
+ for ( const SMDS_MeshElement* closeSeg : foundElems )
+ {
+ if ( closeSeg == prevSeg ||
+ closeSeg >= seg ||
+ closeSeg == nextSeg )
+ continue;
+
+ gp_Pnt intPnt;
+ gp_Pnt2d uv;
+ if ( intersectSegments( seg, closeSeg, face, intPnt, uv ))
+ {
+ int i0, i1;
+ const SMDS_MeshNode* intNode0 = findNode( intPnt, _tol, seg, segInternalNodes, i0 );
+ const SMDS_MeshNode* intNode1 = findNode( intPnt, _tol, closeSeg, segInternalNodes, i1 );
+ if ( !intNode0 && intNode1 )
+ {
+ segInternalNodes[ seg ].push_back( intNode1 );
+ }
+ else if ( !intNode1 && intNode0 )
+ {
+ segInternalNodes[ closeSeg ].push_back( intNode0 );
+ }
+ else if ( intNode1 && intNode0 )
+ {
+ if ( intNode1 == intNode0 )
+ continue;
+ if ( i0 < 0 && i1 < 0 )
+ {
+ nodeGroupsToMerge.push_back // merge end nodes
+ ( std::list< const SMDS_MeshNode* >({ intNode0, intNode1 }));
+ }
+ else if ( i0 < 0 )
+ {
+ segInternalNodes[ closeSeg ][ i1 ] = intNode0;
+ }
+ else if ( i1 < 0 )
+ {
+ segInternalNodes[ seg ][ i0 ] = intNode1;
+ }
+ else // two internal nodes coincide
+ {
+ segInternalNodes[ seg ][ i0 ] = intNode1;
+ nodeGroupsToMerge.push_back
+ ( std::list< const SMDS_MeshNode* >({ intNode1, intNode0 }));
+ }
+ }
+ else // ( !intNode1 && !intNode0 )
+ {
+ intNode0 = _helper.AddNode( intPnt.X(), intPnt.Y(), intPnt.Z() );
+ meshDS->SetNodeOnFace( intNode0, face, uv.X(), uv.Y() );
+ segInternalNodes[ seg ].push_back( intNode0 );
+ segInternalNodes[ closeSeg ].push_back( intNode0 );
+ }
+ }
+ }
+
+ prevSeg = seg;
+
+ } // loop on segments of a branch
+ } // loop on branches
+
+
+ findIntersectionWithSeamEdge( face, segInternalNodes ); // on periodic FACE
+
+
+ // Split segments
+
+ for ( auto& seg2nodes : segInternalNodes )
+ {
+ const SMDS_MeshElement* seg = seg2nodes.first;
+ std::vector< const SMDS_MeshNode* > & nodes = seg2nodes.second;
+ if ( nodes.empty() ) continue;
+
+ const SMDS_MeshNode* n0 = seg->GetNode( 0 );
+ const SMDS_MeshNode* n1 = seg->GetNode( 1 );
+ nodes.push_back( n1 );
+
+ // sort nodes on the segment
+ gp_Pnt p0 = SMESH_NodeXYZ( n0 );
+ std::map< double, const SMDS_MeshNode* > sortedNodes;
+ for ( SMESH_NodeXYZ pn : nodes )
+ sortedNodes.insert({ p0.SquareDistance( pn ), pn.Node() });
+
+ // make new segments
+ for ( auto & d2n : sortedNodes )
+ {
+ n1 = d2n.second;
+ SMDS_MeshElement* newSeg = _helper.AddEdge( n0, n1 );
+ n0 = n1;
+ meshDS->SetMeshElementOnShape( newSeg, face );
+ SMESH_MeshEditor::AddToSameGroups( newSeg, seg, meshDS );
+ }
+ meshDS->RemoveFreeElement( seg, /*submesh=*/nullptr );
+ }
+
+
+ // merge equal nodes
+ SMESH_MeshEditor( _mesh ).MergeNodes( nodeGroupsToMerge );
+}
+
+//================================================================================
+/*!
+ * \brief Find intersections of segments with a seam EDGE on a periodic FACE
+ */
+//================================================================================
+
+void BLSURFPlugin_EnforcedMesh1D::findIntersectionWithSeamEdge( const TopoDS_Face & face,
+ TNodesOnSeg & segInternalNodes )
+{
+ _helper.SetSubShape( face );
+ if ( !_helper.HasSeam() )
+ return;
+
+ SMESHDS_Mesh* meshDS = _helper.GetMeshDS();
+ SMESHDS_SubMesh* sm = meshDS->MeshElements( face );
+ if ( !sm || sm->NbElements() == 0 )
+ return;
+
+ TopTools_MapOfShape treatedEdges;
+ for ( TopExp_Explorer edgeExp( face, TopAbs_EDGE ); edgeExp.More(); edgeExp.Next() )
+ {
+ const TopoDS_Edge& edge = TopoDS::Edge( edgeExp.Current() );
+ if ( !_helper.IsSeamShape( edge ) || !treatedEdges.Add( edge ))
+ continue;
+
+ for ( SMDS_ElemIteratorPtr setIt = sm->GetElements(); setIt->more(); )
+ {
+ const SMDS_MeshElement* segment = setIt->next();
+ const SMESH_NodeXYZ pn0 = segment->GetNode( 0 );
+ const SMESH_NodeXYZ pn1 = segment->GetNode( 1 );
+
+ gp_XY uv0 = _helper.GetNodeUV( face, pn0.Node() );
+ gp_XY uv1 = _helper.GetNodeUV( face, pn1.Node() );
+
+ for ( int iCoo = 1; iCoo <= 2; ++iCoo )
+ if ( iCoo & _helper.GetPeriodicIndex() )
+ {
+ double distParam = Abs( uv0.Coord( iCoo ) - uv1.Coord( iCoo ));
+ if ( distParam > 0.5 * _helper.GetPeriod( iCoo ))
+ {
+ double paramOnE; TopoDS_Edge edge2;
+ gp_Pnt edgeIntPnt = getEdgeIntersection( edge, pn0, pn1, edge2, paramOnE );
+ if ( edge2.IsNull() )
+ continue;
+
+ const SMDS_MeshNode* nodeOnSeam = findNodeOnEdge( edgeIntPnt, edge );
+ bool isOnEdge = nodeOnSeam;
+
+ int indexOnSegment = 3;
+ if ( !nodeOnSeam )
+ nodeOnSeam = findNode( edgeIntPnt, _tol, segment, segInternalNodes, indexOnSegment );
+
+ if ( !nodeOnSeam )
+ {
+ nodeOnSeam = _helper.AddNode( edgeIntPnt.X(), edgeIntPnt.Y(), edgeIntPnt.Z() );
+ }
+
+ if ( !isOnEdge )
+ {
+ addNodeOnEdge( nodeOnSeam, edge, paramOnE );
+ }
+ if ( indexOnSegment == 3 )
+ segInternalNodes[ segment ].push_back( nodeOnSeam );
+ }
+ }
+ }
+ }
+}
+
+//================================================================================
+/*!
+ * \brief Intersect two segments
+ * \param [in] seg1 - segment 1
+ * \param [in] seg2 - segment 2
+ * \param [in] face - the FACE on which segments lie
+ * \param [out] intPnt - intersection point
+ * \param [out] intUV - UV of intersection point on the FACE
+ * \return bool - true if intersection found
+ */
+//================================================================================
+
+bool BLSURFPlugin_EnforcedMesh1D::intersectSegments( const SMDS_MeshElement* seg1,
+ const SMDS_MeshElement* seg2,
+ const TopoDS_Face& face,
+ gp_Pnt & intPnt,
+ gp_Pnt2d & intUV ) const
+{
+ SMESH_NodeXYZ n10 = seg1->GetNode(0);
+ SMESH_NodeXYZ n11 = seg1->GetNode(1);
+ SMESH_NodeXYZ n20 = seg2->GetNode(0);
+ SMESH_NodeXYZ n21 = seg2->GetNode(1);
+ if ( n10 == n20 || n10 == n21 || n11 == n20 || n10 == n21 )
+ return false;
+
+ gp_Lin lin1( n10, n11 - n10 );
+ gp_Lin lin2( n20, n21 - n20 );
+
+ Extrema_ExtElC extrema( lin1, lin2, Precision::Angular() );
+
+ if ( !extrema.IsDone() || extrema.IsParallel() )
+ return false;
+
+ Extrema_POnCurv poc1, poc2;
+ extrema.Points( 1, poc1, poc2 );
+
+ double len1 = lin1.Direction().XYZ() * ( n11 - n10 );
+ double len2 = lin2.Direction().XYZ() * ( n21 - n20 );
+ double u1 = poc1.Parameter();
+ double u2 = poc2.Parameter();
+
+ if ( u1 < -_tol || u1 > len1 + _tol )
+ return false;
+ if ( u2 < -_tol || u2 > len2 + _tol )
+ return false;
+
+ intPnt = 0.5 * ( poc1.Value().XYZ() + poc2.Value().XYZ() );
+
+ // compute approximate UV
+
+ u1 /= len1;
+ u2 /= len2;
+
+ gp_XY uv10 = _helper.GetNodeUV( face, n10.Node(), n11.Node() );
+ gp_XY uv11 = _helper.GetNodeUV( face, n11.Node(), n10.Node() );
+ gp_XY uv1 = uv10 * ( 1 - u1 ) + uv11 * u1;
+
+ gp_XY uv20 = _helper.GetNodeUV( face, n20.Node(), n21.Node() );
+ gp_XY uv21 = _helper.GetNodeUV( face, n21.Node(), n20.Node() );
+ gp_XY uv2 = uv20 * ( 1 - u2 ) + uv21 * u2;
+
+ intUV = 0.5 * ( uv1 + uv2 );
+
+ // compute precise UV and XYZ by projecting intPnt to the FACE
+
+ Handle(ShapeAnalysis_Surface) surface = _helper.GetSurface( face );
+ intUV = surface->NextValueOfUV( intUV, intPnt, _tol );
+ if ( surface->Gap() > Min( len1, len2 ))
+ intUV = surface->ValueOfUV( intPnt, _tol );
+
+ intPnt = surface->Value( intUV );
+
+ return true;
+}
+
+//================================================================================
+/*!
+ * \brief Setup predicates to detect nodes on FACE boundary
+ * \param [in] shape - shape containing FACEs to mesh
+ */
+//================================================================================
+
+void BLSURFPlugin_EnforcedMesh1D::setupPredicates( const TopoDS_Shape& theShape )
+{
+ if ( _onVertexPredicate )
+ return;
+
+ _onVertexPredicate.reset( new TPredicate() );
+ _onVertexPredicate->SetTolerance( _tol );
+ _onVertexPredicate->SetMesh( _helper.GetMeshDS() );
+ {
+ TopTools_IndexedMapOfShape vertices;
+ TopExp::MapShapes( theShape, TopAbs_VERTEX, vertices );
+ TopoDS_Compound vCompound;
+ BRep_Builder builder;
+ builder.MakeCompound( vCompound );
+ for ( const TopoDS_Shape& v : vertices )
+ builder.Add( vCompound, v );
+
+ _onVertexPredicate->SetShape( vCompound, SMDSAbs_Node );
+ }
+
+
+ _onEdgePredicate.reset( new TPredicate() );
+ _onEdgePredicate->SetTolerance( _tol );
+ _onEdgePredicate->SetMesh( _helper.GetMeshDS() );
+ {
+ TopTools_IndexedMapOfShape edges;
+ TopExp::MapShapes( theShape, TopAbs_EDGE, edges );
+ TopoDS_Compound eCompound;
+ BRep_Builder builder;
+ builder.MakeCompound( eCompound );
+ for ( const TopoDS_Shape& e : edges )
+ builder.Add( eCompound, e );
+
+ _onEdgePredicate->SetShape( eCompound, SMDSAbs_Node );
+ }
+ return;
+}
+
+//================================================================================
+/*!
+ * \brief Find or create a group of edges with given name
+ */
+//================================================================================
+
+SMDS_MeshGroup* BLSURFPlugin_EnforcedMesh1D::getGroup( const std::string& groupName )
+{
+ SMDS_MeshGroup* group = nullptr;
+ if ( !groupName.empty() )
+ {
+ if ( _name2Group.count( groupName ))
+ return _name2Group[ groupName ];
+
+ // find existing group
+ for ( SMESH_Mesh::GroupIteratorPtr grIt = _mesh->GetGroups(); grIt->more(); )
+ {
+ SMESH_Group* grp = grIt->next();
+ SMESHDS_Group* grpDS = dynamic_cast< SMESHDS_Group* >( grp->GetGroupDS() );
+ if ( grpDS &&
+ grpDS->GetType() == SMDSAbs_Edge &&
+ groupName == grp->GetName() )
+ {
+ _name2Group[ groupName ] = & grpDS->SMDSGroup();
+ return & grpDS->SMDSGroup();
+ }
+ }
+
+ // create a new group
+ SMESH_Group* grp = _mesh->AddGroup( SMDSAbs_Edge, groupName.c_str() );
+ SMESHDS_Group* grpDS = static_cast< SMESHDS_Group* >( grp->GetGroupDS() );
+
+ group = & grpDS->SMDSGroup();
+ _name2Group[ groupName ] = group;
+ }
+ return group;
+}
+
+//================================================================================
+/*!
+ * \brief Look for a node dividing a given EDGE
+ */
+//================================================================================
+
+const SMDS_MeshNode* BLSURFPlugin_EnforcedMesh1D::findNodeOnEdge( const gp_Pnt& p,
+ const TopoDS_Edge& edge )
+{
+ // look for an equal node on the EDGE
+ if ( std::vector< const SMDS_MeshNode* >* nodesOnE = _nodesOnEdge.ChangeSeek( edge ))
+ for ( const SMDS_MeshNode* n : *nodesOnE )
+ if ( p.SquareDistance( SMESH_NodeXYZ( n )) < _tol * _tol )
+ {
+ return n;
+ }
+
+ return nullptr;
+}
+
+//================================================================================
+/*!
+ * \brief Add a node to an EDGE
+ */
+//================================================================================
+
+void BLSURFPlugin_EnforcedMesh1D::addNodeOnEdge( const SMDS_MeshNode* node,
+ const TopoDS_Edge& edge,
+ const double u)
+{
+ _mesh->GetMeshDS()->SetNodeOnEdge( node, edge, u );
+
+ std::vector< const SMDS_MeshNode* > * nodesOnE = _nodesOnEdge.ChangeSeek( edge );
+ if ( !nodesOnE )
+ nodesOnE = _nodesOnEdge.Bound( edge, std::vector< const SMDS_MeshNode* >() );
+
+ nodesOnE->push_back( node );
+}
+
+//================================================================================
+/*!
+ * \brief Create EDGEs by dividing a given EDGE by nodes on it
+ * \param [in] edge - the EDGE to divide
+ * \param [in] nodes - the nodes to divide by
+ */
+//================================================================================
+
+void BLSURFPlugin_EnforcedMesh1D::
+
+splitEdgeByNodes( TopoDS_Edge edge, const std::vector< const SMDS_MeshNode* >& nodes )
+{
+ if ( nodes.empty() )
+ return;
+
+ edge.Orientation( TopAbs_FORWARD );
+
+ TopoDS_Vertex v0 = _helper.IthVertex( 0, edge );
+ TopoDS_Vertex v1 = _helper.IthVertex( 1, edge );
+
+ // create VERTEXes and sort them along the EDGE
+
+ std::map< double, TopoDS_Vertex > sortedVertices;
+
+ BRepAdaptor_Curve curve( edge );
+ for ( SMESH_NodeXYZ pn : nodes )
+ {
+ gp_Pnt projPnt;
+ double u;
+ ShapeAnalysis_Curve().Project( curve, pn, _tol, projPnt, u, false );
+ projPnt = curve.Value( u );
+
+ TopoDS_Vertex v = BRepBuilderAPI_MakeVertex( projPnt );
+
+ sortedVertices.insert({ u, v });
+
+ _nOnE2Vertex[ pn.Node() ] = v;
+ }
+ sortedVertices.insert({ BRep_Tool::Parameter( v1, edge ), v1 });
+
+
+ // create EDGEs
+
+ BRep_Builder builder;
+ std::vector< TopoDS_Edge >& newEdges = *_edgeSplitsOfEdge.Bound( edge, TEdge2Edges::value_type());
+
+ double u0 = BRep_Tool::Parameter( v0, edge );
+ for ( auto& u2v : sortedVertices )
+ {
+ double u1 = u2v.first;
+ v1 = u2v.second;
+
+ TopoDS_Shape newShape = edge.EmptyCopied();
+ TopoDS_Edge newEdge = TopoDS::Edge( newShape );
+ builder.Add( newEdge, v0 );
+ builder.Add( newEdge, v1 );
+ builder.Range( newEdge, u0, u1 );
+ newEdges.push_back( newEdge );
+
+ v0 = v1;
+ u0 = u1;
+ }
+
+ return;
+}
+
+//================================================================================
+/*!
+ * \brief Return true if there are enforced segments on a FACE. Start iteration on segments
+ */
+//================================================================================
+
+bool BLSURFPlugin_EnforcedMesh1D::HasSegmentsOnFace( const TopoDS_Face& face )
+{
+ _segIterator.reset();
+
+ if ( _faces.Contains( face ))
+ {
+ _currentFace = face;
+ _segIterator = _helper.GetMeshDS()->MeshElements( face )->GetElements();
+
+ _helper.SetSubShape( face );
+
+ return _segIterator->more();
+ }
+ return false;
+}
+
+
+//================================================================================
+/*!
+ * \brief Return next segment on the FACE
+ */
+//================================================================================
+
+bool BLSURFPlugin_EnforcedMesh1D::NextSegment( Segmemnt & seg,
+ TopTools_IndexedMapOfShape & vertexTags )
+{
+ if ( _segIterator && _segIterator->more() )
+ {
+ const SMDS_MeshElement* segment = _segIterator->next();
+
+ while ( segment->GetType() != SMDSAbs_Edge && _segIterator->more() )
+ segment = _segIterator->next();
+ if ( segment->GetType() != SMDSAbs_Edge )
+ return false;
+
+ const SMDS_MeshNode * node[2] = { segment->GetNode(0),
+ segment->GetNode(1) };
+
+ seg._tag = _segTag++;
+
+ seg._xyz[0] = SMESH_NodeXYZ( node[0]);
+ seg._xyz[1] = SMESH_NodeXYZ( node[1]);
+
+ seg._uv[0] = _helper.GetNodeUV( _currentFace, node[0], node[1] );
+ seg._uv[1] = _helper.GetNodeUV( _currentFace, node[1], node[0] );
+
+ seg._pcurve = new Geom2d_Line( seg._uv[0], ( seg._uv[1] - seg._uv[0] ));
+
+ seg._u[0] = 0.0;
+ seg._u[1] = ( seg._uv[1] - seg._uv[0] ).Modulus();
+
+ for ( int i = 0; i < 2; ++i )
+ {
+ auto n2v = _nOnE2Vertex.find( node[i] ); // find VERTEX by node
+
+ if ( n2v != _nOnE2Vertex.end() )
+ seg._vTag[i] = vertexTags.Add( n2v->second );
+ else
+ seg._vTag[i] = _nodeTag0 + _nodeTags.Add( node[i] );
+ }
+
+ if ( !_isQuadratic )
+ _mesh->GetMeshDS()->UnSetMeshElementOnShape( segment, _currentFace );
+
+ return true;
+ }
+ return false;
+}
+
+//================================================================================
+/*!
+ * \brief Return enforced node by the tag that was returned by Segmemnt::_vTag[i]
+ */
+//================================================================================
+
+const SMDS_MeshNode*
+BLSURFPlugin_EnforcedMesh1D::GetNodeByTag( int tag,
+ const TopTools_IndexedMapOfShape & vertexTags )
+{
+ const SMDS_MeshNode* node = nullptr;
+
+ if ( tag <= vertexTags.Size() && !_nOnE2Vertex.empty() )
+ {
+ const TopoDS_Shape& vertex = vertexTags( tag );
+
+ for ( auto n2v = _nOnE2Vertex.begin(); n2v != _nOnE2Vertex.end(); ++n2v )
+ if ( vertex.IsSame( n2v->second ))
+ {
+ node = n2v->first;
+ _nOnE2Vertex.erase( n2v );
+ return node;
+ }
+ }
+
+ tag -= _nodeTag0;
+
+ bool isValid = ( 0 < tag && tag <= _nodeTags.Size() );
+ if ( isValid )
+ node = _nodeTags( tag );
+
+ return node;
+}
+
+//================================================================================
+/*!
+ * \brief Return true if a tag corresponds to the tag of enforced segment
+ * that was returned by Segment::_tag
+ */
+//================================================================================
+
+bool BLSURFPlugin_EnforcedMesh1D::IsSegmentTag( int tag ) const
+{
+ return ( _segTag0 <= tag && tag <= _segTag );
+}
+
+//================================================================================
+/*!
+ * \brief Return tag of EDGE by tags of its splits
+ */
+//================================================================================
+
+int BLSURFPlugin_EnforcedMesh1D::GetTagOfSplitEdge( int splitTag ) const
+{
+ auto sTag2eTag = _splitTags2EdgeTag.find( splitTag );
+ return ( sTag2eTag == _splitTags2EdgeTag.end() ) ? splitTag : sTag2eTag->second;
+}
--- /dev/null
+// Copyright (C) 2007-2021 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
+//
+// File : BLSURFPlugin_EnforcedMesh1D.hxx
+// Author : Edward AGAPOV (OCC)
+
+#ifndef __BLSURFPlugin_EnforcedMesh1D_HXX__
+#define __BLSURFPlugin_EnforcedMesh1D_HXX__
+
+#include "BLSURFPlugin_Hypothesis.hxx"
+
+#include <SMESH_ControlsDef.hxx>
+#include <SMESH_MesherHelper.hxx>
+
+#include <Geom2d_Curve.hxx>
+#include <NCollection_DataMap.hxx>
+#include <NCollection_IndexedMap.hxx>
+#include <TopTools_IndexedMapOfShape.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS_Vertex.hxx>
+#include <gp_Pnt.hxx>
+#include <gp_Pnt2d.hxx>
+
+#include <vector>
+#include <map>
+
+class SMDS_MeshElement;
+class SMDS_MeshGroup;
+class SMDS_MeshNode;
+class SMESH_Mesh;
+
+/*!
+ * \brief Implement 1D mesh into the mesh made by MG-CADSurf
+ */
+class BLSURFPlugin_EnforcedMesh1D
+{
+public:
+
+ BLSURFPlugin_EnforcedMesh1D( SMESH_MesherHelper& helper,
+ const BLSURFPlugin_Hypothesis* hyp );
+
+ ~BLSURFPlugin_EnforcedMesh1D();
+
+ // Return EDGEs resulted from division of FACE boundary by enforced segments
+ bool GetSplitsOfEdge( const TopoDS_Edge& edge,
+ std::vector< TopoDS_Edge > & splits,
+ TopTools_IndexedMapOfShape & edgeTags );
+
+ // Return true if there are enforced segments on a FACE. Start iteration on segments
+ bool HasSegmentsOnFace( const TopoDS_Face& face );
+
+ // Data of an enforced segment to provide MG-CADSurf with
+ struct Segmemnt
+ {
+ int _tag;
+ Handle(Geom2d_Curve) _pcurve;
+
+ // data of two ends
+ double _u [2];
+ gp_XY _uv [2];
+ gp_XYZ _xyz [2];
+ int _vTag[2];
+ };
+
+ // Return next segment on the FACE. Iteration starts upon calling HasSegmentsOnFace()
+ bool NextSegment( Segmemnt & seg, TopTools_IndexedMapOfShape & vertexTags );
+
+ // Return enforced node by tag
+ const SMDS_MeshNode* GetNodeByTag( int tag, const TopTools_IndexedMapOfShape & vertexTags );
+
+ // Return true if a tad corresponds to an enforced segment
+ bool IsSegmentTag( int tag ) const;
+
+ // Return tag of EDGE by tags of its splits
+ int GetTagOfSplitEdge( int splitTag ) const;
+
+ typedef std::map< const SMDS_MeshElement* , std::vector< const SMDS_MeshNode* > > TNodesOnSeg;
+
+private:
+
+ void copyEnforcedMesh( const BLSURFPlugin_Hypothesis::EnforcedMesh& theEnfMesh,
+ const BLSURFPlugin_Hypothesis* theHyp,
+ const TopoDS_Shape& theShape);
+
+ const SMDS_MeshNode* copyEnforcedNode( const SMDS_MeshNode* enfNode );
+
+ void setupPredicates( const TopoDS_Shape& shape );
+
+ void splitSegmentOnSeveralShapes( const SMDS_MeshElement* segment );
+
+ void splitSelfIntersectingSegments( const TopoDS_Shape & face );
+
+ void findIntersectionWithSeamEdge( const TopoDS_Face & face, TNodesOnSeg & segInternalNodes );
+
+ bool intersectSegments( const SMDS_MeshElement* seg1, const SMDS_MeshElement* seg2,
+ const TopoDS_Face& face, gp_Pnt& intPnt, gp_Pnt2d& inUV ) const;
+
+ gp_Pnt getEdgeIntersection( const TopoDS_Shape& faceOrEdge,
+ const gp_XYZ& xyz0, const gp_XYZ& xyz1,
+ TopoDS_Edge & edge, double & paramOnEdge );
+
+ void splitEdgeByNodes( TopoDS_Edge edge, const std::vector< const SMDS_MeshNode* >& nodes);
+
+ SMDS_MeshGroup* getGroup( const std::string& groupName );
+
+ const SMDS_MeshNode* findNodeOnEdge( const gp_Pnt& p, const TopoDS_Edge& edge );
+ void addNodeOnEdge( const SMDS_MeshNode*node , const TopoDS_Edge& edge, const double u = 0. );
+
+
+ SMESH_Mesh* _mesh;
+ TopoDS_Shape _shape;
+ SMESH_MesherHelper _helper;
+ bool _isQuadratic;
+ std::map< std::string, SMDS_MeshGroup* > _name2Group;
+ double _tol;
+ TopTools_IndexedMapOfShape _faces;
+
+ // segments whose nodes are on different FACEs;
+ // such segments will be split into segments lying each on own FACE
+ std::vector< const SMDS_MeshElement* > _segmentsOnSeveralShapes;
+
+ // nodes projected on EDGEs; EDGEs will be divided by them
+ typedef NCollection_DataMap< TopoDS_Edge,
+ std::vector< const SMDS_MeshNode* >,
+ TopTools_ShapeMapHasher> TEdge2Nodes;
+ typedef NCollection_DataMap< TopoDS_Edge,
+ std::vector< TopoDS_Edge >,
+ TopTools_ShapeMapHasher> TEdge2Edges;
+ TEdge2Nodes _nodesOnEdge;
+ TEdge2Edges _edgeSplitsOfEdge; // result of EDGE division by nodes
+ std::map< int, int > _splitTags2EdgeTag;
+ std::map< const SMDS_MeshNode* , TopoDS_Vertex > _nOnE2Vertex; // VERTEXes on _nodesOnEdge
+
+ typedef SMESH::Controls::ElementsOnShape TPredicate;
+ typedef SMESH::Controls::ElementsOnShapePtr TPredicatePtr;
+ TPredicatePtr _onVertexPredicate;
+ TPredicatePtr _onEdgePredicate;
+
+ // for iteration of segments of FACE
+
+ SMDS_ElemIteratorPtr _segIterator;
+ TopoDS_Face _currentFace;
+ int _segTag0;
+ int _segTag;
+
+ typedef NCollection_IndexedMap< const SMDS_MeshNode* > TNodeIndMap;
+ TNodeIndMap _nodeTags;
+ int _nodeTag0;
+
+ // nodes not projected to geometry; they are reused during next projection to geometry
+ std::vector< const SMDS_MeshNode* > _freeNodes;
+
+};
+
+
+#endif
//
#include "BLSURFPlugin_Hypothesis.hxx"
#include "BLSURFPlugin_Attractor.hxx"
-#include "SMESH_Gen_i.hxx"
-#include <utilities.h>
-#include <cstring>
-#include <iostream>
-#include <sstream>
+
+#include <SMESHDS_Group.hxx>
+#include <SMESHDS_Mesh.hxx>
+#include <SMESH_Gen_i.hxx>
+#include <SMESH_Group.hxx>
+#include <SMESH_TryCatch.hxx>
#include <Basics_Utils.hxx>
+#include <utilities.h>
// cascade include
-#include "ShapeAnalysis.hxx"
+#include <ShapeAnalysis.hxx>
// CORBA includes
#include CORBA_CLIENT_HEADER(SALOMEDS)
}
return faceTag;
}
+
+//=============================================================================
+void BLSURFPlugin_Hypothesis::SetEnforcedMeshes( std::vector< EnforcedMesh > & enforcedMeshes )
+{
+ if ( _enforcedMeshes != enforcedMeshes )
+ {
+ _enforcedMeshes.swap( enforcedMeshes );
+ NotifySubMeshesHypothesisModification();
+ }
+}
+
+//================================================================================
+/*!
+ * \brief Return elements of 1D enforced mesh. Result can be NULL
+ */
+//================================================================================
+
+SMDS_ElemIteratorPtr
+BLSURFPlugin_Hypothesis::GetEnforcedSegments( const EnforcedMesh& enfMesh,
+ SMESH_Mesh* & mesh ) const
+{
+ SMDS_ElemIteratorPtr it;
+ if (( mesh = SMESH_Hypothesis::GetMeshByPersistentID( enfMesh._meshID )))
+ {
+ mesh->Load();
+
+ switch( enfMesh._type )
+ {
+ case ENFORCED_MESH:
+ it = mesh->GetMeshDS()->elementsIterator( SMDSAbs_Edge );
+ break;
+
+ case ENFORCED_GROUP:
+ if ( SMESH_Group* grp = mesh->GetGroup( enfMesh._subID ))
+ {
+ if ( grp->GetGroupDS()->GetType() == SMDSAbs_Edge )
+ it = grp->GetGroupDS()->GetElements();
+ }
+ break;
+
+ case ENFORCED_SUBMESH:
+ if ( SMESH_subMesh* sm = mesh->GetSubMeshContaining( enfMesh._subID ))
+ if ( SMESHDS_SubMesh * smDS = sm->GetSubMeshDS() )
+ {
+ it = smDS->GetElements();
+ if ( it->more() && it->next()->GetType() != SMDSAbs_Edge )
+ it = SMDS_ElemIteratorPtr();
+ else
+ it = smDS->GetElements();
+ }
+ break;
+ }
+ }
+ return it;
+}
+
+
//=============================================================================
void BLSURFPlugin_Hypothesis::SetPreCADMergeEdges(bool theVal)
{
std::ostringstream hpStream;
boost::archive::text_oarchive( hpStream ) << _hyperPatchEntriesList;
std::string hpString = hpStream.str();
- save << " " << hpString.size() << " " << hpString;
+ SMESHDS_Hypothesis::SaveString( save, hpString );
+ // Enforced meshes
+ std::ostringstream enfMStream;
+ boost::archive::text_oarchive( enfMStream ) << _enforcedMeshes;
+ std::string enfMString = enfMStream.str();
+ SMESHDS_Hypothesis::SaveString( save, enfMString );
return save;
}
}
// hyper-patches as entries (issue bos #20543)
- if ( static_cast<bool>( load >> i ) && i > 0 )
+ std::string buffer;
+ if ( SMESHDS_Hypothesis::LoadString( load, buffer ))
{
- std::string buffer( i, '\0' );
- load.get( buffer[0] ); // remove a white-space
- load.get( & buffer[0], i + 1 );
+ std::istringstream istream( buffer.data() );
+ boost::archive::text_iarchive archive( istream );
+ SMESH_TRY;
+ archive >> _hyperPatchEntriesList;
+ SMESH_CATCH( SMESH::printErrorInDebugMode );
+ }
+ // Enforced meshes (issue bos $16292)
+ buffer.clear();
+ if ( SMESHDS_Hypothesis::LoadString( load, buffer ))
+ {
std::istringstream istream( buffer.data() );
boost::archive::text_iarchive archive( istream );
- try {
- archive >> _hyperPatchEntriesList;
- }
- catch (...) {}
+ SMESH_TRY;
+ archive >> _enforcedMeshes;
+ SMESH_CATCH( SMESH::printErrorInDebugMode );
}
return load;
}
+namespace boost {
+ namespace serialization {
+
+ //=======================================================================
+ //function : serialize
+ //purpose : serialize EnforcedMesh
+ //=======================================================================
+
+ template<class Archive>
+ void serialize(Archive & ar, BLSURFPlugin_Hypothesis::EnforcedMesh & enfM,
+ const unsigned int /*version*/)
+ {
+ ar & enfM._meshID;
+ ar & enfM._subID;
+ ar & enfM._type;
+ ar & enfM._groupName;
+ }
+
+ } // namespace serialization
+} // namespace boost
+
+
void BLSURFPlugin_Hypothesis::LoadFacesPeriodicity(std::istream & load)
{
bool isOK = true;
#ifndef _BLSURFPlugin_Hypothesis_HXX_
#define _BLSURFPlugin_Hypothesis_HXX_
-#include "SMESH_Hypothesis.hxx"
+#include "BLSURFPlugin_Attractor.hxx"
+
+#include <SMDS_ElemIterator.hxx>
+#include <SMESH_Hypothesis.hxx>
+#include <smIdType.hxx>
+
#include <vector>
#include <map>
#include <set>
-#include <stdexcept>
#include <string>
-#include <cstring>
-#include <sstream>
-#include <utilities.h>
-#include <smIdType.hxx>
-#include "BLSURFPlugin_Attractor.hxx"
+
+class SMESH_Mesh;
// Parameters for work of MG-CADSurf
+enum EnforcedMeshType { ENFORCED_MESH, ENFORCED_GROUP, ENFORCED_SUBMESH };
+
class BLSURFPlugin_Hypothesis: public SMESH_Hypothesis
{
public:
std::string GetTags();
// Hyper-patches
- typedef std::set< int > THyperPatchTags;
- typedef std::vector< THyperPatchTags > THyperPatchList;
- typedef std::set< std::string > THyperPatchEntries;
+ typedef std::set< int > THyperPatchTags;
+ typedef std::vector< THyperPatchTags > THyperPatchList;
+ typedef std::set< std::string > THyperPatchEntries;
typedef std::vector< THyperPatchEntries > THyperPatchEntriesList;
void SetHyperPatches(const THyperPatchList& hpl, bool notifyMesh=true);
const THyperPatchEntriesList& GetHyperPatchEntries() const { return _hyperPatchEntriesList; }
static int GetHyperPatchTag( int faceTag, const BLSURFPlugin_Hypothesis* hyp, int* iPatch=0 );
+ // Enforced mesh
+ struct EnforcedMesh
+ {
+ int _meshID; // persistent mesh ID
+ int _subID; // either persistent group ID or sub-shape ID for sub-mesh
+ EnforcedMeshType _type; /* specify what _subID means:
+ - nothing for ENFORCED_MESH
+ - group ID for ENFORCED_GROUP
+ - sub-shape ID for ENFORCED_SUBMESH */
+ std::string _groupName; // name of a group to add mesh edges to
+
+ bool operator==(const EnforcedMesh& em ) const
+ {
+ return ( _meshID == em._meshID && _subID == em._subID &&
+ _type == em._type && _groupName == em._groupName );
+ }
+ };
+
+ void SetEnforcedMeshes( std::vector< EnforcedMesh > & enforcedMeshes );
+ const std::vector< EnforcedMesh > & GetEnforcedMeshes() const { return _enforcedMeshes; }
+ SMDS_ElemIteratorPtr GetEnforcedSegments( const EnforcedMesh& enfMesh,
+ SMESH_Mesh* & mesh ) const;
+
void SetPreCADMergeEdges(bool theVal);
bool GetPreCADMergeEdges() const { return _preCADMergeEdges; }
TSizeMap _attractors;
TAttractorMap _classAttractors;
- TFaceEntryEnfVertexListMap _faceEntryEnfVertexListMap;
- TEnfVertexList _enfVertexList;
+ TFaceEntryEnfVertexListMap _faceEntryEnfVertexListMap;
+ TEnfVertexList _enfVertexList;
// maps to get "manual" enf vertex (through their coordinates)
- TFaceEntryCoordsListMap _faceEntryCoordsListMap;
- TCoordsEnfVertexMap _coordsEnfVertexMap;
+ TFaceEntryCoordsListMap _faceEntryCoordsListMap;
+ TCoordsEnfVertexMap _coordsEnfVertexMap;
// maps to get "geom" enf vertex (through their geom entries)
- TFaceEntryEnfVertexEntryListMap _faceEntryEnfVertexEntryListMap;
- TEnfVertexEntryEnfVertexMap _enfVertexEntryEnfVertexMap;
- TGroupNameNodeIDMap _groupNameNodeIDMap;
+ TFaceEntryEnfVertexEntryListMap _faceEntryEnfVertexEntryListMap;
+ TEnfVertexEntryEnfVertexMap _enfVertexEntryEnfVertexMap;
+ TGroupNameNodeIDMap _groupNameNodeIDMap;
// Enable internal enforced vertices on specific face if requested by user
// TFaceEntryInternalVerticesList _faceEntryInternalVerticesList;
- bool _enforcedInternalVerticesAllFaces;
- TEnfGroupName _enforcedInternalVerticesAllFacesGroup;
+ bool _enforcedInternalVerticesAllFaces;
+ TEnfGroupName _enforcedInternalVerticesAllFacesGroup;
- TPreCadPeriodicityVector _preCadFacesPeriodicityVector;
- TPreCadPeriodicityVector _preCadEdgesPeriodicityVector;
+ TPreCadPeriodicityVector _preCadFacesPeriodicityVector;
+ TPreCadPeriodicityVector _preCadEdgesPeriodicityVector;
+
+ TFacesPeriodicityVector _facesPeriodicityVector;
+ TEdgesPeriodicityVector _edgesPeriodicityVector;
+ TVerticesPeriodicityVector _verticesPeriodicityVector;
- TFacesPeriodicityVector _facesPeriodicityVector;
- TEdgesPeriodicityVector _edgesPeriodicityVector;
- TVerticesPeriodicityVector _verticesPeriodicityVector;
+ THyperPatchList _hyperPatchList;
+ THyperPatchEntriesList _hyperPatchEntriesList;
- THyperPatchList _hyperPatchList;
- THyperPatchEntriesList _hyperPatchEntriesList;
+ std::vector< EnforcedMesh > _enforcedMeshes; // enforced 1D meshes
// Called by SaveTo to store content of _preCadFacesPeriodicityVector and _preCadEdgesPeriodicityVector
void SavePreCADPeriodicity(std::ostream & save, const char* shapeType);
#include <SMESH_Gen.hxx>
#include <SMESH_Gen_i.hxx>
+#include <SMESH_Group_i.hxx>
#include <SMESH_PythonDump.hxx>
#include <SALOMEDS_wrap.hxx>
using namespace std;
+namespace
+{
+ //================================================================================
+ /*!
+ * \brief Return persistent ID of a mesh
+ * \param [in] mesh - the mesh
+ * \return int - -1 in case of failure
+ */
+ //================================================================================
+
+ int GetMeshPersistentId( SMESH::SMESH_Mesh_ptr mesh )
+ {
+ int id = -1;
+ if ( SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh ))
+ id = mesh_i->GetImpl().GetMeshDS()->GetPersistentId();
+ return id;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Return persistent ID of a group or sub-mesh
+ * \param [in] meshPart - the mesh part
+ * \param [out] isGroup - return true if meshPart is a group
+ * \return int - -1 in case if meshPart is neither a group nor a sub-mesh
+ */
+ //================================================================================
+
+ int GetMeshPartPersistentId( SMESH::SMESH_IDSource_ptr meshPart, bool & isGroup )
+ {
+ int id = -1;
+ isGroup = false;
+ SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( meshPart );
+ if ( group_i )
+ {
+ id = group_i->GetLocalID();
+ isGroup = true;
+ }
+ else
+ {
+ SMESH::SMESH_subMesh_var subMesh = SMESH::SMESH_subMesh::_narrow( meshPart );
+ if ( !subMesh->_is_nil() )
+ id = subMesh->GetId();
+ }
+ return id;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Find a mesh in the study by mesh persistent ID
+ */
+ //================================================================================
+
+ SMESH::SMESH_Mesh_ptr FindMeshByID( int theMeshID )
+ {
+ SMESH::SMESH_Mesh_var mesh;
+
+ SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
+ CORBA::String_var compDataType = gen->ComponentDataType();
+ SALOMEDS::Study_var aStudy = gen->getStudyServant();
+ SALOMEDS::SComponent_wrap genSO = aStudy->FindComponent( compDataType.in() );
+ if ( !genSO->_is_nil() )
+ {
+ SALOMEDS::ChildIterator_wrap anIter = aStudy->NewChildIterator( genSO );
+ for ( ; anIter->More(); anIter->Next() )
+ {
+ SALOMEDS::SObject_wrap so = anIter->Value();
+ CORBA::Object_var obj = gen->SObjectToObject( so );
+ mesh = SMESH::SMESH_Mesh::_narrow( obj );
+ if ( !mesh->_is_nil() && GetMeshPersistentId( mesh ) == theMeshID )
+ break;
+ mesh = SMESH::SMESH_Mesh::_nil();
+ }
+ }
+ return mesh._retn();
+ }
+
+ //================================================================================
+ /*!
+ * \brief Return a group by its ID
+ */
+ //================================================================================
+
+ SMESH::SMESH_GroupBase_ptr GetGroupByID( SMESH::SMESH_Mesh_ptr mesh, int ID )
+ {
+ SMESH::SMESH_GroupBase_var group;
+ if ( !CORBA::is_nil( mesh ))
+ {
+ SMESH::ListOfGroups_var groups = mesh->GetGroups();
+ for ( CORBA::ULong i = 0; i < groups->length(); ++i )
+ if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( groups[i] ))
+ if ( group_i->GetLocalID() == ID )
+ {
+ group = SMESH::SMESH_GroupBase::_narrow( groups[i] );
+ break;
+ }
+ }
+ return group._retn();
+ }
+
+ //================================================================================
+ /*!
+ * \brief Return a sub-mesh by sub-shape ID
+ */
+ //================================================================================
+
+ SMESH::SMESH_subMesh_ptr GetSubMeshByID( SMESH::SMESH_Mesh_ptr mesh,
+ const int shapeID,
+ CORBA::Long subMeshTag )
+ {
+ SMESH::SMESH_subMesh_var subMesh;
+ if ( !CORBA::is_nil( mesh ))
+ {
+ SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
+ SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( mesh );
+ SALOMEDS::Study_var aStudy = gen->getStudyServant();
+ SALOMEDS::SObject_wrap subMeshRootSO;
+ if ( !meshSO->_is_nil() && meshSO->FindSubObject( subMeshTag, subMeshRootSO.inout() ))
+ {
+ SALOMEDS::ChildIterator_wrap anIter = aStudy->NewChildIterator( subMeshRootSO );
+ for ( ; anIter->More(); anIter->Next() )
+ {
+ SALOMEDS::SObject_wrap so = anIter->Value();
+ CORBA::Object_var obj = gen->SObjectToObject( so );
+ subMesh = SMESH::SMESH_subMesh::_narrow( obj );
+ if ( !subMesh->_is_nil() && subMesh->GetId() == shapeID )
+ break;
+ subMesh = SMESH::SMESH_subMesh::_nil();
+ }
+ }
+ return subMesh._retn();
+ }
+ return subMesh._retn();
+ }
+
+} // namespace
+
//=============================================================================
/*!
* BLSURFPlugin_Hypothesis_i::BLSURFPlugin_Hypothesis_i
return (CORBA::Short) this->GetImpl()->GetVerbosity();
}
+
+//=============================================================================
+void BLSURFPlugin_Hypothesis_i::SetEnforcedMeshes(const BLSURFPlugin::EnforcedMeshesList& theMeshes )
+{
+ std::vector< ::BLSURFPlugin_Hypothesis::EnforcedMesh > enforcedMeshes;
+ for ( CORBA::ULong i = 0; i < theMeshes.length(); ++i )
+ {
+ const BLSURFPlugin::MG_EnforcedMesh1D & inEM = theMeshes[ i ];
+ if ( CORBA::is_nil( inEM.mesh ))
+ THROW_SALOME_CORBA_EXCEPTION( "NULL enforced mesh",SALOME::BAD_PARAM );
+
+ SMESH::SMESH_Mesh_var mesh = inEM.mesh->GetMesh();
+ if ( CORBA::is_nil( mesh ))
+ THROW_SALOME_CORBA_EXCEPTION( "BAD enforced mesh",SALOME::BAD_PARAM );
+
+ int meshID = GetMeshPersistentId( mesh );
+ if ( meshID < 0 )
+ THROW_SALOME_CORBA_EXCEPTION( "BAD enforced mesh",SALOME::BAD_PARAM );
+
+ bool isGroup = false;
+ int partID = GetMeshPartPersistentId( inEM.mesh, isGroup );
+ ::EnforcedMeshType partType = ENFORCED_MESH;
+ if ( partID > -1 )
+ partType = isGroup ? ENFORCED_GROUP : ENFORCED_SUBMESH;
+
+ enforcedMeshes.push_back({ meshID, partID, partType, inEM.groupName.in() });
+ }
+
+ this->GetImpl()->SetEnforcedMeshes( enforcedMeshes );
+
+ // dump
+
+ SMESH::TPythonDump pyDump;
+ pyDump << BLSURFPlugin::BLSURFPlugin_Hypothesis_var( _this() )
+ << ".SetEnforcedMeshes([ ";
+
+ for ( CORBA::ULong i = 0; i < theMeshes.length(); ++i )
+ {
+ const BLSURFPlugin::MG_EnforcedMesh1D & inEM = theMeshes[ i ];
+ pyDump << "BLSURFPlugin.MG_EnforcedMesh1D( " << inEM.mesh.in() << ", ";
+ if ( inEM.groupName.in() && inEM.groupName.in()[0] )
+ pyDump << "'" << inEM.groupName.in() << "'";
+ else
+ pyDump << "''";
+ pyDump << ")" << ( i + 1 < theMeshes.length() ? ", " : "])");
+ }
+}
+
+//=============================================================================
+
+BLSURFPlugin::EnforcedMeshesList* BLSURFPlugin_Hypothesis_i::GetEnforcedMeshes()
+{
+ const std::vector< ::BLSURFPlugin_Hypothesis::EnforcedMesh > & hypEnfMeshes =
+ this->GetImpl()->GetEnforcedMeshes();
+
+ BLSURFPlugin::EnforcedMeshesList_var outEnfMeshes = new BLSURFPlugin::EnforcedMeshesList();
+ outEnfMeshes->length( hypEnfMeshes.size() );
+
+ int nbMeshes = 0;
+ for ( size_t i = 0; i < hypEnfMeshes.size(); ++i )
+ {
+ const ::BLSURFPlugin_Hypothesis::EnforcedMesh& enfMeshData = hypEnfMeshes[ i ];
+ BLSURFPlugin::MG_EnforcedMesh1D & outEnfMesh = outEnfMeshes[ nbMeshes ];
+
+ SMESH::SMESH_Mesh_var mesh = FindMeshByID( enfMeshData._meshID );
+ switch ( enfMeshData._type ) {
+ case ENFORCED_MESH :
+ {
+ outEnfMesh.mesh = SMESH::SMESH_IDSource::_narrow( mesh );
+ break;
+ }
+ case ENFORCED_GROUP :
+ {
+ SMESH::SMESH_GroupBase_var group = GetGroupByID( mesh, enfMeshData._subID );
+ outEnfMesh.mesh = SMESH::SMESH_IDSource::_narrow( group );
+ break;
+ }
+ case ENFORCED_SUBMESH:
+ {
+ SMESH::SMESH_subMesh_var subMesh;
+ subMesh = GetSubMeshByID( mesh, enfMeshData._subID, SMESH::Tag_SubMeshOnEdge );
+ if ( CORBA::is_nil( subMesh ))
+ subMesh = GetSubMeshByID( mesh, enfMeshData._subID, SMESH::Tag_SubMeshOnCompound );
+
+ outEnfMesh.mesh = SMESH::SMESH_IDSource::_narrow( subMesh );
+ break;
+ }
+ default: continue;
+ }
+ outEnfMesh.groupName = enfMeshData._groupName.c_str();
+
+ nbMeshes += ( !CORBA::is_nil( outEnfMesh.mesh ));
+ }
+ outEnfMeshes->length( nbMeshes );
+
+ return outEnfMeshes._retn();
+}
+
//=============================================================================
void BLSURFPlugin_Hypothesis_i::SetEnforceCadEdgesSize( CORBA::Boolean toEnforce )
{
void SetVerbosity(CORBA::Short theVal);
CORBA::Short GetVerbosity();
+ /*!
+ * Set/Get enforced 1D meshes
+ */
+ void SetEnforcedMeshes( const BLSURFPlugin::EnforcedMeshesList& enforcedMeshes );
+ BLSURFPlugin::EnforcedMeshesList* GetEnforcedMeshes();
+
void SetEnforceCadEdgesSize( CORBA::Boolean toEnforce );
CORBA::Boolean GetEnforceCadEdgesSize();
BLSURFPlugin_Hypothesis.hxx
BLSURFPlugin_Hypothesis_i.hxx
BLSURFPlugin_Attractor.hxx
+ BLSURFPlugin_EnforcedMesh1D.hxx
)
# --- sources ---
BLSURFPlugin_Hypothesis_i.cxx
BLSURFPlugin_i.cxx
BLSURFPlugin_Attractor.cxx
+ BLSURFPlugin_EnforcedMesh1D.cxx
)
# --- scripts ---
STD_TAB = 0,
ADV_TAB,
SMP_TAB,
- ENF_TAB,
+ ENF_V_TAB,
+ ENF_M_TAB,
PERIODICITY_TAB,
HYPERPATCH_TAB,
SMP_NAME_COLUMN =0,
ENF_VER_ENTRY_COLUMN,
ENF_VER_GROUP_COLUMN,
ENF_VER_NB_COLUMNS,
-// Periodicity
+
+ // Enforced 1D meshes
+ ENF_MESH_NB_COLUMNS = 2,
+
+ // Periodicity
PERIODICITY_OBJ_SOURCE_COLUMN = 0,
PERIODICITY_OBJ_TARGET_COLUMN,
PERIODICITY_P1_SOURCE_COLUMN,
lay->addWidget( myTabWidget );
myName = 0;
-
+
// basic parameters
myStdGroup = new QWidget();
QGridLayout* aStdLayout = new QGridLayout( myStdGroup );
aStdLayout->setSpacing( 6 );
aStdLayout->setMargin( 11 );
-
+
if( isCreation() )
myName = new QLineEdit( myStdGroup );
myStdWidget = new BLSURFPluginGUI_StdWidget(myStdGroup);
if ( !hasGeom() ) {
myStdWidget->myPhysicalMesh->removeItem( PhysicalLocalSize );
}
-
+
int row = 0;
if( isCreation() ) {
aStdLayout->addWidget( new QLabel( tr( "SMESH_NAME" ), myStdGroup ), 0, 0, 1, 1 );
aStdLayout->addWidget( myName, row++, 1, 1, 3 );
}
aStdLayout->addWidget( myStdWidget, row++, 0, 1, 4 );
-
+
row = 0;
if( isCreation() )
row = 1;
aStdLayout->setRowStretch(row,1);
aStdLayout->setColumnStretch(1,1);
-
+
// advanced parameters
myAdvGroup = new QWidget();
QGridLayout* anAdvLayout = new QGridLayout( myAdvGroup );
anAdvLayout->setSpacing( 6 );
- anAdvLayout->setMargin( 11 );
+ anAdvLayout->setMargin( 11 );
myAdvWidget = new BLSURFPluginGUI_AdvWidget(myAdvGroup);
anAdvLayout->addWidget( myAdvWidget );
//Layout
QGridLayout* anSmpLayout = new QGridLayout(mySmpGroup);
-
+
// Table
mySizeMapTable = new QTreeWidget( mySmpGroup );
mySizeMapTable ->setMinimumWidth(200);
anEnfLayout->addWidget(myEnforcedTreeWidget, 0, 0, ENF_VER_NB_LINES, 1);
QGridLayout* anEnfLayout2 = new QGridLayout(myEnfGroup);
-// FACE AND VERTEX SELECTION
+ // FACE AND VERTEX SELECTION
//anEnfLayout2->addWidget(myEnfFaceWdg, ENF_VER_FACE, 0, 1, 2);
anEnfLayout2->addWidget(myEnfVertexWdg, ENF_VER_VERTEX, 0, 1, 2);
anEnfLayout2->addWidget(myXCoordLabel, ENF_VER_X_COORD, 0, 1, 1);
anEnfLayout2->setRowStretch(ENF_VER_NB_LINES+1, 1);
anEnfLayout->addLayout(anEnfLayout2, 0,1,ENF_VER_NB_LINES+1,2);
+ // ---------------------------
+ // Enforced meshes parameters
+ // ---------------------------
+
+ myEnfMeshGroup = new QWidget();
+ QGridLayout* anEnfMeshLayout = new QGridLayout(myEnfMeshGroup);
+
+ myEnfMeshTableWdg = new QTableWidget(myEnfGroup);
+ //myEnfMeshTableWdg->setRowCount( 0 );
+ myEnfMeshTableWdg->setColumnCount( ENF_MESH_NB_COLUMNS );
+ myEnfMeshTableWdg->setSortingEnabled(true);
+ myEnfMeshTableWdg->verticalHeader()->hide();
+ myEnfMeshTableWdg->setHorizontalHeaderLabels( QStringList()
+ << tr( "ENF_NAME_COLUMN" )
+ << tr( "ENF_GROUP_COLUMN" ));
+ myEnfMeshTableWdg->horizontalHeader()->setStretchLastSection(true);
+ myEnfMeshTableWdg->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
+ myEnfMeshTableWdg->setAlternatingRowColors(true);
+ myEnfMeshTableWdg->setSelectionMode(QAbstractItemView::ExtendedSelection);
+ myEnfMeshTableWdg->setSelectionBehavior(QAbstractItemView::SelectItems);
+ myEnfMeshTableWdg->resizeColumnsToContents();
+ //myEnfMeshTableWdg->setItemDelegate(new EnforcedMeshTableWidgetDelegate());
+
+ myEnfMeshWdg = new StdMeshersGUI_ObjectReferenceParamWdg( SMESH::IDSOURCE_EDGE, myEnfMeshGroup, /*multiSel=*/false);
+ myEnfMeshWdg->SetDefaultText(tr("ENF_SELECT_MESH"), "QLineEdit { color: grey }");
+
+ myEnfMeshWdg->AvoidSimultaneousSelection(myEnfVertexWdg);
+ myEnfMeshWdg->AvoidSimultaneousSelection(myGeomSelWdg1);
+ myEnfMeshWdg->AvoidSimultaneousSelection(myGeomSelWdg2);
+ myEnfMeshWdg->AvoidSimultaneousSelection(myAttSelWdg);
+
+ QLabel* enforcedGroupNameLabel = new QLabel( tr( "ENF_GROUP_LABEL" ), myEnfMeshGroup );
+ myEnforcedGroupName = new QLineEdit(myEnfMeshGroup);
+
+ myAddEnfMeshButton = new QPushButton(tr("ENF_ADD"),myEnfMeshGroup);
+ myRemoveEnfMeshButton = new QPushButton(tr("ENF_REMOVE"),myEnfMeshGroup);
+
+ QGridLayout* anEnfMeshLayout2 = new QGridLayout(myEnfMeshGroup);
+ anEnfMeshLayout2->addWidget(myEnfMeshWdg, 0, 0, 1, 2);
+ anEnfMeshLayout2->addWidget(enforcedGroupNameLabel, 1, 0, 1, 1);
+ anEnfMeshLayout2->addWidget(myEnforcedGroupName, 1, 1, 1, 1);
+ anEnfMeshLayout2->addWidget(myAddEnfMeshButton, 2, 0, 1, 2);
+ anEnfMeshLayout2->addWidget(myRemoveEnfMeshButton, 3, 0, 1, 2);
+ anEnfMeshLayout2->setRowStretch( 4, 1 );
+
+ anEnfMeshLayout->addWidget(myEnfMeshTableWdg, 0, 0, 5, 1);
+ anEnfMeshLayout->addLayout(anEnfMeshLayout2, 0, 1, 1, 1);
+ anEnfMeshLayout->setRowStretch( 2, 1 );
+
+
// ---
// Periodicity parameters
myPeriodicityGroup = new QWidget( dlg() );
myTabWidget->insertTab( ADV_TAB, myAdvGroup, tr( "BLSURF_ADV_ARGS" ) );
if ( hasGeom() ) {
myTabWidget->insertTab( SMP_TAB, mySmpGroup, tr( "LOCAL_SIZE" ) );
- myTabWidget->insertTab( ENF_TAB, myEnfGroup, tr( "BLSURF_ENF_VER" ) );
+ myTabWidget->insertTab( ENF_V_TAB, myEnfGroup, tr( "BLSURF_ENF_VER" ) );
+ myTabWidget->insertTab( ENF_M_TAB, myEnfMeshGroup, tr( "ENF_MESH" ) );
myTabWidget->insertTab( PERIODICITY_TAB, myPeriodicityGroup, tr( "BLSURF_PERIODICITY" ) );
myTabWidget->insertTab( HYPERPATCH_TAB, hpGroup, tr( "BLSURF_HYPERPATCH_TAB" ));
}
{
mySmpGroup->hide();
myEnfGroup->hide();
+ myEnfMeshGroup->hide();
myPeriodicityGroup->hide();
hpGroup->hide();
}
myTabWidget->setCurrentIndex( STD_TAB );
- connect( myAdvWidget->addBtn, SIGNAL( clicked() ), this, SLOT( onAddOption() ) );
+ connect( myAdvWidget->addBtn, SIGNAL( clicked() ), SLOT( onAddOption() ) );
// Size Maps
- connect( addMapButton, SIGNAL( clicked()), this, SLOT( onAddMap() ) );
- connect( removeMapButton, SIGNAL( clicked()), this, SLOT( onRemoveMap() ) );
- connect( modifyMapButton, SIGNAL( clicked()), this, SLOT( onModifyMap() ) );
- connect( mySizeMapTable, SIGNAL( itemClicked (QTreeWidgetItem *, int)),this, SLOT( onSmpItemClicked(QTreeWidgetItem *, int) ) );
- connect( myGeomSelWdg2, SIGNAL( contentModified() ), this, SLOT( onMapGeomContentModified() ) );
- connect( myGeomSelWdg1, SIGNAL( contentModified() ), this, SLOT( onMapGeomContentModified() ) );
- connect( myAttSelWdg, SIGNAL( contentModified() ), this, SLOT( onMapGeomContentModified() ) );
- connect( mySizeMapTable, SIGNAL( itemChanged (QTreeWidgetItem *, int)),this, SLOT( onSetSizeMap(QTreeWidgetItem *, int) ) );
- connect( myAttractorCheck, SIGNAL( stateChanged ( int )), this, SLOT( onAttractorClicked( int ) ) );
- connect( myConstSizeCheck, SIGNAL( stateChanged ( int )), this, SLOT( onConstSizeClicked( int ) ) );
- connect( smpTab, SIGNAL( currentChanged ( int )), this, SLOT( onTabChanged( int ) ) );
- connect( myTabWidget, SIGNAL( currentChanged ( int )), this, SLOT( onTabChanged( int ) ) );
+ connect( addMapButton, SIGNAL( clicked()), SLOT( onAddMap() ) );
+ connect( removeMapButton, SIGNAL( clicked()), SLOT( onRemoveMap() ) );
+ connect( modifyMapButton, SIGNAL( clicked()), SLOT( onModifyMap() ) );
+ connect( mySizeMapTable, SIGNAL( itemClicked (QTreeWidgetItem *, int)), SLOT( onSmpItemClicked(QTreeWidgetItem *, int) ) );
+ connect( myGeomSelWdg2, SIGNAL( contentModified() ), SLOT( onMapGeomContentModified() ) );
+ connect( myGeomSelWdg1, SIGNAL( contentModified() ), SLOT( onMapGeomContentModified() ) );
+ connect( myAttSelWdg, SIGNAL( contentModified() ), SLOT( onMapGeomContentModified() ) );
+ connect( mySizeMapTable, SIGNAL( itemChanged (QTreeWidgetItem *, int)), SLOT( onSetSizeMap(QTreeWidgetItem *, int) ) );
+ connect( myAttractorCheck, SIGNAL( stateChanged ( int )), SLOT( onAttractorClicked( int ) ) );
+ connect( myConstSizeCheck, SIGNAL( stateChanged ( int )), SLOT( onConstSizeClicked( int ) ) );
+ connect( smpTab, SIGNAL( currentChanged ( int )), SLOT( onTabChanged( int ) ) );
+ connect( myTabWidget, SIGNAL( currentChanged ( int )), SLOT( onTabChanged( int ) ) );
// Enforced vertices
- connect( myEnforcedTreeWidget,SIGNAL( itemClicked(QTreeWidgetItem *, int)), this, SLOT( synchronizeCoords() ) );
- connect( myEnforcedTreeWidget,SIGNAL( itemChanged(QTreeWidgetItem *, int)), this, SLOT( updateEnforcedVertexValues(QTreeWidgetItem *, int) ) );
- connect( myEnforcedTreeWidget,SIGNAL( itemSelectionChanged() ), this, SLOT( synchronizeCoords() ) );
- connect( addVertexButton, SIGNAL( clicked()), this, SLOT( onAddEnforcedVertices() ) );
- connect( removeVertexButton, SIGNAL( clicked()), this, SLOT( onRemoveEnforcedVertex() ) );
- connect( myEnfVertexWdg, SIGNAL( contentModified()), this, SLOT( onSelectEnforcedVertex() ) );
- connect( myInternalEnforcedVerticesAllFaces, SIGNAL( stateChanged ( int )), this, SLOT( onInternalVerticesClicked( int ) ) );
+ connect( myEnforcedTreeWidget,SIGNAL( itemClicked(QTreeWidgetItem *, int)), SLOT( synchronizeCoords() ) );
+ connect( myEnforcedTreeWidget,SIGNAL( itemChanged(QTreeWidgetItem *, int)), SLOT( updateEnforcedVertexValues(QTreeWidgetItem *, int) ) );
+ connect( myEnforcedTreeWidget,SIGNAL( itemSelectionChanged() ), SLOT( synchronizeCoords() ) );
+ connect( addVertexButton, SIGNAL( clicked()), SLOT( onAddEnforcedVertices() ) );
+ connect( removeVertexButton, SIGNAL( clicked()), SLOT( onRemoveEnforcedVertex() ) );
+ connect( myEnfVertexWdg, SIGNAL( contentModified()), SLOT( onSelectEnforcedVertex() ) );
+ connect( myInternalEnforcedVerticesAllFaces, SIGNAL( stateChanged ( int )), SLOT( onInternalVerticesClicked( int ) ) );
+
+ // Enforced mesh
+ connect( myAddEnfMeshButton, SIGNAL( clicked()), SLOT( onAddEnforcedMesh()));
+ connect( myRemoveEnfMeshButton, SIGNAL( clicked()), SLOT( onRemoveEnforcedMesh()));
+ connect( myEnfMeshWdg, SIGNAL( contentModified()), SLOT( onEnforcedMeshSelected()));
+ connect( myEnfMeshTableWdg, SIGNAL( itemSelectionChanged()), SLOT( onEnfMeshTableSelected()));
+
// Periodicity
- connect( myPeriodicityAddButton, SIGNAL( clicked()), this, SLOT( onAddPeriodicity() ) );
- connect( myPeriodicityRemoveButton, SIGNAL( clicked()), this, SLOT( onRemovePeriodicity() ) );
- connect( myPeriodicityTreeWidget, SIGNAL( itemClicked(QTreeWidgetItem*, int)), this, SLOT( onPeriodicityTreeClicked(QTreeWidgetItem *, int) ) );
- connect( myPeriodicityGroupBox2, SIGNAL(toggled(bool)), this, SLOT(onPeriodicityByVerticesChecked(bool)));
+ connect( myPeriodicityAddButton, SIGNAL( clicked()), SLOT( onAddPeriodicity() ) );
+ connect( myPeriodicityRemoveButton, SIGNAL( clicked()), SLOT( onRemovePeriodicity() ) );
+ connect( myPeriodicityTreeWidget, SIGNAL( itemClicked(QTreeWidgetItem*, int)), SLOT( onPeriodicityTreeClicked(QTreeWidgetItem *, int) ) );
+ connect( myPeriodicityGroupBox2, SIGNAL(toggled(bool)), SLOT(onPeriodicityByVerticesChecked(bool)));
ListOfWidgets::const_iterator anIt = myPeriodicitySelectionWidgets.begin();
for (; anIt != myPeriodicitySelectionWidgets.end(); anIt++)
{
StdMeshersGUI_ObjectReferenceParamWdg * w1 = ( StdMeshersGUI_ObjectReferenceParamWdg* ) ( *anIt );
- connect( w1, SIGNAL(contentModified ()), this, SLOT(onPeriodicityContentModified()));
+ connect( w1, SIGNAL( contentModified ()), SLOT( onPeriodicityContentModified() ));
}
}
// Hyper patches
+
QString patchEntries;
for ( int i = 0; i < data.hyperpatches.size(); ++i )
{
that->myStdWidget->onPhysicalMeshChanged();
that->myStdWidget->onGeometricMeshChanged();
that->onStateChange();
+
+ // Enforced mesh
+
+ BLSURFPlugin::BLSURFPlugin_Hypothesis_var h =
+ BLSURFPlugin::BLSURFPlugin_Hypothesis::_narrow( initParamsHypothesis() );
+
+ BLSURFPlugin::EnforcedMeshesList_var enfMeshes = h->GetEnforcedMeshes();
+ for ( CORBA::ULong i = 0; i < enfMeshes->length(); ++i )
+ {
+ BLSURFPlugin::MG_EnforcedMesh1D & enfMesh = enfMeshes[i];
+ that->addEnforcedMesh( enfMesh.mesh.in(), enfMesh.groupName.in() );
+ }
}
/** BLSURFPluginGUI_HypothesisCreator::storeParams()
h->SetHyperPatches( hpl );
+ // Enforced meshes
+ BLSURFPlugin::EnforcedMeshesList_var enfMeshesList = new BLSURFPlugin::EnforcedMeshesList();
+ enfMeshesList->length( myEnfMeshTableWdg->rowCount() );
+
+ int nbMeshes = 0;
+ for ( int row = 0, nbRow = myEnfMeshTableWdg->rowCount(); row < nbRow; ++row )
+ {
+ QTableWidgetItem * meshCell = myEnfMeshTableWdg->item( row, 0 );
+ QString entry = meshCell->data( Qt::UserRole ).toString();
+ QTableWidgetItem * groupCell = myEnfMeshTableWdg->item( row, 1 );
+ QString groupName = groupCell->text();
+
+ SMESH::SMESH_IDSource_var mesh = SMESH::EntryToInterface< SMESH::SMESH_IDSource >( entry );
+ if ( !mesh->_is_nil() )
+ {
+ enfMeshesList[ nbMeshes ].mesh = SMESH::SMESH_IDSource::_duplicate( mesh );
+ enfMeshesList[ nbMeshes ].groupName = CORBA::string_dup( groupName.toStdString().c_str() );
+ ++nbMeshes;
+ }
+ }
+ enfMeshesList->length( nbMeshes );
+
+ h->SetEnforcedMeshes( enfMeshesList );
+
+
} // try
catch(...) {
ok = false;
myPeriodicityP1TargetWdg ->deactivateSelection();
myPeriodicityP2TargetWdg ->deactivateSelection();
myPeriodicityP3TargetWdg ->deactivateSelection();
+ myEnfMeshWdg ->deactivateSelection();
if ( myHyPatchFaceSelBtn->isChecked() )
myHyPatchFaceSelBtn->toggle();
if ( myHyPatchGroupSelBtn->isChecked() )
mySmpSizeSpin->RangeStepAndValidator(minSize, maxSize, 1.0, "length_precision");
myAttSizeSpin->RangeStepAndValidator(minSize, maxSize, 1.0, "length_precision");
}
+
+ if ( tab == ENF_M_TAB )
+ {
+ myEnfMeshWdg->activateSelection();
+ onEnforcedMeshSelected(); // update buttons
+ onEnfMeshTableSelected();
+ if ( myEnforcedGroupName->text().isEmpty() )
+ myEnforcedGroupName->setText("Group 1D");
+ }
}
void BLSURFPluginGUI_HypothesisCreator::onAttractorClicked(int state)
}
}
+//================================================================================
+/*!
+ * \brief Add a new row in Enforced mesh table
+ */
+//================================================================================
+
+void BLSURFPluginGUI_HypothesisCreator::addEnforcedMesh( SMESH::SMESH_IDSource_ptr mesh,
+ const QString& groupName )
+{
+ _PTR(SObject) sobj = SMESH::FindSObject( mesh );
+ if ( !sobj )
+ return;
+
+ QString meshEntry = sobj->GetID().c_str();
+ QString meshName = sobj->GetName().c_str();
+
+ QTableWidgetItem* meshCell = new QTableWidgetItem( meshName );
+ meshCell->setData( Qt::UserRole, meshEntry );
+ meshCell->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled );
+
+ QTableWidgetItem* groupCell = new QTableWidgetItem( groupName );
+ groupCell->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable );
+
+ int row = myEnfMeshTableWdg->rowCount();
+ myEnfMeshTableWdg->insertRow( row );
+ myEnfMeshTableWdg->setItem( row, 0, meshCell );
+ myEnfMeshTableWdg->setItem( row, 1, groupCell );
+
+ myEnfMeshTableWdg->resizeColumnToContents( 0 );
+ myEnfMeshTableWdg->resizeColumnToContents( 1 );
+}
+
+//================================================================================
+/*!
+ * \brief SLOT called when [Add] is clicked in Enforced mesh tab.
+ * Add an item to the enforced meshes table
+ */
+//================================================================================
+
+void BLSURFPluginGUI_HypothesisCreator::onAddEnforcedMesh()
+{
+ if ( myEnfMeshWdg->NbObjects() != 1 )
+ return;
+
+ SMESH::SMESH_IDSource_var mesh = myEnfMeshWdg->GetObject< SMESH::SMESH_IDSource >();
+ QString groupName = myEnforcedGroupName->text().simplified();
+
+ addEnforcedMesh( mesh, groupName );
+
+ selectionMgr()->clearSelected();
+ myEnfMeshWdg->SetObject( SMESH::SMESH_IDSource::_nil() );
+}
+
+//================================================================================
+/*!
+ * \brief SLOT called when [Remove] is clicked in Enforced mesh tab.
+ * Remove a selected mesh from the enforced meshes table
+ */
+//================================================================================
+
+void BLSURFPluginGUI_HypothesisCreator::onRemoveEnforcedMesh()
+{
+ QList<int> selectedRows;
+ QList<QTableWidgetItem *> selectedItems = myEnfMeshTableWdg->selectedItems();
+ QTableWidgetItem* item;
+ int row;
+ foreach( item, selectedItems )
+ {
+ row = item->row();
+ if (!selectedRows.contains( row ) )
+ selectedRows.append(row);
+ }
+
+ qSort( selectedRows );
+ QListIterator<int> it( selectedRows );
+ it.toBack();
+ while ( it.hasPrevious() ) {
+ row = it.previous();
+ myEnfMeshTableWdg->removeRow(row );
+ }
+
+ myEnfMeshTableWdg->selectionModel()->clearSelection();
+
+ onEnforcedMeshSelected(); // to activate [Add] if possible
+}
+
+//================================================================================
+/*!
+ * \brief SLOT called when mesh selection changes. Enable/disable [Add] button
+ */
+//================================================================================
+
+void BLSURFPluginGUI_HypothesisCreator::onEnforcedMeshSelected()
+{
+ bool enable = ( myEnfMeshWdg->NbObjects() == 1 );
+ if ( enable )
+ {
+ // check if a selected mesh contains segments
+ SMESH::SMESH_IDSource_var mesh = myEnfMeshWdg->GetObject< SMESH::SMESH_IDSource >();
+ if (( enable = !mesh->_is_nil() ))
+ {
+ SMESH::array_of_ElementType_var types = mesh->GetTypes();
+ if (( enable = ( types->length() > 0 )))
+ {
+ enable = false;
+ for ( CORBA::ULong i = 0; i < types->length() && !enable; ++i )
+ enable = ( types[ i ] = SMESH::EDGE );
+ }
+ }
+
+ // check if this mesh is already in the table
+ if ( enable )
+ {
+ _PTR(SObject) sobj = SMESH::FindSObject( mesh );
+ if (( enable = bool( sobj )))
+ {
+ QString meshEntry = sobj->GetID().c_str();
+ for ( int row = 0, nbRow = myEnfMeshTableWdg->rowCount(); row < nbRow && enable; ++row )
+ {
+ QTableWidgetItem * cell = myEnfMeshTableWdg->item( row, 0 );
+ enable = ( meshEntry != cell->data( Qt::UserRole ).toString() );
+ }
+ }
+ }
+ }
+ myAddEnfMeshButton->setEnabled( enable );
+}
+
+//================================================================================
+/*!
+ * \brief SLOT called when selection changes in the table. Enable/disable [Remove] button
+ */
+//================================================================================
+
+void BLSURFPluginGUI_HypothesisCreator::onEnfMeshTableSelected()
+{
+ bool enable = !myEnfMeshTableWdg->selectedItems().empty();
+
+ myRemoveEnfMeshButton->setEnabled( enable );
+}
+
+//================================================================================
+/*!
+ * \brief Return false if algorithm is a re-mesher
+ */
+//================================================================================
+
bool BLSURFPluginGUI_HypothesisCreator::hasGeom() const
{
return hypType() == BLSURFPlugin_Hypothesis::GetHypType(true);
void onSelectEnforcedVertex();
void clearEnforcedVertexWidgets();
void onInternalVerticesClicked(int);
+ // Enforced mesh tab
+ void onAddEnforcedMesh();
+ void onRemoveEnforcedMesh();
+ void onEnforcedMeshSelected();
+ void onEnfMeshTableSelected();
// Periodicity tab
void onPeriodicityByVerticesChecked(bool);
void onAddPeriodicity();
void addHyPatchToTable(const QString& tags, const QString& entries);
bool hasGeom() const;
+ void addEnforcedMesh( SMESH::SMESH_IDSource_ptr mesh, const QString& groupName );
+
private:
QTabWidget* myTabWidget;
QCheckBox *myInternalEnforcedVerticesAllFaces;
QLineEdit *myInternalEnforcedVerticesAllFacesGroup;
+
+ // Enforced meshes
+ QWidget* myEnfMeshGroup;
+ StdMeshersGUI_ObjectReferenceParamWdg *myEnfMeshWdg;
+ QTableWidget* myEnfMeshTableWdg;
+ QLineEdit* myEnforcedGroupName;
+ QPushButton* myAddEnfMeshButton;
+ QPushButton* myRemoveEnfMeshButton;
+
+
+
// map = entry , size map
QMap<QString, QString> mySMPMap; // Map <face entry, size>
QMap<QString, TAttractorVec > myATTMap; // Map <face entry, att. entry, etc>
class EnforcedTreeWidgetDelegate : public QItemDelegate
{
- Q_OBJECT
+ Q_OBJECT
public:
EnforcedTreeWidgetDelegate(QObject *parent = 0);
const QModelIndex &index) const;
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
- const QModelIndex &index) const;
+ const QModelIndex &index) const;
bool vertexExists(QAbstractItemModel *model, const QModelIndex &index, QString value) const;
};
<translation>Hyper-patch</translation>
</message>
</context>
+<context>
+ <name>BLSURFPluginGUI_HypothesisCreator</name>
+ <message>
+ <source>ENF_NAME_COLUMN</source>
+ <translation>1D object</translation>
+ </message>
+ <message>
+ <source>ENF_GROUP_COLUMN</source>
+ <translation>Group name</translation>
+ </message>
+ <message>
+ <source>ENF_SELECT_MESH</source>
+ <translation>Select 1D object</translation>
+ </message>
+ <message>
+ <source>ENF_GROUP_LABEL</source>
+ <translation>Group name</translation>
+ </message>
+ <message>
+ <source>ENF_ADD</source>
+ <translation>Add</translation>
+ </message>
+ <message>
+ <source>ENF_REMOVE</source>
+ <translation>Remove</translation>
+ </message>
+ <message>
+ <source>ENF_MESH</source>
+ <translation>Enforced mesh</translation>
+ </message>
+</context>
<context>
<name>BLSURFPluginGUI_AdvWidget</name>
<message>