6 #include "GmshConfig.h"
19 #include <BOPTools_AlgoTools.hxx>
20 #include <BOPTools_AlgoTools2D.hxx>
21 #include <BRepBndLib.hxx>
22 #include <BRepClass_FaceClassifier.hxx>
23 #include <BRepLProp_SLProps.hxx>
24 #include <BRepTools.hxx>
25 #include <BRep_Builder.hxx>
26 #include <Bnd_Box.hxx>
27 #include <Geom_BSplineSurface.hxx>
28 #include <Geom_BezierSurface.hxx>
29 #include <Geom_ConicalSurface.hxx>
30 #include <Geom_CylindricalSurface.hxx>
31 #include <Geom_Plane.hxx>
32 #include <Geom_SphericalSurface.hxx>
33 #include <Geom_SurfaceOfRevolution.hxx>
34 #include <Geom_ToroidalSurface.hxx>
35 #include <IntTools_Context.hxx>
36 #include <ShapeAnalysis.hxx>
37 #include <ShapeFix_Wire.hxx>
38 #include <Standard_Version.hxx>
39 #include <TopExp_Explorer.hxx>
42 #include <gp_Sphere.hxx>
44 OCCFace::OCCFace(
GModel *m, TopoDS_Face s,
int num)
45 :
GFace(m, num), _s(s), _sf(s, Standard_True), _radius(-1)
51 writeBREP(
"debugSurface.brep");
54 void OCCFace::_setup()
60 TopExp_Explorer exp2, exp3;
61 for(exp2.Init(_s.Oriented(TopAbs_FORWARD), TopAbs_WIRE); exp2.More();
63 TopoDS_Wire wire = TopoDS::Wire(exp2.Current());
73 Msg::Debug(
"OCC surface %d - new wire", tag());
76 for(exp3.Init(wire, TopAbs_EDGE); exp3.More(); exp3.Next()) {
77 TopoDS_Edge edge = TopoDS::Edge(exp3.Current());
79 if(model()->getOCCInternals())
80 e = model()->getOCCInternals()->getEdgeForOCCShape(model(), edge);
81 if(!e) {
Msg::Error(
"Unknown curve in surface %d", tag()); }
82 else if(edge.Orientation() == TopAbs_INTERNAL &&
84 Msg::Debug(
"Adding embedded curve %d in surface %d", e->
tag(), tag());
85 embedded_edges.push_back(e);
92 int ori = edge.Orientation() ? -1 : 1;
102 Msg::Warning(
"Recomputing incorrect OpenCASCADE wire in surface %d", tag());
103 std::vector<GEdge*>
edges;
109 l_edges.push_back(it->getEdge());
110 l_dirs.push_back(it->getSign());
111 if(el.
count() == 2) {
112 it->getEdge()->meshAttributes.minimumMeshSegments =
113 std::max(it->getEdge()->meshAttributes.minimumMeshSegments, 2);
115 if(el.
count() == 1) {
116 it->getEdge()->meshAttributes.minimumMeshSegments =
117 std::max(it->getEdge()->meshAttributes.minimumMeshSegments, 3);
120 edgeLoops.push_back(el);
123 for(exp2.Init(_s.Oriented(TopAbs_FORWARD), TopAbs_VERTEX, TopAbs_EDGE);
124 exp2.More(); exp2.Next()) {
125 TopoDS_Vertex vertex = TopoDS::Vertex(exp2.Current());
127 if(model()->getOCCInternals())
128 v = model()->getOCCInternals()->getVertexForOCCShape(model(), vertex);
129 if(!v) {
Msg::Error(
"Unknown point in surface %d", tag()); }
130 else if(vertex.Orientation() == TopAbs_INTERNAL &&
132 Msg::Debug(
"Adding embedded point %d in surface %d", v->
tag(), tag());
133 embedded_vertices.insert(v);
137 BRepAdaptor_Surface surface(_s);
138 _periodic[0] = surface.IsUPeriodic();
139 _periodic[1] = surface.IsVPeriodic();
140 if(_periodic[0]) _period[0] = surface.UPeriod();
141 if(_periodic[1]) _period[1] = surface.VPeriod();
143 ShapeAnalysis::GetFaceUVBounds(_s, _umin, _umax, _vmin, _vmax);
144 Msg::Debug(
"OCC surface %d with %d parameter bounds (%g,%g)(%g,%g)", tag(),
145 l_edges.size(), _umin, _umax, _vmin, _vmax);
147 _occface = BRep_Tool::Surface(_s);
156 const double du = _umax - _umin;
157 const double utol = std::max(fabs(du) * 1e-8, 1e-12);
162 const double dv = _vmax - _vmin;
163 const double vtol = std::max(fabs(dv) * 1e-8, 1e-12);
167 _projector.Init(_occface, umin, umax, vmin, vmax);
170 BRepAdaptor_Surface surface(_s);
171 gp_Sphere sphere = surface.Sphere();
172 _radius = sphere.Radius();
173 gp_Pnt loc = sphere.Location();
174 _center =
SPoint3(loc.X(), loc.Y(), loc.Z());
179 for(std::size_t i = 0; i < l_edges.size(); i++) {
180 GEdge *e = l_edges[i];
182 OCCEdge *occe =
dynamic_cast<OCCEdge *
>(e);
183 if(occe && !e->
is3D()) occe->setTrimmed(
this);
185 for(std::size_t i = 0; i < embedded_edges.size(); i++) {
186 GEdge *e = embedded_edges[i];
189 OCCEdge *occe =
dynamic_cast<OCCEdge *
>(e);
190 if(occe && !e->
is3D()) occe->setTrimmed(
this);
197 buildSTLTriangulation();
206 if(stl_vertices_xyz.size()) {
208 for(std::size_t i = 0; i < stl_vertices_xyz.size(); i++)
209 bbox += stl_vertices_xyz[i];
216 BRepBndLib::Add(_s, b);
217 }
catch(Standard_Failure &err) {
218 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
221 double xmin, ymin, zmin, xmax, ymax, zmax;
222 b.Get(xmin, ymin, zmin, xmax, ymax, zmax);
238 _occface->D1(param.
x(), param.
y(), pnt, du, dv);
240 SVector3 t1(du.X(), du.Y(), du.Z());
241 SVector3 t2(dv.X(), dv.Y(), dv.Z());
244 if(_s.Orientation() == TopAbs_REVERSED)
return n * (-1.);
252 _occface->D1(param.
x(), param.
y(), pnt, du, dv);
261 gp_Vec du, dv, duu, dvv, duv;
262 _occface->D2(param.
x(), param.
y(), pnt, du, dv, duu, dvv, duv);
264 dudu =
SVector3(duu.X(), duu.Y(), duu.Z());
265 dvdv =
SVector3(dvv.X(), dvv.Y(), dvv.Z());
266 dudv =
SVector3(duv.X(), duv.Y(), duv.Z());
269 GPoint OCCFace::point(
double par1,
double par2)
const
271 double pp[2] = {par1, par2};
272 gp_Pnt val = _occface->Value(par1, par2);
273 return GPoint(val.X(), val.Y(), val.Z(),
this, pp);
276 bool OCCFace::_project(
const double p[3],
double uv[2],
double xyz[3])
const
278 gp_Pnt pnt(p[0], p[1], p[2]);
279 _projector.Perform(pnt);
280 if(!_projector.NbPoints()) {
281 Msg::Debug(
"Projection of point (%g, %g, %g) on surface %d failed", p[0],
285 _projector.LowerDistanceParameters(uv[0], uv[1]);
287 if(uv[0] < _umin || uv[0] > _umax || uv[1] < _vmin || uv[1] > _vmax)
288 Msg::Debug(
"Point projection is out of surface parameter bounds");
291 pnt = _projector.NearestPoint();
300 const double initialGuess[2])
const
302 #if defined(HAVE_ALGLIB)
307 double uv[2], xyz[3];
308 if(_project(qp.
data(), uv, xyz))
309 return GPoint(xyz[0], xyz[1], xyz[2],
this, uv);
315 bool convTestXYZ)
const
321 if(_project(qp.
data(), uv,
nullptr))
329 if(_occface->DynamicType() == STANDARD_TYPE(Geom_Plane))
331 else if(_occface->DynamicType() == STANDARD_TYPE(Geom_ToroidalSurface))
333 else if(_occface->DynamicType() == STANDARD_TYPE(Geom_BezierSurface))
334 return BezierSurface;
335 else if(_occface->DynamicType() == STANDARD_TYPE(Geom_CylindricalSurface))
337 else if(_occface->DynamicType() == STANDARD_TYPE(Geom_ConicalSurface))
339 else if(_occface->DynamicType() == STANDARD_TYPE(Geom_SurfaceOfRevolution))
340 return SurfaceOfRevolution;
341 else if(_occface->DynamicType() == STANDARD_TYPE(Geom_SphericalSurface))
343 else if(_occface->DynamicType() == STANDARD_TYPE(Geom_BSplineSurface))
344 return BSplineSurface;
348 double OCCFace::curvatureMax(
const SPoint2 ¶m)
const
350 const double eps = 1.e-12;
351 BRepLProp_SLProps prop(_sf, 2, eps);
352 prop.SetParameters(param.
x(), param.
y());
354 if(!prop.IsCurvatureDefined()) {
return eps; }
356 return std::max(fabs(prop.MinCurvature()), fabs(prop.MaxCurvature()));
361 double &curvMin)
const
363 const double eps = 1.e-12;
364 BRepLProp_SLProps prop(_sf, 2, eps);
365 prop.SetParameters(param.
x(), param.
y());
367 if(!prop.IsCurvatureDefined()) {
return -1.; }
369 curvMax = prop.MaxCurvature();
370 curvMin = prop.MinCurvature();
372 gp_Dir dMax = gp_Dir();
373 gp_Dir dMin = gp_Dir();
374 prop.CurvatureDirections(dMax, dMin);
376 dirMax[0] = dMax.X();
377 dirMax[1] = dMax.Y();
378 dirMax[2] = dMax.Z();
379 dirMin[0] = dMin.X();
380 dirMin[1] = dMin.Y();
381 dirMin[2] = dMin.Z();
386 bool OCCFace::containsPoint(
const SPoint3 &pt)
const
388 const Standard_Real
tolerance = BRep_Tool::Tolerance(_s);
389 BRepClass_FaceClassifier faceClassifier;
390 faceClassifier.Perform(_s, gp_Pnt{pt.
x(), pt.
y(), pt.
z()},
tolerance);
391 const TopAbs_State state = faceClassifier.State();
392 return (state == TopAbs_IN || state == TopAbs_ON);
395 bool OCCFace::containsParam(
const SPoint2 &pt)
397 const Standard_Real
tolerance = BRep_Tool::Tolerance(_s);
398 BRepClass_FaceClassifier faceClassifier;
399 faceClassifier.Perform(_s, gp_Pnt2d{pt.
x(), pt.
y()},
tolerance);
400 const TopAbs_State state = faceClassifier.State();
401 return (state == TopAbs_IN || state == TopAbs_ON);
404 bool OCCFace::buildSTLTriangulation(
bool force)
406 if(stl_triangles.size() && !force)
return true;
407 stl_vertices_uv.clear();
408 stl_vertices_xyz.clear();
409 stl_triangles.clear();
410 if(!model()->getOCCInternals()->makeFaceSTL(
411 _s, stl_vertices_uv, stl_vertices_xyz, stl_normals, stl_triangles)) {
412 Msg::Info(
"OpenCASCADE triangulation of surface %d failed", tag());
419 std::vector<GEdge *>
const &e =
edges();
420 for(
auto it = e.begin(); it != e.end(); it++) {
421 if((*it)->stl_vertices_xyz.size() == 0) {
422 const TopoDS_Edge *
c = (TopoDS_Edge *)(*it)->getNativePtr();
423 model()->getOCCInternals()->makeEdgeSTLFromFace(
424 *
c, _s, &((*it)->stl_vertices_xyz));
431 bool OCCFace::isSphere(
double &radius,
SPoint3 ¢er)
const
438 default:
return false;
442 void OCCFace::writeBREP(
const char *filename)
448 BRepTools::Write(
c, filename);