欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 国际 > 使用Python实现图形学曲线和曲面的NURBS算法

使用Python实现图形学曲线和曲面的NURBS算法

2025/7/5 9:11:16 来源:https://blog.csdn.net/qq_42568323/article/details/142462394  浏览:    关键词:使用Python实现图形学曲线和曲面的NURBS算法

目录

    • 使用Python实现图形学曲线和曲面的NURBS算法
      • 引言
      • NURBS曲线的数学原理
        • 1. NURBS曲线定义
        • 2. 权重的作用
      • NURBS曲线的Python实现
        • 1. 类结构设计
        • 2. 代码实现
        • 3. 代码详解
        • 使用示例
      • NURBS曲面的扩展
        • NURBS曲面类实现
      • 总结

使用Python实现图形学曲线和曲面的NURBS算法

引言

NURBS(Non-Uniform Rational B-Splines,非均匀有理B样条)是一种广泛应用于计算机图形学、CAD、动画设计和3D建模的数学表示方法。它是B样条(B-spline)的推广,能够表示直线、圆弧、椭圆以及更复杂的自由曲线和曲面。NURBS通过增加权重,赋予了控制点不同的影响力,从而能够精确表示圆形等几何形状。

本文将介绍NURBS曲线和曲面的基本原理,并使用Python面向对象的思想实现NURBS算法。

NURBS曲线的数学原理

1. NURBS曲线定义

NURBS曲线由控制点、权重和节点向量定义。给定 n + 1 n+1 n+1 个控制点 P 0 , P 1 , . . . , P n P_0, P_1, ..., P_n P0,P1,...,Pn,每个控制点对应一个权重 w 0 , w 1 , . . . , w n w_0, w_1, ..., w_n w0,w1,...,wn,NURBS曲线在参数 t t t 处的点 C ( t ) C(t) C(t) 的表达式为:

C ( t ) = ∑ i = 0 n N i , p ( t ) w i P i ∑ i = 0 n N i , p ( t ) w i C(t) = \frac{\sum_{i=0}^{n} N_{i,p}(t) w_i P_i}{\sum_{i=0}^{n} N_{i,p}(t) w_i} C(t)=i=0nNi,p(t)wii=0nNi,p(t)wiPi

其中:

  • N i , p ( t ) N_{i,p}(t) Ni,p(t) 是B样条基函数,和B样条曲线的定义一致。
  • w i w_i wi 是控制点的权重,控制点对曲线的影响力大小。
  • 节点向量 t t t 决定参数空间的分布。
2. 权重的作用

权重 w i w_i wi 决定了每个控制点对曲线的影响力。若所有权重相等,则NURBS曲线退化为普通的B样条曲线;而如果控制点的某些权重远大于其他权重,则这些控制点对曲线形状的影响力会更大。

NURBS曲线的Python实现

1. 类结构设计

我们将设计以下几个类:

  • Point2D:表示二维平面上的点。
  • NURBSCurve:用于计算和绘制NURBS曲线的类。
2. 代码实现
import numpy as np# 定义二维点类
class Point2D:def __init__(self, x, y):self.x = xself.y = ydef __repr__(self):return f"({self.x}, {self.y})"# 定义NURBS曲线类
class NURBSCurve:def __init__(self, control_points, weights, degree, knot_vector=None):"""初始化NURBS曲线:param control_points: 控制点的列表,每个控制点是一个 Point2D 对象:param weights: 控制点的权重列表:param degree: NURBS的阶数(degree):param knot_vector: 节点向量,若为None,则使用均匀节点向量"""self.control_points = control_pointsself.weights = weightsself.degree = degreeself.num_control_points = len(control_points)# 生成均匀节点向量if knot_vector is None:self.knot_vector = self._generate_uniform_knot_vector()else:self.knot_vector = knot_vectordef _generate_uniform_knot_vector(self):"""生成均匀的节点向量:return: 均匀节点向量"""n = self.num_control_points - 1p = self.degreereturn [0] * (p + 1) + list(range(1, n - p + 1)) + [n - p + 1] * (p + 1)def _basis_function(self, i, k, t):"""计算B样条基函数:param i: 控制点索引:param k: 当前阶数:param t: 参数值:return: 基函数值"""if k == 0:return 1.0 if self.knot_vector[i] <= t < self.knot_vector[i+1] else 0.0else:# 计算两个部分coef1 = 0.0if self.knot_vector[i+k] != self.knot_vector[i]:coef1 = (t - self.knot_vector[i]) / (self.knot_vector[i+k] - self.knot_vector[i]) * self._basis_function(i, k-1, t)coef2 = 0.0if self.knot_vector[i+k+1] != self.knot_vector[i+1]:coef2 = (self.knot_vector[i+k+1] - t) / (self.knot_vector[i+k+1] - self.knot_vector[i+1]) * self._basis_function(i+1, k-1, t)return coef1 + coef2def calculate_point(self, t):"""计算曲线在参数t处的点:param t: 参数值 t, 范围 [0, 1]:return: 返回曲线在 t 处的 Point2D 点"""numerator_x = 0.0numerator_y = 0.0denominator = 0.0for i in range(self.num_control_points):b = self._basis_function(i, self.degree, t)numerator_x += b * self.weights[i] * self.control_points[i].xnumerator_y += b * self.weights[i] * self.control_points[i].ydenominator += b * self.weights[i]return Point2D(numerator_x / denominator, numerator_y / denominator)def generate_curve_points(self, num_points=100):"""生成NURBS曲线上的点:param num_points: 生成的曲线上点的数量:return: 返回点列表,表示NURBS曲线"""curve_points = []for t in np.linspace(self.knot_vector[self.degree], self.knot_vector[-self.degree-1], num_points):curve_points.append(self.calculate_point(t))return curve_points# 使用示例
if __name__ == "__main__":# 定义控制点control_points = [Point2D(0, 0), Point2D(1, 2), Point2D(3, 3), Point2D(4, 0)]# 定义权重weights = [1, 0.5, 0.5, 1]# 创建NURBS曲线对象,阶数为3(三次NURBS)nurbs_curve = NURBSCurve(control_points, weights, degree=3)# 生成并输出曲线上的点curve_points = nurbs_curve.generate_curve_points()print("NURBS曲线上的点:")for point in curve_points:print(point)
3. 代码详解
  • Point2D 类:表示二维平面上的一个点,包含点的 x x x y y y 坐标。

  • NURBSCurve 类:该类用于计算NURBS曲线,主要包括以下方法:

    • __init__():初始化NURBS曲线,包括控制点、权重、阶数和节点向量。如果未提供节点向量,将自动生成一个均匀节点向量。
    • _generate_uniform_knot_vector():生成均匀节点向量。
    • _basis_function():递归计算B样条基函数。
    • calculate_point():计算曲线在参数 t t t 处的点,权重会影响控制点对曲线的贡献。
    • generate_curve_points():生成NURBS曲线上的多个点,用于近似表示曲线的形状。
使用示例

假设我们有4个控制点 ( 0 , 0 ) , ( 1 , 2 ) , ( 3 , 3 ) , ( 4 , 0 ) (0, 0), (1, 2), (3, 3), (4, 0) (0,0),(1,2),(3,3),(4,0),并为其中两个控制点设置较小的权重 0.5 0.5 0.5,这将影响曲线的形状。生成的曲线在权重较大的控制点附近会更接近这些点。

NURBS曲面的扩展

NURBS曲线可以扩展为NURBS曲面。NURBS曲面是由二维控制点网格、权重矩阵以及两个方向的节点向量控制的。

NURBS曲面类实现
# 定义NURBS曲面类
class NURBSSurface:def __init__(self, control_points_grid, weights_grid, degree_u, degree_v, knot_vector_u=None, knot_vector_v=None):"""初始化NURBS曲面:param control_points_grid: 控制点的二维网格,每个点是Point2D 对象:param weights_grid: 权重的二维网格:param degree_u: u方向的NURBS阶数:param degree_v: v方向的NURBS阶数:param knot_vector_u: u方向的节点向量:param knot_vector_v: v方向的节点向量"""self.control_points_grid = control_points_gridself.weights_grid = weights_gridself.degree_u = degree_uself.degree_v = degree_vself.num_control_points_u = len(control_points_grid)self.num_control_points_v = len(control_points_grid[0])# 生成均匀节点向量if knot_vector_u is None:self.knot_vector_u = self._generate_uniform_knot_vector(self.num_control_points_u, self.degree_u)else:self.knot_vector_u = knot_vector_uif knot_vector_v is None:self.knot_vector_v = self._generate_uniform_knot_vector(self.num_control_points_v, self.degree_v)else:self.knot_vector_v = knot_vector_vdef _generate_uniform_knot_vector(self, num_control_points, degree):"""生成均匀的节点向量:param num_control_points: 控制点数量:param degree: NURBS阶数:return: 均匀节点向量"""return [0] * (degree + 1) + list(range(1, num_control_points - degree)) + [num_control_points - degree] * (degree + 1)def calculate_point(self, u, v):"""计算NURBS曲面在参数 (u, v) 处的点:param u: u方向参数值:param v: v方向参数值:return: 返回曲面在 (u, v) 处的 Point2D 点"""numerator_x = 0.0numerator_y = 0.0denominator = 0.0for i in range(self.num_control_points_u):for j in range(self.num_control_points_v):b_u = NURBSCurve._basis_function(self, i, self.degree_u, u)b_v = NURBSCurve._basis_function(self, j, self.degree_v, v)numerator_x += b_u * b_v * self.weights_grid[i][j] * self.control_points_grid[i][j].xnumerator_y += b_u * b_v * self.weights_grid[i][j] * self.control_points_grid[i][j].ydenominator += b_u * b_v * self.weights_grid[i][j]return Point2D(numerator_x / denominator, numerator_y / denominator)def generate_surface_points(self, num_points_u=10, num_points_v=10):"""生成NURBS曲面上的点:param num_points_u: u方向点的数量:param num_points_v: v方向点的数量:return: 返回二维点列表,表示NURBS曲面"""surface_points = []for u in np.linspace(self.knot_vector_u[self.degree_u], self.knot_vector_u[-self.degree_u-1], num_points_u):row = []for v in np.linspace(self.knot_vector_v[self.degree_v], self.knot_vector_v[-self.degree_v-1], num_points_v):row.append(self.calculate_point(u, v))surface_points.append(row)return surface_points

总结

NURBS通过引入权重使得在精确描述几何图形(如圆和椭圆)时更加灵活。本文通过面向对象的思想,详细介绍了NURBS曲线和曲面的实现原理,并给出了Python的具体实现。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词