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
19 // BLSURFPlugin : C++ implementation
20 // File : BLSURFPlugin_BLSURF.cxx
21 // Authors : Francis KLOSS (OCC) & Patrick LAUG (INRIA) & Lioka RAZAFINDRAZAKA (CEA)
22 // & Aurelien ALLEAUME (DISTENE)
25 //=============================================================================
29 #include "BLSURFPlugin_BLSURF.hxx"
30 #include "BLSURFPlugin_Hypothesis.hxx"
32 #include <SMESH_Gen.hxx>
33 #include <SMESH_Mesh.hxx>
34 #include <SMESH_ControlsDef.hxx>
36 #include <SMESHDS_Mesh.hxx>
37 #include <SMDS_MeshElement.hxx>
38 #include <SMDS_MeshNode.hxx>
40 #include <utilities.h>
45 #include <BRep_Tool.hxx>
47 #include <TopExp_Explorer.hxx>
49 #include <NCollection_Map.hxx>
50 #include <Standard_ErrorHandler.hxx>
53 #include <distene/api.h>
56 #include <Geom_Surface.hxx>
57 #include <Handle_Geom_Surface.hxx>
58 #include <Geom2d_Curve.hxx>
59 #include <Handle_Geom2d_Curve.hxx>
60 #include <Geom_Curve.hxx>
61 #include <Handle_Geom_Curve.hxx>
62 #include <TopoDS_Vertex.hxx>
63 #include <TopoDS_Edge.hxx>
64 #include <TopoDS_Wire.hxx>
65 #include <TopoDS_Face.hxx>
66 #include <TopoDS_Shape.hxx>
67 #include <gp_Pnt2d.hxx>
68 #include <TopTools_IndexedMapOfShape.hxx>
69 #include <BRepTools.hxx>
75 //=============================================================================
79 //=============================================================================
81 BLSURFPlugin_BLSURF::BLSURFPlugin_BLSURF(int hypId, int studyId,
83 : SMESH_2D_Algo(hypId, studyId, gen)
85 MESSAGE("BLSURFPlugin_BLSURF::BLSURFPlugin_BLSURF");
88 _shapeType = (1 << TopAbs_FACE); // 1 bit /shape type
89 _compatibleHypothesis.push_back("BLSURF_Parameters");
90 _requireDescretBoundary = false;
91 _onlyUnaryInput = false;
95 //=============================================================================
99 //=============================================================================
101 BLSURFPlugin_BLSURF::~BLSURFPlugin_BLSURF()
103 MESSAGE("BLSURFPlugin_BLSURF::~BLSURFPlugin_BLSURF");
106 //=============================================================================
110 //=============================================================================
112 bool BLSURFPlugin_BLSURF::CheckHypothesis
114 const TopoDS_Shape& aShape,
115 SMESH_Hypothesis::Hypothesis_Status& aStatus)
119 list<const SMESHDS_Hypothesis*>::const_iterator itl;
120 const SMESHDS_Hypothesis* theHyp;
122 const list<const SMESHDS_Hypothesis*>& hyps = GetUsedHypothesis(aMesh, aShape);
123 int nbHyp = hyps.size();
126 aStatus = SMESH_Hypothesis::HYP_OK;
127 return true; // can work with no hypothesis
131 theHyp = (*itl); // use only the first hypothesis
133 string hypName = theHyp->GetName();
135 if (hypName == "BLSURF_Parameters")
137 _hypothesis = static_cast<const BLSURFPlugin_Hypothesis*> (theHyp);
139 if ( _hypothesis->GetPhysicalMesh() == BLSURFPlugin_Hypothesis::DefaultSize &&
140 _hypothesis->GetGeometricMesh() == BLSURFPlugin_Hypothesis::DefaultGeom )
141 // hphy_flag = 0 and hgeo_flag = 0 is not allowed (spec)
142 aStatus = SMESH_Hypothesis::HYP_BAD_PARAMETER;
144 aStatus = SMESH_Hypothesis::HYP_OK;
147 aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
149 return aStatus == SMESH_Hypothesis::HYP_OK;
152 //=============================================================================
154 * Pass parameters to BLSURF
156 //=============================================================================
158 inline std::string to_string(double d)
160 std::ostringstream o;
165 inline std::string to_string(int i)
167 std::ostringstream o;
172 void BLSURFPlugin_BLSURF::SetParameters(const BLSURFPlugin_Hypothesis* hyp, blsurf_session_t *bls)
174 int _topology = BLSURFPlugin_Hypothesis::GetDefaultTopology();
175 int _physicalMesh = BLSURFPlugin_Hypothesis::GetDefaultPhysicalMesh();
176 double _phySize = BLSURFPlugin_Hypothesis::GetDefaultPhySize();
177 int _geometricMesh = BLSURFPlugin_Hypothesis::GetDefaultGeometricMesh();
178 double _angleMeshS = BLSURFPlugin_Hypothesis::GetDefaultAngleMeshS();
179 double _angleMeshC = BLSURFPlugin_Hypothesis::GetDefaultAngleMeshC();
180 double _gradation = BLSURFPlugin_Hypothesis::GetDefaultGradation();
181 bool _quadAllowed = BLSURFPlugin_Hypothesis::GetDefaultQuadAllowed();
182 bool _decimesh = BLSURFPlugin_Hypothesis::GetDefaultDecimesh();
183 int _verb = BLSURFPlugin_Hypothesis::GetDefaultVerbosity();
186 MESSAGE("BLSURFPlugin_BLSURF::SetParameters");
187 _topology = (int) hyp->GetTopology();
188 _physicalMesh = (int) hyp->GetPhysicalMesh();
189 _phySize = hyp->GetPhySize();
190 _geometricMesh = (int) hyp->GetGeometricMesh();
191 _angleMeshS = hyp->GetAngleMeshS();
192 _angleMeshC = hyp->GetAngleMeshC();
193 _gradation = hyp->GetGradation();
194 _quadAllowed = hyp->GetQuadAllowed();
195 _decimesh = hyp->GetDecimesh();
196 _verb = hyp->GetVerbosity();
198 if ( hyp->GetPhyMin() != ::BLSURFPlugin_Hypothesis::undefinedDouble() )
199 blsurf_set_param(bls, "hphymin", to_string(hyp->GetPhyMin()).c_str());
200 if ( hyp->GetPhyMax() != ::BLSURFPlugin_Hypothesis::undefinedDouble() )
201 blsurf_set_param(bls, "hphymax", to_string(hyp->GetPhyMax()).c_str());
202 if ( hyp->GetGeoMin() != ::BLSURFPlugin_Hypothesis::undefinedDouble() )
203 blsurf_set_param(bls, "hgeomin", to_string(hyp->GetGeoMin()).c_str());
204 if ( hyp->GetGeoMax() != ::BLSURFPlugin_Hypothesis::undefinedDouble() )
205 blsurf_set_param(bls, "hgeomax", to_string(hyp->GetGeoMax()).c_str());
207 const BLSURFPlugin_Hypothesis::TOptionValues & opts = hyp->GetOptionValues();
208 BLSURFPlugin_Hypothesis::TOptionValues::const_iterator opIt;
209 for ( opIt = opts.begin(); opIt != opts.end(); ++opIt )
210 if ( !opIt->second.empty() ) {
212 cout << "blsurf_set_param(): " << opIt->first << " = " << opIt->second << endl;
214 blsurf_set_param(bls, opIt->first.c_str(), opIt->second.c_str());
218 MESSAGE("BLSURFPlugin_BLSURF::SetParameters using defaults");
221 blsurf_set_param(bls, "topo_points", _topology > 0 ? "1" : "0");
222 blsurf_set_param(bls, "topo_curves", _topology > 0 ? "1" : "0");
223 blsurf_set_param(bls, "topo_project", _topology > 0 ? "1" : "0");
224 blsurf_set_param(bls, "clean_boundary", _topology > 1 ? "1" : "0");
225 blsurf_set_param(bls, "close_boundary", _topology > 1 ? "1" : "0");
226 blsurf_set_param(bls, "hphy_flag", to_string(_physicalMesh).c_str());
227 blsurf_set_param(bls, "hphydef", to_string(_phySize).c_str());
228 blsurf_set_param(bls, "hgeo_flag", to_string(_geometricMesh).c_str());
229 blsurf_set_param(bls, "angle_meshs", to_string(_angleMeshS).c_str());
230 blsurf_set_param(bls, "angle_meshc", to_string(_angleMeshC).c_str());
231 blsurf_set_param(bls, "gradation", to_string(_gradation).c_str());
232 blsurf_set_param(bls, "patch_independent", _decimesh ? "1" : "0");
233 blsurf_set_param(bls, "element", _quadAllowed ? "q1.0" : "p1");
234 blsurf_set_param(bls, "verb", to_string(_verb).c_str());
237 status_t curv_fun(real t, real *uv, real *dt, real *dtt, void *user_data);
238 status_t surf_fun(real *uv, real *xyz, real*du, real *dv,
239 real *duu, real *duv, real *dvv, void *user_data);
240 status_t message_callback(message_t *msg, void *user_data);
242 //=============================================================================
246 //=============================================================================
248 bool BLSURFPlugin_BLSURF::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape) {
250 MESSAGE("BLSURFPlugin_BLSURF::Compute");
252 if (aShape.ShapeType() == TopAbs_COMPOUND) {
253 cout << " the shape is a COMPOUND" << endl;
256 cout << " the shape is UNKNOWN" << endl;
259 context_t *ctx = context_new();
260 context_set_message_callback(ctx, message_callback, &_comment);
262 cad_t *c = cad_new(ctx);
264 TopTools_IndexedMapOfShape fmap;
265 TopTools_IndexedMapOfShape emap;
266 TopTools_IndexedMapOfShape pmap;
267 vector<Handle(Geom2d_Curve)> curves;
268 vector<Handle(Geom_Surface)> surfaces;
277 for (TopExp_Explorer face_iter(aShape,TopAbs_FACE);face_iter.More();face_iter.Next()) {
278 TopoDS_Face f=TopoDS::Face(face_iter.Current());
279 if (fmap.FindIndex(f) > 0)
284 surfaces.push_back(BRep_Tool::Surface(f));
285 cad_face_t *fce = cad_face_new(c, iface, surf_fun, surfaces.back());
286 cad_face_set_tag(fce, iface);
287 if(f.Orientation() != TopAbs_FORWARD){
288 cad_face_set_orientation(fce, CAD_ORIENTATION_REVERSED);
290 cad_face_set_orientation(fce, CAD_ORIENTATION_FORWARD);
293 for (TopExp_Explorer edge_iter(f,TopAbs_EDGE);edge_iter.More();edge_iter.Next()) {
294 TopoDS_Edge e = TopoDS::Edge(edge_iter.Current());
295 int ic = emap.FindIndex(e);
300 curves.push_back(BRep_Tool::CurveOnSurface(e, f, tmin, tmax));
301 cad_edge_t *edg = cad_edge_new(fce, ic, tmin, tmax, curv_fun, curves.back());
302 cad_edge_set_tag(edg, ic);
303 cad_edge_set_property(edg, EDGE_PROPERTY_SOFT_REQUIRED);
304 if (e.Orientation() == TopAbs_INTERNAL)
305 cad_edge_set_property(edg, EDGE_PROPERTY_INTERNAL);
309 gp_Pnt2d e0 = curves.back()->Value(tmin);
310 gp_Pnt ee0 = surfaces.back()->Value(e0.X(), e0.Y());
311 Standard_Real d1=0,d2=0;
312 for (TopExp_Explorer ex_edge(e ,TopAbs_VERTEX); ex_edge.More(); ex_edge.Next()) {
313 TopoDS_Vertex v = TopoDS::Vertex(ex_edge.Current());
318 d1 = ee0.SquareDistance(BRep_Tool::Pnt(v));
321 d2 = ee0.SquareDistance(BRep_Tool::Pnt(v));
323 *ip = pmap.FindIndex(v);
329 cout << "An edge does not have 2 extremities." << endl;
332 cad_edge_set_extremities(edg, ip1, ip2);
334 cad_edge_set_extremities(edg, ip2, ip1);
342 blsurf_session_t *bls = blsurf_session_new(ctx);
343 blsurf_data_set_cad(bls, c);
345 SetParameters(_hypothesis, bls);
348 cout << "Beginning of Surface Mesh generation" << endl;
351 // Issue 0019864. On DebianSarge, FE signals do not obey to OSD::SetSignal(false)
353 feclearexcept( FE_ALL_EXCEPT );
354 int oldFEFlags = fedisableexcept( FE_ALL_EXCEPT );
357 status_t status = STATUS_ERROR;
362 status = blsurf_compute_mesh(bls);
365 catch ( std::exception& exc ) {
366 _comment += exc.what();
368 catch (Standard_Failure& ex) {
369 _comment += ex.DynamicType()->Name();
370 if ( ex.GetMessageString() && strlen( ex.GetMessageString() )) {
372 _comment += ex.GetMessageString();
376 if ( _comment.empty() )
377 _comment = "Exception in blsurf_compute_mesh()";
379 if ( status != STATUS_OK) {
380 blsurf_session_delete(bls);
384 return error(_comment);
388 cout << "End of Surface Mesh generation" << endl;
392 blsurf_data_get_mesh(bls, &msh);
394 blsurf_session_delete(bls);
398 return error(_comment);
402 integer nv, ne, nt, nq, vtx[4], tag;
405 mesh_get_vertex_count(msh, &nv);
406 mesh_get_edge_count(msh, &ne);
407 mesh_get_triangle_count(msh, &nt);
408 mesh_get_quadrangle_count(msh, &nq);
411 SMESHDS_Mesh* meshDS = aMesh.GetMeshDS();
412 SMDS_MeshNode** nodes = new SMDS_MeshNode*[nv+1];
413 bool* tags = new bool[nv+1];
415 for(int iv=1;iv<=nv;iv++) {
416 mesh_get_vertex_coordinates(msh, iv, xyz);
417 mesh_get_vertex_tag(msh, iv, &tag);
418 nodes[iv] = meshDS->AddNode(xyz[0], xyz[1], xyz[2]);
419 // internal point are tagged to zero
421 meshDS->SetNodeOnVertex(nodes[iv], TopoDS::Vertex(pmap(tag)));
428 for(int it=1;it<=ne;it++) {
429 mesh_get_edge_vertices(msh, it, vtx);
430 SMDS_MeshEdge* edg = meshDS->AddEdge(nodes[vtx[0]], nodes[vtx[1]]);
431 mesh_get_edge_tag(msh, it, &tag);
434 meshDS->SetNodeOnEdge(nodes[vtx[0]], TopoDS::Edge(emap(tag)));
435 tags[vtx[0]] = false;
438 meshDS->SetNodeOnEdge(nodes[vtx[1]], TopoDS::Edge(emap(tag)));
439 tags[vtx[1]] = false;
441 meshDS->SetMeshElementOnShape(edg, TopoDS::Edge(emap(tag)));
445 for(int it=1;it<=nt;it++) {
446 mesh_get_triangle_vertices(msh, it, vtx);
447 SMDS_MeshFace* tri = meshDS->AddFace(nodes[vtx[0]], nodes[vtx[1]], nodes[vtx[2]]);
448 mesh_get_triangle_tag(msh, it, &tag);
449 meshDS->SetMeshElementOnShape(tri, TopoDS::Face(fmap(tag)));
451 meshDS->SetNodeOnFace(nodes[vtx[0]], TopoDS::Face(fmap(tag)));
452 tags[vtx[0]] = false;
455 meshDS->SetNodeOnFace(nodes[vtx[1]], TopoDS::Face(fmap(tag)));
456 tags[vtx[1]] = false;
459 meshDS->SetNodeOnFace(nodes[vtx[2]], TopoDS::Face(fmap(tag)));
460 tags[vtx[2]] = false;
464 for(int it=1;it<=nq;it++) {
465 mesh_get_quadrangle_vertices(msh, it, vtx);
466 SMDS_MeshFace* quad = meshDS->AddFace(nodes[vtx[0]], nodes[vtx[1]], nodes[vtx[2]], nodes[vtx[3]]);
467 mesh_get_quadrangle_tag(msh, it, &tag);
468 meshDS->SetMeshElementOnShape(quad, TopoDS::Face(fmap(tag)));
470 meshDS->SetNodeOnFace(nodes[vtx[0]], TopoDS::Face(fmap(tag)));
471 tags[vtx[0]] = false;
474 meshDS->SetNodeOnFace(nodes[vtx[1]], TopoDS::Face(fmap(tag)));
475 tags[vtx[1]] = false;
478 meshDS->SetNodeOnFace(nodes[vtx[2]], TopoDS::Face(fmap(tag)));
479 tags[vtx[2]] = false;
482 meshDS->SetNodeOnFace(nodes[vtx[3]], TopoDS::Face(fmap(tag)));
483 tags[vtx[3]] = false;
489 /* release the mesh object */
490 blsurf_data_regain_mesh(bls, msh);
492 /* clean up everything */
493 blsurf_session_delete(bls);
498 // Issue 0019864. On DebianSarge, FE signals do not obey to OSD::SetSignal(false)
500 if ( oldFEFlags > 0 )
501 feenableexcept( oldFEFlags );
502 feclearexcept( FE_ALL_EXCEPT );
508 //=============================================================================
512 //=============================================================================
514 ostream & BLSURFPlugin_BLSURF::SaveTo(ostream & save)
519 //=============================================================================
523 //=============================================================================
525 istream & BLSURFPlugin_BLSURF::LoadFrom(istream & load)
530 //=============================================================================
534 //=============================================================================
536 ostream & operator << (ostream & save, BLSURFPlugin_BLSURF & hyp)
538 return hyp.SaveTo( save );
541 //=============================================================================
545 //=============================================================================
547 istream & operator >> (istream & load, BLSURFPlugin_BLSURF & hyp)
549 return hyp.LoadFrom( load );
552 status_t curv_fun(real t, real *uv, real *dt, real *dtt, void *user_data)
554 const Geom2d_Curve*pargeo = (const Geom2d_Curve*) user_data;
559 uv[0]=P.X(); uv[1]=P.Y();
565 dt[0]=V1.X(); dt[1]=V1.Y();
571 dtt[0]=V2.X(); dtt[1]=V2.Y();
577 status_t surf_fun(real *uv, real *xyz, real*du, real *dv,
578 real *duu, real *duv, real *dvv, void *user_data)
580 const Geom_Surface* geometry = (const Geom_Surface*) user_data;
584 P=geometry->Value(uv[0],uv[1]); // S.D0(U,V,P);
585 xyz[0]=P.X(); xyz[1]=P.Y(); xyz[2]=P.Z();
592 geometry->D1(uv[0],uv[1],P,D1U,D1V);
593 du[0]=D1U.X(); du[1]=D1U.Y(); du[2]=D1U.Z();
594 dv[0]=D1V.X(); dv[1]=D1V.Y(); dv[2]=D1V.Z();
597 if(duu && duv && dvv){
602 geometry->D2(uv[0],uv[1],P,D1U,D1V,D2U,D2V,D2UV);
603 duu[0]=D2U.X(); duu[1]=D2U.Y(); duu[2]=D2U.Z();
604 duv[0]=D2UV.X(); duv[1]=D2UV.Y(); duv[2]=D2UV.Z();
605 dvv[0]=D2V.X(); dvv[1]=D2V.Y(); dvv[2]=D2V.Z();
611 status_t message_callback(message_t *msg, void *user_data)
613 integer errnumber = 0;
615 message_get_number(msg, &errnumber);
616 message_get_description(msg, &desc);
617 if ( errnumber < 0 ) {
618 string * error = (string*)user_data;
619 // if ( !error->empty() )
621 // remove ^A from the tail
622 int len = strlen( desc );
623 while (len > 0 && desc[len-1] != '\n')
625 error->append( desc, len );