多边形变形:确保内部顶点始终处于边界范围内
核心方法指引
1. 重心坐标映射法
- 适用场景:初始边界为凸多边形(符合你的限定条件),目标边界可凸可凹
- 原理:把内部顶点的位置转换成初始边界顶点的线性组合权重(重心坐标),再用该权重结合目标边界顶点坐标,计算内部顶点的目标位置
- 优势:实现简单,能保证内部顶点始终处于目标边界内部,无需关注变形中间步骤
- 关键步骤:
- 计算内部顶点在初始凸多边形中的重心权重
- 代入目标边界顶点坐标,推导内部顶点的最终位置
2. 径向基函数(RBF)插值法
- 适用场景:目标边界为凸或凹多边形,需保留原内部顶点的相对形状关系
- 原理:以边界顶点的起止坐标为控制点,构建薄板样条(TPS)等径向基函数的插值场,对内部顶点做坐标映射
- 优势:变形结果平滑自然,无需依赖初始凸性的额外限制
- 关键提示:TPS是这类场景下的首选基函数,能较好保留局部几何特征
3. 重新三角化法
- 适用场景:对原内部顶点位置无保留需求,仅需适配目标边界的三角化结构
- 原理:直接基于目标边界顶点,用Delaunay三角化算法重新生成内部网格
- 优势:完全适配目标边界,无需处理原内部顶点的映射问题,生成的三角网格质量较高
Python实现参考
重心坐标映射示例
import numpy as np def compute_barycentric(vertex, boundary_vertices): n = len(boundary_vertices) # 构建线性方程组求解重心权重 A = np.vstack([boundary_vertices.T, np.ones(n)]) b = np.array([vertex[0], vertex[1], 1]) weights = np.linalg.lstsq(A.T, b, rcond=None)[0] weights /= np.sum(weights) # 归一化确保权重和为1 return weights def map_to_target(weights, target_boundary): return np.dot(weights, target_boundary) # 测试代码 start_boundary = np.array([[0,0], [1,0], [1,1], [0,1]]) target_boundary = np.array([[0,0], [2,0], [2,2], [0,3]]) internal_vertex = np.array([0.5, 0.5]) weights = compute_barycentric(internal_vertex, start_boundary) target_internal = map_to_target(weights, target_boundary) print(target_internal)
TPS径向基函数插值示例
import numpy as np from scipy.interpolate import Rbf # 边界顶点起止坐标 start_points = np.array([[0,0], [1,0], [1,1], [0,1]]) target_points = np.array([[0,0], [2,0], [2,2], [0,3]]) # 创建TPS插值器 rbf_x = Rbf(start_points[:,0], start_points[:,1], target_points[:,0], function='thin_plate') rbf_y = Rbf(start_points[:,0], start_points[:,1], target_points[:,1], function='thin_plate') # 映射内部顶点 internal_points = np.array([[0.5, 0.5], [0.25, 0.75]]) target_x = rbf_x(internal_points[:,0], internal_points[:,1]) target_y = rbf_y(internal_points[:,0], internal_points[:,1]) target_internal = np.column_stack((target_x, target_y)) print(target_internal)
Delaunay重新三角化示例
import numpy as np from scipy.spatial import Delaunay import matplotlib.pyplot as plt # 目标边界顶点(需按顺序构成简单多边形) target_boundary = np.array([[0,0], [2,0], [2,2], [0,3]]) # 生成目标边界内的内部点 np.random.seed(42) internal_points = np.random.rand(10, 2) * np.array([2, 3]) # 过滤边界外的点 tri = Delaunay(target_boundary) valid_internal = internal_points[tri.find_simplex(internal_points) != -1] # 合并顶点并重新三角化 all_points = np.vstack([target_boundary, valid_internal]) final_tri = Delaunay(all_points) # 可视化结果 plt.triplot(all_points[:,0], all_points[:,1], final_tri.simplices) plt.plot(target_boundary[:,0], target_boundary[:,1], 'ro') plt.plot(valid_internal[:,0], valid_internal[:,1], 'bo') plt.show()
资料推荐
- 《计算机图形学原理及实践》:详细讲解重心坐标、插值变形和三角化算法的原理与工程实现
- 《Thin Plate Splines for Image Warping》:TPS径向基函数变形的经典论文,可深入理解插值逻辑
内容的提问来源于stack exchange,提问作者TheFamousRat
相关产品推荐
相关产品推荐

