diff --git a/src/Mod/Part/App/Geometry.cpp b/src/Mod/Part/App/Geometry.cpp
index c6d6d54dfd..561d3a78da 100644
--- a/src/Mod/Part/App/Geometry.cpp
+++ b/src/Mod/Part/App/Geometry.cpp
@@ -3657,7 +3657,7 @@ TopoDS_Shape GeomSurface::toShape() const
bool GeomSurface::tangentU(double u, double v, gp_Dir& dirU) const
{
Handle(Geom_Surface) s = Handle(Geom_Surface)::DownCast(handle());
- GeomLProp_SLProps prop(s,u,v,1,Precision::Confusion());
+ GeomLProp_SLProps prop(s,u,v,2,Precision::Confusion());
if (prop.IsTangentUDefined()) {
prop.TangentU(dirU);
return true;
@@ -3669,7 +3669,7 @@ bool GeomSurface::tangentU(double u, double v, gp_Dir& dirU) const
bool GeomSurface::tangentV(double u, double v, gp_Dir& dirV) const
{
Handle(Geom_Surface) s = Handle(Geom_Surface)::DownCast(handle());
- GeomLProp_SLProps prop(s,u,v,1,Precision::Confusion());
+ GeomLProp_SLProps prop(s,u,v,2,Precision::Confusion());
if (prop.IsTangentVDefined()) {
prop.TangentV(dirV);
return true;
@@ -3678,6 +3678,68 @@ bool GeomSurface::tangentV(double u, double v, gp_Dir& dirV) const
return false;
}
+bool GeomSurface::normal(double u, double v, gp_Dir& dir) const
+{
+ Handle(Geom_Surface) s = Handle(Geom_Surface)::DownCast(handle());
+ GeomLProp_SLProps prop(s,u,v,2,Precision::Confusion());
+ if (prop.IsNormalDefined()) {
+ dir = prop.Normal();
+ return true;
+ }
+
+ return false;
+}
+
+bool GeomSurface::isUmbillic(double u, double v) const
+{
+ Handle(Geom_Surface) s = Handle(Geom_Surface)::DownCast(handle());
+ GeomLProp_SLProps prop(s,u,v,2,Precision::Confusion());
+ if (prop.IsCurvatureDefined()) {
+ return prop.IsUmbilic();
+ }
+
+ throw Base::RuntimeError("No curvature defined");
+}
+
+double GeomSurface::curvature(double u, double v, Curvature type) const
+{
+ Handle(Geom_Surface) s = Handle(Geom_Surface)::DownCast(handle());
+ GeomLProp_SLProps prop(s,u,v,2,Precision::Confusion());
+ if (prop.IsCurvatureDefined()) {
+ double value = 0;
+ switch (type) {
+ case Maximum:
+ value = prop.MaxCurvature();
+ break;
+ case Minimum:
+ value = prop.MinCurvature();
+ break;
+ case Mean:
+ value = prop.MeanCurvature();
+ break;
+ case Gaussian:
+ value = prop.GaussianCurvature();
+ break;
+ }
+
+ return value;
+ }
+
+ throw Base::RuntimeError("No curvature defined");
+}
+
+void GeomSurface::curvatureDirections(double u, double v, gp_Dir& maxD, gp_Dir& minD) const
+{
+ Handle(Geom_Surface) s = Handle(Geom_Surface)::DownCast(handle());
+ GeomLProp_SLProps prop(s,u,v,2,Precision::Confusion());
+ if (prop.IsCurvatureDefined()) {
+ prop.CurvatureDirections(maxD, minD);
+ return;
+ }
+
+ throw Base::RuntimeError("No curvature defined");
+}
+
// -------------------------------------------------
TYPESYSTEM_SOURCE(Part::GeomBezierSurface,Part::GeomSurface)
diff --git a/src/Mod/Part/App/Geometry.h b/src/Mod/Part/App/Geometry.h
index ddf0f519c9..63eb9b19f5 100644
--- a/src/Mod/Part/App/Geometry.h
+++ b/src/Mod/Part/App/Geometry.h
@@ -727,12 +727,27 @@ class PartExport GeomSurface : public Geometry
{
TYPESYSTEM_HEADER();
public:
+ enum Curvature {
+ Maximum,
+ Minimum,
+ Mean,
+ Gaussian
+ };
+
GeomSurface();
virtual ~GeomSurface();
TopoDS_Shape toShape() const;
bool tangentU(double u, double v, gp_Dir& dirU) const;
bool tangentV(double u, double v, gp_Dir& dirV) const;
+ bool normal(double u, double v, gp_Dir& dir) const;
+
+ /** @name Curvature information */
+ //@{
+ bool isUmbillic(double u, double v) const;
+ double curvature(double u, double v, Curvature) const;
+ void curvatureDirections(double u, double v, gp_Dir& maxD, gp_Dir& minD) const;
+ //@}
};
class PartExport GeomBezierSurface : public GeomSurface
diff --git a/src/Mod/Part/App/GeometrySurfacePy.xml b/src/Mod/Part/App/GeometrySurfacePy.xml
index 856b80dd9c..7d80c7c935 100644
--- a/src/Mod/Part/App/GeometrySurfacePy.xml
+++ b/src/Mod/Part/App/GeometrySurfacePy.xml
@@ -24,15 +24,47 @@
- Computes the point of parameter (u,v) on this surface
+ value(u,v) -> Point
+Computes the point of parameter (u,v) on this surface
- Computes the tangent of parameter (u,v) on this geometry
+ tangent(u,v) -> (Vector,Vector)
+Computes the tangent of parameter (u,v) on this geometry
-
+
+
+ normal(u,v) -> Vector
+Computes the normal of parameter (u,v) on this geometry
+
+
+
+
+ isUmbillic(u,v) -> bool
+Check if the geometry on parameter is an umbillic point,
+i.e. maximum and minimum curvature are equal.
+
+
+
+
+ curvature(u,v,type) -> float
+The value of type must be one of this: Max, Min, Mean or Gauss
+Computes the curvature of parameter (u,v) on this geometry
+
+
+
+
+ curvatureDirections(u,v) -> (Vector,Vector)
+Computes the directions of maximum and minimum curvature
+of parameter (u,v) on this geometry.
+The first vector corresponds to the maximum curvature,
+the second vector corresponds to the minimum curvature.
+
+
+
+
Returns the parametric bounds (U1, U2, V1, V2) of this trimmed surface.
diff --git a/src/Mod/Part/App/GeometrySurfacePyImp.cpp b/src/Mod/Part/App/GeometrySurfacePyImp.cpp
index 01d534a0b0..2ba852f1d3 100644
--- a/src/Mod/Part/App/GeometrySurfacePyImp.cpp
+++ b/src/Mod/Part/App/GeometrySurfacePyImp.cpp
@@ -312,7 +312,7 @@ PyObject* GeometrySurfacePy::tangent(PyObject *args)
return 0;
gp_Dir dir;
Py::Tuple tuple(2);
- GeomLProp_SLProps prop(s,u,v,1,Precision::Confusion());
+ GeomLProp_SLProps prop(s,u,v,2,Precision::Confusion());
if (prop.IsTangentUDefined()) {
prop.TangentU(dir);
tuple.setItem(0, Py::Vector(Base::Vector3d(dir.X(),dir.Y(),dir.Z())));
@@ -335,6 +335,127 @@ PyObject* GeometrySurfacePy::tangent(PyObject *args)
return 0;
}
+PyObject* GeometrySurfacePy::normal(PyObject *args)
+{
+ try {
+ GeomSurface* s = getGeomSurfacePtr();
+ if (s) {
+ double u,v;
+ if (!PyArg_ParseTuple(args, "dd", &u,&v))
+ return 0;
+ gp_Dir d;
+ if (s->normal(u,v,d)) {
+ return new Base::VectorPy(Base::Vector3d(d.X(),d.Y(),d.Z()));
+ }
+ else {
+ PyErr_SetString(PyExc_RuntimeError, "normal at this point is not defined");
+ return 0;
+ }
+ }
+ }
+ catch (Standard_Failure) {
+ Handle(Standard_Failure) e = Standard_Failure::Caught();
+ PyErr_SetString(PartExceptionOCCError, e->GetMessageString());
+ return 0;
+ }
+
+ PyErr_SetString(PartExceptionOCCError, "Geometry is not a surface");
+ return 0;
+}
+
+PyObject* GeometrySurfacePy::isUmbillic(PyObject *args)
+{
+ try {
+ GeomSurface* s = getGeomSurfacePtr();
+ if (s) {
+ double u,v;
+ if (!PyArg_ParseTuple(args, "dd", &u,&v))
+ return 0;
+
+ bool val = s->isUmbillic(u,v);
+ return PyBool_FromLong(val ? 1 : 0);
+ }
+ }
+ catch (Standard_Failure) {
+ Handle(Standard_Failure) e = Standard_Failure::Caught();
+ PyErr_SetString(PartExceptionOCCError, e->GetMessageString());
+ return 0;
+ }
+
+ PyErr_SetString(PartExceptionOCCError, "Geometry is not a surface");
+ return 0;
+}
+
+PyObject* GeometrySurfacePy::curvatureDirections(PyObject *args)
+{
+ try {
+ GeomSurface* s = getGeomSurfacePtr();
+ if (s) {
+ double u,v;
+ if (!PyArg_ParseTuple(args, "dd", &u,&v))
+ return 0;
+
+ gp_Dir maxd, mind;
+ s->curvatureDirections(u,v,maxd,mind);
+
+ Py::Tuple tuple(2);
+ tuple.setItem(0, Py::Vector(Base::Vector3d(maxd.X(),maxd.Y(),maxd.Z())));
+ tuple.setItem(1, Py::Vector(Base::Vector3d(mind.X(),mind.Y(),mind.Z())));
+ return Py::new_reference_to(tuple);
+ }
+ }
+ catch (Standard_Failure) {
+ Handle(Standard_Failure) e = Standard_Failure::Caught();
+ PyErr_SetString(PartExceptionOCCError, e->GetMessageString());
+ return 0;
+ }
+
+ PyErr_SetString(PartExceptionOCCError, "Geometry is not a surface");
+ return 0;
+}
+
+PyObject* GeometrySurfacePy::curvature(PyObject *args)
+{
+ try {
+ GeomSurface* s = getGeomSurfacePtr();
+ if (s) {
+ double u,v;
+ char* type;
+ if (!PyArg_ParseTuple(args, "dds", &u,&v,&type))
+ return 0;
+
+ GeomSurface::Curvature t;
+ if (strcmp(type,"Max") == 0) {
+ t = GeomSurface::Maximum;
+ }
+ else if (strcmp(type,"Min") == 0) {
+ t = GeomSurface::Minimum;
+ }
+ else if (strcmp(type,"Mean") == 0) {
+ t = GeomSurface::Mean;
+ }
+ else if (strcmp(type,"Gauss") == 0) {
+ t = GeomSurface::Gaussian;
+ }
+ else {
+ PyErr_SetString(PyExc_ValueError, "unknown curvature type");
+ return 0;
+ }
+
+ double c = s->curvature(u,v,t);
+ return PyFloat_FromDouble(c);
+ }
+ }
+ catch (Standard_Failure) {
+ Handle(Standard_Failure) e = Standard_Failure::Caught();
+ PyErr_SetString(PartExceptionOCCError, e->GetMessageString());
+ return 0;
+ }
+
+ PyErr_SetString(PartExceptionOCCError, "Geometry is not a surface");
+ return 0;
+}
+
PyObject* GeometrySurfacePy::parameter(PyObject *args)
{
Handle(Geom_Surface) surf = Handle(Geom_Surface)