【3D實踐】3D曲率原理及計算(3D-Mesh)

作者:憨豆酒(YinDou),聯繫我[email protected],熟悉圖形學,圖像處理領域,本章的源代碼可在此倉庫中找到: https://github.com/douysu/person-summary 如果大家發現錯誤以及不合理之處,還希望多多指出。

查了一下中文文章,幾乎沒有一篇介紹曲率原理並且計算曲率的文章。首先總結了一下曲率的原理,參考的內容有:圖形學書籍、維基,和GitHub的項目。
參考內容:
[1] https://libigl.github.io/

[2] https://zh.wikipedia.org/wiki/曲率

[3] https://zh.wikipedia.org/wiki/PLY

[4] https://github.com/alecjacobson/geometry-processing-curvature

[5] http://meshlabstuff.blogspot.com/2010/03/mean-curvature-cavity-map-zbrush-and.html

[6] https://web.archive.org/web/20081203195143/http://www.cs.princeton.edu/~diego/professional/rply/

[7]章毓晉.圖像處理.北京:清華大學出版社,2018

1 曲率原理

什麼是曲率?

曲率是描述幾何體彎曲程度的量,例如三維曲面偏離平面的程度,或者二維曲線偏離直線的程度,也可確定曲面類型。常應用於幾何分析,地理測繪等領域。

例如在材料學中,材料的催化活性主要與表面活性位點有關,而曲率影響活性位點的數量。

曲線P點切線:
曲線任意一點Q,PQ兩點無限接近,所連直線爲切線。

曲線P點曲率:曲線任意一點?_1, ?_2 ,三點確定一圓, ?_1, ?_2 無限接近P點,密切圓半徑r的倒數爲曲率。

平面結論:圓上彎曲程度相同,任意一點曲率相等,越彎曲曲率越大,直線曲率爲0。

曲面曲率:
在曲面上取一點P,曲面在P點的法線爲n,過n可以有無限多個剖切平面,每個剖切平面與曲面相交,交線爲一條平面曲線。
不同的剖切平面上的平面曲線在P點的曲率半徑一般是不相等的。

三維空間中的曲率:
主曲率:曲面上有無數個不同方向的曲線,曲面上的點不同方向具有不同曲率,其中最大值和最小值爲稱爲主曲率 k1 和k2,極值方向稱爲主方向。數學上可證名k1和k2互相垂直。

高斯曲率:兩主曲率乘積,反映曲面在不同方向彎曲程度是否相同。高斯曲率爲正,爲球面。高斯曲率爲負雙曲面。

平均曲率:兩主曲率算數平均數(k1+k2)/2,反映曲面凹凸程度。平均曲率爲正,局部凹。平均曲率爲負,局部凸。

第一個圖形的高斯曲率爲負值,第二個爲0,第三個爲正數。

2 高斯曲率(G)和均值曲率(H)所確定表面類型:

通過高斯曲率和均值曲率的正負判斷曲面類型。

H<0 H=0 H>0
G<0 鞍脊 最小/迷向
G=0 山脊 平面
G>0 山峯

3 曲率的計算

通過一段時間的調研,我發現使用此兩種方式計算曲率比較多。具體鏈接就不給出了,google一下就可以看到教程了案例了。

(1)C++圖形學幾何處理庫libigl

(2)三維幾何處理系統MeshLab

4 本人使用的方式

我採用的第二種方式,使用MeshLab進行處理,得到曲率數據,保存到.ply文件中,在從.ply文件中提取曲率的值即可。這裏我使用了Rply的框架進行ply的文件讀取。

這裏給出main.cpp的代碼

#include <stdio.h> 
#include "rply.h"
#include <fstream>
#include <iostream>
using namespace std;
ofstream outfile;
static int vertex_cb(p_ply_argument argument) {
	long eol;
	ply_get_argument_user_data(argument, NULL, &eol);
	float temp = ply_get_argument_value(argument);
	outfile << temp  << endl;
	printf("%g", ply_get_argument_value(argument));
	if (eol) printf("\n");
	else printf(" ");
	return 1;
}

static int face_cb(p_ply_argument argument) {
	long length, value_index;
	ply_get_argument_property(argument, NULL, &length, &value_index);
	switch (value_index) {
	case 0:
	case 1:
		printf("%g ", ply_get_argument_value(argument));
		break;
	case 2:
		printf("%g\n", ply_get_argument_value(argument));
		break;
	default:
		break;
	}
	return 1;
}

int main(void) {
	outfile.open("mean_curvature_vertex.txt");

	long nvertices;
	p_ply ply = ply_open("Mean_01.ply", NULL);
	if (!ply) return 1;
	if (!ply_read_header(ply)) return 1; //運行檢查
	nvertices = ply_set_read_cb(ply, "vertex", "x", vertex_cb, NULL, 0);
	ply_set_read_cb(ply, "vertex", "y", vertex_cb, NULL, 0);
	ply_set_read_cb(ply, "vertex", "z", vertex_cb, NULL, 0);
	ply_set_read_cb(ply, "vertex", "quality", vertex_cb, NULL, 1);
	//printf("%ld\n", nvertices);
	if (!ply_read(ply)) return 1;
	ply_close(ply);

	outfile.close();//關閉文件流
	getchar();
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章