Compare commits
39 Commits
36194f715e
...
master
Author | SHA1 | Date | |
---|---|---|---|
31d18b0715 | |||
93350f469a | |||
3e03f791cd | |||
be0b840231 | |||
610b0c5633 | |||
539ec4fad7 | |||
fe639d7cf0 | |||
48d652676d | |||
b957e2723d | |||
040971e50f | |||
8b803efbdc | |||
6e53dc13c6 | |||
c3955de037 | |||
98c93372dd | |||
4b804950a0 | |||
b19f149219 | |||
4a7428f1ff | |||
a45fd531f0 | |||
68f6b1e69d | |||
3d4f1f3f1c | |||
2e92096cff | |||
cf422b438f | |||
50bed749b8 | |||
5796a02505 | |||
4e8488e254 | |||
52f26364fd | |||
f4597b0144 | |||
85b21c8436 | |||
44bd8f3b0a | |||
f67bc4c9d7 | |||
1a4a00ac0c | |||
291571938a | |||
fd8f729efb | |||
0e56f3824a | |||
4e60a749e9 | |||
70afbbcdfc | |||
0a7202dc57 | |||
226ef2dc0a | |||
1782687e9a |
10
.gitignore
vendored
@ -4,3 +4,13 @@ out
|
|||||||
build*
|
build*
|
||||||
CmakeSettings.json
|
CmakeSettings.json
|
||||||
*.vtk
|
*.vtk
|
||||||
|
*.aux
|
||||||
|
*.bbl
|
||||||
|
*.blg
|
||||||
|
*.log
|
||||||
|
*.lbl
|
||||||
|
rapport/*.pdf
|
||||||
|
*.toc
|
||||||
|
*.snm
|
||||||
|
*.out
|
||||||
|
*.nav
|
||||||
|
@ -44,28 +44,28 @@ target_compile_features(pfe PRIVATE cxx_std_17)
|
|||||||
|
|
||||||
target_sources(pfe PRIVATE
|
target_sources(pfe PRIVATE
|
||||||
src/main.cc
|
src/main.cc
|
||||||
src/angles_filter.cc
|
src/analysis/angles_filter.cc
|
||||||
src/angles_filter.h
|
src/analysis/angles_filter.h
|
||||||
src/aspect_ratio_filter.cc
|
src/analysis/aspect_ratio_filter.cc
|
||||||
src/aspect_ratio_filter.h
|
src/analysis/aspect_ratio_filter.h
|
||||||
src/dihedral_angles_filter.cc
|
src/analysis/dihedral_angles_filter.cc
|
||||||
src/dihedral_angles_filter.h
|
src/analysis/dihedral_angles_filter.h
|
||||||
src/surface_points_filter.cc
|
src/surface_points_filter.cc
|
||||||
src/surface_points_filter.h
|
src/surface_points_filter.h
|
||||||
src/kd_tree.cc
|
src/kd_tree.cc
|
||||||
src/kd_tree.h
|
src/kd_tree.h
|
||||||
src/mesh_fit_filter.cc
|
src/fitting/mesh_fit_filter.cc
|
||||||
src/mesh_fit_filter.h
|
src/fitting/mesh_fit_filter.h
|
||||||
src/point_tris_dist.cc
|
src/point_tris_dist.cc
|
||||||
src/point_tris_dist.h
|
src/point_tris_dist.h
|
||||||
src/project_surface_points_on_poly.cc
|
src/fitting/project_surface_points_on_poly.cc
|
||||||
src/project_surface_points_on_poly.h
|
src/fitting/project_surface_points_on_poly.h
|
||||||
src/remove_external_cells_filter.cc
|
src/fitting/remove_external_cells_filter.cc
|
||||||
src/remove_external_cells_filter.h
|
src/fitting/remove_external_cells_filter.h
|
||||||
src/relaxation_filter.cc
|
src/fitting/relaxation_filter.cc
|
||||||
src/relaxation_filter.h
|
src/fitting/relaxation_filter.h
|
||||||
src/max_distance_filter.cc
|
src/analysis/max_distance_filter.cc
|
||||||
src/max_distance_filter.h
|
src/analysis/max_distance_filter.h
|
||||||
src/closest_polymesh_point.cc
|
src/closest_polymesh_point.cc
|
||||||
src/closest_polymesh_point.h)
|
src/closest_polymesh_point.h)
|
||||||
|
|
||||||
|
17
LISEZMOI
@ -4,9 +4,24 @@ Projet de fin d'étude de M2 Info Géométrie et Informatique Graphique.
|
|||||||
Compilation :
|
Compilation :
|
||||||
cmake -Bbuild -DCMAKE_BUILD_TYPE=Release && cmake --build build
|
cmake -Bbuild -DCMAKE_BUILD_TYPE=Release && cmake --build build
|
||||||
|
|
||||||
|
|
||||||
Compilation (pour développeurs) :
|
Compilation (pour développeurs) :
|
||||||
cmake -Bbuild \
|
cmake -Bbuild \
|
||||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||||
-DCMAKE_CXX_FLAGS="-Wall -Wextra" \
|
-DCMAKE_CXX_FLAGS="-Wall -Wextra" \
|
||||||
&& cmake --build build
|
&& cmake --build build
|
||||||
|
|
||||||
|
Pour utiliser une installation système de VTK :
|
||||||
|
-DUSE_SYSTEM_VTK=ON
|
||||||
|
|
||||||
|
Pour désactiver la visualisation :
|
||||||
|
-DENABLE_VIEWER=OFF
|
||||||
|
|
||||||
|
Exécution :
|
||||||
|
build/pfe fit|analyze tetmesh polydata [radiusScale relaxationIterCount]
|
||||||
|
|
||||||
|
Produit un fichier nommé out.vtu. En mode `analyze`, ce fichier
|
||||||
|
contient le même modèle que tetmesh mais avec les informations de
|
||||||
|
qualité ajoutée, et affiche des statistiques dans la console.
|
||||||
|
|
||||||
|
En mode `fit`, adapte le tetmesh au polydata, puis effectue
|
||||||
|
l'analyse comme `analyze`.
|
||||||
|
5937
data/half_cow.obj
Normal file
@ -1,8 +1,6 @@
|
|||||||
# Blender v2.79 (sub 0) OBJ File: ''
|
|
||||||
# www.blender.org
|
|
||||||
o Solid
|
o Solid
|
||||||
v 0.000000 0.769688 0.000000
|
v 0.000000 0.769688 0.000000
|
||||||
v 0.000000 0.000000 -0.769688
|
v 0.000000 0.000000 0.769688
|
||||||
v 0.769688 0.000000 0.000000
|
v 0.769688 0.000000 0.000000
|
||||||
v 0.000000 0.000000 0.000000
|
v 0.000000 0.000000 0.000000
|
||||||
s off
|
s off
|
||||||
|
1583
rapport/gig.cls
Normal file
BIN
rapport/img/Pipeline.png
Normal file
After Width: | Height: | Size: 66 KiB |
BIN
rapport/img/Pipeline2.png
Normal file
After Width: | Height: | Size: 97 KiB |
BIN
rapport/img/anisotropique.png
Normal file
After Width: | Height: | Size: 136 KiB |
BIN
rapport/img/cas-échec-2.png
Normal file
After Width: | Height: | Size: 259 KiB |
BIN
rapport/img/cas-échec.png
Normal file
After Width: | Height: | Size: 259 KiB |
BIN
rapport/img/cow-00.png
Normal file
After Width: | Height: | Size: 1.0 MiB |
BIN
rapport/img/cow-01.png
Normal file
After Width: | Height: | Size: 968 KiB |
BIN
rapport/img/cow-02.png
Normal file
After Width: | Height: | Size: 868 KiB |
BIN
rapport/img/cow-03.png
Normal file
After Width: | Height: | Size: 824 KiB |
BIN
rapport/img/cow-04.png
Normal file
After Width: | Height: | Size: 718 KiB |
BIN
rapport/img/cow-05.png
Normal file
After Width: | Height: | Size: 626 KiB |
BIN
rapport/img/cow-06.png
Normal file
After Width: | Height: | Size: 526 KiB |
BIN
rapport/img/cow-07.png
Normal file
After Width: | Height: | Size: 427 KiB |
BIN
rapport/img/cow-08.png
Normal file
After Width: | Height: | Size: 376 KiB |
BIN
rapport/img/cow-09.png
Normal file
After Width: | Height: | Size: 325 KiB |
BIN
rapport/img/cow-10.png
Normal file
After Width: | Height: | Size: 215 KiB |
BIN
rapport/img/cow-11.png
Normal file
After Width: | Height: | Size: 171 KiB |
BIN
rapport/img/cow-12.png
Normal file
After Width: | Height: | Size: 85 KiB |
BIN
rapport/img/cow-head-poly.png
Normal file
After Width: | Height: | Size: 183 KiB |
BIN
rapport/img/cow-head-tet-out.png
Normal file
After Width: | Height: | Size: 162 KiB |
BIN
rapport/img/cow-head-tet.png
Normal file
After Width: | Height: | Size: 132 KiB |
BIN
rapport/img/dist_point_tris_sectors.png
Normal file
After Width: | Height: | Size: 6.3 KiB |
BIN
rapport/img/explosion.png
Normal file
After Width: | Height: | Size: 241 KiB |
BIN
rapport/img/influence-rayon-0-3.png
Normal file
After Width: | Height: | Size: 115 KiB |
BIN
rapport/img/influence-rayon-5-20.png
Normal file
After Width: | Height: | Size: 117 KiB |
BIN
rapport/img/influence-relaxation.png
Normal file
After Width: | Height: | Size: 159 KiB |
BIN
rapport/img/isotropique.png
Normal file
After Width: | Height: | Size: 133 KiB |
BIN
rapport/img/logo-gig.png
Normal file
After Width: | Height: | Size: 424 KiB |
BIN
rapport/img/not_relaxed.png
Normal file
After Width: | Height: | Size: 76 KiB |
BIN
rapport/img/paraview.png
Normal file
After Width: | Height: | Size: 354 KiB |
BIN
rapport/img/plasma.png
Normal file
After Width: | Height: | Size: 435 KiB |
BIN
rapport/img/point_in_polygon.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
rapport/img/project.png
Normal file
After Width: | Height: | Size: 129 KiB |
BIN
rapport/img/project_clip_displace.png
Normal file
After Width: | Height: | Size: 48 KiB |
BIN
rapport/img/project_clip_no_displace.png
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
rapport/img/project_triangle_schema.png
Normal file
After Width: | Height: | Size: 9.6 KiB |
BIN
rapport/img/relaxed.png
Normal file
After Width: | Height: | Size: 77 KiB |
BIN
rapport/img/remove_external.png
Normal file
After Width: | Height: | Size: 94 KiB |
BIN
rapport/img/surface_points.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
rapport/img/symmetry-plane.png
Normal file
After Width: | Height: | Size: 998 KiB |
BIN
rapport/img/vtk-unstructuredgrid-0.png
Normal file
After Width: | Height: | Size: 79 KiB |
BIN
rapport/img/vtk-unstructuredgrid-1.png
Normal file
After Width: | Height: | Size: 162 KiB |
BIN
rapport/img/vtk-unstructuredgrid-2.png
Normal file
After Width: | Height: | Size: 150 KiB |
BIN
rapport/img/vtk-unstructuredgrid-3.png
Normal file
After Width: | Height: | Size: 73 KiB |
BIN
rapport/img/vtk-unstructuredgrid.png
Normal file
After Width: | Height: | Size: 455 KiB |
117
rapport/présentation.txt
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
+------------+
|
||||||
|
| Partie 1/3 |
|
||||||
|
+------------+
|
||||||
|
|
||||||
|
1. Présentation du sujet
|
||||||
|
|
||||||
|
[4/37] Maillages volumiques
|
||||||
|
- Structure composée de cellules polyédriques (tétraèdres, hexaèdres…)
|
||||||
|
reliées entre elles comme pour un maillage polygonal
|
||||||
|
classique, mais les cellules sont en 3D.
|
||||||
|
|
||||||
|
[5/37] Anisotropie
|
||||||
|
Notion de dépendance à l'orientation.
|
||||||
|
Image : plasma dans un réacteur à fusion nucléaire. On distingue clairement
|
||||||
|
une direction principale qui est la « boucle ». Cet exemple présente
|
||||||
|
donc de l'anisotropie.
|
||||||
|
|
||||||
|
[6/37] Anisotropie
|
||||||
|
Plus formellement, un champ de métriques.
|
||||||
|
Une métrique définit la déformation locale.
|
||||||
|
|
||||||
|
À gauche : isotropie.
|
||||||
|
À droite : espace anisotropique circulaire.
|
||||||
|
|
||||||
|
[7/37] Applications
|
||||||
|
Principalement dans le domaine de la simulation physique
|
||||||
|
Notamment la mécanique des fluides, où ils sont utilisés comme base de
|
||||||
|
discrétisation pour porter les calculs.
|
||||||
|
|
||||||
|
Par rapport à une simple voxélisation : résolution adaptative, plus
|
||||||
|
haute résolution dans les zones « intéressantes », pas de perte de temps
|
||||||
|
sur les calculs dans les zones moins intéressantes.
|
||||||
|
|
||||||
|
Par rapport à une voxélisation multi-niveaux comme un octree ou un
|
||||||
|
maillage isotropique, la forme des cellules peut être adaptée au
|
||||||
|
problème pour encore améliorer la précision des calculs. Le problème
|
||||||
|
reste maintenant de générer ces maillages anisotropiques.
|
||||||
|
|
||||||
|
[8/37]
|
||||||
|
Présente des approches pour la génération de maillages surfaciques (et
|
||||||
|
pas volumiques) anisotropes.
|
||||||
|
D'après leur conclusion : « Bien qu'elles soient toutes prouvablement
|
||||||
|
correctes, aucune des méthodes présentées n'est universellement
|
||||||
|
pratique ».
|
||||||
|
De plus, celle avec les résultats les « moins pires » est coûteuse en
|
||||||
|
temps de calcul, ce qui ne ferait qu'empirer après adaptation sur
|
||||||
|
maillages volumiques.
|
||||||
|
|
||||||
|
+------------+
|
||||||
|
| Partie 2/3 |
|
||||||
|
+------------+
|
||||||
|
|
||||||
|
[11/37]
|
||||||
|
Difficile d'imaginer en trois mois qu'on puisse produire une solution
|
||||||
|
qui fonctionne quand une thèse entière qui ne se consacre qu'au
|
||||||
|
surfacique y peine.
|
||||||
|
|
||||||
|
[17/37]
|
||||||
|
Présentation de la chaîne de traitement « pipeline »
|
||||||
|
Deux modes : analyse et adaptation
|
||||||
|
Image : en mode adaptation. En mode analyse on enlève simplement les
|
||||||
|
étapes qui modifient la géométrie du maillage.
|
||||||
|
|
||||||
|
[19/37]
|
||||||
|
point-in-polygon : permet de détecter si un point est dans un
|
||||||
|
polygone. On tire un rayon depuis le point vers l'infini et compte le
|
||||||
|
nombre d'intersections, pair : le points est hors du polygone,
|
||||||
|
impair : le point est dans le polygone.
|
||||||
|
|
||||||
|
[20/37]
|
||||||
|
Les cellules dont tous les points sont à l'extérieur du maillage
|
||||||
|
surfaciques sont supprimées.
|
||||||
|
|
||||||
|
[21/37]
|
||||||
|
Les points de surface sont ensuite marqués. Pour cela on détecte
|
||||||
|
quelles faces sont mitoyennes, ce qu'on peut déduire car on sait à
|
||||||
|
quelle cellules appartiennent chaque point.
|
||||||
|
Si les trois points d'une face appartiennent tous à une autre cellule,
|
||||||
|
c'est que la face qu'ils forment et mitoyenne. Sinon, elle est en
|
||||||
|
surface.
|
||||||
|
|
||||||
|
[22/37]
|
||||||
|
Les points de surface sont ensuite plaqués sur le point du maillage
|
||||||
|
surfacique le plus proche.
|
||||||
|
|
||||||
|
[23/37]
|
||||||
|
En déplaçant les points, on accumule l'information du déplacement de
|
||||||
|
chaque point dans le voisinage dans un certain rayon, pondéré par la
|
||||||
|
distance.
|
||||||
|
|
||||||
|
Le rayon est proportionel à la distance de déplacement multipliée par
|
||||||
|
un facteur, ce qui assure qu'on ne produit pas de cellules inversées
|
||||||
|
dites « chaussettes ».
|
||||||
|
|
||||||
|
Ceci est similaire à la « modification proportionelle » de blender.
|
||||||
|
|
||||||
|
[25/37] et [26/37]
|
||||||
|
Influence du facteur de multiplication du rayon d'action sur la
|
||||||
|
qualité. On voit qu'un rayon de 3 semble maximiser les angles les plus
|
||||||
|
faibles, sans trop réduire les angles les plus élevés pour autant.
|
||||||
|
|
||||||
|
[27/37]
|
||||||
|
Relaxation : on déplace chaque point dans le barycentre de son
|
||||||
|
voisinage. Une itération améliore la qualité du maillage, plus d'une
|
||||||
|
itération la dégrade.
|
||||||
|
|
||||||
|
+------------+
|
||||||
|
| Partie 3/3 |
|
||||||
|
+------------+
|
||||||
|
|
||||||
|
implémentation, moi
|
||||||
|
|
||||||
|
+------------+
|
||||||
|
| Partie 4/3 |
|
||||||
|
+------------+
|
||||||
|
|
||||||
|
résultats et conclusion
|
14
rapport/rapport.bib
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
@phdthesis{rouxellabbe:tel-01419457,
|
||||||
|
TITLE = {{Anisotropic mesh generation}},
|
||||||
|
AUTHOR = {Rouxel-Labbe, Mael},
|
||||||
|
URL = {https://tel.archives-ouvertes.fr/tel-01419457},
|
||||||
|
NUMBER = {2016AZUR4150},
|
||||||
|
SCHOOL = {{Universit{\'e} C{\^o}te d'Azur}},
|
||||||
|
YEAR = {2016},
|
||||||
|
MONTH = Dec,
|
||||||
|
KEYWORDS = {Riemannian Geometry ; Voronoi diagram ; Delaunay triangulation ; Mesh generation ; Anisotropy ; G{\'e}n{\'e}ration de maillages ; G{\'e}ometrie Riemannienne ; Diagramme de Voronoi ; Triangulation de Delaunay ; Anisotropie},
|
||||||
|
TYPE = {Theses},
|
||||||
|
PDF = {https://tel.archives-ouvertes.fr/tel-01419457v2/file/2016AZUR4150.pdf},
|
||||||
|
HAL_ID = {tel-01419457},
|
||||||
|
HAL_VERSION = {v2},
|
||||||
|
}
|
166
rapport/rapport.tex
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
\documentclass{gig}
|
||||||
|
|
||||||
|
\usepackage[utf8]{inputenc}
|
||||||
|
\usepackage[french]{babel}
|
||||||
|
\usepackage[T1]{fontenc}
|
||||||
|
\usepackage{url}
|
||||||
|
\usepackage{caption}
|
||||||
|
\usepackage{listings}
|
||||||
|
\usepackage{graphicx}
|
||||||
|
|
||||||
|
\title{Génération de maillages anisotropes}
|
||||||
|
\author[Jérémy André, Cyril Colin et Christine Cozzolino]
|
||||||
|
{Jérémy André$^1$, Cyril Colin$^1$ et Christine Cozzolino$^1$
|
||||||
|
\\
|
||||||
|
$^1$Aix-Marseille Université}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
|
||||||
|
\maketitle
|
||||||
|
|
||||||
|
\begin{abstract}
|
||||||
|
Nous étudions dans ce rapport la génération de maillages volumiques
|
||||||
|
anisotropes à partir de maillages surfaciques. Nous commençons par
|
||||||
|
une analyse des travaux de la thèse de Mael
|
||||||
|
Rouxel-Labbé\cite{rouxellabbe:tel-01419457}. Nous redéfinissons
|
||||||
|
ensuite les objectifs du projet, et présentons notre méthode pour y
|
||||||
|
répondre. Enfin, nous analysons les résultats obtenus.
|
||||||
|
\end{abstract}
|
||||||
|
|
||||||
|
\keywords{Génération de maillages, Maillages volumiques, Anisotropie}
|
||||||
|
|
||||||
|
\section{Présentation du sujet}
|
||||||
|
Les maillages volumiques sont des structures qui représentent la
|
||||||
|
surface mais aussi l'intérieur d'un objet, contrairement aux maillages
|
||||||
|
surfaciques classiques. Ils sont composés de cellules qui sont des
|
||||||
|
polyèdres liés entre eux par leurs sommets, et peuvent être agencés de
|
||||||
|
manière structurée ou non structurée. Un maillage volumique peut par
|
||||||
|
exemple être un assemblage de voxels, auquel cas le maillage est
|
||||||
|
structuré et les cellules sont des cubes.
|
||||||
|
|
||||||
|
Une des applications de ces maillage est dans le domaine de la
|
||||||
|
simulation, où l'on peut discrétiser un problème continu en se servant
|
||||||
|
des cellules du maillage comme base de la discrétisation.
|
||||||
|
|
||||||
|
Dans certains domaines, comme par exemple la mécanique des fluides,
|
||||||
|
les conditions de la simulation rendent innéficace un maillage
|
||||||
|
structuré : leur résolution fixe limite la précision dans les zones
|
||||||
|
« intéressantes » comme celles ou un fluide intéragit avec une
|
||||||
|
surface, tout en étant inutilement coûteuse dans les zones moins
|
||||||
|
intéressantes.
|
||||||
|
|
||||||
|
En plus d'augmenter la résolution dans les zones intéressantes, la
|
||||||
|
précision des calculs peut aussi être augmentée en adaptant la forme
|
||||||
|
des cellules aux conditions locales : il faut donc que celles-ci
|
||||||
|
puissent être irrégulières pour pouvoir les transformer et étirer pour
|
||||||
|
les adapter.
|
||||||
|
|
||||||
|
Ainsi, l'utilisation de maillages volumiques non structurés s'est
|
||||||
|
imposée comme solution pour tous les problèmes de ce type, posant
|
||||||
|
cependant l'autre problème qu'est leur génération.
|
||||||
|
|
||||||
|
\section{Présentation de la thèse}
|
||||||
|
\section{Justification de la non-utilisation des travaux de la thèse}
|
||||||
|
La thèse de Rouxel-Labbé offre une excellente introduction du domaine
|
||||||
|
et des méthodes utilisées, mais les résultats des approches qu'elle
|
||||||
|
développe sont peu satisfaisant.
|
||||||
|
\begin{quote}
|
||||||
|
We have sought approaches that combine theoretical soundness, that
|
||||||
|
is the capacity to prove that the desired result is obtained under
|
||||||
|
certain conditions, and practicality. Our results are mixed: while
|
||||||
|
we have proposed a number of methods that were all provably correct,
|
||||||
|
none of these methods were universally practical.
|
||||||
|
\end{quote}
|
||||||
|
De plus, parmis les approches proposées, celle qui présente les
|
||||||
|
meilleurs résultats à le défaut d'être lourde en temps de calcul sur
|
||||||
|
des maillages surfaciques. L'adapter à des maillages volumiques la
|
||||||
|
rendrait donc encore moins pratiquable.
|
||||||
|
|
||||||
|
\section{Redéfinition des objectifs}
|
||||||
|
Au vu de la complexité du problème, notre encadrant à décidé de
|
||||||
|
redéfinir nos objectifs.
|
||||||
|
|
||||||
|
Nous partons désormais d'un maillage volumique tétrahédrique existant
|
||||||
|
mais qui approxime que grossièrement le maillage surfacique, et devons
|
||||||
|
tenter de le rendre plus fidèle au maillage surfacique en évitant de
|
||||||
|
dégrader la qualité.
|
||||||
|
|
||||||
|
%-----------------------------------------------------------------------
|
||||||
|
\section{Redéfinition de nos objectifs}
|
||||||
|
La thèse de Rouxel-Labbé présente une excellente introduction du
|
||||||
|
domaine en plus d'un état de l'art remarquable, mais les approches
|
||||||
|
qu'elle propose restent assez limitée. L’auteur lui-même indique
|
||||||
|
que bien que prouvablement correctes, elles sont limitées dans leurs
|
||||||
|
applications. De plus, une des méthodes présentées qui fournit les
|
||||||
|
meilleurs résultats à le défaut d'être coûteuse en temps de calcul,
|
||||||
|
défaut qui ne ferait que s'aggraver si on la traduisait dans le
|
||||||
|
domaine des maillages volumiques.
|
||||||
|
|
||||||
|
Pour cette raison, et au vu de la complexité de la tâche, notre
|
||||||
|
encadrant a redéfini nos objectifs : il s'agit désormais de prendre un
|
||||||
|
maillage tétraédrique généré à partir d'un maillage surfacique de
|
||||||
|
manière simpliste, et de l'adapter pour réduire l'écart entre le
|
||||||
|
maillage surfacique et le maillage tétraédrique sans trop dégrader la
|
||||||
|
qualité de celui-ci.
|
||||||
|
%-----------------------------------------------------------------------
|
||||||
|
\section{Résultats et validation}
|
||||||
|
Notre méthode présente des résultats en demi-teinte. Elle réussi
|
||||||
|
effectivement à grandement diminuer la distance entre le maillage
|
||||||
|
polygonal source et le maillage tétraédrique, mais pas sans générer
|
||||||
|
par endroit des zones de très faible qualité. De plus, elle ne peut
|
||||||
|
pas toujours corriger les défauts causés par la tétraédrisation
|
||||||
|
initiale.
|
||||||
|
|
||||||
|
Les points les plus éloignés du maillage surfacique après application
|
||||||
|
de notre méthode sont en effet ceux où trop de détails et de géométrie
|
||||||
|
ont été perdus dans la tétrahédrisation (voir figure
|
||||||
|
\ref{fig:cow-head}). On peut également y voir un défaut de notre
|
||||||
|
méthode de projection qui choisit les points les plus proches.
|
||||||
|
|
||||||
|
\begin{figure*}
|
||||||
|
\centering
|
||||||
|
\begin{tabular}{ccc}
|
||||||
|
\includegraphics[width=4.7cm]{img/cow-head-poly.png} &
|
||||||
|
\includegraphics[width=4.7cm]{img/cow-head-tet.png} &
|
||||||
|
\includegraphics[width=4.7cm]{img/cow-head-tet-out.png} \\
|
||||||
|
\end{tabular}
|
||||||
|
\caption{Tête de la vache dans le maillage polygonal source, le
|
||||||
|
maillage tétraédrique initial, et le maillage tétraédrique après
|
||||||
|
application de notre méthode, de gauche à droite respectivement.}
|
||||||
|
\label{fig:cow-head}
|
||||||
|
\end{figure*}
|
||||||
|
|
||||||
|
L'étape de relaxation améliore la qualité du maillage en minimisant le
|
||||||
|
nombre de cellules qui ont des angles faibles. Cependant en faire plus
|
||||||
|
d'une itération dégrade le maillage plus que de ne pas faire de
|
||||||
|
relaxation du tout. Les angles moins faibles ne sont eux que peu
|
||||||
|
affectés (Voir figure \ref{fig:courbe-relaxation}).
|
||||||
|
|
||||||
|
\begin{figure*}
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=14cm]{img/influence-relaxation.png} \\
|
||||||
|
\caption{Influence de la relaxation sur les angles dièdres}
|
||||||
|
\label{fig:courbe-relaxation}
|
||||||
|
\end{figure*}
|
||||||
|
|
||||||
|
Pour ce qui est du rayon d'action de la modification proportionelle,
|
||||||
|
un multiplicateur de rayon de 3 réduit grandement la proportion de
|
||||||
|
cellules avec des angles très faible, mais au-delà de ça l'effet est
|
||||||
|
négligeable (Voir figure \ref{fig:courbe-rayon}).
|
||||||
|
|
||||||
|
\begin{figure*}
|
||||||
|
\centering
|
||||||
|
\begin{tabular}{cc}
|
||||||
|
\includegraphics[width=8cm]{img/influence-rayon-0-3.png} &
|
||||||
|
\includegraphics[width=8cm]{img/influence-rayon-5-20.png} \\
|
||||||
|
\end{tabular}
|
||||||
|
\caption{Influence du rayon de modification proportionelle sur les
|
||||||
|
angles dièdres}
|
||||||
|
\label{fig:courbe-rayon}
|
||||||
|
\end{figure*}
|
||||||
|
|
||||||
|
\newpage
|
||||||
|
\bibliography{rapport}
|
||||||
|
\bibliographystyle{refig-alpha}
|
||||||
|
|
||||||
|
\end{document}
|
1449
rapport/refig-alpha.bst
Normal file
15
rapport/slides.bib
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
@article{plasma,
|
||||||
|
author = {Helander, P and Beidler, C and Bird, T and Drevlak, M and Feng, Y. and Hatzky, R and Jenko, Frank and Kleiber, R. and Proll, Josefine and Turkin, Yu and Xanthopoulos, Panagiotis},
|
||||||
|
year = {2012},
|
||||||
|
month = {11},
|
||||||
|
pages = {124009},
|
||||||
|
title = {Stellarator and tokamak plasmas: A comparison},
|
||||||
|
volume = {54},
|
||||||
|
journal = {Plasma Physics and Controlled Fusion},
|
||||||
|
doi = {10.1088/0741-3335/54/12/124009}
|
||||||
|
}
|
||||||
|
|
||||||
|
@misc{gamma,
|
||||||
|
author = {Frédéric Alauzet et al.},
|
||||||
|
howpublished = {https://team.inria.fr/gamma/}
|
||||||
|
}
|
272
rapport/slides.tex
Normal file
@ -0,0 +1,272 @@
|
|||||||
|
\documentclass{beamer}
|
||||||
|
|
||||||
|
\usepackage[french]{babel}
|
||||||
|
\usepackage[utf8]{inputenc}
|
||||||
|
\usepackage[T1]{fontenc}
|
||||||
|
\usepackage{csquotes}
|
||||||
|
\usepackage[backend=biber]{biblatex}
|
||||||
|
|
||||||
|
\addbibresource{slides.bib}
|
||||||
|
|
||||||
|
\usetheme{JuanLesPins}
|
||||||
|
\beamertemplatenavigationsymbolsempty
|
||||||
|
\setbeamertemplate{footline}[frame number]
|
||||||
|
|
||||||
|
\makeatletter
|
||||||
|
\newlength\graphwidth
|
||||||
|
\setlength\graphwidth{10.5cm}
|
||||||
|
\newlength\graphheight
|
||||||
|
\setlength\graphheight{5.5cm}
|
||||||
|
\makeatother
|
||||||
|
|
||||||
|
\title{Génération de maillages anisotropes}
|
||||||
|
\author{Jérémy André, Cyril Colin, Christine Cozzolino}
|
||||||
|
\institute{Aix-Marseille Université} \date{\today}
|
||||||
|
\titlegraphic{\includegraphics[width=2.5cm]{img/logo-gig.png}}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
|
||||||
|
\begin{frame}
|
||||||
|
\titlepage
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\begin{frame}{Plan}
|
||||||
|
\tableofcontents[hideallsubsections]
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\AtBeginSection[] {
|
||||||
|
\begin{frame}{Plan}
|
||||||
|
\tableofcontents[currentsection]
|
||||||
|
\end{frame}
|
||||||
|
}
|
||||||
|
|
||||||
|
\section{Présentation du sujet}
|
||||||
|
|
||||||
|
\begin{frame}{Maillages volumiques}
|
||||||
|
\centering
|
||||||
|
\begin{figure}
|
||||||
|
\begin{tabular}{cc}
|
||||||
|
\includegraphics[width=4.5cm]{img/cow-00.png} &
|
||||||
|
\includegraphics[width=4.5cm]{img/cow-03.png} \\
|
||||||
|
\includegraphics[width=4.5cm]{img/cow-06.png} &
|
||||||
|
\includegraphics[width=4.5cm]{img/cow-09.png} \\
|
||||||
|
\end{tabular}
|
||||||
|
\caption{Différentes coupes du maillage volumique d'une vache}
|
||||||
|
\end{figure}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\begin{frame}{Anisotropie}
|
||||||
|
\centering
|
||||||
|
\begin{figure}
|
||||||
|
\includegraphics[height=\graphheight]{img/plasma.png}
|
||||||
|
\caption{Plasma dans un réacteur à fusion nucléaire \cite{plasma}}
|
||||||
|
\end{figure}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\begin{frame}{Anisotropie}
|
||||||
|
\centering
|
||||||
|
\begin{figure}
|
||||||
|
\begin{tabular}{cc}
|
||||||
|
\includegraphics[width=4.5cm]{img/isotropique.png} &
|
||||||
|
\includegraphics[width=4.5cm]{img/anisotropique.png}
|
||||||
|
\end{tabular}
|
||||||
|
\caption{À gauche : plan isotropique. À droite : plan anisotropique circulaire.}
|
||||||
|
\end{figure}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\begin{frame}{Applications}
|
||||||
|
\begin{figure}[htb]
|
||||||
|
\includegraphics[width=9cm]{img/symmetry-plane.png}
|
||||||
|
\caption{\label{fig:inria-gamma}
|
||||||
|
Image issue du projet GAMMA d'Inria \cite{gamma}
|
||||||
|
}
|
||||||
|
\end{figure}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
|
||||||
|
\section{Thèse de Rouxel-Labbé}
|
||||||
|
|
||||||
|
\begin{frame}
|
||||||
|
\begin{itemize}
|
||||||
|
\item Excellente introduction et état de l'art
|
||||||
|
\item Plusieurs approches proposées
|
||||||
|
\item Des résultats en demi-teinte
|
||||||
|
\end{itemize}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
|
||||||
|
\section{Redéfinition du sujet}
|
||||||
|
|
||||||
|
\begin{frame}
|
||||||
|
Le sujet étant jugé trop complexe, notre encadrant nous guide vers
|
||||||
|
un sujet un peu simplifié.
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\begin{frame}
|
||||||
|
\titlepage
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\begin{frame}[plain]{}
|
||||||
|
\hspace*{-12mm}
|
||||||
|
\includegraphics[width=\paperwidth]{img/explosion.png}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\title{Approximation et amélioration de la qualité des maillages tétrahédriques}
|
||||||
|
\begin{frame}
|
||||||
|
\titlepage
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\begin{frame}
|
||||||
|
\begin{block}{Nouveau sujet}
|
||||||
|
Adapter un maillage tétrahédrique simple existant au maillage
|
||||||
|
surfacique utilisé pour le générer, tout en préservant sa qualité.
|
||||||
|
\end{block}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\section{Présentation de notre méthode}
|
||||||
|
|
||||||
|
\begin{frame}
|
||||||
|
\centering
|
||||||
|
\begin{figure}
|
||||||
|
\includegraphics[height=\graphheight]{img/pipeline2.png}
|
||||||
|
\caption{Chaîne de traitement de notre approche}
|
||||||
|
\end{figure}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\subsection{Pré-traitement}
|
||||||
|
|
||||||
|
\begin{frame}
|
||||||
|
\begin{itemize}
|
||||||
|
\item Suppression des cellules externes
|
||||||
|
\item Détection des points de surface
|
||||||
|
\end{itemize}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\begin{frame}
|
||||||
|
\centering
|
||||||
|
\begin{figure}
|
||||||
|
\includegraphics[height=\graphheight]{img/point_in_polygon.png}
|
||||||
|
\caption{Point-dans-polygone}
|
||||||
|
\end{figure}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\begin{frame}{Suppression des cellules externes}
|
||||||
|
\centering
|
||||||
|
\begin{figure}
|
||||||
|
\includegraphics[width=\graphwidth]{img/remove_external.png}
|
||||||
|
\caption{Cellules supprimées}
|
||||||
|
\end{figure}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\begin{frame}
|
||||||
|
\centering
|
||||||
|
\begin{figure}
|
||||||
|
\includegraphics[width=\graphwidth]{img/surface_points.png}
|
||||||
|
\caption{Détection des points de surface}
|
||||||
|
\end{figure}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\subsection{Projection des points}
|
||||||
|
|
||||||
|
\begin{frame}{Recherche des points les plus proches}
|
||||||
|
\centering
|
||||||
|
\begin{figure}
|
||||||
|
\includegraphics[height=\graphheight]{img/project_triangle_schema.png}
|
||||||
|
\caption{Méthode de recherche du point le plus proche}
|
||||||
|
\end{figure}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\begin{frame}
|
||||||
|
\centering
|
||||||
|
\begin{figure}
|
||||||
|
\includegraphics[width=\graphwidth]{img/project.png}
|
||||||
|
\caption{Vache après projection des points}
|
||||||
|
\end{figure}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\subsection{« Modification proportionelle »}
|
||||||
|
|
||||||
|
\begin{frame}{Sans}
|
||||||
|
\centering
|
||||||
|
\includegraphics[height=\graphheight]{img/project_clip_no_displace.png}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\begin{frame}{Avec}
|
||||||
|
\centering
|
||||||
|
\includegraphics[height=\graphheight]{img/project_clip_displace.png}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\begin{frame}{Rayon d'influence}
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=\graphwidth]{img/influence-rayon-0-3.png}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\begin{frame}{Rayon d'influence}
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=\graphwidth]{img/influence-rayon-5-20.png}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\subsection{Relaxation}
|
||||||
|
|
||||||
|
\begin{frame}
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=\graphwidth]{img/influence-relaxation.png}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
|
||||||
|
\section{Implémentation}
|
||||||
|
|
||||||
|
\begin{frame}
|
||||||
|
\centering
|
||||||
|
Bibliothèque de Kitware sous license libre pour la manipulation de
|
||||||
|
données scientifiques 3D.
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\begin{frame}{VTK}
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=\graphwidth]{img/vtk-unstructuredgrid-0.png}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\begin{frame}{VTK}
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=\graphwidth]{img/vtk-unstructuredgrid-1.png}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\begin{frame}{VTK}
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=\graphwidth]{img/vtk-unstructuredgrid-2.png}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\begin{frame}{VTK}
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=\graphwidth]{img/vtk-unstructuredgrid-3.png}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\begin{frame}{Paraview}
|
||||||
|
\centering
|
||||||
|
\begin{figure}
|
||||||
|
\includegraphics[height=5cm]{img/paraview.png}
|
||||||
|
\caption{Capture d'écran de Paraview}
|
||||||
|
\end{figure}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
|
||||||
|
\section{Résultats}
|
||||||
|
|
||||||
|
\subsection{Cas dégénéré}
|
||||||
|
|
||||||
|
\begin{frame}
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=\graphwidth]{img/cas-échec.png}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\begin{frame}
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=\graphwidth]{img/cas-échec-2.png}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\begin{frame}
|
||||||
|
\printbibliography
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\end{document}
|
@ -72,6 +72,7 @@ vtkTypeBool DihedralAnglesFilter::RequestData(
|
|||||||
|
|
||||||
i += 6;
|
i += 6;
|
||||||
}
|
}
|
||||||
|
it->Delete();
|
||||||
AverageMinDegrees /= input->GetNumberOfCells();
|
AverageMinDegrees /= input->GetNumberOfCells();
|
||||||
AverageMinDegrees = AverageMinDegrees * 180. / 3.141592653589793;
|
AverageMinDegrees = AverageMinDegrees * 180. / 3.141592653589793;
|
||||||
MinMinDegrees = MinMinDegrees * 180. / 3.141592653589793;
|
MinMinDegrees = MinMinDegrees * 180. / 3.141592653589793;
|
@ -1,5 +1,5 @@
|
|||||||
#include "max_distance_filter.h"
|
#include "max_distance_filter.h"
|
||||||
#include "closest_polymesh_point.h"
|
#include "../closest_polymesh_point.h"
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <vtkPolyData.h>
|
#include <vtkPolyData.h>
|
||||||
@ -44,20 +44,32 @@ vtkTypeBool MaxDistanceFilter::RequestData(vtkInformation *request,
|
|||||||
links2->BuildLinks(input2);
|
links2->BuildLinks(input2);
|
||||||
MaxDist = 0;
|
MaxDist = 0;
|
||||||
for (vtkIdType i = 0; i < input1->GetNumberOfPoints(); i++) {
|
for (vtkIdType i = 0; i < input1->GetNumberOfPoints(); i++) {
|
||||||
|
vtkIdType nCells = links1->GetNcells(i);
|
||||||
|
if (nCells == 0) continue;
|
||||||
double point[3];
|
double point[3];
|
||||||
input1->GetPoint(i, point);
|
input1->GetPoint(i, point);
|
||||||
double vec[3];
|
double vec[3];
|
||||||
double dist;
|
double dist;
|
||||||
closestPolyMeshPoint(input2, point, tree2, links2, vec, &dist);
|
closestPolyMeshPoint(input2, point, tree2, links2, vec, &dist);
|
||||||
MaxDist = std::max(dist, MaxDist);
|
if (dist > MaxDist) {
|
||||||
|
MaxDist = dist;
|
||||||
|
MaxId = i;
|
||||||
|
MaxInput = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (vtkIdType i = 0; i < input2->GetNumberOfPoints(); i++) {
|
for (vtkIdType i = 0; i < input2->GetNumberOfPoints(); i++) {
|
||||||
|
vtkIdType nCells = links2->GetNcells(i);
|
||||||
|
if (nCells == 0) continue;
|
||||||
double point[3];
|
double point[3];
|
||||||
input2->GetPoint(i, point);
|
input2->GetPoint(i, point);
|
||||||
double vec[3];
|
double vec[3];
|
||||||
double dist;
|
double dist;
|
||||||
closestPolyMeshPoint(input1, point, tree1, links1, vec, &dist);
|
closestPolyMeshPoint(input1, point, tree1, links1, vec, &dist);
|
||||||
MaxDist = std::max(dist, MaxDist);
|
if (dist > MaxDist) {
|
||||||
|
MaxDist = dist;
|
||||||
|
MaxId = i;
|
||||||
|
MaxInput = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
@ -14,9 +14,13 @@ public:
|
|||||||
vtkInformationVector **inputVector,
|
vtkInformationVector **inputVector,
|
||||||
vtkInformationVector *outputVector) override;
|
vtkInformationVector *outputVector) override;
|
||||||
vtkGetMacro(MaxDist, double);
|
vtkGetMacro(MaxDist, double);
|
||||||
|
vtkGetMacro(MaxId, vtkIdType);
|
||||||
|
vtkGetMacro(MaxInput, vtkIdType);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
double MaxDist;
|
double MaxDist;
|
||||||
|
vtkIdType MaxId;
|
||||||
|
vtkIdType MaxInput;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
|||||||
#include <vtkDoubleArray.h>
|
#include <vtkDoubleArray.h>
|
||||||
#include <vtkCellIterator.h>
|
#include <vtkCellIterator.h>
|
||||||
|
|
||||||
#include "kd_tree.h"
|
#include "../kd_tree.h"
|
||||||
|
|
||||||
vtkStandardNewMacro(MeshFitFilter);
|
vtkStandardNewMacro(MeshFitFilter);
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
#include "project_surface_points_on_poly.h"
|
#include "project_surface_points_on_poly.h"
|
||||||
#include "closest_polymesh_point.h"
|
#include "../closest_polymesh_point.h"
|
||||||
|
|
||||||
#include <vtkUnstructuredGrid.h>
|
#include <vtkUnstructuredGrid.h>
|
||||||
#include <vtkPointData.h>
|
#include <vtkPointData.h>
|
||||||
@ -48,26 +48,41 @@ void findPointsWithinRadius(double radius, vtkPointSet *pointSet,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ProjectSurfacePointsOnPoly::moveSurfacePoint(vtkUnstructuredGrid *tetMesh,
|
vtkSmartPointer<vtkIdList> removeSurfacePoints(vtkIdList *list,
|
||||||
vtkPolyData *polyMesh,
|
vtkIntArray *isSurface) {
|
||||||
vtkIdType pointId,
|
vtkNew<vtkIdList> affectedPoints;
|
||||||
std::vector<double> &motionVectors,
|
affectedPoints->Allocate(list->GetNumberOfIds());
|
||||||
std::vector<unsigned> &numberOfAffectors,
|
for (vtkIdType i = 0; i < list->GetNumberOfIds(); i++) {
|
||||||
vtkKdTree *polyMeshKdTree,
|
vtkIdType id = list->GetId(i);
|
||||||
vtkKdTree *tetMeshKdTree,
|
if (!isSurface->GetValue(id)) {
|
||||||
vtkStaticCellLinks *links) {
|
affectedPoints->InsertNextId(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return affectedPoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ProjectSurfacePointsOnPoly::moveSurfacePoint(
|
||||||
|
vtkUnstructuredGrid *tetMesh,
|
||||||
|
vtkPolyData *polyMesh,
|
||||||
|
vtkIdType pointId,
|
||||||
|
std::vector<double> &motionVectors,
|
||||||
|
std::vector<unsigned> &numberOfAffectors,
|
||||||
|
vtkKdTree *polyMeshKdTree,
|
||||||
|
vtkKdTree *tetMeshKdTree,
|
||||||
|
vtkStaticCellLinks *links) {
|
||||||
double point[3];
|
double point[3];
|
||||||
tetMesh->GetPoint(pointId, point);
|
tetMesh->GetPoint(pointId, point);
|
||||||
double direction[3];
|
double direction[3];
|
||||||
double distance;
|
double distance;
|
||||||
|
|
||||||
closestPolyMeshPoint(
|
closestPolyMeshPoint(
|
||||||
polyMesh, point, polyMeshKdTree, links, direction, &distance);
|
polyMesh, point, polyMeshKdTree, links, direction, &distance);
|
||||||
vtkNew<vtkIdList> affectedPoints;
|
vtkNew<vtkIdList> pointsInRadius;
|
||||||
findPointsWithinRadius(distance * RadiusScale, tetMesh, point, affectedPoints);
|
findPointsWithinRadius(distance * RadiusScale, tetMesh, point, pointsInRadius);
|
||||||
|
auto affectedPoints = removeSurfacePoints(pointsInRadius, isSurface);
|
||||||
// tetMeshKdTree->FindPointsWithinRadius(distance * RadiusScale, point, affectedPoints);
|
// tetMeshKdTree->FindPointsWithinRadius(distance * RadiusScale, point, affectedPoints);
|
||||||
|
|
||||||
if(distance > 0) for (vtkIdType j = 0; j < affectedPoints->GetNumberOfIds(); j++) {
|
for (vtkIdType j = 0; j < affectedPoints->GetNumberOfIds(); j++) {
|
||||||
vtkIdType affectedPointId = affectedPoints->GetId(j);
|
vtkIdType affectedPointId = affectedPoints->GetId(j);
|
||||||
double affectedPoint[3];
|
double affectedPoint[3];
|
||||||
tetMesh->GetPoint(affectedPointId, affectedPoint);
|
tetMesh->GetPoint(affectedPointId, affectedPoint);
|
||||||
@ -82,7 +97,6 @@ void ProjectSurfacePointsOnPoly::moveSurfacePoint(vtkUnstructuredGrid *tetMesh,
|
|||||||
double motion[3] = {direction[0], direction[1], direction[2]};
|
double motion[3] = {direction[0], direction[1], direction[2]};
|
||||||
double factor = 1. - std::sqrt(dist2) / (distance * RadiusScale);
|
double factor = 1. - std::sqrt(dist2) / (distance * RadiusScale);
|
||||||
vtkMath::MultiplyScalar(motion, factor);
|
vtkMath::MultiplyScalar(motion, factor);
|
||||||
//std::cout << std::sqrt(dist2) << " " << (distance * radiusScale) << " " << factor << "\n";
|
|
||||||
motionVectors[affectedPointId * 3 + 0] += motion[0];
|
motionVectors[affectedPointId * 3 + 0] += motion[0];
|
||||||
motionVectors[affectedPointId * 3 + 1] += motion[1];
|
motionVectors[affectedPointId * 3 + 1] += motion[1];
|
||||||
motionVectors[affectedPointId * 3 + 2] += motion[2];
|
motionVectors[affectedPointId * 3 + 2] += motion[2];
|
||||||
@ -96,20 +110,13 @@ void ProjectSurfacePointsOnPoly::moveSurfacePoint(vtkUnstructuredGrid *tetMesh,
|
|||||||
|
|
||||||
|
|
||||||
static void applyMotionVectors(vtkUnstructuredGrid *tetMesh,
|
static void applyMotionVectors(vtkUnstructuredGrid *tetMesh,
|
||||||
vtkIdTypeArray *surfacePoints,
|
|
||||||
std::vector<double> &motionVectors,
|
std::vector<double> &motionVectors,
|
||||||
const std::vector<unsigned> &numberOfAffectors) {
|
const std::vector<unsigned> &numberOfAffectors) {
|
||||||
for (vtkIdType i = 0; i < tetMesh->GetNumberOfPoints(); i++) {
|
for (vtkIdType i = 0; i < tetMesh->GetNumberOfPoints(); i++) {
|
||||||
bool skip = false;
|
|
||||||
for (vtkIdType j = 0; j < surfacePoints->GetNumberOfTuples(); j++) {
|
|
||||||
if (i == surfacePoints->GetValue(j)) skip = true;
|
|
||||||
}
|
|
||||||
if (skip) continue;
|
|
||||||
if(numberOfAffectors[i] == 0) continue;
|
if(numberOfAffectors[i] == 0) continue;
|
||||||
double point[3];
|
double point[3];
|
||||||
tetMesh->GetPoint(i, point);
|
tetMesh->GetPoint(i, point);
|
||||||
double *motion = motionVectors.data() + (i * 3);
|
double *motion = motionVectors.data() + (i * 3);
|
||||||
|
|
||||||
vtkMath::MultiplyScalar(motion, 1. / numberOfAffectors[i]);
|
vtkMath::MultiplyScalar(motion, 1. / numberOfAffectors[i]);
|
||||||
vtkMath::Subtract(point, motion, point);
|
vtkMath::Subtract(point, motion, point);
|
||||||
tetMesh->GetPoints()->SetPoint(i, point);
|
tetMesh->GetPoints()->SetPoint(i, point);
|
||||||
@ -142,7 +149,9 @@ vtkTypeBool ProjectSurfacePointsOnPoly::RequestData(
|
|||||||
tetMeshKdTree->BuildLocatorFromPoints(vtkPointSet::SafeDownCast(tetMesh));
|
tetMeshKdTree->BuildLocatorFromPoints(vtkPointSet::SafeDownCast(tetMesh));
|
||||||
|
|
||||||
vtkIdTypeArray *surfacePoints =
|
vtkIdTypeArray *surfacePoints =
|
||||||
vtkIdTypeArray::SafeDownCast(tetMesh->GetFieldData()->GetArray("surface_points"));
|
vtkIdTypeArray::SafeDownCast(tetMesh->GetFieldData()->GetArray("surfacePoints"));
|
||||||
|
isSurface = vtkIntArray::SafeDownCast(
|
||||||
|
output->GetPointData()->GetArray("isSurface"));
|
||||||
std::vector<double> motionVectors(3 * tetMesh->GetNumberOfPoints(), 0);
|
std::vector<double> motionVectors(3 * tetMesh->GetNumberOfPoints(), 0);
|
||||||
std::vector<unsigned> numberOfAffectors(tetMesh->GetNumberOfPoints(), 0);
|
std::vector<unsigned> numberOfAffectors(tetMesh->GetNumberOfPoints(), 0);
|
||||||
for (vtkIdType i = 0; i < surfacePoints->GetNumberOfTuples(); i++) {
|
for (vtkIdType i = 0; i < surfacePoints->GetNumberOfTuples(); i++) {
|
||||||
@ -153,8 +162,7 @@ vtkTypeBool ProjectSurfacePointsOnPoly::RequestData(
|
|||||||
polyMeshKdTree, tetMeshKdTree,
|
polyMeshKdTree, tetMeshKdTree,
|
||||||
links);
|
links);
|
||||||
}
|
}
|
||||||
applyMotionVectors(tetMesh, surfacePoints,
|
applyMotionVectors(tetMesh, motionVectors, numberOfAffectors);
|
||||||
motionVectors, numberOfAffectors);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
@ -25,6 +25,8 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
int affectedNeighborsCount = 0;
|
int affectedNeighborsCount = 0;
|
||||||
double RadiusScale;
|
double RadiusScale;
|
||||||
|
vtkIntArray *isSurface = nullptr;
|
||||||
|
|
||||||
~ProjectSurfacePointsOnPoly() override = default;
|
~ProjectSurfacePointsOnPoly() override = default;
|
||||||
|
|
||||||
void moveSurfacePoint(vtkUnstructuredGrid *tetMesh,
|
void moveSurfacePoint(vtkUnstructuredGrid *tetMesh,
|
@ -30,7 +30,7 @@ vtkTypeBool RelaxationFilter::RequestData(
|
|||||||
vtkNew<vtkIdList> neighborCells;
|
vtkNew<vtkIdList> neighborCells;
|
||||||
vtkNew<vtkIdList> cellPoints;
|
vtkNew<vtkIdList> cellPoints;
|
||||||
vtkIdTypeArray *surfacePoints = vtkIdTypeArray::SafeDownCast(
|
vtkIdTypeArray *surfacePoints = vtkIdTypeArray::SafeDownCast(
|
||||||
output->GetFieldData()->GetArray("surface_points"));
|
output->GetFieldData()->GetArray("surfacePoints"));
|
||||||
vtkIntArray *isSurface = vtkIntArray::SafeDownCast(
|
vtkIntArray *isSurface = vtkIntArray::SafeDownCast(
|
||||||
output->GetPointData()->GetArray("isSurface"));
|
output->GetPointData()->GetArray("isSurface"));
|
||||||
std::set<vtkIdType> neighbors;
|
std::set<vtkIdType> neighbors;
|
@ -1,5 +1,5 @@
|
|||||||
#include "remove_external_cells_filter.h"
|
#include "remove_external_cells_filter.h"
|
||||||
#include "point_tris_dist.h"
|
#include "../point_tris_dist.h"
|
||||||
|
|
||||||
#include <vtkCellType.h>
|
#include <vtkCellType.h>
|
||||||
#include <vtkUnstructuredGrid.h>
|
#include <vtkUnstructuredGrid.h>
|
||||||
@ -60,6 +60,7 @@ vtkTypeBool RemoveExternalCellsFilter::RequestData(
|
|||||||
outCells->InsertNextCell(it->GetPointIds());
|
outCells->InsertNextCell(it->GetPointIds());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
it->Delete();
|
||||||
output->SetCells(VTK_TETRA, outCells);
|
output->SetCells(VTK_TETRA, outCells);
|
||||||
output->SetPoints(tetMesh->GetPoints());
|
output->SetPoints(tetMesh->GetPoints());
|
||||||
|
|
57
src/main.cc
@ -1,9 +1,9 @@
|
|||||||
#include "dihedral_angles_filter.h"
|
#include "analysis/dihedral_angles_filter.h"
|
||||||
#include "remove_external_cells_filter.h"
|
#include "analysis/max_distance_filter.h"
|
||||||
|
#include "fitting/remove_external_cells_filter.h"
|
||||||
|
#include "fitting/project_surface_points_on_poly.h"
|
||||||
|
#include "fitting/relaxation_filter.h"
|
||||||
#include "surface_points_filter.h"
|
#include "surface_points_filter.h"
|
||||||
#include "project_surface_points_on_poly.h"
|
|
||||||
#include "relaxation_filter.h"
|
|
||||||
#include "max_distance_filter.h"
|
|
||||||
|
|
||||||
#include <vtkGeometryFilter.h>
|
#include <vtkGeometryFilter.h>
|
||||||
#include <vtkCellArrayIterator.h>
|
#include <vtkCellArrayIterator.h>
|
||||||
@ -37,7 +37,7 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
|
|
||||||
vtkSmartPointer<vtkAlgorithm> readerFromFileName(const char *fileName) {
|
vtkAlgorithm *readerFromFileName(const char *fileName) {
|
||||||
std::string extension =
|
std::string extension =
|
||||||
vtksys::SystemTools::GetFilenameLastExtension(fileName);
|
vtksys::SystemTools::GetFilenameLastExtension(fileName);
|
||||||
if (extension == ".vtk") {
|
if (extension == ".vtk") {
|
||||||
@ -61,21 +61,39 @@ vtkSmartPointer<vtkAlgorithm> readerFromFileName(const char *fileName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void usage(char **argv) {
|
||||||
|
std::cerr << "Usage: " << argv[0] << " analyze|fit tetmesh polydata [radiusScale relaxationIterCount]" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
if (!(argc == 3 || argc == 5)) {
|
if (argc < 4) {
|
||||||
std::cerr << "Usage: " << argv[0] << " tetmesh polydata [radiusScale relaxationIterCount]" << std::endl;
|
usage(argv);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
bool fit = false;
|
||||||
|
if (std::string(argv[1]) == "fit") {
|
||||||
|
fit = true;
|
||||||
|
} else if (std::string(argv[1]) != "analyze") {
|
||||||
|
usage(argv);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
if ((fit && argc > 6) || (!fit && argc != 4)) {
|
||||||
|
usage(argv);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
double radiusScale = 2.;
|
double radiusScale = 2.;
|
||||||
int iterCount = 1;
|
int iterCount = 1;
|
||||||
if(argc > 3) {
|
if(argc > 4) {
|
||||||
radiusScale = std::stod(argv[3]);
|
radiusScale = std::stod(argv[4]);
|
||||||
iterCount = std::stoi(argv[4]);
|
}
|
||||||
|
if (argc > 5) {
|
||||||
|
iterCount = std::stoi(argv[5]);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto tetMeshReader = readerFromFileName(argv[1]);
|
auto tetMeshReader = readerFromFileName(argv[2]);
|
||||||
auto polyMeshReader = readerFromFileName(argv[2]);
|
auto polyMeshReader = readerFromFileName(argv[3]);
|
||||||
|
|
||||||
vtkNew<RemoveExternalCellsFilter> removeExternalCellsFilter;
|
vtkNew<RemoveExternalCellsFilter> removeExternalCellsFilter;
|
||||||
removeExternalCellsFilter->SetInputConnection(0,
|
removeExternalCellsFilter->SetInputConnection(0,
|
||||||
@ -97,8 +115,13 @@ int main(int argc, char **argv) {
|
|||||||
relaxationFilter->SetInputConnection(project->GetOutputPort());
|
relaxationFilter->SetInputConnection(project->GetOutputPort());
|
||||||
|
|
||||||
vtkNew<DihedralAnglesFilter> dihedralAnglesFilter;
|
vtkNew<DihedralAnglesFilter> dihedralAnglesFilter;
|
||||||
dihedralAnglesFilter->SetInputConnection(
|
if (fit) {
|
||||||
relaxationFilter->GetOutputPort());
|
dihedralAnglesFilter->SetInputConnection(
|
||||||
|
relaxationFilter->GetOutputPort());
|
||||||
|
} else {
|
||||||
|
dihedralAnglesFilter->SetInputConnection(
|
||||||
|
tetMeshReader->GetOutputPort());
|
||||||
|
}
|
||||||
|
|
||||||
vtkNew<vtkGeometryFilter> geometryFilter;
|
vtkNew<vtkGeometryFilter> geometryFilter;
|
||||||
geometryFilter->SetInputConnection(dihedralAnglesFilter->GetOutputPort());
|
geometryFilter->SetInputConnection(dihedralAnglesFilter->GetOutputPort());
|
||||||
@ -115,6 +138,8 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
maxDistanceFilter->Update();
|
maxDistanceFilter->Update();
|
||||||
std::cerr << "Max distance: " << maxDistanceFilter->GetMaxDist() << "\n"
|
std::cerr << "Max distance: " << maxDistanceFilter->GetMaxDist() << "\n"
|
||||||
|
<< "Max dist point id: " << maxDistanceFilter->GetMaxId()
|
||||||
|
<< " in " << (maxDistanceFilter->GetMaxInput() == 0 ? "tetMesh\n" : "polyMesh\n")
|
||||||
<< "Average min angle: " << dihedralAnglesFilter->GetAverageMinDegrees() << "\n"
|
<< "Average min angle: " << dihedralAnglesFilter->GetAverageMinDegrees() << "\n"
|
||||||
<< "Min min angle: " << dihedralAnglesFilter->GetMinMinDegrees() << "\n";
|
<< "Min min angle: " << dihedralAnglesFilter->GetMinMinDegrees() << "\n";
|
||||||
|
|
||||||
@ -148,5 +173,7 @@ int main(int argc, char **argv) {
|
|||||||
renderWindow->Render();
|
renderWindow->Render();
|
||||||
renderWindowInteractor->Start();
|
renderWindowInteractor->Start();
|
||||||
#endif
|
#endif
|
||||||
|
tetMeshReader->Delete();
|
||||||
|
polyMeshReader->Delete();
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
#include <vtkStaticCellLinks.h>
|
#include <vtkStaticCellLinks.h>
|
||||||
#include <vtkIntArray.h>
|
#include <vtkIntArray.h>
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
vtkStandardNewMacro(SurfacePointsFilter);
|
vtkStandardNewMacro(SurfacePointsFilter);
|
||||||
@ -32,7 +34,7 @@ vtkTypeBool SurfacePointsFilter::RequestData(
|
|||||||
|
|
||||||
/* Create an array to store the IDs of surface points. */
|
/* Create an array to store the IDs of surface points. */
|
||||||
vtkNew<vtkIdTypeArray> surfacePoints;
|
vtkNew<vtkIdTypeArray> surfacePoints;
|
||||||
surfacePoints->SetName("surface_points");
|
surfacePoints->SetName("surfacePoints");
|
||||||
surfacePoints->SetNumberOfComponents(1);
|
surfacePoints->SetNumberOfComponents(1);
|
||||||
vtkNew<vtkIntArray> isSurface;
|
vtkNew<vtkIntArray> isSurface;
|
||||||
isSurface->SetName("isSurface");
|
isSurface->SetName("isSurface");
|
||||||
@ -46,6 +48,7 @@ vtkTypeBool SurfacePointsFilter::RequestData(
|
|||||||
|
|
||||||
vtkNew<vtkIdList> neighborCells;
|
vtkNew<vtkIdList> neighborCells;
|
||||||
vtkNew<vtkIdList> facePoints;
|
vtkNew<vtkIdList> facePoints;
|
||||||
|
std::set<vtkIdType> surfacePointsSet;
|
||||||
auto *it = input->NewCellIterator();
|
auto *it = input->NewCellIterator();
|
||||||
for (it->InitTraversal(); !it->IsDoneWithTraversal(); it->GoToNextCell()) {
|
for (it->InitTraversal(); !it->IsDoneWithTraversal(); it->GoToNextCell()) {
|
||||||
vtkIdList *cellPointIds = it->GetPointIds();
|
vtkIdList *cellPointIds = it->GetPointIds();
|
||||||
@ -60,15 +63,20 @@ vtkTypeBool SurfacePointsFilter::RequestData(
|
|||||||
neighborCells);
|
neighborCells);
|
||||||
facePoints->Reset();
|
facePoints->Reset();
|
||||||
if (neighborCells->GetNumberOfIds() == 0) {
|
if (neighborCells->GetNumberOfIds() == 0) {
|
||||||
surfacePoints->InsertNextValue(idA);
|
surfacePointsSet.insert(idA);
|
||||||
surfacePoints->InsertNextValue(idB);
|
surfacePointsSet.insert(idB);
|
||||||
surfacePoints->InsertNextValue(idC);
|
surfacePointsSet.insert(idC);
|
||||||
isSurface->SetValue(idA, 1);
|
isSurface->SetValue(idA, 1);
|
||||||
isSurface->SetValue(idB, 1);
|
isSurface->SetValue(idB, 1);
|
||||||
isSurface->SetValue(idC, 1);
|
isSurface->SetValue(idC, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
it->Delete();
|
||||||
|
surfacePoints->Allocate(surfacePointsSet.size());
|
||||||
|
for (const vtkIdType &id : surfacePointsSet) {
|
||||||
|
surfacePoints->InsertNextValue(id);
|
||||||
|
}
|
||||||
|
|
||||||
output->GetPointData()->SetScalars(isSurface);
|
output->GetPointData()->SetScalars(isSurface);
|
||||||
output->GetFieldData()->AddArray(surfacePoints);
|
output->GetFieldData()->AddArray(surfacePoints);
|
||||||
|