Lloydスムージング(CGALライブラリ) †
Lloydスムージングはメッシュ・エネルギーが最小になるように、メッシュの節点を動かしてメッシュ全体にスムージングをかけます。全体にスムージングをかけるので、品質の悪いメッシュを探しだして、それを改善するような手法ではありません。
メッシュ・エネルギーは、関数f(x) = x^2を区分的な1次関数で補間した際のL1-誤差で表されます。Lloydスムージングの場合は、メッシュ節点のボロノイ要素を線形補間したものから算出します。
ここでは、CGALライブラリのLloydスムージングを使用します。
3次元画像データをデローニー分割 †
まず、2本の菅が交差するような画像データをデローニー分割してテトラメッシュを作成します。画像データは下図のようになっています。管は画像のピクセルで表されるため凸凹になっています。
この画像データをスムージングなしでデローニー分割しテトラメッシュにします。結果は下図のようになりました。表面メッシュの大きさに偏りがあり、凸凹感もあります。
Lloydスムージング †
上のデローニー分割で作成したテトラメッシュにLloydスムージングをかけてみます。
プログラムは、CGALの例題"Tuning Mesh Optimization"を修正しました。
プログラムを実行した結果は下図のようになりました。テトラメッシュの辺の比が改善され、凸凹感も少なくなりました。
LloydSmoothing.cxx †
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
-
!
-
!
-
!
-
!
-
-
!
|
|
|
|
|
|
-
|
!
|
-
!
|
-
!
|
|
-
!
|
|
-
|
|
!
-
!
|
|
|
|
|
|
|
|
|
|
!
| #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Mesh_triangulation_3.h>
#include <CGAL/Mesh_complex_3_in_triangulation_3.h>
#include <CGAL/Mesh_criteria_3.h>
#include <CGAL/Labeled_image_mesh_domain_3.h>
#include <CGAL/make_mesh_3.h>
#include <CGAL/Image_3.h>
#include <CGAL/IO/Complex_3_in_triangulation_3_to_vtk.h>
#include <vtkMetaImageReader.h>
#include <vtkSmartPointer.h>
#include <vtkUnstructuredGrid.h>
#include <vtkXMLUnstructuredGridWriter.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Labeled_image_mesh_domain_3<CGAL::Image_3,K> Mesh_domain;
typedef CGAL::Mesh_triangulation_3<Mesh_domain>::type Tr;
typedef CGAL::Mesh_complex_3_in_triangulation_3<Tr> C3t3;
typedef CGAL::Mesh_criteria_3<Tr> Mesh_criteria;
using namespace CGAL::parameters;
int main()
{
vtkSmartPointer<vtkMetaImageReader> reader =
vtkSmartPointer<vtkMetaImageReader>::New();
reader->SetFileName("data/image.mha");
reader->Update();
CGAL::Image_3 image;
if (!image.read_vtk_image_data(reader->GetOutput()))
{
return 0;
}
Mesh_domain domain(image);
Mesh_criteria criteria(facet_angle=30, facet_size=0.1, facet_distance=1,
cell_radius_edge_ratio=3, cell_size=0.1);
C3t3 c3t3 = CGAL::make_mesh_3<C3t3>(domain, criteria, no_perturb(), no_exude());
CGAL::lloyd_optimize_mesh_3(c3t3, domain, time_limit=30);
vtkSmartPointer<vtkUnstructuredGrid> output =
vtkSmartPointer<vtkUnstructuredGrid>::New();
CGAL::output_c3t3_to_vtk_unstructured_grid(c3t3, output);
vtkSmartPointer<vtkXMLUnstructuredGridWriter> writer =
vtkSmartPointer<vtkXMLUnstructuredGridWriter>::New();
writer->SetFileName("out.vtu");
writer->SetInput(output);
writer->Update();
return 0;
}
|
ダウンロードとビルド †
画像データ: