Skip to content

Computational Surfaces

Computational surfaces are representations extending the curves presented in the relevant section. Parametric surfaces are trivially implemented by reusing the code developed for curves.

Bézier Surfaces

Bézier surfaces extend Bézier curves is a straight forward manner. First instead of list of control points, surfaces require a grid of control points, with rows and columns associated with the u and v directions. (1) To produce a point on the surface, each row of control points is evaluated using the first surface parameter as if it represents a Bezier curve. This results into a list of points which is evaluated using the second parameter as if it represents a Bezier curve. This approach can be used for computing derivatives and all associated surface properties.

  1. Associating rows and columns with the u and v directions is subject to implementation conventions.
class BezierSurface:
    def __init__( self, points ):
        self.Points = points

    def Evaluate( self, u, v ):
        curves = [BezierCurve( row )
            for row in self.Points]

        points = [curve.Evaluate( u )
            for curve in curves]

        curve = BezierCurve( points )
        return curve.Evaluate( v )

Rhino exports a BezierSurface class however it is not implementing the Surface interface, see documentation. The Nurbs class however can be used instead because when the number of control points equals the degree + 1 per direction, and the control point weights are zero, then a Nurbs surface is effectively equivalent to a Bezier surface.

BSpline Surfaces

BSpline surfaces extend BSpline curves in exactly the same manner as Bezier curves do for surfaces. Like BSpline curves, the degree per direction must be specified for BSpline surfaces. Evaluating points and derivatives follows the same construction.

class BSplineSurface:
    def __init__( self, points, degree = [1, 1] ):
        self.Points = points
        self.Degree = degree

    def Evaluate( self, u, v ):
        curves = [BSplineCurve( row, self.Degree[0] )
            for row in self.Points]

        points = [curve.Evaluate( u )
            for curve in curves]

        curve = BSplineCurve( points, self.Degree[1] )
        return curve.Evaluate( v )

In Rhino BSpline surfaces are represented as a subset of non-rational Nurbs surfaces, that is Nurbs surfaces where all control point weights are zero.

Nurbs Surfaces

Unsurprisingly, Nurbs surfaces extend their curve analog using exactly the same principle as the previous parametric surfaces. The only difference in that the control net contains rational points.

class NurbsSurface:
    def __init__( self, points, degree = [1, 1] ):
        self.Points = points
        self.Degree = degree

    def Evaluate( self, u, v ):
        curves = [NurbsCurve( row, self.Degree[0] )
            for row in self.Points]

        points = [curve.Evaluate( u )
            for curve in curves]

        curve = NurbsCurve( points, self.Degree[1] )
        return curve.Evaluate( v )

Rhino's NurbsSurface supports numerous construction methods, accessed via the NurbsSurface.Create* methods, as well as operations including , see documentation.

""" Manual Construction (avoid)
"""
nu, nv = 3, 4
surface = NurbsSurface.Create( 3,
    False, 2, 2, nu, nv )

#-- Must Set Control Points
for iu in range( nu ):
    for iv in range( nv ):
        surface.Points.SetControlPoint( iu, iv,
            ControlPoint( iu, iv, iu | iv, 0.0 ) )

#-- Must Create Knot Vectors
surface.KnotsU.CreateUniformKnots( 1.0 )
surface.KnotsV.CreateUniformKnots( 1.0 )

""" Surface Construction
"""
surface = NurbsSurface.CreateFromCorners(
    Point3d( 0.0, 0.0, 0.0 ),
    Point3d( 1.0, 0.0, 0.0 ),
    Point3d( 0.0, 1.0, 0.0 ),
    Point3d( 1.0, 1.0, 0.0 ) )

surface = NurbsSurface.CreateFromPoints(
    [Point3d( 0.0, 0.0, 0.0 ),
     Point3d( 1.0, 0.0, 0.0 ),
     Point3d( 0.0, 1.0, 0.0 ),
     Point3d( 1.0, 1.0, 0.0 )],
     2, 2, 1, 1 )

""" Surface Points and Vectors
"""
point = surface.PointAt( u, v )
normal = surface.NormalAt( u, v )
_, plane = surface.FrameAt( u, v )
curvature = surface.CurvatureAt( u, v )

""" Iso Parametric Curves
"""
iso_u = surface.IsoCurve( 0, u )
iso_v = surface.IsoCurve( 1, v )

""" Projection
"""
_, u, v = surface.ClosestPoint(
    Point3d( px, py, pz ) )