1 // Copyright (C) 2007-2008 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 // File : BLSURFPlugin_BLSURF.cxx
21 // Authors : Francis KLOSS (OCC) & Patrick LAUG (INRIA) & Lioka RAZAFINDRAZAKA (CEA)
22 // & Aurelien ALLEAUME (DISTENE)
25 #include "BLSURFPlugin_BLSURF.hxx"
26 #include "BLSURFPlugin_Hypothesis.hxx"
28 #include <SMESH_Gen.hxx>
29 #include <SMESH_Mesh.hxx>
30 #include <SMESH_ControlsDef.hxx>
32 #include <SMESHDS_Mesh.hxx>
33 #include <SMDS_MeshElement.hxx>
34 #include <SMDS_MeshNode.hxx>
36 #include <utilities.h>
41 #include <BRep_Tool.hxx>
43 #include <TopExp_Explorer.hxx>
45 #include <NCollection_Map.hxx>
46 #include <Standard_ErrorHandler.hxx>
49 #include <distene/api.h>
52 #include <Geom_Surface.hxx>
53 #include <Handle_Geom_Surface.hxx>
54 #include <Geom2d_Curve.hxx>
55 #include <Handle_Geom2d_Curve.hxx>
56 #include <Geom_Curve.hxx>
57 #include <Handle_Geom_Curve.hxx>
58 #include <TopoDS_Vertex.hxx>
59 #include <TopoDS_Edge.hxx>
60 #include <TopoDS_Wire.hxx>
61 #include <TopoDS_Face.hxx>
62 #include <TopoDS_Shape.hxx>
63 #include <gp_Pnt2d.hxx>
64 #include <TopTools_IndexedMapOfShape.hxx>
65 #include <BRepTools.hxx>
71 //=============================================================================
75 //=============================================================================
77 BLSURFPlugin_BLSURF::BLSURFPlugin_BLSURF(int hypId, int studyId,
79 : SMESH_2D_Algo(hypId, studyId, gen)
81 MESSAGE("BLSURFPlugin_BLSURF::BLSURFPlugin_BLSURF");
84 _shapeType = (1 << TopAbs_FACE); // 1 bit /shape type
85 _compatibleHypothesis.push_back("BLSURF_Parameters");
86 _requireDescretBoundary = false;
87 _onlyUnaryInput = false;
91 //=============================================================================
95 //=============================================================================
97 BLSURFPlugin_BLSURF::~BLSURFPlugin_BLSURF()
99 MESSAGE("BLSURFPlugin_BLSURF::~BLSURFPlugin_BLSURF");
102 //=============================================================================
106 //=============================================================================
108 bool BLSURFPlugin_BLSURF::CheckHypothesis
110 const TopoDS_Shape& aShape,
111 SMESH_Hypothesis::Hypothesis_Status& aStatus)
115 list<const SMESHDS_Hypothesis*>::const_iterator itl;
116 const SMESHDS_Hypothesis* theHyp;
118 const list<const SMESHDS_Hypothesis*>& hyps = GetUsedHypothesis(aMesh, aShape);
119 int nbHyp = hyps.size();
122 aStatus = SMESH_Hypothesis::HYP_OK;
123 return true; // can work with no hypothesis
127 theHyp = (*itl); // use only the first hypothesis
129 string hypName = theHyp->GetName();
131 if (hypName == "BLSURF_Parameters")
133 _hypothesis = static_cast<const BLSURFPlugin_Hypothesis*> (theHyp);
135 if ( _hypothesis->GetPhysicalMesh() == BLSURFPlugin_Hypothesis::DefaultSize &&
136 _hypothesis->GetGeometricMesh() == BLSURFPlugin_Hypothesis::DefaultGeom )
137 // hphy_flag = 0 and hgeo_flag = 0 is not allowed (spec)
138 aStatus = SMESH_Hypothesis::HYP_BAD_PARAMETER;
140 aStatus = SMESH_Hypothesis::HYP_OK;
143 aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
145 return aStatus == SMESH_Hypothesis::HYP_OK;
148 //=============================================================================
150 * Pass parameters to BLSURF
152 //=============================================================================
154 inline std::string to_string(double d)
156 std::ostringstream o;
161 inline std::string to_string(int i)
163 std::ostringstream o;
168 void BLSURFPlugin_BLSURF::SetParameters(const BLSURFPlugin_Hypothesis* hyp, blsurf_session_t *bls)
170 int _topology = BLSURFPlugin_Hypothesis::GetDefaultTopology();
171 int _physicalMesh = BLSURFPlugin_Hypothesis::GetDefaultPhysicalMesh();
172 double _phySize = BLSURFPlugin_Hypothesis::GetDefaultPhySize();
173 int _geometricMesh = BLSURFPlugin_Hypothesis::GetDefaultGeometricMesh();
174 double _angleMeshS = BLSURFPlugin_Hypothesis::GetDefaultAngleMeshS();
175 double _angleMeshC = BLSURFPlugin_Hypothesis::GetDefaultAngleMeshC();
176 double _gradation = BLSURFPlugin_Hypothesis::GetDefaultGradation();
177 bool _quadAllowed = BLSURFPlugin_Hypothesis::GetDefaultQuadAllowed();
178 bool _decimesh = BLSURFPlugin_Hypothesis::GetDefaultDecimesh();
179 int _verb = BLSURFPlugin_Hypothesis::GetDefaultVerbosity();
182 MESSAGE("BLSURFPlugin_BLSURF::SetParameters");
183 _topology = (int) hyp->GetTopology();
184 _physicalMesh = (int) hyp->GetPhysicalMesh();
185 _phySize = hyp->GetPhySize();
186 _geometricMesh = (int) hyp->GetGeometricMesh();
187 _angleMeshS = hyp->GetAngleMeshS();
188 _angleMeshC = hyp->GetAngleMeshC();
189 _gradation = hyp->GetGradation();
190 _quadAllowed = hyp->GetQuadAllowed();
191 _decimesh = hyp->GetDecimesh();
192 _verb = hyp->GetVerbosity();
194 if ( hyp->GetPhyMin() != ::BLSURFPlugin_Hypothesis::undefinedDouble() )
195 blsurf_set_param(bls, "hphymin", to_string(hyp->GetPhyMin()).c_str());
196 if ( hyp->GetPhyMax() != ::BLSURFPlugin_Hypothesis::undefinedDouble() )
197 blsurf_set_param(bls, "hphymax", to_string(hyp->GetPhyMax()).c_str());
198 if ( hyp->GetGeoMin() != ::BLSURFPlugin_Hypothesis::undefinedDouble() )
199 blsurf_set_param(bls, "hgeomin", to_string(hyp->GetGeoMin()).c_str());
200 if ( hyp->GetGeoMax() != ::BLSURFPlugin_Hypothesis::undefinedDouble() )
201 blsurf_set_param(bls, "hgeomax", to_string(hyp->GetGeoMax()).c_str());
203 const BLSURFPlugin_Hypothesis::TOptionValues & opts = hyp->GetOptionValues();
204 BLSURFPlugin_Hypothesis::TOptionValues::const_iterator opIt;
205 for ( opIt = opts.begin(); opIt != opts.end(); ++opIt )
206 if ( !opIt->second.empty() ) {
208 cout << "blsurf_set_param(): " << opIt->first << " = " << opIt->second << endl;
210 blsurf_set_param(bls, opIt->first.c_str(), opIt->second.c_str());
214 MESSAGE("BLSURFPlugin_BLSURF::SetParameters using defaults");
217 blsurf_set_param(bls, "topo_points", _topology > 0 ? "1" : "0");
218 blsurf_set_param(bls, "topo_curves", _topology > 0 ? "1" : "0");
219 blsurf_set_param(bls, "topo_project", _topology > 0 ? "1" : "0");
220 blsurf_set_param(bls, "clean_boundary", _topology > 1 ? "1" : "0");
221 blsurf_set_param(bls, "close_boundary", _topology > 1 ? "1" : "0");
222 blsurf_set_param(bls, "hphy_flag", to_string(_physicalMesh).c_str());
223 blsurf_set_param(bls, "hphydef", to_string(_phySize).c_str());
224 blsurf_set_param(bls, "hgeo_flag", to_string(_geometricMesh).c_str());
225 blsurf_set_param(bls, "angle_meshs", to_string(_angleMeshS).c_str());
226 blsurf_set_param(bls, "angle_meshc", to_string(_angleMeshC).c_str());
227 blsurf_set_param(bls, "gradation", to_string(_gradation).c_str());
228 blsurf_set_param(bls, "patch_independent", _decimesh ? "1" : "0");
229 blsurf_set_param(bls, "element", _quadAllowed ? "q1.0" : "p1");
230 blsurf_set_param(bls, "verb", to_string(_verb).c_str());
233 status_t curv_fun(real t, real *uv, real *dt, real *dtt, void *user_data);
234 status_t surf_fun(real *uv, real *xyz, real*du, real *dv,
235 real *duu, real *duv, real *dvv, void *user_data);
236 status_t message_callback(message_t *msg, void *user_data);
238 //=============================================================================
242 //=============================================================================
244 bool BLSURFPlugin_BLSURF::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape) {
246 MESSAGE("BLSURFPlugin_BLSURF::Compute");
248 if (aShape.ShapeType() == TopAbs_COMPOUND) {
249 cout << " the shape is a COMPOUND" << endl;
252 cout << " the shape is UNKNOWN" << endl;
255 context_t *ctx = context_new();
256 context_set_message_callback(ctx, message_callback, &_comment);
258 cad_t *c = cad_new(ctx);
260 TopTools_IndexedMapOfShape fmap;
261 TopTools_IndexedMapOfShape emap;
262 TopTools_IndexedMapOfShape pmap;
263 vector<Handle(Geom2d_Curve)> curves;
264 vector<Handle(Geom_Surface)> surfaces;
273 for (TopExp_Explorer face_iter(aShape,TopAbs_FACE);face_iter.More();face_iter.Next()) {
274 TopoDS_Face f=TopoDS::Face(face_iter.Current());
275 if (fmap.FindIndex(f) > 0)
280 surfaces.push_back(BRep_Tool::Surface(f));
281 cad_face_t *fce = cad_face_new(c, iface, surf_fun, surfaces.back());
282 cad_face_set_tag(fce, iface);
283 if(f.Orientation() != TopAbs_FORWARD){
284 cad_face_set_orientation(fce, CAD_ORIENTATION_REVERSED);
286 cad_face_set_orientation(fce, CAD_ORIENTATION_FORWARD);
289 for (TopExp_Explorer edge_iter(f,TopAbs_EDGE);edge_iter.More();edge_iter.Next()) {
290 TopoDS_Edge e = TopoDS::Edge(edge_iter.Current());
291 int ic = emap.FindIndex(e);
296 curves.push_back(BRep_Tool::CurveOnSurface(e, f, tmin, tmax));
297 cad_edge_t *edg = cad_edge_new(fce, ic, tmin, tmax, curv_fun, curves.back());
298 cad_edge_set_tag(edg, ic);
299 cad_edge_set_property(edg, EDGE_PROPERTY_SOFT_REQUIRED);
300 if (e.Orientation() == TopAbs_INTERNAL)
301 cad_edge_set_property(edg, EDGE_PROPERTY_INTERNAL);
305 gp_Pnt2d e0 = curves.back()->Value(tmin);
306 gp_Pnt ee0 = surfaces.back()->Value(e0.X(), e0.Y());
307 Standard_Real d1=0,d2=0;
308 for (TopExp_Explorer ex_edge(e ,TopAbs_VERTEX); ex_edge.More(); ex_edge.Next()) {
309 TopoDS_Vertex v = TopoDS::Vertex(ex_edge.Current());
314 d1 = ee0.SquareDistance(BRep_Tool::Pnt(v));
317 d2 = ee0.SquareDistance(BRep_Tool::Pnt(v));
319 *ip = pmap.FindIndex(v);
325 cout << "An edge does not have 2 extremities." << endl;
328 cad_edge_set_extremities(edg, ip1, ip2);
330 cad_edge_set_extremities(edg, ip2, ip1);
338 blsurf_session_t *bls = blsurf_session_new(ctx);
339 blsurf_data_set_cad(bls, c);
341 SetParameters(_hypothesis, bls);
344 cout << "Beginning of Surface Mesh generation" << endl;
347 // Issue 0019864. On DebianSarge, FE signals do not obey to OSD::SetSignal(false)
349 feclearexcept( FE_ALL_EXCEPT );
350 int oldFEFlags = fedisableexcept( FE_ALL_EXCEPT );
353 status_t status = STATUS_ERROR;
358 status = blsurf_compute_mesh(bls);
361 catch ( std::exception& exc ) {
362 _comment += exc.what();
364 catch (Standard_Failure& ex) {
365 _comment += ex.DynamicType()->Name();
366 if ( ex.GetMessageString() && strlen( ex.GetMessageString() )) {
368 _comment += ex.GetMessageString();
372 if ( _comment.empty() )
373 _comment = "Exception in blsurf_compute_mesh()";
375 if ( status != STATUS_OK) {
376 blsurf_session_delete(bls);
380 return error(_comment);
384 cout << "End of Surface Mesh generation" << endl;
388 blsurf_data_get_mesh(bls, &msh);
390 blsurf_session_delete(bls);
394 return error(_comment);
398 integer nv, ne, nt, nq, vtx[4], tag;
401 mesh_get_vertex_count(msh, &nv);
402 mesh_get_edge_count(msh, &ne);
403 mesh_get_triangle_count(msh, &nt);
404 mesh_get_quadrangle_count(msh, &nq);
407 SMESHDS_Mesh* meshDS = aMesh.GetMeshDS();
408 SMDS_MeshNode** nodes = new SMDS_MeshNode*[nv+1];
409 bool* tags = new bool[nv+1];
411 for(int iv=1;iv<=nv;iv++) {
412 mesh_get_vertex_coordinates(msh, iv, xyz);
413 mesh_get_vertex_tag(msh, iv, &tag);
414 nodes[iv] = meshDS->AddNode(xyz[0], xyz[1], xyz[2]);
415 // internal point are tagged to zero
417 meshDS->SetNodeOnVertex(nodes[iv], TopoDS::Vertex(pmap(tag)));
424 for(int it=1;it<=ne;it++) {
425 mesh_get_edge_vertices(msh, it, vtx);
426 SMDS_MeshEdge* edg = meshDS->AddEdge(nodes[vtx[0]], nodes[vtx[1]]);
427 mesh_get_edge_tag(msh, it, &tag);
430 meshDS->SetNodeOnEdge(nodes[vtx[0]], TopoDS::Edge(emap(tag)));
431 tags[vtx[0]] = false;
434 meshDS->SetNodeOnEdge(nodes[vtx[1]], TopoDS::Edge(emap(tag)));
435 tags[vtx[1]] = false;
437 meshDS->SetMeshElementOnShape(edg, TopoDS::Edge(emap(tag)));
441 for(int it=1;it<=nt;it++) {
442 mesh_get_triangle_vertices(msh, it, vtx);
443 SMDS_MeshFace* tri = meshDS->AddFace(nodes[vtx[0]], nodes[vtx[1]], nodes[vtx[2]]);
444 mesh_get_triangle_tag(msh, it, &tag);
445 meshDS->SetMeshElementOnShape(tri, TopoDS::Face(fmap(tag)));
447 meshDS->SetNodeOnFace(nodes[vtx[0]], TopoDS::Face(fmap(tag)));
448 tags[vtx[0]] = false;
451 meshDS->SetNodeOnFace(nodes[vtx[1]], TopoDS::Face(fmap(tag)));
452 tags[vtx[1]] = false;
455 meshDS->SetNodeOnFace(nodes[vtx[2]], TopoDS::Face(fmap(tag)));
456 tags[vtx[2]] = false;
460 for(int it=1;it<=nq;it++) {
461 mesh_get_quadrangle_vertices(msh, it, vtx);
462 SMDS_MeshFace* quad = meshDS->AddFace(nodes[vtx[0]], nodes[vtx[1]], nodes[vtx[2]], nodes[vtx[3]]);
463 mesh_get_quadrangle_tag(msh, it, &tag);
464 meshDS->SetMeshElementOnShape(quad, TopoDS::Face(fmap(tag)));
466 meshDS->SetNodeOnFace(nodes[vtx[0]], TopoDS::Face(fmap(tag)));
467 tags[vtx[0]] = false;
470 meshDS->SetNodeOnFace(nodes[vtx[1]], TopoDS::Face(fmap(tag)));
471 tags[vtx[1]] = false;
474 meshDS->SetNodeOnFace(nodes[vtx[2]], TopoDS::Face(fmap(tag)));
475 tags[vtx[2]] = false;
478 meshDS->SetNodeOnFace(nodes[vtx[3]], TopoDS::Face(fmap(tag)));
479 tags[vtx[3]] = false;
485 /* release the mesh object */
486 blsurf_data_regain_mesh(bls, msh);
488 /* clean up everything */
489 blsurf_session_delete(bls);
494 // Issue 0019864. On DebianSarge, FE signals do not obey to OSD::SetSignal(false)
496 if ( oldFEFlags > 0 )
497 feenableexcept( oldFEFlags );
498 feclearexcept( FE_ALL_EXCEPT );
504 //=============================================================================
508 //=============================================================================
510 ostream & BLSURFPlugin_BLSURF::SaveTo(ostream & save)
515 //=============================================================================
519 //=============================================================================
521 istream & BLSURFPlugin_BLSURF::LoadFrom(istream & load)
526 //=============================================================================
530 //=============================================================================
532 ostream & operator << (ostream & save, BLSURFPlugin_BLSURF & hyp)
534 return hyp.SaveTo( save );
537 //=============================================================================
541 //=============================================================================
543 istream & operator >> (istream & load, BLSURFPlugin_BLSURF & hyp)
545 return hyp.LoadFrom( load );
548 status_t curv_fun(real t, real *uv, real *dt, real *dtt, void *user_data)
550 const Geom2d_Curve*pargeo = (const Geom2d_Curve*) user_data;
555 uv[0]=P.X(); uv[1]=P.Y();
561 dt[0]=V1.X(); dt[1]=V1.Y();
567 dtt[0]=V2.X(); dtt[1]=V2.Y();
573 status_t surf_fun(real *uv, real *xyz, real*du, real *dv,
574 real *duu, real *duv, real *dvv, void *user_data)
576 const Geom_Surface* geometry = (const Geom_Surface*) user_data;
580 P=geometry->Value(uv[0],uv[1]); // S.D0(U,V,P);
581 xyz[0]=P.X(); xyz[1]=P.Y(); xyz[2]=P.Z();
588 geometry->D1(uv[0],uv[1],P,D1U,D1V);
589 du[0]=D1U.X(); du[1]=D1U.Y(); du[2]=D1U.Z();
590 dv[0]=D1V.X(); dv[1]=D1V.Y(); dv[2]=D1V.Z();
593 if(duu && duv && dvv){
598 geometry->D2(uv[0],uv[1],P,D1U,D1V,D2U,D2V,D2UV);
599 duu[0]=D2U.X(); duu[1]=D2U.Y(); duu[2]=D2U.Z();
600 duv[0]=D2UV.X(); duv[1]=D2UV.Y(); duv[2]=D2UV.Z();
601 dvv[0]=D2V.X(); dvv[1]=D2V.Y(); dvv[2]=D2V.Z();
607 status_t message_callback(message_t *msg, void *user_data)
609 integer errnumber = 0;
611 message_get_number(msg, &errnumber);
612 message_get_description(msg, &desc);
613 if ( errnumber < 0 ) {
614 string * error = (string*)user_data;
615 // if ( !error->empty() )
617 // remove ^A from the tail
618 int len = strlen( desc );
619 while (len > 0 && desc[len-1] != '\n')
621 error->append( desc, len );