3. 坐标系与数据表示:XY平面坐标系、离散点云数据、Z值作为高度场

好,咱们正式开始动手之前,得先把「地图」和「语言」搞清楚。

曲面建模说白了,就是在三维空间里描述一张「膜」的形状。但计算机不认识曲面,它只认识数字。所以我们需要一套规则,把几何问题变成数学问题,再变成数据问题。

这一章,我们就来拆解这套规则的核心:坐标系怎么建、点云数据长什么样、Z值为什么能当高度用。

3.1 XY平面坐标系:曲面的「地基」

所有多项式曲面,都建立在XY平面坐标系之上。你可以把XY平面想象成一张无限大的网格纸,每个网格交叉点都有一个唯一的坐标 (x, y)。

我个人习惯把X轴定义为东西方向,Y轴定义为南北方向。当然,数学上没这个限制,你完全可以反过来。但一旦定下来,整个项目里就别再改了——我在项目中见过因为坐标系方向不统一,导致两个模块的曲面拼不上,查了三天bug才发现是X和Y定义反了。

核心约定:
  • X轴:水平方向,向右为正
  • Y轴:垂直方向,向上为正
  • 原点O:(0, 0),通常取数据区域的左下角或中心
  • 单位:与你的实际物理单位一致(毫米、米、英寸都行)

为什么强调这个?因为多项式曲面的表达式是:

Z = f(x, y) = a₀ + a₁x + a₂y + a₃x² + a₄xy + a₅y² + ...

你看,x和y是输入,Z是输出。没有坐标系,x和y就是无根之木。

3.2 离散点云数据:曲面的「骨架」

现实世界里的曲面是连续的,但计算机只能处理离散的点。所以我们需要用「点云」来近似描述曲面。

点云,说白了就是一堆 (x, y, Z) 三元组的集合。每个点代表曲面上某个位置的高度信息。

点云数据的典型来源:
  • 三维扫描仪(激光、结构光)
  • 坐标测量机(CMM)
  • 仿真软件导出(有限元网格节点)
  • 数学函数采样(我们课程主要用这个)

举个例子,假设我们想描述一个简单的抛物面 Z = x² + y²。在 [-2, 2] 范围内均匀采样,得到的数据长这样:

点序号 x y Z = x² + y²
1 -2.0 -2.0 8.0
2 -2.0 -1.0 5.0
3 -2.0 0.0 4.0
4 -2.0 1.0 5.0
5 -2.0 2.0 8.0
... ... ... ...
25 2.0 2.0 8.0

一共25个点(5×5网格)。这就是最原始的离散点云数据。

注意:点云不是越多越好。点太多,计算量爆炸;点太少,拟合出来的曲面失真。我一般先按经验密度采样,然后通过残差分析判断是否需要加密。

3.3 Z值作为高度场:从二维到三维的「升维」

现在关键问题来了:我们明明有 (x, y, Z) 三个坐标,为什么偏偏把Z叫做「高度场」?

原因很简单:在曲面建模里,我们通常假设XY平面是「水平面」,Z轴垂直于它向上。这样,Z值就天然代表了曲面在某个 (x, y) 位置上的「高度」。

这种表示法叫高度场(Height Field),也叫2.5D表示。它有个重要限制:每个 (x, y) 只能对应一个Z值。换句话说,曲面不能有「倒悬」或「折叠」——比如一个拱桥的底面,用高度场就描述不了。

高度场的数学定义:

Z = f(x, y),其中 f 是单值函数。对于定义域内的任意 (x, y),有且仅有一个 Z 值与之对应。

那为什么我们还要用高度场?因为简单、稳定、计算快。多项式曲面拟合的本质,就是在高度场假设下,寻找一个多项式函数 f,使得 f(x, y) 尽可能逼近所有采样点的 Z 值。

3.4 知识体系总览

下面这张图,把本章的核心概念串起来了:

坐标系与数据表示 · 知识结构 XY平面坐标系 X轴:水平向右 Y轴:垂直向上 原点O:(0,0) 离散点云数据 (x, y, Z) 三元组 均匀/随机采样 扫描/仿真/函数 Z值作为高度场 核心约束:每个 (x, y) 只能对应一个 Z 值 → 曲面不能有倒悬或折叠 应用场景:地形建模、光学镜面设计、CAE仿真结果可视化

3.5 一个完整的例子:从函数到点云

光说不练假把式。我们拿一个实际函数走一遍流程。

假设我们要建模的曲面是:

Z = 3 + 2x - y + 0.5x² - 0.3xy + 0.8y²

这是一个二元二次多项式。我们想在 x ∈ [-5, 5], y ∈ [-5, 5] 的矩形区域内采样。

步骤1:确定采样网格

我习惯用等间距网格。比如每1个单位采一个点,那么x方向11个点,y方向11个点,总共121个点。

步骤2:生成坐标对

遍历所有 (x, y) 组合:

x = -5, -4, -3, ..., 4, 5
y = -5, -4, -3, ..., 4, 5

步骤3:计算Z值

把每个 (x, y) 代入多项式,算出对应的Z。

步骤4:组装点云

最终数据长这样(只展示前5行):

# x y Z
1 -5.0 -5.0 45.5
2 -5.0 -4.0 39.2
3 -5.0 -3.0 33.5
4 -5.0 -2.0 28.4
5 -5.0 -1.0 23.9
小技巧:实际项目中,我一般先用Python的numpy.meshgrid生成网格坐标,然后向量化计算Z值。这样比循环快10倍以上。后面章节我们会专门讲代码实现。

3.6 避坑指南

做这行久了,踩过的坑比吃过的盐还多。分享几个常见的:

  • 坐标系单位不一致:我曾经接手过一个项目,扫描数据用毫米,仿真数据用米,结果拟合出来的曲面扭曲得像麻花。统一单位是第一步。
  • 点云分布不均匀:有些区域点很密,有些区域点很疏。这样拟合出来的曲面在稀疏区域误差极大。我一般会做一次「均匀化重采样」。
  • Z值范围过大:如果Z值从0.001到1000,跨度太大,数值计算容易出问题。建议做归一化处理,把Z缩放到[-1, 1]或[0, 1]区间。
  • 忘记检查异常点:扫描数据里经常有飞点(outlier)。一个飞点就能把整个多项式拟合带偏。我每次拿到数据,第一件事就是画散点图,肉眼扫一遍。
重要提醒:高度场假设不是万能的。如果你的曲面有垂直面、倒扣面或者悬挑结构,高度场表示法会直接失效。这时候需要改用参数曲面或网格曲面。我们这门课只处理高度场适用的场景,请务必确认你的数据符合这个前提。