Specific Direction Curvature

Is there any way to find the curvature of a surface in a specific direction? the current methods are just for U or V direction.


Rostamani's picture

This is also my question too. I don't know about finding the curvature in u or v direction by BRepLProp_SLProps I could just find min/max/mean/gaussian curvature in a specific u,v parameters of the surface. Could some body please help find the curvature in specific direction for a surface in a point on it?


Qr Qr's picture

Try this:

  Handle(Geom_Surface) surf = ...; // Your surface
  gp_Pnt2d UV = ...; // Your point of interest
  gp_Vec2d T  = ...; // Your direction of interest
  // Calculate differential properties
  BRepLProp_SLProps Props(surf, UV.X(), UV.Y(), 2, 1e-7);
  if ( !Props.IsCurvatureDefined() )
    std::cout << "Error: curvature is not defined" << std::endl;
    return false;
  // Get differential properties
  const gp_Vec Xu  = Props.D1U();
  const gp_Vec Xv  = Props.D1V();
  const gp_Vec Xuu = Props.D2U();
  const gp_Vec Xuv = Props.DUV();
  const gp_Vec Xvv = Props.D2V();
  const gp_Vec n   = Props.Normal();
  // Coefficients of the FFF
  const double E = Xu.Dot(Xu);
  const double F = Xu.Dot(Xv);
  const double G = Xv.Dot(Xv);
  // Coefficients of the SFF
  const double L = n.Dot(Xuu);
  const double M = n.Dot(Xuv);
  const double N = n.Dot(Xvv);
  // Calculate curvature using the coefficients of both fundamental forms
  if ( Abs( T.X() ) < 1.0e-5 )
    k = N / G;
    const double lambda = T.Y() / T.X();
    k = (L + 2*M*lambda + N*lambda*lambda) / (E + 2*F*lambda + G*lambda*lambda);

Rostamani's picture

I really don't know the reason that why nobody responses some question, if really there is no solution and nobody knows these! I wish at least the forum supervisor could help the no responses' questions even by saying there is no solution you have to write a new algorithm for this purpose.

jelle's picture

This out of scope for OCC, its far too specific for a general API call.
Why dont you sample the surface and than define a function to match the property your looking for?

Rostamani's picture

Dear Jelle
How can I sample a surface for this purpose?

jelle's picture

Here's some python(occ) code that might help you.
Notice the "_setup_trimmed" method for testing if a sample is not taken at a trimmed part of the surface.


from OCC.TopoDS import *
from OCC.BRep import *
from OCC.BRepTools import *
from OCC.BRepTopAdaptor import *
from OCC.GeomLProp import *
from OCC.gp import *
from OCC.TopAbs import *

import numpy, math
from scipy.ndimage import spline_filter, map_coordinates

class SampleSurface(object):
def __init__(self, srf, resU, resV):
# sample resolutions
self.resU, self.resV = resU, resV

# adapt a face to a surface
if isinstance(srf, TopoDS_Face):
self.face = srf
self.srf = BRep_Tool().Surface(srf)
raise NotImplementedError, 'only TopoDS_Face instances supported'

# uv bounds
self.u_min, self.v_min, self.u_max, self.v_max = GeomLProp_SurfaceTool().Bounds(self.srf)

self.u, self.v = numpy.mgrid[self.u_min : self.u_max : complex(self.resU),
self.v_min : self.v_max : complex(self.resV)

# not used yet
self.coeffs_u, self.coeffs_v = spline_filter(self.u), spline_filter(self.v)

self.uv_grid = numpy.dstack((self.u, self.v))
self.curvature = GeomLProp_SLProps(self.srf,

self.cl = self._setup_trimmed()

def _setup_trimmed(self):
#tol = 1e-4
tol = 1e-9
u1,u2, v1,v2 = BRepTools().UVBounds(self.face)
dailen = (u2-u1)*(u2-u1) + (v2-v1)*(v2-v1)
#dailen = math.sqrt(dailen) / 400.
#dailen = math.sqrt(dailen) / 4000.
#tol = max([dailen, tol])
return BRepTopAdaptor_FClass2d(self.face, tol)

def is_uv_in_face_domain(self, u, v):
'''checks if curve is trimmed
uv = gp_Pnt2d(u,v)
if self.cl.Perform(uv) == TopAbs_IN:
return True
return False

def _sample_grid(self, curvatureType='gaussian'):
samples the surface' curvature
curvature types are:
*gaussian ( default )
self.curvature_grid = numpy.zeros(( self.uv_grid.shape[0], self.uv_grid.shape[1] ), numpy.float)
self.trimmed_grid = numpy.zeros_like(self.curvature_grid)

if curvatureType == 'gaussian':
sample = self.curvature.GaussianCurvature

elif curvatureType == None:
# if you just care about the distance map

elif curvatureType == 'max':
sample = self.curvature.MaxCurvature

elif curvatureType == 'min':
sample = self.curvature.MinCurvature

elif curvatureType == 'mean':
sample = self.curvature.MeanCurvature

elif curvatureType == 'normal':
sample = self.curvature.Normal

elif curvatureType == 'tangent':
raise NotImplementedError, 'double value...'
def tangent():
tU = self.curvature.TangentU()
tV = self.curvature.TangentV()
return tU, tV
sample = tangent

elif curvatureType == 'principal_curvature':
raise NotImplementedError, 'double value...'
sample = self.curvature.CurvatureDirections

elif curvatureType == 'umbilic':
self.curvature_grid = numpy.zeros(( self.uv_grid.shape[0], self.uv_grid.shape[1] ), numpy.bool8)
sample = self.curvature.IsUmbilic

raise AssertionError, '%s not a sampling type' % (curvatureType)

_trimmed_areas = []
_curvature_lowest = 1000

for indxA, a in enumerate(self.uv_grid):
for indxB, b in enumerate(a):
u,v = b
#print 'u,v', u,v
if curvatureType is not None:
_curvature = sample()
if _curvature < _curvature_lowest:
_curvature_lowest = _curvature
self.curvature_grid[indxA, indxB] = _curvature
if not self.is_uv_in_face_domain(u, v):
_trimmed_areas.append((indxA, indxB))

for i in _trimmed_areas:
# black out those areas in the curvature map that are on the trimmed part of the face
self.curvature_grid[i[0], i[1]] = _curvature_lowest
# identify a trimmed area in the trimmed_grid
self.trimmed_grid[i[0], i[1]] = 255.0 #1.

return self.curvature_grid

def interpolate_uv_grid(self, _u, _v):
vectorize this shit
@param _u:
@param _v:
raise NotImplementedError
uuu = map_coordinates(self.coeffs_u, _u, prefilter=False)
vvv = map_coordinates(self.coeffs_v, _v, prefilter=False)
return uuu[0], vvv[0]

def sample_gaussian(self):
return self._sample_grid('gaussian')

def sample_max(self):
return self._sample_grid('max')

def sample_min(self):
return self._sample_grid('min')

def sample_mean(self):
return self._sample_grid('mean')

def sample_umbilic(self):
return self._sample_grid('umbilic')

def sample_trimmed(self):
return self._sample_grid(curvatureType=None)

jelle's picture

too bad its difficult to post code on this forum, while retaining its formatting ;(

Rostamani's picture

Thanks Jelle,
Where can I find the code for vc++?

jelle's picture

The code was meant to give you an idea about how to approach the problem. Forums are not places where you delegate homework.

Rostamani's picture

That was only a question. Thank you very much Jelle.

marchand's picture


is it possible to get a working example program?
(ie a sample surface, call of an analysis subprogram for example to get curvature at a specific point)
i am trying to construct a spline surface through a rectangular 9 points mesh, and analyse normal and curvature at central point.