7 #include "GmshConfig.h"
17 #include <Standard_Version.hxx>
19 #include <Geom2dLProp_CLProps2d.hxx>
20 #include <Geom_BezierCurve.hxx>
21 #include <Geom_OffsetCurve.hxx>
22 #include <Geom_Ellipse.hxx>
23 #include <Geom_Parabola.hxx>
24 #include <Geom_Hyperbola.hxx>
25 #include <Geom_TrimmedCurve.hxx>
26 #include <Geom_Circle.hxx>
27 #include <Geom_Line.hxx>
28 #include <Geom_Conic.hxx>
29 #include <Geom_BSplineCurve.hxx>
30 #include <Bnd_Box.hxx>
31 #include <BRepLProp_CLProps.hxx>
32 #include <BRepBndLib.hxx>
33 #include <BRepAdaptor_Curve.hxx>
34 #include <BRepAdaptor_Surface.hxx>
35 #include <BRep_Builder.hxx>
36 #include <BOPTools_AlgoTools.hxx>
39 :
GEdge(m, num, v1, v2), _c(
c), _trimmed(nullptr)
43 if(_c.Orientation() == TopAbs_INTERNAL ||
44 _c.Orientation() == TopAbs_EXTERNAL) {
45 _c = TopoDS::Edge(_c.Oriented(TopAbs_FORWARD));
47 _curve = BRep_Tool::Curve(_c, _s0, _s1);
54 if(!_curve.IsNull()) {
60 const double du = umax - umin;
61 const double utol = std::max(fabs(du) * 1e-8, 1e-12);
65 _projector.Init(_curve, umin, umax);
68 if(_curve->DynamicType() == STANDARD_TYPE(Geom_BSplineCurve))
69 _nbpoles = Handle(Geom_BSplineCurve)::DownCast(_curve)->NbPoles();
70 else if(_curve->DynamicType() == STANDARD_TYPE(Geom_BezierCurve))
71 _nbpoles = Handle(Geom_BezierCurve)::DownCast(_curve)->NbPoles();
75 void OCCEdge::delFace(
GFace *
f)
77 if(_trimmed ==
f) _trimmed =
nullptr;
83 if(
CTX::instance()->geom.occBoundsUseSTL && stl_vertices_xyz.size()) {
93 for(std::size_t i = 0; i < stl_vertices_xyz.size(); i++)
94 bbox += stl_vertices_xyz[i];
100 BRepBndLib::Add(_c, b);
101 }
catch(Standard_Failure &err) {
102 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
105 double xmin, ymin, zmin, xmax, ymax, zmax;
106 b.Get(xmin, ymin, zmin, xmax, ymax, zmax);
122 const TopoDS_Face *s = (TopoDS_Face *)((OCCFace *)face->
getNativePtr());
124 _curve2d = BRep_Tool::CurveOnSurface(_c, *s, s0, s1);
128 void OCCEdge::setTrimmed(OCCFace *
f)
132 const TopoDS_Face *s = (TopoDS_Face *)_trimmed->getNativePtr();
133 _curve2d = BRep_Tool::CurveOnSurface(_c, *s, _s0, _s1);
134 if(_curve2d.IsNull()) _trimmed =
nullptr;
138 SPoint2 OCCEdge::reparamOnFace(
const GFace *face,
double epar,
int dir)
const
141 const GPoint pt = point(epar);
146 const TopoDS_Face *s = (TopoDS_Face *)face->
getNativePtr();
148 Handle(Geom2d_Curve) c2d;
150 if(dir == 1) { c2d = BRep_Tool::CurveOnSurface(_c, *s, t0, t1); }
152 c2d = BRep_Tool::CurveOnSurface(_c_rev, *s, t0, t1);
156 Msg::Warning(
"Curve %d is not on surface %d - computing closest point",
158 const GPoint pt = point(epar);
160 double guess[2] = {0, 0};
166 gp_Pnt2d pnt = c2d->Value(epar);
173 double dx = p1.
x() - p2.
x();
174 double dy = p1.
y() - p2.
y();
175 double dz = p1.
z() - p2.
z();
176 if(sqrt(dx * dx + dy * dy + dz * dz) >
CTX::instance()->geom.tolerance) {
178 "Reparam on surface was inaccurate for curve %d on surface %d "
180 tag(), face->
tag(), epar);
181 Msg::Debug(
"On the surface %d local (%g %g) global (%g %g %g)",
182 face->
tag(), u, v, p2.
x(), p2.
y(), p2.
z());
183 Msg::Debug(
"On the curve %d local (%g) global (%g %g %g)", tag(), epar,
184 p1.
x(), p1.
y(), p1.
z());
185 double guess[2] = {u, v};
191 dx = p1.
x() - p2.
x();
192 dy = p1.
y() - p2.
y();
193 dz = p1.
z() - p2.
z();
194 if(sqrt(dx * dx + dy * dy + dz * dz) >
197 "Closest point was inaccurate for curve %d on surface %d "
199 tag(), face->
tag(), epar);
200 Msg::Warning(
"On the surface %d local (%g %g) global (%g %g %g)",
201 face->
tag(), u, v, p2.
x(), p2.
y(), p2.
z());
202 Msg::Warning(
"On the curve %d local (%g) global (%g %g %g)", tag(),
203 epar, p1.
x(), p1.
y(), p1.
z());
211 bool OCCEdge::_project(
const double p[3],
double &u,
double xyz[3])
const
213 if(_curve.IsNull()) {
214 Msg::Error(
"OpenCASCADE curve is null in projection");
218 gp_Pnt pnt(p[0], p[1], p[2]);
219 _projector.Perform(pnt);
221 if(!_projector.NbPoints()) {
222 Msg::Debug(
"Projection of point (%g, %g, %g) on curve %d failed", p[0],
227 u = _projector.LowerDistanceParameter();
229 if(u < _s0 || u > _s1)
230 Msg::Debug(
"Point projection is out of curve parameter bounds");
233 pnt = _projector.NearestPoint();
247 if(_project(qp.
data(), u, xyz))
248 return GPoint(xyz[0], xyz[1], xyz[2],
this, u);
253 double OCCEdge::parFromPoint(
const SPoint3 &qp)
const
259 if(_project(qp.
data(), u,
nullptr))
265 bool OCCEdge::containsPoint(
const SPoint3 &pt)
const
269 if(_project(pt.
data(), u, xyz.
data())) {
270 const Standard_Real
tolerance = BRep_Tool::Tolerance(_c);
276 bool OCCEdge::isSeam(
const GFace *face)
const
279 const TopoDS_Face *s = (TopoDS_Face *)face->
getNativePtr();
286 const Handle(Geom_Surface)& surf = BRep_Tool::Surface(*s, l);
287 bool ret = BRep_Tool::IsClosed(_c, surf, l);
291 GPoint OCCEdge::point(
double par)
const
295 _curve2d->Value(par).Coord(u, v);
296 return _trimmed->point(u, v);
298 else if(!_curve.IsNull()) {
299 gp_Pnt pnt = _curve->Value(par);
300 return GPoint(pnt.X(), pnt.Y(), pnt.Z(),
this, par);
302 else if(degenerate(0)) {
303 return GPoint(getBeginVertex()->x(), getBeginVertex()->y(),
304 getBeginVertex()->
z());
308 "OpenCASCADE curve %d is neither a 3D curve nor a trimmed curve", tag());
313 SVector3 OCCEdge::firstDer(
double par)
const
315 BRepAdaptor_Curve brepc(_c);
316 BRepLProp_CLProps prop(brepc, 1, 1e-5);
317 prop.SetParameter(par);
318 gp_Vec d1 = prop.D1();
319 return SVector3(d1.X(), d1.Y(), d1.Z());
324 if(_curve.IsNull()) {
325 if(_curve2d.IsNull())
327 else if(_curve2d->DynamicType() == STANDARD_TYPE(Geom_Circle))
329 else if(_curve2d->DynamicType() == STANDARD_TYPE(Geom_Line))
331 else if(_curve2d->DynamicType() == STANDARD_TYPE(Geom_Ellipse))
333 else if(_curve2d->DynamicType() == STANDARD_TYPE(Geom_Parabola))
335 else if(_curve2d->DynamicType() == STANDARD_TYPE(Geom_Hyperbola))
337 else if(_curve2d->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve))
339 else if(_curve2d->DynamicType() == STANDARD_TYPE(Geom_OffsetCurve))
341 else if(_curve2d->DynamicType() == STANDARD_TYPE(Geom_BSplineCurve))
343 else if(_curve2d->DynamicType() == STANDARD_TYPE(Geom_BezierCurve))
345 else if(_curve2d->DynamicType() == STANDARD_TYPE(Geom_Conic))
350 if(_curve->DynamicType() == STANDARD_TYPE(Geom_Circle))
352 else if(_curve->DynamicType() == STANDARD_TYPE(Geom_Line))
354 else if(_curve->DynamicType() == STANDARD_TYPE(Geom_Parabola))
356 else if(_curve->DynamicType() == STANDARD_TYPE(Geom_Hyperbola))
358 else if(_curve->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve))
360 else if(_curve->DynamicType() == STANDARD_TYPE(Geom_OffsetCurve))
362 else if(_curve->DynamicType() == STANDARD_TYPE(Geom_Ellipse))
364 else if(_curve->DynamicType() == STANDARD_TYPE(Geom_BSplineCurve))
366 else if(_curve->DynamicType() == STANDARD_TYPE(Geom_BezierCurve))
368 else if(_curve->DynamicType() == STANDARD_TYPE(Geom_Conic))
374 int OCCEdge::minimumMeshSegments()
const
382 else if(geomType() == Circle || geomType() == Ellipse) {
383 double a = fabs(_s0 - _s1);
388 np = (int)(0.99 + (n - 1) * a / (2 * M_PI));
396 if(getBeginVertex() == getEndVertex()) np = std::max(4, np);
398 return std::max(np, meshAttributes.minimumMeshSegments);
401 int OCCEdge::minimumDrawSegments()
const
406 if(geomType() == Line)
412 double OCCEdge::curvature(
double par)
const
414 const double eps = 1.e-15;
416 if(degenerate(0))
return eps;
419 if(_curve.IsNull()) {
420 Geom2dLProp_CLProps2d aCLProps(_curve2d, 2, eps);
421 aCLProps.SetParameter(par);
422 if(!aCLProps.IsTangentDefined())
425 Crv = aCLProps.Curvature();
428 BRepAdaptor_Curve brepc(_c);
429 BRepLProp_CLProps prop(brepc, 2, eps);
430 prop.SetParameter(par);
431 if(!prop.IsTangentDefined())
434 Crv = prop.Curvature();
436 if(Crv <= eps) Crv = eps;
440 void OCCEdge::writeGEO(FILE *fp)
442 if(geomType() == Circle) {
444 if(_curve.IsNull()) {
445 center = Handle(Geom_Circle)::DownCast(_curve2d)->Location();
448 center = Handle(Geom_Circle)::DownCast(_curve)->Location();
451 if(_s1 - _s0 < M_PI && getBeginVertex() && getEndVertex()) {
452 fprintf(fp,
"p%d = newp;\n", tag());
453 fprintf(fp,
"Point(p%d + 1) = {%.16g, %.16g, %.16g};\n", tag(),
454 center.X(), center.Y(), center.Z());
455 fprintf(fp,
"Circle(%d) = {%d, p%d + 1, %d};\n", tag(),
456 getBeginVertex()->tag(), tag(), getEndVertex()->tag());