公有域几何工具库中的参数曲线和曲面





5.00/5 (3投票s)
描述参数曲线和曲面以及如何使用我的公有域 HTML 3D 库生成它们
引言
本页面描述了参数曲线和曲面以及如何使用我的公有域 几何工具库 生成它们。
该库最新版本的源代码可在 几何工具库项目页面 获取。
目录
什么是参数曲面?
参数曲面是通过评估向量函数的结果生成的曲面。这个向量函数接受两个数字 U 和 V,并返回一个 3D 点 X、Y 和 Z。每个 (U, V) 点对应一个位于曲面上的 (X, Y, Z) 点。
3D 中的向量函数是三个函数的组合,每个维度一个
- F(u, v) = [ x(u, v), y(u, v), z(u, v) ];
x 函数在给定 u 和 v 的情况下返回 X 坐标,y 和 z 同样。由于 z 函数返回 Z 坐标,如果 z 始终返回相同的值,则曲面将是 2D 的。
例如,如果我们有一个由以下函数定义的参数曲面
- x(u, v) = u * v
- y(u, v) = -u
- z(u, v) = u * sqrt(v)
并且我们评估 UV 点 (2, 4),那么我们有
- F(2, 4) = [ 2 * 4, -2, 2 * sqrt(4) ];
- F(2, 4) = [ 8, -2, 4 ];
所以 (8, -2, 4) 是位于此参数曲面上的一个点,通过评估不同的 UV 点可以找到曲面上的任何其他点。顺便说一句,曲面看起来像这样
为什么是两个变量?
曲面函数接受两个变量 u 和 v,因为参数曲面可以看作是矩形网格的“变形”版本。向量函数将此网格“变形”为三维曲面。
几何工具库中的参数曲面
几何工具库使用名为 SurfaceBuilder
的类支持参数曲面。它有助于使用参数曲面函数生成顶点坐标和其他属性。以下辅助函数 makeMesh
生成参数曲面网格。注释详细解释了 makeMesh
的工作原理。
function makeMesh(func,resolutionU, resolutionV){
"use strict";
if(typeof resolutionV === "undefined" || resolutionV === null)resolutionV = resolutionU;
if(typeof resolutionU === "undefined" || resolutionU === null)resolutionU = 50;
if(typeof resolutionV === "undefined" || resolutionV === null)resolutionV = 50;
// define a color gradient evaluator for
// demonstration purposes. Instead of X, Y, and Z,
// generate a Red/Green/Blue color based on
// the same parameters U and V as the surface
// function for 3D points.
var colorGradient = {
"evaluate":function(u, v) {
return [1 - u, v, u];
}
};
return new H3DU.SurfaceBuilder()
.positionNormal(func)
.attribute(colorGradient, H3DU.Semantic.COLOR)
// Evaluate the surface and generate a triangle
// mesh, using resolution+1 different U coordinates,
// and resolution+1 different V coordinates.
// Instead of H3DU.Mesh.TRIANGLES, we could use
// H3DU.Mesh.LINES to create a wireframe mesh,
// or H3DU.Mesh.POINTS to create a point mesh.
.evalSurface(H3DU.Mesh.TRIANGLES, resolutionU, resolutionV)
.toMeshBuffer();
}
在几何工具库中,曲面评估器
对象定义了一个方法evaluate
,该方法在给定 U 参数和 V 参数的情况下返回一个 3D 点。(默认情况下,U 和 V 都从 0 到 1 之间取值。)
以下代码是一个非常简单的曲面评估器
对象。
var evaluator = {
"evaluate":function(u, v){
// Take the U parameter as the X coordinate,
// the V parameter as the Y coordinate, and 0 as
// the Z coordinate.
return [u, v, 0];
}
};
该评估器
仅在右上象限生成一个正方形
以下评估器
生成一个圆形圆盘
var evaluator = {
"evaluate":function(u, v){
// Return disc coordinates.
return [u*Math.cos(v),u*Math.sin(v),0];
},
// Declare the usual range of the coordinates
"endPoints":function(){ return [0,1,0,Math.PI*2]; }
};
现在是有趣的部分:这个评估器
返回的不是一个圆盘,而是一个锥体,其长度沿着负 Z 轴延伸
var evaluator = {
"evaluate":function(u, v){
// Return cone coordinates, using the u
// parameter as the Z axis.
return [u*Math.cos(v),u*Math.sin(v),-u];
},
// Declare the usual range of the coordinates
"endPoints":function(){ return [0,1,0,Math.PI*2]; }
};
以下形状已旋转以显示 Z 轴;旋转并不完美。
请注意,以上所有三个示例都使用一个名为evaluator
的值。可以使用类似以下代码为曲面evaluator
生成网格缓冲区
var meshBuffer = SurfaceBuilder.surfaceToBuffer(evaluator);
从参数曲面生成的 3D 网格缓冲区与任何其他网格缓冲区一样,用于其他网格缓冲区的相同函数和方法也可以用于此网格缓冲区。有关更多信息,请参阅 H3DU.MeshBuffer
和 Shape
类的 API 参考。
链接曲面函数
使用曲面评估器
对象的技术非常灵活。事实上,您可以链接评估器
,使用一个评估器
的输出作为另一个评估器
的输入。这可以用于将曲面点变换到新的位置。
举个例子,我们将定义一个新的评估器
,它移动参数曲面的位置。它接受一个现有曲面评估器
和要移动曲面的单位数 X、Y 和 Z。请注意,此类别包含自己的evaluate
方法,允许其自身传递给H3DU.SurfaceBuilder
类的方法或上面的makeMesh
方法。
function SurfaceShifter(evaluator, x, y, z) {
// Shift the surface by X units.
this.x = x;
// Shift the surface by Y units.
this.y = y;
// Shift the surface by Z units.
this.z = z;
this.evaluator = evaluator;
// Define the surface shifter function
this.evaluate = function(u, v){
// Get the coordinates from the source evaluator
var retval = this.evaluator.evaluate(u, v);
// Shift the coordinates
retval[0]+=this.x;
retval[1]+=this.y;
retval[2]+=this.z;
// And return the new coordinates.
return retval;
}
this.endPoints=function(){
return this.evaluator.endPoints()
}
}
以下是其用法示例。我们将使用上面给出的圆盘曲面,并创建一个SurfaceShifter
对象,将圆盘水平和垂直移动 3 个单位(默认情况下,圆盘将以原点 (0, 0, 0) 为中心)。
// This is the disc surface from before
var evaluator = {
"evaluate":function(u, v){
// Extend the range of v
v*=Math.PI*2;
// Return circle coordinates.
return [u*Math.cos(v),u*Math.sin(v),0];
},
"endPoints":function() { return [0,Math.PI*2] }
}
// Create a shifter that results in the circle being moved 3 units
// up and 3 units to the right
evaluator = new SurfaceShifter(evaluator, 3, 3, 0);
参数曲线
几何工具库还包括对生成参数曲线的支持。参数曲线是由向量函数生成的曲线,类似于参数曲面,但现在函数只使用一个变量,如下所示
- C(u) = [ x(u), y(u), z(u) ];
如前所述,x、y 和 z 函数返回曲线的相应坐标。并且每个 (U) 点对应一个位于曲面上的 (X, Y, Z) 点。
曲线函数只接受一个 u 变量,因为参数曲线可以看作是直线的“变形”版本。
参数曲线的一个简单例子是圆。事实上,上面给出的圆盘曲面的相同源代码也可以用作圆的参数曲线函数,因为它只使用变量 u,而不使用 v。
请注意,任何只使用 u 的曲面评估器都可以轻松地用作参数曲线评估器,并且任何 v 参数保持相同值(例如 0、1 或任何其他常数)的曲面也可以。
生成参数曲线
几何工具库的 CurveBuilder
类为参数曲线生成顶点。
使用以下代码生成描述参数曲线的网格。它假定 evaluator
是一个参数曲线对象,就像上面的圆形示例一样。
var meshBuffer = CurveBuilder.curveToBuffer(evaluator);
几何工具库中的曲线和曲面评估器
几何工具库发行版包括以下曲线和曲面评估器
。下面列出的所有类都包含一个evaluate
方法,该方法返回位于曲线或曲面上的 3D 点。
通用曲线包括
- B 样条曲线。这些曲线由控制点(控制曲线的形状但不一定位于曲线上)和节点矢量(控制控制点的行为)组成。B 样条曲线包括 NURBS 曲线(非均匀有理 B 样条曲线,带权重和非均匀节点),使其成为设置曲线行为的强大方式。B 样条曲线使用 BSplineCurve 类创建。
- 贝塞尔曲线。这些曲线的第一个和最后一个控制点是曲线的端点。贝塞尔曲线是 B 样条曲线的子集,使用 BSplineCurve.fromBezierCurve 方法创建。
- 分段曲线。这些曲线由一个或多个其他曲线组成。分段曲线使用 PiecewiseCurve 类创建。
通用曲面包括
- 贝塞尔曲面。3D 曲面,其中每条网格线都是贝塞尔曲线。贝塞尔曲面使用 BSplineSurface.fromBezierSurface 方法创建。
- B 样条曲面。3D 曲面,其中每条网格线都是 B 样条或 NURBS 曲线。B 样条曲面使用 BSplineSurface 类创建。
特殊曲面包括
- 管。以“加厚”3D 曲线形式的 3D 曲面。管使用
CurveTube
类创建,这是几何工具库中的一个补充扩展。 - 旋转曲面。通过旋转 2D 曲线生成的曲面。旋转曲面使用
SurfaceOfRevolution
类创建,这是几何工具库中的一个补充扩展。
其他页面
我在 CodeProject 上的以下页面也讨论了几何工具库,前身为公有域 HTML 3D 库