1.基础知识
1.1 显式(Explicit)和隐式(Implicit)几何
- Implicit:几何上的点符合某种特定的关系,如代数表达式,水平集和距离函数等;
优点:1. 准确的描述;2. 针对几何的查询更简单(比如判断是否在几何体内,是否和几何体相交);3.拓扑变换更易处理。
- Explicit:直接给出点的信息,如点云、多边形网格、NURBS。
1.2 曲线(Curves)
重点是Bezier Curves(贝塞尔曲线);
贝塞尔曲线的代数表达式推导如下:
贝塞尔曲线有个缺点:当起始的点数过多,就会导致曲线难以控制(每个起始点作为控制点的影响小)。为了解决这个问题,分段贝塞尔曲线是最常用的方法。
分段贝塞尔曲线最需要关注的是两段曲线连接处的光滑问题。
解决该问题的结论是:当两侧控制点与分段交接点共线且形成的线段长度相等时,满足曲线平滑性质。
1.3 曲面(surfaces)
bezier surfaces:将贝塞尔曲线扩展到面上。
2. 网格的操作
Mesh subdivision;
Mesh simplification;
Mesh regularization;
2.1 subdivison(细分)
首先产生更多的三角形,然后调整他们的位置。
2.1.1 Loop subdivision
只针对三角形网格
- 先产生更多的三角形:
- 调整每个点的位置,新产生的点和旧的点调整方式不同。
2.1.2 Catmull-Clark Subdivision
任意多边形网格
- degree(度):一个点相邻点的个数;
- Extraordinary vertex(奇异点):度不为4的点; 基本思路:
- 每个面增加一个顶点,每条边的中点增加一个顶点;
2. 第一次细分步骤后,所有的非四边形面消失了,形成了奇异点,之后只需要重复步骤1即可。
2.2 Simplification(简化)
消融影响小的顶点
怎样定义顶点对整体的影响呢? 使用二次度量误差(Quadric Error Metrics)
QEM定义为顶点到其领域的三角面的距离的平方和。
边的QEM是顶点的QEM之和。
计算出每条边的QEM后,每次消融QEM最小的边,再计算所有边的QEM;
重复上述步骤,达到预期效果为止。
3. 作业
实现de Casteljau算法来绘制由4个控制点表示的Bézier曲线
cv::Point2f recursive_bezier(const std::vector<cv::Point2f> &control_points, float t)
{
// TODO: Implement de Casteljau's algorithm
auto p = control_points;
int loop = 0;
while (loop < control_points.size() - 1)
{
for (int i = 0; i < control_points.size() - loop; i++)
{
p[i].x = (1 - t) * p[i].x + t * p[i + 1].x;
p[i].y = (1 - t) * p[i].y + t * p[i + 1].y;
}
loop++;
}
return cv::Point2f(p[0]);
}
void bezier(const std::vector<cv::Point2f> &control_points, cv::Mat &window)
{
// TODO: Iterate through all t = 0 to t = 1 with small steps, and call de Casteljau's
// recursive Bezier algorithm.
for (double t = 0.0; t <= 1.0; t += 0.00001)
{
auto point = recursive_bezier(control_points, t);
window.at<cv::Vec3b>(point.y, point.x)[1] = 255;
}
}
对于每一个t都需要且只需要最终的点坐标,所以先复制一个控制点数组(以防后来赋值操作改变了控制点数组的值),然后两个点算出t分点的坐标,并用索引小的元素存储坐标。