OpenCV矩阵运算之顶点法向量计算
2017-08-14 19:57
204 查看
OpenCV进行顶点法向量计算
先介绍一下我接触此题的背景。我需要将一个.obj文件中的vn即顶点法向量计算出来。现在有的数据是f(三角面片索引),v(顶点坐标),但是网上找的代码不是很多,逻辑也不是很清楚,因此自己写了代码,并与大家分享。有错误敬请指出!顶点法向量的计算方法
这里大概摘自这篇文章最简单也是最直接的求顶点的法向量的方法是遍历此顶点所关联的所有三角形,将这些三角形上的法向量单位化后叠加,然后求出法向量的均值即可。
伪代码:
vertexNormal = (0,0,0); for each triangle connect to current vertex; vertexNormal += triangleNormal; vertexNormal /= connectedTriangleNums;
但这样求出的法向量往往效果不好,特别是当一些很小的多边形共面时。为了解决这个问题就需要使各个三角形并不是简单的等比例贡献法向量。直观上很容易发现,每个三角形与顶点相关联的那个角的大小是变化的,因此就可以使用此角度的大小来作为单个三角形对顶点法向量的贡献因子。
vertexNormal = 0,0,0; totalAngle = 0; for each triangle connect to current vertex; angle = acos(dot(edge1 , edge2)); vertexNormal += trangleNormal * angle; totalAngle += angle; vertexNormal /= totalAngle;
在实现时要注意,使用的角为关联当前顶点的那个角。
本文采用的算法是第二种
但是,根据数据结构不同,具体按需要编写代码
实现代码及解析
为每一个顶点定义一个存储法向量和与总角度的结构体:using namespace cv; typedef struct vet_data { Vec3f vn; double total_angle; } vet_data;
新建点与面数据进行模拟:
Vec3f v[4] = { Vec3f(33.7193, 24.7910, 50.5333), Vec3f(34.6217, 23.1564, 51.2146), Vec3f(42.6307, 22.9352, 49.5766), 4000 Vec3f(41.6282, 24.5848, 48.7240) }; Vec3f f[4] = { Vec3f(0, 1, 2), Vec3f(0, 2, 3), Vec3f(1, 2, 3), Vec3f(0, 1, 3) };
初始化:
vet_data v_data[4]; for(int i = 0; i < 4; ++i) { v_data[i].vn = Vec3f(0,0,0); v_data[i].total_angle = 0; }
运算过程:
for(int i = 0; i < 4; ++i) { int indx[3]; for(int j = 0;j < 3; ++j) { indx[j] = f[i][j]; } Vec3f v0 = v[indx[0]], v1 = v[indx[1]], v2 = v[indx[2]]; Vec3f e1 = v1 - v0; Vec3f e2 = v2 - v1; Vec3f vn = normalize(e1.cross(e2)); double angle[3] = { 0.0, 0.0, 0.0 }; double t1, t2, t3; t1 = (v1 - v0).dot(v2 - v0) / mod(v1 - v0) / mod(v2 - v0) * CV_PI / 180.0; t2 = (v0 - v1).dot(v2 - v1) / mod(v0 - v1) / mod(v2 - v1) * CV_PI / 180.0; t3 = (v0 - v2).dot(v1 - v2) / mod(v0 - v2) / mod(v1 - v2) * CV_PI / 180.0; angle[0] = acos(t1); angle[1] = acos(t2); angle[2] = acos(t3); cout << angle[0] << " " << angle[1] << " " << angle[2] << "\t# " << t1 << " " << t2 << " " << t3 << std::endl; for(int i = 0; i < 3; ++i) { v_data[indx[i]].vn += vn * angle[i]; v_data[indx[i]].total_angle += angle[i]; } } ofstream out("outputvn.txt"); out << "-----vn-------" << endl; for(int i = 0; i < 4; ++i) { Vec3f vn = v_data[i].vn / v_data[i].total_angle; out << "vn" << " " << vn[0] << " " << vn[1] << " " << vn[2] << std::endl; cout << "vn" << " " << vn[0] << " " << vn[1] << " " << vn[2] << std::endl; }
相关文章推荐
- 六、STL的数值计算---数组(向量)运算---gslice类和gslice_array类模板
- 六、STL的数值计算---数组(向量)运算---mask_array类
- 4000 六、STL的数值计算---数组(向量)运算---indirect_array类
- UVa 11437:Triangle Fun(计算几何综合应用,求直线交点,向量运算,求三角形面积)
- 计算三角网格的顶点法向量
- OpenCV矩阵(向量)运算
- osg::NodeVisitor中计算一个节点对应的世界变换矩阵、法向量、顶点坐标
- 三维模型顶点法向量和偏导数的计算方法
- 六、STL的数值计算---向量(数组)运算--valarray类
- 六、STL的数值计算---数组(向量)运算---数组子集类-slice类和slice_array类模板
- 土圭垚㙓数学课(二)视锥体八个顶点的计算方法
- 逻辑运算&(2+3的计算过程)
- (十一)processing中的向量运算方法
- 实验5-2: 编制程序,输入m、n(m≥n≥0)后,计算下列表达式的值并输出。 要求将计算阶乘的运算编写作函数fact(n),函数返回值的类型为float
- OpenCV矩阵运算
- leetcode_461. Hamming Distance 计算汉明距离,按位异或运算,计算整数的二进制表示中1的个数 java
- 大数据运算系统(4)--- 内存计算系统
- 用switch控制运算符,输入两个数,计算他们的运算结果;
- BZOJ-2829信用卡凸包 凸包+向量旋转计算
- POJ 3347 Kadj Squares 复杂的线段相交问题。这个题目是计算几何的扩大数据运算的典型应用 有时候扩大数据范围避免浮点误差,这个题就是应用