/*************************************/
/* Auteur : Rémi Synave */
/* Date de création : 01/03/07 */
/* Date de modification : 15/03/15 */
/* Version : 0.4 */
/*************************************/
/*************************************/
/* Auteur : Romain Leguay */
/* Nguyen Haiduong */
/* Marianne Fichoux */
/* Date de modification : 26/05/09 */
/* Version : 0.2 */
/*************************************/
/***************************************************************************/
/* This file is part of a2ri. */
/* */
/* a2ri is free software: you can redistribute it and/or modify it */
/* under the terms of the GNU Lesser General Public License as published */
/* by the Free Software Foundation, either version 3 of the License, or */
/* (at your option) any later version. */
/* */
/* a2ri is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU Lesser General Public License for more details. */
/* */
/* You should have received a copy of the GNU Lesser General Public */
/* License along with a2ri. */
/* If not, see . */
/***************************************************************************/
#include "model.h"
/********** INTERMEDIATE TYPES AND FUNCTIONS **********/
/* Les fonctions intermédiaires sont préfixées de IF */
/* et les types intermédiaires de IT */
/********** MAIN FUNCTIONS **********/
/**
Initialisation d'un modèle avec un maillage vide
@param m pointeur sur le modèle
@return aucun
*/
void
a2ri_vf_init (
vf_model * m)
{
m->ve = NULL;
m->fa = NULL;
m->nbvertex = 0;
m->nbface = 0;
}
/**
Libération de l'espace mémoire utilisé
@param m pointeur sur le modèle
*/
void
a2ri_vf_free (
vf_model * m)
{
for (int i = 0; i < m->nbvertex; i++)
free (m->ve[i].incidentvertices);
free (m->ve);
free (m->fa);
}
/**
Clonage du vf_model
@param m pointeur sur le modèle
@return un vf_model identique
*/
vf_model *
a2ri_vf_clone (
const vf_model * const m)
{
vf_model *retour = (vf_model *) malloc (sizeof (vf_model));
a2ri_vf_init (retour);
retour->xmin = m->xmin;
retour->xmax = m->xmax;
retour->ymin = m->ymin;
retour->ymax = m->ymax;
retour->zmin = m->zmin;
retour->zmax = m->zmax;
for (int i = 0; i < m->nbvertex; i++)
{
a2ri_vf_add_vertex (retour, m->ve[i].x, m->ve[i].y, m->ve[i].z);
retour->ve[i].incidentvertices = NULL;
list_int_clone (m->ve[i].incidentvertices, m->ve[i].nbincidentvertices,
&(retour->ve[i].incidentvertices));
retour->ve[i].nbincidentvertices = m->ve[i].nbincidentvertices;
}
for (int i = 0; i < m->nbface; i++)
{
a2ri_vf_add_face (retour, m->fa[i].ve1, m->fa[i].ve2, m->fa[i].ve3);
}
return retour;
}
/**
//affichage des caractéristiques générales d'un modèle (nombre de sommets et de faces)
@param m le modèle
@return aucun
*/
void
a2ri_vf_display (
const vf_model * const m)
{
printf ("********************\nModel :");
printf ("\n\t%d vertices\n", m->nbvertex);
printf ("\t%d faces\n", m->nbface);
printf
("Bounding Box : [%4.2f , %4.2f , %4.2f] - [%4.2f , %4.2f , %4.2f]\n",
m->xmin, m->ymin, m->zmin, m->xmax, m->ymax, m->zmax);
printf ("********************\n");
}
/**
//affichage des caractéristiques détaillées d'un modèle (nombre de sommets, de faces et leurs adjacences)
@param m le modèle
@return aucun
*/
void
a2ri_vf_display_detail (
const vf_model * const m)
{
int i;
printf ("********************\nModel :");
if (m->nbvertex)
{
printf ("\n\t%d vertices\n", m->nbvertex);
for (i = 0; i < m->nbvertex; i++)
{
printf ("\t\t%5d - ", i);
vf_vertex_display_detail (&(m->ve[i]));
printf ("\n");
}
}
if (m->nbface)
{
printf ("\n\t%d faces\n", m->nbface);
for (i = 0; i < m->nbface; i++)
{
printf ("\t\t%5d - (%d , %d , %d) ",
i, m->fa[i].ve1, m->fa[i].ve2, m->fa[i].ve3);
printf ("\n\n");
}
}
printf
("\nBounding Box : [%4.2f , %4.2f , %4.2f] - [%4.2f , %4.2f , %4.2f]\n",
m->xmin, m->ymin, m->zmin, m->xmax, m->ymax, m->zmax);
printf ("********************\n");
}
/**
mis à jour du numéro d'arete en fonction de la taille de la table de hachage
@param e arete à mettre à jour
@param m le modele - parametre inutilisé
@param table la table de hachage
@return aucun
*/
/**
@TODO
*/
/*void
a2ri_vf_update_num_edge (
vf_edge * e,
const vf_model * const m,
const hashtable * const table)
{
vf_model *temp;
temp = m;
e->att_int = hashtable_size (table);
}*/
/**
mis à jour de la longueur de l'arete
@param e arete à mettre à jour
@param m le modele
@param table la table de hachage - parametre inutilisé
@return aucun
*/
void
a2ri_vf_update_length_edge (
vf_edge * e,
const vf_model * const m,
hashtable * table)
{
point3d p1,
p2;
point3d_init (&p1, m->ve[e->ve1].x, m->ve[e->ve1].y, m->ve[e->ve1].z);
point3d_init (&p2, m->ve[e->ve2].x, m->ve[e->ve2].y, m->ve[e->ve2].z);
e->att_double = point3d_length (&p1, &p2);
}
/**
Construction de la table de hachage contenant toutes les aretes d'un vf_model
@param m le modele
@param func tableau de fonctions devant etre appliqué
@param nbfunc taille du tableau de fonctions
@return la table de hachage
*/
hashtable *
a2ri_vf_construction_edge_table (
const vf_model * const m,
ptf_func_hashtable * func,
int nbfunc)
{
int p1,
p2;
hashtable *table = hashtable_new (m->nbvertex + m->nbface);
a2ri_erreur_critique_si(table==NULL,
"erreur allocation memoire pour table dans a2ri_vf_construction_edge_table\n");
for (int i = 0; i < m->nbface; i++)
{
p1 = m->fa[i].ve1;
p2 = m->fa[i].ve2;
vf_edge *edgetemp = hashtable_look_for (table, p1, p2);
if (edgetemp == NULL)
{
edgetemp = (vf_edge *) malloc (sizeof (vf_edge));
a2ri_erreur_critique_si (edgetemp == NULL,
"erreur allocation memoire pour edgetemp\na2ri_vf_construction_edge_table");
edgetemp->ve1 = p1;
edgetemp->ve2 = p2;
edgetemp->att_int = -1;
edgetemp->att_double = -1;
for (int j = 0; j < nbfunc; j++)
func[j] (edgetemp, m, table);
edgetemp->nbsharedfaces = 0;
edgetemp->sharedfaces = NULL;
list_int_add (&(edgetemp->sharedfaces), &(edgetemp->nbsharedfaces),
i, WITH_REDUNDANCE);
hashtable_add (table, edgetemp);
}
else
list_int_add (&(edgetemp->sharedfaces), &(edgetemp->nbsharedfaces), i,
WITH_REDUNDANCE);
p1 = m->fa[i].ve2;
p2 = m->fa[i].ve3;
edgetemp = hashtable_look_for (table, p1, p2);
if (edgetemp == NULL)
{
edgetemp = (vf_edge *) malloc (sizeof (vf_edge));
a2ri_erreur_critique_si (edgetemp == NULL,
"erreur allocation memoire pour edgetemp\na2ri_vf_construction_edge_table");
edgetemp->ve1 = p1;
edgetemp->ve2 = p2;
edgetemp->att_int = -1;
edgetemp->att_double = -1;
for (int j = 0; j < nbfunc; j++)
func[j] (edgetemp, m, table);
edgetemp->nbsharedfaces = 0;
edgetemp->sharedfaces = NULL;
list_int_add (&(edgetemp->sharedfaces), &(edgetemp->nbsharedfaces),
i, WITH_REDUNDANCE);
hashtable_add (table, edgetemp);
}
else
list_int_add (&(edgetemp->sharedfaces), &(edgetemp->nbsharedfaces), i,
WITH_REDUNDANCE);
p1 = m->fa[i].ve3;
p2 = m->fa[i].ve1;
edgetemp = hashtable_look_for (table, p1, p2);
if (edgetemp == NULL)
{
edgetemp = (vf_edge *) malloc (sizeof (vf_edge));
a2ri_erreur_critique_si (edgetemp == NULL,
"erreur allocation memoire pour edgetemp\na2ri_vf_construction_edge_table");
edgetemp->ve1 = p1;
edgetemp->ve2 = p2;
edgetemp->att_int = -1;
edgetemp->att_double = -1;
for (int j = 0; j < nbfunc; j++)
func[j] (edgetemp, m, table);
edgetemp->nbsharedfaces = 0;
edgetemp->sharedfaces = NULL;
list_int_add (&(edgetemp->sharedfaces), &(edgetemp->nbsharedfaces),
i, WITH_REDUNDANCE);
hashtable_add (table, edgetemp);
}
else
list_int_add (&(edgetemp->sharedfaces), &(edgetemp->nbsharedfaces), i,
WITH_REDUNDANCE);
}
return table;
}
/**
Ajout d'un vertex (x,y,z) au modèle
@param m pointeur sur le modèle
@param x coordonnée x du vertex
@param y coordonnée y
@param z coordonnée z
@return 1 si succès, 0 sinon
*/
int
a2ri_vf_add_vertex (
vf_model * m,
double x,
double y,
double z)
{
if (m->ve == NULL)
{
m->ve = (vf_vertex *) malloc (sizeof (vf_vertex));
a2ri_erreur_critique_si (m->ve == NULL,
"erreur allocation memoire pour m->ve\na2ri_vf_add_vertex");
}
else
{
vf_vertex *tempve;
tempve =
(vf_vertex *) realloc (m->ve, (m->nbvertex + 1) * sizeof (vf_vertex));
a2ri_erreur_critique_si (tempve == NULL,
"erreur allocation memoire pour m->ve\na2ri_vf_add_vertex");
m->ve=tempve;
}
m->ve[m->nbvertex].x = x;
m->ve[m->nbvertex].y = y;
m->ve[m->nbvertex].z = z;
m->ve[m->nbvertex].incidentvertices = NULL;
m->ve[m->nbvertex].nbincidentvertices = 0;
(m->nbvertex)++;
return 1;
}
/**
Recherche d'un vertex dans un modèle
@param m le modèle
@param x coordonnée x du vertex à rechercher
@param y coordonnée y
@param z coordonnée z
@return numéro du vertex dans la liste de vertex du modèle, -1 si le vertex n'est pas trouvé.
*/
int
a2ri_vf_search_vertex (
const vf_model * const m,
double x,
double y,
double z)
{
int i;
for (i = 0; i < m->nbvertex; i++)
if (m->ve[i].x == x && m->ve[i].y == y && m->ve[i].z == z)
return i;
return -1;
}
/**
Retrait d'un sommet du modèle. L'opération ne peut être effectué que si le sommet n'est référencée dans aucune face.
@param m le modèle
@param numvertex numèro du vertex à retirer
@return 1 si succès, 0 sinon
*/
int
a2ri_vf_remove_vertex (
vf_model * m,
int numvertex)
{
int j,
*list1 = NULL,
size1 = 0;
vf_vertex *tempve;
if (m->fa == NULL)
{
//si numvertex est plus grand que le nombre de sommet
if (numvertex > m->nbvertex)
return 0;
//si le sommet est encore présent (utilisé) dans une face, on ne peut pas le supprimer
for (int i = 0; i < m->nbface; i++)
if (m->fa[i].ve1 == numvertex || m->fa[i].ve2 == numvertex
|| m->fa[i].ve3 == numvertex)
return 0;
//décalage de la liste de sommet
for (int i = numvertex; i < (m->nbvertex) - 1; i++)
{
m->ve[i].x = m->ve[i + 1].x;
m->ve[i].y = m->ve[i + 1].y;
m->ve[i].z = m->ve[i + 1].z;
m->ve[i].incidentvertices = m->ve[i + 1].incidentvertices;
m->ve[i].nbincidentvertices = m->ve[i + 1].nbincidentvertices;
}
tempve =
(vf_vertex *) realloc (m->ve,
((m->nbvertex) - 1) * sizeof (vf_vertex));
a2ri_erreur_critique_si (tempve == NULL,
"erreur allocation memoire pour m->ve\na2ri_vf_remove_vertex");
m->ve=tempve;
m->nbvertex = m->nbvertex - 1;
//suppression du vertex dans les sommets incidents et décalages pour les valeurs supérieurs à numvertex
for (int i = 0; i < m->nbvertex; i++)
{
j = 0;
while (j < m->ve[i].nbincidentvertices)
{
if (m->ve[i].incidentvertices[j] == numvertex)
list_int_remove (&(m->ve[i].incidentvertices),
&(m->ve[i].nbincidentvertices), j);
else
{
if (m->ve[i].incidentvertices[j] > numvertex)
m->ve[i].incidentvertices[j]--;
j++;
}
}
}
}
else
{
if (m->ve[numvertex].nbincidentvertices == 0)
{
//décalage de la liste de sommet
for (int i = numvertex; i < (m->nbvertex) - 1; i++)
{
m->ve[i].x = m->ve[i + 1].x;
m->ve[i].y = m->ve[i + 1].y;
m->ve[i].z = m->ve[i + 1].z;
m->ve[i].incidentvertices = m->ve[i + 1].incidentvertices;
m->ve[i].nbincidentvertices = m->ve[i + 1].nbincidentvertices;
}
tempve =
(vf_vertex *) realloc (m->ve,
((m->nbvertex) - 1) * sizeof (vf_vertex));
a2ri_erreur_critique_si (tempve == NULL,
"erreur allocation memoire pour m->ve\na2ri_vf_remove_vertex");
m->ve=tempve;
m->nbvertex = m->nbvertex - 1;
for (int i = 0; i < m->nbface; i++)
{
if (m->fa[i].ve1 >= numvertex)
m->fa[i].ve1 = m->fa[i].ve1 - 1;
if (m->fa[i].ve2 >= numvertex)
m->fa[i].ve2 = m->fa[i].ve2 - 1;
if (m->fa[i].ve3 >= numvertex)
m->fa[i].ve3 = m->fa[i].ve3 - 1;
}
}
else
{
for (int i = 0; i < m->nbface; i++)
if (m->fa[i].ve1 == numvertex || m->fa[i].ve2 == numvertex
|| m->fa[i].ve3 == numvertex)
list_int_add (&list1, &size1, i, WITH_REDUNDANCE);
list_int_sort (list1, size1, DESC);
for (int i = 0; i < size1; i++)
a2ri_vf_remove_face (m, list1[i]);
free (list1);
}
}
return 1;
}
/**
Retrait d'une liste de sommets du modèle. L'opération ne peut être effectué que si le sommet n'est référencée dans aucune face.
@param m le modèle
@param numvertex numèro du vertex à retirer
@return 1 si succès, 0 sinon
*/
int
a2ri_vf_remove_list_of_vertex (
vf_model * m,
int *listvertex,
int sizelist)
{
int *list1 = NULL,
size1 = 0;
if (m->fa == NULL)
{
list_int_sort (listvertex, sizelist, DESC);
for (int i = 0; i < sizelist; i++)
a2ri_vf_remove_vertex (m, listvertex[i]);
}
else
{
for (int i = 0; i < sizelist; i++)
for (int j = 0; j < m->nbface; j++)
if (m->fa[j].ve1 == listvertex[i]
|| m->fa[j].ve2 == listvertex[i]
|| m->fa[j].ve3 == listvertex[i])
list_int_add (&list1, &size1, j, WITHOUT_REDUNDANCE);
list_int_sort (list1, size1, DESC);
for (int i = 0; i < size1; i++)
a2ri_vf_remove_face (m, list1[i]);
free (list1);
}
return 1;
}
/**
Ajout d'une face défini par trois points (numéros d'index dans la liste de points) au modèle
@param m pointeur sur le modèle
@param ve1 index du premier point
@param ve2 index du second point
@param ve3 index du troisième point
@return 1 si succès, 0 sinon
*/
int
a2ri_vf_add_face (
vf_model * m,
int ve1,
int ve2,
int ve3)
{
if (m->fa == NULL)
{
m->fa = (vf_face *) malloc (sizeof (vf_face));
a2ri_erreur_critique_si (m->fa == NULL,
"erreur allocation memoire pour m->fa\na2ri_vf_add_face");
}
else
{
vf_face *tempfa;
tempfa = (vf_face *) realloc (m->fa, (m->nbface + 1) * sizeof (vf_face));
a2ri_erreur_critique_si (tempfa == NULL,
"erreur allocation memoire pour m->fa\na2ri_vf_add_face");
m->fa=tempfa;
}
m->fa[m->nbface].ve1 = ve1;
m->fa[m->nbface].ve2 = ve2;
m->fa[m->nbface].ve3 = ve3;
list_int_add (&(m->ve[ve1].incidentvertices),
&(m->ve[ve1].nbincidentvertices), ve2, WITHOUT_REDUNDANCE);
list_int_add (&(m->ve[ve2].incidentvertices),
&(m->ve[ve2].nbincidentvertices), ve1, WITHOUT_REDUNDANCE);
list_int_add (&(m->ve[ve1].incidentvertices),
&(m->ve[ve1].nbincidentvertices), ve3, WITHOUT_REDUNDANCE);
list_int_add (&(m->ve[ve3].incidentvertices),
&(m->ve[ve3].nbincidentvertices), ve1, WITHOUT_REDUNDANCE);
list_int_add (&(m->ve[ve3].incidentvertices),
&(m->ve[ve3].nbincidentvertices), ve2, WITHOUT_REDUNDANCE);
list_int_add (&(m->ve[ve2].incidentvertices),
&(m->ve[ve2].nbincidentvertices), ve3, WITHOUT_REDUNDANCE);
(m->nbface)++;
return 1;
}
/**
Recherche d'une face dans un modèle
@param m le modèle
@param ve1 index d'un point
@param ve2 index d'un point
@param ve3 index d'un point
@return numéro de la face dans la liste de face du modèle, -1 si la face n'est pas trouvée.
@warning Cette fonction est sensible à l'orientation de la face.
Exemple pour un modèle m:
@code
liste de faces (index -> ve1 ve2 ve3):
0 -> 0 1 2
1 -> 0 2 3
2 -> 0 3 1
3 -> 1 3 2
@endcode
le code
@code
a2ri_vf_search_face(m,0,3,1);
ou
a2ri_vf_search_face(m,3,1,0);
ou
a2ri_vf_search_face(m,1,0,3);
@endcode
retournera 2 alors que
@code
a2ri_vf_search_face(m,3,0,1);
@endcode
retournera -1
*/
int
a2ri_vf_search_face (
const vf_model * const m,
int ve1,
int ve2,
int ve3)
{
for (int i = 0; i < m->nbface; i++)
{
if (m->fa[i].ve1 == ve1)
if ((m->fa[i].ve2 == ve2 && m->fa[i].ve3 == ve3))
return i;
if (m->fa[i].ve1 == ve2)
if ((m->fa[i].ve2 == ve3 && m->fa[i].ve3 == ve1))
return i;
if (m->fa[i].ve1 == ve3)
if ((m->fa[i].ve2 == ve1 && m->fa[i].ve3 == ve2))
return i;
}
return -1;
}
/**
Retrait d'une face du modèle. La fonction enlève également les sommets qui ne sont plus utilisés.
@param m le modèle
@param numface numèro de la face à retirer
@return 1 si succès, 0 sinon
*/
int
a2ri_vf_remove_face (
vf_model * m,
int numface)
{
int ve[3],
k;
vf_face *tempfa;
vf_vertex *tempve;
//le numero de la face est supérieur au nombre de faces du modèle
if (numface > m->nbface)
return 0;
//on récupére les numéros des sommets pour ensuite essayer de les supprimer
ve[0] = m->fa[numface].ve1;
ve[1] = m->fa[numface].ve2;
ve[2] = m->fa[numface].ve3;
list_int_sort (ve, 3, DESC);
//décalage des faces
for (int i = numface; i < (m->nbface) - 1; i++)
{
m->fa[i].ve1 = m->fa[i + 1].ve1;
m->fa[i].ve2 = m->fa[i + 1].ve2;
m->fa[i].ve3 = m->fa[i + 1].ve3;
}
tempfa =
(vf_face *) realloc (m->fa, ((m->nbface) - 1) * sizeof (vf_face));
a2ri_erreur_critique_si (tempfa == NULL,
"erreur allocation memoire pour m->fa\na2ri_vf_remove_face");
m->fa=tempfa;
m->nbface = m->nbface - 1;
//on essaye de supprimer les trois sommets
/****************************/
for (int i = 0; i < 3; i++)
{
int numvertex = ve[i];
//si le sommet est encore présent (utilisé) dans une face, on ne peut pas le supprime
k = 0;
for (int j = 0; j < m->nbface; j++)
if (m->fa[j].ve1 == numvertex || m->fa[j].ve2 == numvertex
|| m->fa[j].ve3 == numvertex)
k++;
if (!k)
{
free (m->ve[numvertex].incidentvertices);
//décalage de la liste de sommet
for (int j = numvertex; j < (m->nbvertex) - 1; j++)
{
m->ve[j].x = m->ve[j + 1].x;
m->ve[j].y = m->ve[j + 1].y;
m->ve[j].z = m->ve[j + 1].z;
m->ve[j].incidentvertices = m->ve[j + 1].incidentvertices;
m->ve[j].nbincidentvertices =
m->ve[j + 1].nbincidentvertices;
}
tempve =
(vf_vertex *) realloc (m->ve,
((m->nbvertex) -
1) * sizeof (vf_vertex));
a2ri_erreur_critique_si (tempve == NULL,
"erreur allocation memoire pour m->ve\na2ri_vf_remove_face");
m->ve=tempve;
m->nbvertex = m->nbvertex - 1;
//suppression du vertex dans les sommets incidents et décalages pour les valeurs supérieurs à numvertex
for (int j = 0; j < m->nbvertex; j++)
{
k = 0;
while (k < m->ve[j].nbincidentvertices)
{
if (m->ve[j].incidentvertices[k] == numvertex)
list_int_remove (&(m->ve[j].incidentvertices),
&(m->ve[j].nbincidentvertices), k);
else
{
if (m->ve[j].incidentvertices[k] > numvertex)
m->ve[j].incidentvertices[k]--;
k++;
}
}
}
//mis à jour des numéro de sommet dans les faces
for (int j = 0; j < m->nbface; j++)
{
if (m->fa[j].ve1 > numvertex)
m->fa[j].ve1 = m->fa[j].ve1 - 1;
if (m->fa[j].ve2 > numvertex)
m->fa[j].ve2 = m->fa[j].ve2 - 1;
if (m->fa[j].ve3 > numvertex)
m->fa[j].ve3 = m->fa[j].ve3 - 1;
}
}
}
/****************************/
return 1;
}
/**
Retrait d'une liste de faces du modèle. La fonction enlève également les sommets qui ne sont plus utilisés.
@param m le modèle
@param numface numèro de la face à retirer
@return 1 si succès, 0 sinon
*/
int
a2ri_vf_remove_list_of_face (
vf_model * m,
int *listface,
int sizelist)
{
list_int_sort (listface, sizelist, DESC);
for (int i = 0; i < sizelist; i++)
a2ri_vf_remove_face (m, listface[i]);
return 1;
}
/**
Translation du modèle
@param m pointeur sur le modèle à translater
@param delta pointeur sur le vecteur de translation
@return aucun
*/
void
a2ri_vf_translate (
vf_model * m,
const vector3d * const delta)
{
//translation de tous les sommets
for (int i = 0; i < m->nbvertex; i++)
vf_vertex_translate (&((*m).ve[i]), delta);
//translation de la bounding box
m->xmin += delta->dx;
m->xmax += delta->dx;
m->ymin += delta->dy;
m->ymax += delta->dy;
m->zmin += delta->dz;
m->zmax += delta->dz;
}
/**
Translation d'un modele afin qu'il se trouve centré sur l'origine (0,0,0)
@param m le modele a centrer
@return aucun
**/
void
a2ri_vf_center (
vf_model * m)
{
vector3d delta;
vector3d_init (&delta, -((m->xmin + m->xmax)) / 2.0,
-((m->ymin + m->ymax) / 2.0), -((m->zmin + m->zmax) / 2.0));
a2ri_vf_translate (m, &delta);
}
/**
Rotation d'un modèle en radian autour de l'axe X
@param v pointeur sur le modèle
@param angle angle de rotation du modèle en radian
@return aucun
*/
void
a2ri_vf_rotateX_radian (
vf_model * m,
double angle)
{
//rotation de tous les sommets
for (int i = 0; i < m->nbvertex; i++)
{
vf_vertex_rotateX_radian (&(m->ve[i]), angle);
//mis à jour de la bounding box
if (i == 0)
{
m->xmin = m->ve[i].x;
m->xmax = m->ve[i].x;
m->ymin = m->ve[i].y;
m->ymax = m->ve[i].y;
m->zmin = m->ve[i].z;
m->zmax = m->ve[i].z;
}
else
{
if (m->xmin > m->ve[i].x)
m->xmin = m->ve[i].x;
if (m->xmax < m->ve[i].x)
m->xmax = m->ve[i].x;
if (m->ymin > m->ve[i].y)
m->ymin = m->ve[i].y;
if (m->ymax < m->ve[i].y)
m->ymax = m->ve[i].y;
if (m->zmin > m->ve[i].z)
m->zmin = m->ve[i].z;
if (m->zmax < m->ve[i].z)
m->zmax = m->ve[i].z;
}
}
}
/**
Rotation d'un modèle en degré autour de l'axe X
@param v pointeur sur le modèle
@param angle angle de rotation du modèle en degré
@return aucun
*/
void
a2ri_vf_rotateX_degre (
vf_model * m,
double angle)
{
//rotation de tous les sommets
for (int i = 0; i < m->nbvertex; i++)
{
vf_vertex_rotateX_degre (&(m->ve[i]), angle);
//mis à jour de la bounding box
if (i == 0)
{
m->xmin = m->ve[i].x;
m->xmax = m->ve[i].x;
m->ymin = m->ve[i].y;
m->ymax = m->ve[i].y;
m->zmin = m->ve[i].z;
m->zmax = m->ve[i].z;
}
else
{
if (m->xmin > m->ve[i].x)
m->xmin = m->ve[i].x;
if (m->xmax < m->ve[i].x)
m->xmax = m->ve[i].x;
if (m->ymin > m->ve[i].y)
m->ymin = m->ve[i].y;
if (m->ymax < m->ve[i].y)
m->ymax = m->ve[i].y;
if (m->zmin > m->ve[i].z)
m->zmin = m->ve[i].z;
if (m->zmax < m->ve[i].z)
m->zmax = m->ve[i].z;
}
}
}
/**
Rotation d'un modèle en radian suivant l'axe X de centre (cx,cy,cz)
@param v pointeur sur le modèle
@param angle angle de rotation du modèle en radian
@param centre pointeur sur le point3d servant de centre à la rotation
@return aucun
*/
void
a2ri_vf_rotateX_radian_center (
vf_model * m,
double angle,
const point3d * const centre)
{
//rotation de tous les sommets
for (int i = 0; i < m->nbvertex; i++)
{
vf_vertex_rotateX_center_radian (&(m->ve[i]), angle, centre);
//mis à jour de la bounding box
if (i == 0)
{
m->xmin = m->ve[i].x;
m->xmax = m->ve[i].x;
m->ymin = m->ve[i].y;
m->ymax = m->ve[i].y;
m->zmin = m->ve[i].z;
m->zmax = m->ve[i].z;
}
else
{
if (m->xmin > m->ve[i].x)
m->xmin = m->ve[i].x;
if (m->xmax < m->ve[i].x)
m->xmax = m->ve[i].x;
if (m->ymin > m->ve[i].y)
m->ymin = m->ve[i].y;
if (m->ymax < m->ve[i].y)
m->ymax = m->ve[i].y;
if (m->zmin > m->ve[i].z)
m->zmin = m->ve[i].z;
if (m->zmax < m->ve[i].z)
m->zmax = m->ve[i].z;
}
}
}
/**
Rotation d'un modèle en degre suivant l'axe X de centre (cx,cy,cz)
@param v pointeur sur le modèle
@param angle angle de rotation du modèle en degre
@param centre pointeur sur le point3d servant de centre à la rotation
@return aucun
*/
void
a2ri_vf_rotateX_degre_center (
vf_model * m,
double angle,
const point3d * const centre)
{
//rotation de tous les sommets
for (int i = 0; i < m->nbvertex; i++)
{
vf_vertex_rotateX_center_degre (&(m->ve[i]), angle, centre);
//mis à jour de la bounding box
if (i == 0)
{
m->xmin = m->ve[i].x;
m->xmax = m->ve[i].x;
m->ymin = m->ve[i].y;
m->ymax = m->ve[i].y;
m->zmin = m->ve[i].z;
m->zmax = m->ve[i].z;
}
else
{
if (m->xmin > m->ve[i].x)
m->xmin = m->ve[i].x;
if (m->xmax < m->ve[i].x)
m->xmax = m->ve[i].x;
if (m->ymin > m->ve[i].y)
m->ymin = m->ve[i].y;
if (m->ymax < m->ve[i].y)
m->ymax = m->ve[i].y;
if (m->zmin > m->ve[i].z)
m->zmin = m->ve[i].z;
if (m->zmax < m->ve[i].z)
m->zmax = m->ve[i].z;
}
}
}
/**
Rotation d'un modèle en radian autour de l'axe Y
@param v pointeur sur le modèle
@param angle angle de rotation du modèle en radian
@return aucun
*/
void
a2ri_vf_rotateY_radian (
vf_model * m,
double angle)
{
//rotation de tous les sommets
for (int i = 0; i < m->nbvertex; i++)
{
vf_vertex_rotateY_radian (&(m->ve[i]), angle);
//mis à jour de la bounding box
if (i == 0)
{
m->xmin = m->ve[i].x;
m->xmax = m->ve[i].x;
m->ymin = m->ve[i].y;
m->ymax = m->ve[i].y;
m->zmin = m->ve[i].z;
m->zmax = m->ve[i].z;
}
else
{
if (m->xmin > m->ve[i].x)
m->xmin = m->ve[i].x;
if (m->xmax < m->ve[i].x)
m->xmax = m->ve[i].x;
if (m->ymin > m->ve[i].y)
m->ymin = m->ve[i].y;
if (m->ymax < m->ve[i].y)
m->ymax = m->ve[i].y;
if (m->zmin > m->ve[i].z)
m->zmin = m->ve[i].z;
if (m->zmax < m->ve[i].z)
m->zmax = m->ve[i].z;
}
}
}
/**
Rotation d'un modèle en degré autour de l'axe Y
@param v pointeur sur le modèle
@param angle angle de rotation du modèle en degré
@return aucun
*/
void
a2ri_vf_rotateY_degre (
vf_model * m,
double angle)
{
//rotation de tous les sommets
for (int i = 0; i < m->nbvertex; i++)
{
vf_vertex_rotateY_degre (&(m->ve[i]), angle);
//mis à jour de la bounding box
if (i == 0)
{
m->xmin = m->ve[i].x;
m->xmax = m->ve[i].x;
m->ymin = m->ve[i].y;
m->ymax = m->ve[i].y;
m->zmin = m->ve[i].z;
m->zmax = m->ve[i].z;
}
else
{
if (m->xmin > m->ve[i].x)
m->xmin = m->ve[i].x;
if (m->xmax < m->ve[i].x)
m->xmax = m->ve[i].x;
if (m->ymin > m->ve[i].y)
m->ymin = m->ve[i].y;
if (m->ymax < m->ve[i].y)
m->ymax = m->ve[i].y;
if (m->zmin > m->ve[i].z)
m->zmin = m->ve[i].z;
if (m->zmax < m->ve[i].z)
m->zmax = m->ve[i].z;
}
}
}
/**
Rotation d'un modèle en radian suivant l'axe Y de centre (cx,cy,cz)
@param v pointeur sur le modèle
@param angle angle de rotation du modèle en radian
@param centre pointeur sur le point3d servant de centre à la rotation
@return aucun
*/
void
a2ri_vf_rotateY_radian_center (
vf_model * m,
double angle,
const point3d * const centre)
{
//rotation de tous les sommets
for (int i = 0; i < m->nbvertex; i++)
{
vf_vertex_rotateY_center_radian (&(m->ve[i]), angle, centre);
//mis à jour de la bounding box
if (i == 0)
{
m->xmin = m->ve[i].x;
m->xmax = m->ve[i].x;
m->ymin = m->ve[i].y;
m->ymax = m->ve[i].y;
m->zmin = m->ve[i].z;
m->zmax = m->ve[i].z;
}
else
{
if (m->xmin > m->ve[i].x)
m->xmin = m->ve[i].x;
if (m->xmax < m->ve[i].x)
m->xmax = m->ve[i].x;
if (m->ymin > m->ve[i].y)
m->ymin = m->ve[i].y;
if (m->ymax < m->ve[i].y)
m->ymax = m->ve[i].y;
if (m->zmin > m->ve[i].z)
m->zmin = m->ve[i].z;
if (m->zmax < m->ve[i].z)
m->zmax = m->ve[i].z;
}
}
}
/**
Rotation d'un modèle en degre suivant l'axe Y de centre (cx,cy,cz)
@param v pointeur sur le modèle
@param angle angle de rotation du modèle en degre
@param centre pointeur sur le point3d servant de centre à la rotation
@return aucun
*/
void
a2ri_vf_rotateY_degre_center (
vf_model * m,
double angle,
const point3d * const centre)
{
//rotation de tous les sommets
for (int i = 0; i < m->nbvertex; i++)
{
vf_vertex_rotateY_center_degre (&(m->ve[i]), angle, centre);
//mis à jour de la bounding box
if (i == 0)
{
m->xmin = m->ve[i].x;
m->xmax = m->ve[i].x;
m->ymin = m->ve[i].y;
m->ymax = m->ve[i].y;
m->zmin = m->ve[i].z;
m->zmax = m->ve[i].z;
}
else
{
if (m->xmin > m->ve[i].x)
m->xmin = m->ve[i].x;
if (m->xmax < m->ve[i].x)
m->xmax = m->ve[i].x;
if (m->ymin > m->ve[i].y)
m->ymin = m->ve[i].y;
if (m->ymax < m->ve[i].y)
m->ymax = m->ve[i].y;
if (m->zmin > m->ve[i].z)
m->zmin = m->ve[i].z;
if (m->zmax < m->ve[i].z)
m->zmax = m->ve[i].z;
}
}
}
/**
Rotation d'un modèle en radian autour de l'axe Z
@param v pointeur sur le modèle
@param angle angle de rotation du modèle en radian
@return aucun
*/
void
a2ri_vf_rotateZ_radian (
vf_model * m,
double angle)
{
//rotation de tous les sommets
for (int i = 0; i < m->nbvertex; i++)
{
vf_vertex_rotateZ_radian (&(m->ve[i]), angle);
//mis à jour de la bounding box
if (i == 0)
{
m->xmin = m->ve[i].x;
m->xmax = m->ve[i].x;
m->ymin = m->ve[i].y;
m->ymax = m->ve[i].y;
m->zmin = m->ve[i].z;
m->zmax = m->ve[i].z;
}
else
{
if (m->xmin > m->ve[i].x)
m->xmin = m->ve[i].x;
if (m->xmax < m->ve[i].x)
m->xmax = m->ve[i].x;
if (m->ymin > m->ve[i].y)
m->ymin = m->ve[i].y;
if (m->ymax < m->ve[i].y)
m->ymax = m->ve[i].y;
if (m->zmin > m->ve[i].z)
m->zmin = m->ve[i].z;
if (m->zmax < m->ve[i].z)
m->zmax = m->ve[i].z;
}
}
}
/**
Rotation d'un modèle en degré autour de l'axe Z
@param v pointeur sur le modèle
@param angle angle de rotation du modèle en degré
@return aucun
*/
void
a2ri_vf_rotateZ_degre (
vf_model * m,
double angle)
{
//rotation de tous les sommets
for (int i = 0; i < m->nbvertex; i++)
{
vf_vertex_rotateZ_degre (&(m->ve[i]), angle);
//mis à jour de la bounding box
if (i == 0)
{
m->xmin = m->ve[i].x;
m->xmax = m->ve[i].x;
m->ymin = m->ve[i].y;
m->ymax = m->ve[i].y;
m->zmin = m->ve[i].z;
m->zmax = m->ve[i].z;
}
else
{
if (m->xmin > m->ve[i].x)
m->xmin = m->ve[i].x;
if (m->xmax < m->ve[i].x)
m->xmax = m->ve[i].x;
if (m->ymin > m->ve[i].y)
m->ymin = m->ve[i].y;
if (m->ymax < m->ve[i].y)
m->ymax = m->ve[i].y;
if (m->zmin > m->ve[i].z)
m->zmin = m->ve[i].z;
if (m->zmax < m->ve[i].z)
m->zmax = m->ve[i].z;
}
}
}
/**
Rotation d'un modèle en radian suivant l'axe Z de centre (cx,cy,cz)
@param v pointeur sur le modèle
@param angle angle de rotation du modèle en radian
@param centre pointeur sur le point3d servant de centre à la rotation
@return aucun
*/
void
a2ri_vf_rotateZ_radian_center (
vf_model * m,
double angle,
const point3d * const centre)
{
//rotation de tous les sommets
for (int i = 0; i < m->nbvertex; i++)
{
vf_vertex_rotateZ_center_radian (&(m->ve[i]), angle, centre);
//mis à jour de la bounding box
if (i == 0)
{
m->xmin = m->ve[i].x;
m->xmax = m->ve[i].x;
m->ymin = m->ve[i].y;
m->ymax = m->ve[i].y;
m->zmin = m->ve[i].z;
m->zmax = m->ve[i].z;
}
else
{
if (m->xmin > m->ve[i].x)
m->xmin = m->ve[i].x;
if (m->xmax < m->ve[i].x)
m->xmax = m->ve[i].x;
if (m->ymin > m->ve[i].y)
m->ymin = m->ve[i].y;
if (m->ymax < m->ve[i].y)
m->ymax = m->ve[i].y;
if (m->zmin > m->ve[i].z)
m->zmin = m->ve[i].z;
if (m->zmax < m->ve[i].z)
m->zmax = m->ve[i].z;
}
}
}
/**
Rotation d'un modèle en degre suivant l'axe Z de centre (cx,cy,cz)
@param v pointeur sur le modèle
@param angle angle de rotation du modèle en degre
@param centre pointeur sur le point3d servant de centre à la rotation
@return aucun
*/
void
a2ri_vf_rotateZ_degre_center (
vf_model * m,
double angle,
const point3d * const centre)
{
//rotation de tous les sommets
for (int i = 0; i < m->nbvertex; i++)
{
vf_vertex_rotateZ_center_degre (&(m->ve[i]), angle, centre);
//mis à jour de la bounding box
if (i == 0)
{
m->xmin = m->ve[i].x;
m->xmax = m->ve[i].x;
m->ymin = m->ve[i].y;
m->ymax = m->ve[i].y;
m->zmin = m->ve[i].z;
m->zmax = m->ve[i].z;
}
else
{
if (m->xmin > m->ve[i].x)
m->xmin = m->ve[i].x;
if (m->xmax < m->ve[i].x)
m->xmax = m->ve[i].x;
if (m->ymin > m->ve[i].y)
m->ymin = m->ve[i].y;
if (m->ymax < m->ve[i].y)
m->ymax = m->ve[i].y;
if (m->zmin > m->ve[i].z)
m->zmin = m->ve[i].z;
if (m->zmax < m->ve[i].z)
m->zmax = m->ve[i].z;
}
}
}
/**
Rotation d'un modèle en degré suivant l'axe donnée
@param m pointeur sur le modèle
@param angle angle de rotation du modèle en degre
@param axe l'axe de rotation
@return aucun
*/
void
a2ri_vf_rotate_axe_radian (
vf_model * m,
double angle,
const vector3d * const axe)
{
gsl_matrix *identity3,
*A,
*B,
*M;
double x = axe->dx;
double y = axe->dy;
double z = axe->dz;
identity3 = gsl_matrix_alloc (3, 3);
gsl_matrix_set_identity (identity3);
A = gsl_matrix_alloc (3, 3);
gsl_matrix_set (A, 0, 0, x * x);
gsl_matrix_set (A, 0, 1, x * y);
gsl_matrix_set (A, 0, 2, x * z);
gsl_matrix_set (A, 1, 0, x * y);
gsl_matrix_set (A, 1, 1, y * y);
gsl_matrix_set (A, 1, 2, y * z);
gsl_matrix_set (A, 2, 0, x * z);
gsl_matrix_set (A, 2, 1, y * z);
gsl_matrix_set (A, 2, 2, z * z);
B = gsl_matrix_alloc (3, 3);
gsl_matrix_set (B, 0, 0, 0);
gsl_matrix_set (B, 0, 1, -z);
gsl_matrix_set (B, 0, 2, y);
gsl_matrix_set (B, 1, 0, z);
gsl_matrix_set (B, 1, 1, 0);
gsl_matrix_set (B, 1, 2, -x);
gsl_matrix_set (B, 2, 0, -y);
gsl_matrix_set (B, 2, 1, x);
gsl_matrix_set (B, 2, 2, 0);
M =
matrix_add (matrix_add
(matrix_mul_scale (identity3, cos (angle)),
matrix_mul_scale (A, 1 - cos (angle))), matrix_mul_scale (B,
sin
(angle)));
//rotation de tous les sommets
for (int i = 0; i < m->nbvertex; i++)
{
vf_vertex_rotate_axe_radian (&(m->ve[i]), M);
//mis à jour de la bounding box
if (i == 0)
{
m->xmin = m->ve[i].x;
m->xmax = m->ve[i].x;
m->ymin = m->ve[i].y;
m->ymax = m->ve[i].y;
m->zmin = m->ve[i].z;
m->zmax = m->ve[i].z;
}
else
{
if (m->xmin > m->ve[i].x)
m->xmin = m->ve[i].x;
if (m->xmax < m->ve[i].x)
m->xmax = m->ve[i].x;
if (m->ymin > m->ve[i].y)
m->ymin = m->ve[i].y;
if (m->ymax < m->ve[i].y)
m->ymax = m->ve[i].y;
if (m->zmin > m->ve[i].z)
m->zmin = m->ve[i].z;
if (m->zmax < m->ve[i].z)
m->zmax = m->ve[i].z;
}
}
gsl_matrix_free (A);
gsl_matrix_free (B);
gsl_matrix_free (M);
gsl_matrix_free (identity3);
}
/**
Calcul de l'aire totale d'un modèle
@param m le modèle
@return aire totale du modèle
*/
double
a2ri_vf_area (
const vf_model * const m)
{
int ve1,
ve2,
ve3;
double sumarea = 0.0;
point3d A,
B,
C;
//somme des aires de toutes les faces
for (int i = 0; i < m->nbface; i++)
{
ve1 = m->fa[i].ve1;
ve2 = m->fa[i].ve2;
ve3 = m->fa[i].ve3;
point3d_init (&A, m->ve[ve1].x, m->ve[ve1].y, m->ve[ve1].z);
point3d_init (&B, m->ve[ve2].x, m->ve[ve2].y, m->ve[ve2].z);
point3d_init (&C, m->ve[ve3].x, m->ve[ve3].y, m->ve[ve3].z);
sumarea += point3d_area (&A, &B, &C);
}
return sumarea;
}
/**
Trouve les faces entourant un sommet
@param m le modèle
@param numve numéro du sommet
@param list liste des numéros de faces
@param size nombre de faces
@return aucun
**/
void
a2ri_vf_faces_next_vertex (
const vf_model * const m,
int numve,
int **list,
int *size)
{
vf_edge *edgetemp;
hashtable *table = a2ri_vf_construction_edge_table (m, NULL, 0);
*list = NULL;
*size = 0;
for (int i = 0; i < m->ve[numve].nbincidentvertices; i++)
{
edgetemp =
hashtable_look_for (table, numve, m->ve[numve].incidentvertices[i]);
for (int j = 0; j < edgetemp->nbsharedfaces; j++)
list_int_add (list, size, edgetemp->sharedfaces[j],
WITHOUT_REDUNDANCE);
}
hashtable_free (table);
free (table);
}
/**
Trouve les faces entourant un sommet avec une hashtable contenant les aretes fournie
@param m le modèle
@param numve numéro du sommet
@param list liste des numéros de faces
@param size nombre de faces
@param table la hashtable
@return aucun
**/
void
a2ri_vf_faces_next_vertex_with_hashtable (
const vf_model * const m,
int numve,
int **list,
int *size,
const hashtable * const table)
{
vf_edge *edgetemp;
*list = NULL;
*size = 0;
for (int i = 0; i < m->ve[numve].nbincidentvertices; i++)
{
edgetemp =
hashtable_look_for (table, numve, m->ve[numve].incidentvertices[i]);
for (int j = 0; j < edgetemp->nbsharedfaces; j++)
list_int_add (list, size, edgetemp->sharedfaces[j],
WITHOUT_REDUNDANCE);
}
}
/**
calcul d'une normale à la face
@param m le modele
@param numfa numéro de la face
@return vecteur normal à la face
*/
vector3d
a2ri_vf_normal_face (
const vf_model * const m,
int numfa)
{
vector3d AB,
AC;
vector3d_init (&AB, m->ve[m->fa[numfa].ve2].x - m->ve[m->fa[numfa].ve1].x,
m->ve[m->fa[numfa].ve2].y - m->ve[m->fa[numfa].ve1].y,
m->ve[m->fa[numfa].ve2].z - m->ve[m->fa[numfa].ve1].z);
vector3d_init (&AC, m->ve[m->fa[numfa].ve3].x - m->ve[m->fa[numfa].ve1].x,
m->ve[m->fa[numfa].ve3].y - m->ve[m->fa[numfa].ve1].y,
m->ve[m->fa[numfa].ve3].z - m->ve[m->fa[numfa].ve1].z);
return vector3d_vectorialproduct (&AB, &AC);
}
/**
calcul d'une normale au sommet comme étant la moyenne des normales des faces adjacentes au sommet
@param m le modele
@param numve numéro du sommet
@return vecteur normal au sommet
*/
vector3d
a2ri_vf_normal_vertex (
const vf_model * const m,
int numve)
{
int *listface = NULL,
sizelistface = 0;
vector3d normale_sommet;
a2ri_vf_faces_next_vertex (m, numve, &listface, &sizelistface);
vector3d_init (&normale_sommet, 0.0, 0.0, 0.0);
//calcul de la normale au sommet
for (int i = 0; i < sizelistface; i++)
{
vector3d vtemp=a2ri_vf_normal_face (m, listface[i]);
normale_sommet = vector3d_add (&normale_sommet, &vtemp);
}
vector3d_init (&normale_sommet, normale_sommet.dx / sizelistface,
normale_sommet.dy / sizelistface,
normale_sommet.dz / sizelistface);
vector3d_normalize (&normale_sommet);
return normale_sommet;
}
/**
calcul d'une normale au sommet comme étant la moyenne des normales des faces adjacentes au sommet
@param m le modele
@param numve numéro du sommet
@param table table de hachage contenant les aretes
@return vecteur normal au sommet
*/
vector3d
a2ri_vf_normal_vertex_with_hashtable (
const vf_model * const m,
int numve,
const hashtable * const table)
{
int *listface = NULL,
sizelistface = 0;
vector3d normale_sommet;
a2ri_vf_faces_next_vertex_with_hashtable (m, numve, &listface,
&sizelistface, table);
vector3d_init (&normale_sommet, 0.0, 0.0, 0.0);
//calcul de la normale au sommet
for (int i = 0; i < sizelistface; i++)
{
vector3d vtemp=a2ri_vf_normal_face (m, listface[i]);
normale_sommet = vector3d_add (&normale_sommet, &vtemp);
}
vector3d_init (&normale_sommet, normale_sommet.dx / sizelistface,
normale_sommet.dy / sizelistface,
normale_sommet.dz / sizelistface);
vector3d_normalize (&normale_sommet);
free (listface);
return normale_sommet;
}
/**
Concaténation de plusieurs maillages dans un seul modèle
@param m tableau de modèle
@param size nombre de modele numérique
@return un maillage content tous les maillages.
*/
vf_model *
a2ri_vf_concat (
const pt_vf_model * const m,
int size)
{
vf_model *retour = NULL;
int ancienvertex = 0;
retour = (vf_model *) malloc (sizeof (vf_model));
a2ri_erreur_critique_si (retour == NULL,
"erreur d'allocation memoire dans la fonciton a2ri_vf_concat");
a2ri_vf_init (retour);
retour->xmin = retour->xmax = m[0]->ve[0].x;
retour->ymin = retour->ymax = m[0]->ve[0].y;
retour->zmin = retour->zmax = m[0]->ve[0].z;
for (int i = 0; i < size; i++)
{
for (int j = 0; j < m[i]->nbvertex; j++)
{
a2ri_vf_add_vertex (retour, m[i]->ve[j].x, m[i]->ve[j].y,
m[i]->ve[j].z);
if (m[i]->ve[j].x < retour->xmin)
retour->xmin = m[i]->ve[j].x;
if (m[i]->ve[j].y < retour->ymin)
retour->ymin = m[i]->ve[j].y;
if (m[i]->ve[j].z < retour->zmin)
retour->zmin = m[i]->ve[j].z;
if (m[i]->ve[j].x > retour->xmax)
retour->xmax = m[i]->ve[j].x;
if (m[i]->ve[j].y > retour->ymax)
retour->ymax = m[i]->ve[j].y;
if (m[i]->ve[j].z > retour->zmax)
retour->zmax = m[i]->ve[j].z;
}
for (int j = 0; j < m[i]->nbface; j++)
a2ri_vf_add_face (retour, m[i]->fa[j].ve1 + ancienvertex,
m[i]->fa[j].ve2 + ancienvertex,
m[i]->fa[j].ve3 + ancienvertex);
ancienvertex += m[i]->nbvertex;
}
return retour;
}
/**
Ajout des points d'un vf_model dans une partition de l'espace
@param m le modèle
@param sp la partition de l'espace
@return aucun
*/
void
a2ri_vf_space_partition (
const vf_model * const m,
space_partition * sp)
{
point3d p;
for (int i = 0; i < m->nbvertex; i++)
{
point3d_init (&p, m->ve[i].x, m->ve[i].y, m->ve[i].z);
p.att_int = i;
space_partition_add_point (sp, &p);
}
}
/**
Conversion d'un vf_model en liste de point3d
@param m le modèle
@return la liste de point3d
**/
point3d *
a2ri_vf_to_list_point3d(
const vf_model * const m)
{
point3d *retour=(point3d*)malloc(m->nbvertex*sizeof(point3d));
a2ri_erreur_critique_si(retour==NULL,"(a2ri_vf_to_list_point3d) - erreur allocation mémoire pour retour\n");
for(int i=0;inbvertex;i++)
point3d_init(&retour[i],m->ve[i].x,m->ve[i].y,m->ve[i].z);
return retour;
}
/**
Conversion d'un vf_model en vef_model
@param le modèle à convertir
@return le vef_model
**/
vef_model *
a2ri_vf_to_vef (
const vf_model * const m)
{
int p1,
p2,ar1,ar2,ar3;
vef_model *retour=(vef_model*)malloc(sizeof(vef_model));
a2ri_erreur_critique_si(retour==NULL,"erreur allocation mémoire pour retour dans a2ri_vf_to_vef");
a2ri_vef_init(retour);
for(int i=0;inbvertex;i++)
a2ri_vef_add_vertex(retour,m->ve[i].x,m->ve[i].y,m->ve[i].z);
hashtable *table=hashtable_new (m->nbvertex + m->nbface);
for (int i = 0; i < m->nbface; i++)
{
p1 = m->fa[i].ve1;
p2 = m->fa[i].ve2;
vf_edge *edgetemp = hashtable_look_for (table, p1, p2);
if (edgetemp == NULL)
{
edgetemp = (vf_edge *) malloc (sizeof (vf_edge));
a2ri_erreur_critique_si (edgetemp == NULL,
"erreur allocation memoire pour edgetemp\na2ri_vf_to_vef");
edgetemp->ve1 = p1;
edgetemp->ve2 = p2;
edgetemp->att_int = retour->nbedge;
hashtable_add (table, edgetemp);
ar1 = retour->nbedge;
a2ri_vef_add_edge(retour,p1,p2,0);
}
else
ar1=edgetemp->att_int;
p1 = m->fa[i].ve2;
p2 = m->fa[i].ve3;
edgetemp = hashtable_look_for (table, p1, p2);
if (edgetemp == NULL)
{
edgetemp = (vf_edge *) malloc (sizeof (vf_edge));
a2ri_erreur_critique_si (edgetemp == NULL,
"erreur allocation memoire pour edgetemp\na2ri_vf_to_vef");
edgetemp->ve1 = p1;
edgetemp->ve2 = p2;
edgetemp->att_int = retour->nbedge;
hashtable_add (table, edgetemp);
ar2 = retour->nbedge;
a2ri_vef_add_edge(retour,p1,p2,0);
}
else
ar2=edgetemp->att_int;
p1 = m->fa[i].ve3;
p2 = m->fa[i].ve1;
edgetemp = hashtable_look_for (table, p1, p2);
if (edgetemp == NULL)
{
edgetemp = (vf_edge *) malloc (sizeof (vf_edge));
a2ri_erreur_critique_si (edgetemp == NULL,
"erreur allocation memoire pour edgetemp\na2ri_vf_to_vef");
edgetemp->ve1 = p1;
edgetemp->ve2 = p2;
edgetemp->att_int = retour->nbedge;
hashtable_add (table, edgetemp);
ar3 = retour->nbedge;
a2ri_vef_add_edge(retour,p1,p2,0);
}
else
ar3=edgetemp->att_int;
a2ri_vef_add_face(retour,ar1,ar2,ar3);
}
retour->xmin=m->xmin;
retour->xmax=m->xmax;
retour->ymin=m->ymin;
retour->ymax=m->ymax;
retour->zmin=m->zmin;
retour->zmax=m->zmax;
return retour;
}
/**
Initialisation d'un modèle avec un maillage vide
@param m pointeur sur le modèle
@return aucun
*/
void
a2ri_vef_init (
vef_model * m)
{
m->ve = NULL;
m->ed = NULL;
m->fa = NULL;
m->nbvertex = 0;
m->nbedge = 0;
m->nbface = 0;
}
/**
Libération de l'espace mémoire utilisé
@param m pointeur sur le modèle
*/
void
a2ri_vef_free (
vef_model * m)
{
int i;
for (i = 0; i < m->nbvertex; i++)
free (m->ve[i].sharededges);
free (m->ve);
for (i = 0; i < m->nbedge; i++)
free (m->ed[i].sharedfaces);
free (m->ed);
free (m->fa);
}
/**
affichage des caractéristiques générales d'un modèle (nombre de sommets et de faces)
@param m le modèle
@return aucun
*/
void
a2ri_vef_display (
const vef_model * const m)
{
printf ("********************\nModel :");
printf ("\n\t%d vertices\n", m->nbvertex);
printf ("\t%d edges\n", m->nbedge);
printf ("\t%d faces\n", m->nbface);
printf
("Bounding Box : [%4.2f , %4.2f , %4.2f] - [%4.2f , %4.2f , %4.2f]\n",
m->xmin, m->ymin, m->zmin, m->xmax, m->ymax, m->zmax);
printf ("********************\n");
}
/**
affichage des caractéristiques détaillées d'un modèle (nombre de sommets, de faces et leurs adjacences)
@param m le modèle
@return aucun
*/
void
a2ri_vef_display_detail (
const vef_model * const m)
{
int i,
j;
printf ("********************\nModel :");
if (m->nbvertex)
{
printf ("\n\t%d vertices\n", m->nbvertex);
for (i = 0; i < m->nbvertex; i++)
{
printf
("\t\t%5d - [%5.2f , %5.2f , %5.2f]\n\t\t\tvalency : %d - list : ",
i, m->ve[i].x, m->ve[i].y, m->ve[i].z, m->ve[i].nbsharededges);
if (m->ve[i].nbsharededges > 0)
printf ("%d", m->ve[i].sharededges[0]);
for (j = 1; j < m->ve[i].nbsharededges; j++)
printf (" , %d", m->ve[i].sharededges[j]);
printf ("\n\n");
}
}
if (m->nbedge)
{
printf ("\n\t%d edges\n", m->nbedge);
for (i = 0; i < m->nbedge; i++)
{
printf ("\t\t%5d - (%d , %d)\n\t\t\tvalency : %d - list : ",
i, m->ed[i].ve1, m->ed[i].ve2, m->ed[i].nbsharedfaces);
if (m->ed[i].nbsharedfaces > 0)
printf ("%d", m->ed[i].sharedfaces[0]);
for (j = 1; j < m->ed[i].nbsharedfaces; j++)
printf (" , %d", m->ed[i].sharedfaces[j]);
printf ("\n\n");
}
}
if (m->nbface)
{
printf ("\n\t%d faces\n", m->nbface);
for (i = 0; i < m->nbface; i++)
{
printf ("\t\t%5d - (%d , %d , %d)",
i, m->fa[i].ed1, m->fa[i].ed2, m->fa[i].ed3);
printf ("\n\n");
}
}
printf
("\nBounding Box : [%4.2f , %4.2f , %4.2f] - [%4.2f , %4.2f , %4.2f]\n",
m->xmin, m->ymin, m->zmin, m->xmax, m->ymax, m->zmax);
printf ("********************\n");
}
/**
Ajout d'un vertex (x,y,z) au modèle
@param m pointeur sur le modèle
@param x coordonnée x du vertex
@param y coordonnée y
@param z coordonnée z
@return 1 si succès, 0 sinon
*/
int
a2ri_vef_add_vertex (
vef_model * m,
double x,
double y,
double z)
{
//allocation de l'espace mémoire ou réallocation
if (m->ve == NULL)
{
m->ve = (vef_vertex *) malloc (sizeof (vef_vertex));
a2ri_erreur_critique_si (m->ve == NULL,
"erreur allocation memoire pour m->ve\na2ri_vef_add_vertex");
}
else
{
vef_vertex *tempve;
tempve =
(vef_vertex *) realloc (m->ve,
(m->nbvertex + 1) * sizeof (vef_vertex));
a2ri_erreur_critique_si (tempve == NULL,
"erreur allocation memoire pour m->ve\na2ri_vef_add_vertex");
m->ve=tempve;
}
m->ve[m->nbvertex].x = x;
m->ve[m->nbvertex].y = y;
m->ve[m->nbvertex].z = z;
m->ve[m->nbvertex].sharededges = NULL;
m->ve[m->nbvertex].nbsharededges = 0;
(m->nbvertex)++;
return 1;
}
/**
Recherche d'un vertex dans un modèle
@param m le modèle
@param x coordonnée x du vertex à rechercher
@param y coordonnée y
@param z coordonnée z
@return numéro du vertex dans la liste de vertex du modèle, -1 si le vertex n'est pas trouvé.
*/
int
a2ri_vef_search_vertex (
const vef_model * const m,
double x,
double y,
double z)
{
int i;
for (i = 0; i < m->nbvertex; i++)
if (m->ve[i].x == x && m->ve[i].y == y && m->ve[i].z == z)
return i;
return -1;
}
/**
Retrait d'un sommet du modèle. L'opération ne peut être effectué que si le sommet n'est référencée dans aucune face.
@param m le modèle
@param numvertex numèro du vertex à retirer
@return 1 si succès, 0 sinon
*/
int
a2ri_vef_remove_vertex (
vef_model * m,
int numvertex)
{
if (m->ed == NULL)
{
//on vérifie que le sommet existe bien
if (numvertex > m->nbvertex)
return 0;
//on décale les sommets de rang plus élevé
for (int i = numvertex; i < (m->nbvertex) - 1; i++)
{
m->ve[i].x = m->ve[i + 1].x;
m->ve[i].y = m->ve[i + 1].y;
m->ve[i].z = m->ve[i + 1].z;
m->ve[i].sharededges = m->ve[i + 1].sharededges;
m->ve[i].nbsharededges = m->ve[i + 1].nbsharededges;
}
//reallocation de l'espace memoire
vef_vertex *tempve;
tempve =
(vef_vertex *) realloc (m->ve,
((m->nbvertex) - 1) * sizeof (vef_vertex));
a2ri_erreur_critique_si (tempve == NULL,
"erreur allocation memoire pour m->ve\na2ri_vef_remove_vertex");
m->ve=tempve;
m->nbvertex = m->nbvertex - 1;
}
else
{
a2ri_vef_remove_list_of_vertex (m, &numvertex, 1);
}
return 1;
}
/**
Retrait d'un sommet du modèle. L'opération ne peut être effectué que si le sommet n'est référencée dans aucune arete.
@param m le modèle
@param numvertex numèro du vertex à retirer
@return 1 si succès, 0 sinon
*/
int
a2ri_vef_remove_list_of_vertex (
vef_model * m,
int *listvertex,
int size)
{
int *list1 = NULL,
*list2 = NULL,
size1 = 0,
size2 = 0;
list_int_sort (listvertex, size, DESC);
if (m->ed == NULL)
{
for (int i = 0; i < size; i++)
a2ri_vef_remove_vertex (m, listvertex[i]);
return 1;
}
list1 = NULL;
size1 = 0;
for (int i = 0; i < size; i++)
for (int j = 0; j < m->ve[listvertex[i]].nbsharededges; j++)
list_int_add (&list1, &size1, m->ve[listvertex[i]].sharededges[j],
WITHOUT_REDUNDANCE);
list_int_sort (list1, size1, DESC);
if (m->fa == NULL)
{
for (int i = 0; i < size1; i++)
a2ri_vef_remove_edge (m, list1[i]);
free (list1);
return 1;
}
list2 = NULL;
size2 = 0;
for (int i = 0; i < size1; i++)
for (int j = 0; j < m->ed[list1[i]].nbsharedfaces; j++)
list_int_add (&list2, &size2, m->ed[list1[i]].sharedfaces[j],
WITHOUT_REDUNDANCE);
list_int_sort (list2, size2, DESC);
for (int i = 0; i < size2; i++)
a2ri_vef_remove_face (m, list2[i]);
free (list1);
free (list2);
return 1;
return 1;
}
/**
Ajout d'une arete (ve1,ve2) au modèle
@param m pointeur sur le modèle
@param ve1 index du premier point
@param ve2 index du second point
@param verif 1 s'il faut vérifier si l'arete existe deja, 0 sinon
@return 1 si succès, 0 sinon
*/
int
a2ri_vef_add_edge (
vef_model * m,
int ve1,
int ve2,
int verif)
{
//si vérification, on regarde si l'arete existe deja
//sinon on est sur d'ajouter une arete inexistante
if (verif)
if (ve1 >= m->nbvertex || ve2 >= m->nbvertex)
return 0;
if (verif)
if (a2ri_vef_search_edge (m, ve1, ve2) != -1)
return 0;
//allocation ou reallocatin de l'espace memoire
if (m->ed == NULL)
{
m->ed = (vef_edge *) malloc (sizeof (vef_edge));
a2ri_erreur_critique_si (m->ed == NULL,
"erreur allocation memoire pour m->ed\na2ri_vef_add_edge");
}
else
{
vef_edge *temped;
temped =
(vef_edge *) realloc (m->ed, (m->nbedge + 1) * sizeof (vef_edge));
a2ri_erreur_critique_si (temped == NULL,
"erreur allocation memoire pour m->ed\na2ri_vef_add_vertex");
m->ed=temped;
}
m->ed[m->nbedge].ve1 = ve1;
m->ed[m->nbedge].ve2 = ve2;
m->ed[m->nbedge].sharedfaces = NULL;
m->ed[m->nbedge].nbsharedfaces = 0;
(m->nbedge)++;
list_int_add (&(m->ve[ve1].sharededges),
&(m->ve[ve1].nbsharededges),
(m->nbedge) - 1, WITH_REDUNDANCE);
list_int_add (&(m->ve[ve2].sharededges),
&(m->ve[ve2].nbsharededges),
(m->nbedge) - 1, WITH_REDUNDANCE);
return 1;
}
/**
Recherche d'une arete dans un modèle
@param m le modèle
@param ve1 indice d'un point
@param ve2 indice d'un point
@return index de l'arete, -1 si l'arete n'est pas trouvée.
@warning a2ri_vef_search_edge(m,0,1) retournera le meme resultat que a2ri_vef_search_edge(m,1,0).
*/
int
a2ri_vef_search_edge (
const vef_model * const m,
int ve1,
int ve2)
{
int i;
for (i = 0; i < m->nbedge; i++)
if ((m->ed[i].ve1 == ve1 && m->ed[i].ve2 == ve2)
|| (m->ed[i].ve1 == ve2 && m->ed[i].ve2 == ve1))
return i;
return -1;
}
/**
Retrait d'une arete du modèle. L'opération ne peut être effectué que si l'arete n'est référencée dans aucune face.
@param m le modèle
@param numvertex numèro du vertex à retirer
@return 1 si succès, 0 sinon
*/
int
a2ri_vef_remove_edge (
vef_model * m,
int numedge)
{
int k,
ve[2];
vef_vertex *tempve;
vef_edge *temped;
if (m->fa == NULL)
{
//on vérifie l'existence de l'arete
if (numedge > m->nbedge)
return 0;
if (m->ed[numedge].ve1 > m->ed[numedge].ve2)
{
ve[0] = m->ed[numedge].ve1;
ve[1] = m->ed[numedge].ve2;
}
else
{
ve[0] = m->ed[numedge].ve2;
ve[1] = m->ed[numedge].ve1;
}
//on décale les aretes de rang plus élevé
for (int i = numedge; i < (m->nbedge) - 1; i++)
{
m->ed[i].ve1 = m->ed[i + 1].ve1;
m->ed[i].ve2 = m->ed[i + 1].ve2;
m->ed[i].sharedfaces = m->ed[i + 1].sharedfaces;
m->ed[i].nbsharedfaces = m->ed[i + 1].nbsharedfaces;
}
//reallocation memoire
temped =
(vef_edge *) realloc (m->ed, ((m->nbedge) - 1) * sizeof (vef_edge));
a2ri_erreur_critique_si (temped == NULL,
"erreur allocation memoire pour m->ed\na2ri_vef_remove_edge");
m->ed=temped;
m->nbedge = m->nbedge - 1;
// on decale les numeros d'aretes dans les adjacences des sommets
for (int i = 0; i < m->nbvertex; i++)
{
k = 0;
while (k < m->ve[i].nbsharededges)
{
if (m->ve[i].sharededges[k] == numedge)
list_int_remove (&(m->ve[i].sharededges),
&(m->ve[i].nbsharededges), k);
else
{
if (m->ve[i].sharededges[k] > numedge)
(m->ve[i].sharededges[k])--;
k++;
}
}
}
//on essaye de supprimer les sommets
for (int i = 0; i < 2; i++)
if (m->ve[ve[i]].nbsharededges == 0)
{
int numvertex = ve[i];
for (int j = numvertex; j < (m->nbvertex) - 1; j++)
{
m->ve[j].x = m->ve[j + 1].x;
m->ve[j].y = m->ve[j + 1].y;
m->ve[j].z = m->ve[j + 1].z;
m->ve[j].sharededges = m->ve[j + 1].sharededges;
m->ve[j].nbsharededges = m->ve[j + 1].nbsharededges;
}
//reallocation memoire
tempve =
(vef_vertex *) realloc (m->ve,
((m->nbvertex) -
1) * sizeof (vef_vertex));
a2ri_erreur_critique_si (tempve == NULL,
"erreur allocation memoire pour m->ve\na2ri_vef_remove_edge");
m->ve=tempve;
m->nbvertex = m->nbvertex - 1;
for (int j = 0; j < m->nbedge; j++)
{
if (m->ed[j].ve1 > numvertex)
m->ed[j].ve1 = m->ed[j].ve1 - 1;
if (m->ed[j].ve2 > numvertex)
m->ed[j].ve2 = m->ed[j].ve2 - 1;
}
}
}
else
{
a2ri_vef_remove_list_of_edge (m, &numedge, 1);
}
return 1;
}
/**
Retrait d'une liste d'arete du modèle. L'opération ne peut être effectué que si l'arete n'est référencée dans aucune face.
@param m le modèle
@param numvertex numèro du vertex à retirer
@return 1 si succès, 0 sinon
*/
int
a2ri_vef_remove_list_of_edge (
vef_model * m,
int *listedge,
int size)
{
int *list1 = NULL,
size1 = 0;
list_int_sort (listedge, size, DESC);
if (m->fa == NULL)
{
for (int i = 0; i < size; i++)
a2ri_vef_remove_edge (m, listedge[i]);
return 1;
}
list1 = NULL;
size1 = 0;
for (int i = 0; i < size; i++)
for (int j = 0; j < m->ed[listedge[i]].nbsharedfaces; j++)
list_int_add (&list1, &size1, m->ed[listedge[i]].sharedfaces[j],
WITHOUT_REDUNDANCE);
list_int_sort (list1, size1, DESC);
for (int i = 0; i < size1; i++)
a2ri_vef_remove_face (m, list1[i]);
free (list1);
return 1;
}
/**
Ajout d'une face défini par trois points (numéros d'index dans la liste de points) au modèle
@param m pointeur sur le modèle
@param ve1 index du premier point
@param ve2 index du second point
@param ve3 index du troisième point
@return 1 si succès, 0 sinon
*/
int
a2ri_vef_add_face (
vef_model * m,
int ed1,
int ed2,
int ed3)
{
//allocation ou reallocation de l'espace memoire
if (m->fa == NULL)
{
m->fa = (vef_face *) malloc (sizeof (vef_face));
a2ri_erreur_critique_si (m->fa == NULL,
"erreur allocation memoire pour m->fa\na2ri_vef_add_face");
}
else
{
vef_face *tempfa;
tempfa =
(vef_face *) realloc (m->fa, (m->nbface + 1) * sizeof (vef_face));
a2ri_erreur_critique_si (tempfa == NULL,
"erreur allocation memoire pour m->fa\na2ri_vef_add_face");
m->fa=tempfa;
}
m->fa[m->nbface].ed1 = ed1;
m->fa[m->nbface].ed2 = ed2;
m->fa[m->nbface].ed3 = ed3;
(m->nbface)++;
list_int_add (&(m->ed[ed1].sharedfaces),
&(m->ed[ed1].nbsharedfaces),
(m->nbface) - 1, WITH_REDUNDANCE);
list_int_add (&(m->ed[ed2].sharedfaces),
&(m->ed[ed2].nbsharedfaces),
(m->nbface) - 1, WITH_REDUNDANCE);
list_int_add (&(m->ed[ed3].sharedfaces),
&(m->ed[ed3].nbsharedfaces),
(m->nbface) - 1, WITH_REDUNDANCE);
return 1;
}
/**
Recherche d'une face dans un modèle
@param m le modèle
@param ve1 index d'un point
@param ve2 index d'un point
@param ve3 index d'un point
@return numéro de la face dans la liste de face du modèle, -1 si la face n'est pas trouvée.
@warning Cette fonction est sensible à l'orientation de la face.
Exemple pour un modèle m:
A REECRIRE
@code
liste de faces (index -> ve1 ve2 ve3):
0 -> 0 1 2
1 -> 0 2 3
2 -> 0 3 1
3 -> 1 3 2
@endcode
le code
@code
a2ri_vef_search_face(m,0,3,1);
ou
a2ri_vef_search_face(m,3,1,0);
ou
a2ri_vef_search_face(m,1,0,3);
@endcode
retournera 2 alors que
@code
a2ri_vef_search_face(m,3,0,1);
@endcode
retournera -1
*/
int
a2ri_vef_search_face (
const vef_model * const m,
int ed1,
int ed2,
int ed3)
{
int i;
for (i = 0; i < m->nbface; i++)
{
if (m->fa[i].ed1 == ed1)
if ((m->fa[i].ed2 == ed2 && m->fa[i].ed3 == ed3)
|| (m->fa[i].ed2 == ed3 && m->fa[i].ed3 == ed2))
return i;
if (m->fa[i].ed2 == ed1)
if ((m->fa[i].ed1 == ed3 && m->fa[i].ed3 == ed2))
return i;
if (m->fa[i].ed3 == ed1)
if ((m->fa[i].ed2 == ed3 && m->fa[i].ed1 == ed2))
return i;
}
return -1;
}
/**
Retrait d'une face du modèle. La fonction enlève également les sommets qui ne sont plus utilisés.
@param m le modèle
@param numface numèro de la face à retirer
@return 1 si succès, 0 sinon
*/
int
a2ri_vef_remove_face (
vef_model * m,
int numface)
{
int k,
ed[3],
ve[3];
vef_vertex *tempve;
vef_edge *temped;
vef_face *tempfa;
//on verifie l'existence de la face
if (numface > m->nbface)
return 0;
//on garde les numeros d'aretes et de sommet pour esayer de les supprimer ensuite
ed[0] = m->fa[numface].ed1;
ed[1] = m->fa[numface].ed2;
ed[2] = m->fa[numface].ed3;
list_int_sort (ed, 3, DESC);
vef_face_get_vertices (&(m->fa[numface]), m->ed, &ve[0], &ve[1], &ve[2]);
list_int_sort (ve, 3, DESC);
//décalage des faces de rang supérieur
for (int i = numface; i < (m->nbface) - 1; i++)
{
m->fa[i].ed1 = m->fa[i + 1].ed1;
m->fa[i].ed2 = m->fa[i + 1].ed2;
m->fa[i].ed3 = m->fa[i + 1].ed3;
}
//reallocation de l'espace memoire
tempfa =
(vef_face *) realloc (m->fa, ((m->nbface) - 1) * sizeof (vef_face));
a2ri_erreur_critique_si (tempfa == NULL,
"erreur allocation memoire pour m->fa\na2ri_vef_remove_face");
m->fa=tempfa;
m->nbface = m->nbface - 1;
//decalage et suppression dans les adjacences d'aretes
for (int i = 0; i < m->nbedge; i++)
{
k = 0;
while (k < m->ed[i].nbsharedfaces)
{
if (m->ed[i].sharedfaces[k] == numface)
list_int_remove (&(m->ed[i].sharedfaces),
&(m->ed[i].nbsharedfaces), k);
else
{
if (m->ed[i].sharedfaces[k] > numface)
m->ed[i].sharedfaces[k] = m->ed[i].sharedfaces[k] - 1;
k++;
}
}
}
//on essaye de supprimer les aretes inutilisées
for (int i = 0; i < 3; i++)
if (m->ed[ed[i]].nbsharedfaces == 0)
{
int numedge = ed[i];
//on décale les aretes de rang plus élevé
for (int j = numedge; j < (m->nbedge) - 1; j++)
{
m->ed[j].ve1 = m->ed[j + 1].ve1;
m->ed[j].ve2 = m->ed[j + 1].ve2;
m->ed[j].sharedfaces = m->ed[j + 1].sharedfaces;
m->ed[j].nbsharedfaces = m->ed[j + 1].nbsharedfaces;
}
//reallocation memoire
temped =
(vef_edge *) realloc (m->ed,
((m->nbedge) - 1) * sizeof (vef_edge));
a2ri_erreur_critique_si (temped == NULL,
"erreur allocation memoire pour m->ed\na2ri_vef_remove_face");
m->ed=temped;
m->nbedge = m->nbedge - 1;
// on decale les numeros d'aretes dans les adjacences des sommets
for (int j = 0; j < m->nbvertex; j++)
{
k = 0;
while (k < m->ve[j].nbsharededges)
{
if (m->ve[j].sharededges[k] == numedge)
list_int_remove (&(m->ve[j].sharededges),
&(m->ve[j].nbsharededges), k);
else
{
if (m->ve[j].sharededges[k] > numedge)
(m->ve[j].sharededges[k])--;
k++;
}
}
}
// on decale les numeros d'aretes dans les faces
for (int j = 0; j < m->nbface; j++)
{
if (m->fa[j].ed1 > numedge)
m->fa[j].ed1--;
if (m->fa[j].ed2 > numedge)
m->fa[j].ed2--;
if (m->fa[j].ed3 > numedge)
m->fa[j].ed3--;
}
}
//on essaye de supprimer les sommets
for (int i = 0; i < 3; i++)
if (m->ve[ve[i]].nbsharededges == 0)
{
int numvertex = ve[i];
//on décale les sommets de rang plus élevé
for (int j = numvertex; j < (m->nbvertex) - 1; j++)
{
m->ve[j].x = m->ve[j + 1].x;
m->ve[j].y = m->ve[j + 1].y;
m->ve[j].z = m->ve[j + 1].z;
m->ve[j].sharededges = m->ve[j + 1].sharededges;
m->ve[j].nbsharededges = m->ve[j + 1].nbsharededges;
}
//reallocation de l'espace memoire
tempve =
(vef_vertex *) realloc (m->ve,
((m->nbvertex) -
1) * sizeof (vef_vertex));
a2ri_erreur_critique_si (tempve == NULL,
"erreur allocation memoire pour m->ve\na2ri_vef_remove_face");
m->ve=tempve;
m->nbvertex = m->nbvertex - 1;
//on met à jour les numéros de sommets dans les aretes
for (int j = 0; j < m->nbedge; j++)
{
if (m->ed[j].ve1 > numvertex)
m->ed[j].ve1 = m->ed[j].ve1 - 1;
if (m->ed[j].ve2 > numvertex)
m->ed[j].ve2 = m->ed[j].ve2 - 1;
}
}
return 1;
}
/**
Retrait d'une liste de face du modèle. La fonction enlève également les sommets qui ne sont plus utilisés.
@param m le modèle
@param numface numèro de la face à retirer
@return 1 si succès, 0 sinon
*/
int
a2ri_vef_remove_list_of_face (
vef_model * m,
int *listface,
int size)
{
list_int_sort (listface, size, DESC);
for (int i = 0; i < size; i++)
a2ri_vef_remove_face (m, listface[i]);
return 1;
}
/**
Translation du modèle
@param m pointeur sur le modèle à translater
@param delta pointeur sur le vecteur de translation
@return aucun
*/
void
a2ri_vef_translate (
vef_model * m,
const vector3d * const delta)
{
//translation de tous les sommets
for (int i = 0; i < m->nbvertex; i++)
vef_vertex_translate (&(m->ve[i]), delta);
//translation de la bounding box
m->xmin += delta->dx;
m->xmax += delta->dx;
m->ymin += delta->dy;
m->ymax += delta->dy;
m->zmin += delta->dz;
m->zmax += delta->dz;
}
/**
Rotation d'un modèle en radian autour de l'axe X
@param v pointeur sur le modèle
@param angle angle de rotation du modèle en radian
@return aucun
*/
void
a2ri_vef_rotateX_radian (
vef_model * m,
double angle)
{
//rotation de tous les sommets
for (int i = 0; i < m->nbvertex; i++)
{
vef_vertex_rotateX_radian (&(m->ve[i]), angle);
//mis à jour de la bounding box
if (i == 0)
{
m->xmin = m->ve[i].x;
m->xmax = m->ve[i].x;
m->ymin = m->ve[i].y;
m->ymax = m->ve[i].y;
m->zmin = m->ve[i].z;
m->zmax = m->ve[i].z;
}
else
{
if (m->xmin > m->ve[i].x)
m->xmin = m->ve[i].x;
if (m->xmax < m->ve[i].x)
m->xmax = m->ve[i].x;
if (m->ymin > m->ve[i].y)
m->ymin = m->ve[i].y;
if (m->ymax < m->ve[i].y)
m->ymax = m->ve[i].y;
if (m->zmin > m->ve[i].z)
m->zmin = m->ve[i].z;
if (m->zmax < m->ve[i].z)
m->zmax = m->ve[i].z;
}
}
}
/**
Rotation d'un modèle en degré autour de l'axe X
@param v pointeur sur le modèle
@param angle angle de rotation du modèle en degré
@return aucun
*/
void
a2ri_vef_rotateX_degre (
vef_model * m,
double angle)
{
//rotation de tous les sommets
for (int i = 0; i < m->nbvertex; i++)
{
vef_vertex_rotateX_degre (&(m->ve[i]), angle);
//mis à jour de la bounding box
if (i == 0)
{
m->xmin = m->ve[i].x;
m->xmax = m->ve[i].x;
m->ymin = m->ve[i].y;
m->ymax = m->ve[i].y;
m->zmin = m->ve[i].z;
m->zmax = m->ve[i].z;
}
else
{
if (m->xmin > m->ve[i].x)
m->xmin = m->ve[i].x;
if (m->xmax < m->ve[i].x)
m->xmax = m->ve[i].x;
if (m->ymin > m->ve[i].y)
m->ymin = m->ve[i].y;
if (m->ymax < m->ve[i].y)
m->ymax = m->ve[i].y;
if (m->zmin > m->ve[i].z)
m->zmin = m->ve[i].z;
if (m->zmax < m->ve[i].z)
m->zmax = m->ve[i].z;
}
}
}
/**
Rotation d'un modèle en radian suivant l'axe X de centre (cx,cy,cz)
@param v pointeur sur le modèle
@param angle angle de rotation du modèle en radian
@param centre pointeur sur le point3d servant de centre à la rotation
@return aucun
*/
void
a2ri_vef_rotateX_radian_center (
vef_model * m,
double angle,
const point3d * const centre)
{
//rotation de tous les sommets
for (int i = 0; i < m->nbvertex; i++)
{
vef_vertex_rotateX_center_radian (&(m->ve[i]), angle, centre);
//mis à jour de la bounding box
if (i == 0)
{
m->xmin = m->ve[i].x;
m->xmax = m->ve[i].x;
m->ymin = m->ve[i].y;
m->ymax = m->ve[i].y;
m->zmin = m->ve[i].z;
m->zmax = m->ve[i].z;
}
else
{
if (m->xmin > m->ve[i].x)
m->xmin = m->ve[i].x;
if (m->xmax < m->ve[i].x)
m->xmax = m->ve[i].x;
if (m->ymin > m->ve[i].y)
m->ymin = m->ve[i].y;
if (m->ymax < m->ve[i].y)
m->ymax = m->ve[i].y;
if (m->zmin > m->ve[i].z)
m->zmin = m->ve[i].z;
if (m->zmax < m->ve[i].z)
m->zmax = m->ve[i].z;
}
}
}
/**
Rotation d'un modèle en degre suivant l'axe X de centre (cx,cy,cz)
@param v pointeur sur le modèle
@param angle angle de rotation du modèle en degre
@param centre pointeur sur le point3d servant de centre à la rotation
@return aucun
*/
void
a2ri_vef_rotateX_degre_center (
vef_model * m,
double angle,
const point3d * const centre)
{
//rotation de tous les sommets
for (int i = 0; i < m->nbvertex; i++)
{
vef_vertex_rotateX_center_degre (&(m->ve[i]), angle, centre);
//mis à jour de la bounding box
if (i == 0)
{
m->xmin = m->ve[i].x;
m->xmax = m->ve[i].x;
m->ymin = m->ve[i].y;
m->ymax = m->ve[i].y;
m->zmin = m->ve[i].z;
m->zmax = m->ve[i].z;
}
else
{
if (m->xmin > m->ve[i].x)
m->xmin = m->ve[i].x;
if (m->xmax < m->ve[i].x)
m->xmax = m->ve[i].x;
if (m->ymin > m->ve[i].y)
m->ymin = m->ve[i].y;
if (m->ymax < m->ve[i].y)
m->ymax = m->ve[i].y;
if (m->zmin > m->ve[i].z)
m->zmin = m->ve[i].z;
if (m->zmax < m->ve[i].z)
m->zmax = m->ve[i].z;
}
}
}
/**
Rotation d'un modèle en radian autour de l'axe Y
@param v pointeur sur le modèle
@param angle angle de rotation du modèle en radian
@return aucun
*/
void
a2ri_vef_rotateY_radian (
vef_model * m,
double angle)
{
//rotation de tous les sommets
for (int i = 0; i < m->nbvertex; i++)
{
vef_vertex_rotateY_radian (&(m->ve[i]), angle);
//mis à jour de la bounding box
if (i == 0)
{
m->xmin = m->ve[i].x;
m->xmax = m->ve[i].x;
m->ymin = m->ve[i].y;
m->ymax = m->ve[i].y;
m->zmin = m->ve[i].z;
m->zmax = m->ve[i].z;
}
else
{
if (m->xmin > m->ve[i].x)
m->xmin = m->ve[i].x;
if (m->xmax < m->ve[i].x)
m->xmax = m->ve[i].x;
if (m->ymin > m->ve[i].y)
m->ymin = m->ve[i].y;
if (m->ymax < m->ve[i].y)
m->ymax = m->ve[i].y;
if (m->zmin > m->ve[i].z)
m->zmin = m->ve[i].z;
if (m->zmax < m->ve[i].z)
m->zmax = m->ve[i].z;
}
}
}
/**
Rotation d'un modèle en degré autour de l'axe Y
@param v pointeur sur le modèle
@param angle angle de rotation du modèle en degré
@return aucun
*/
void
a2ri_vef_rotateY_degre (
vef_model * m,
double angle)
{
//rotation de tous les sommets
for (int i = 0; i < m->nbvertex; i++)
{
vef_vertex_rotateY_degre (&(m->ve[i]), angle);
//mis à jour de la bounding box
if (i == 0)
{
m->xmin = m->ve[i].x;
m->xmax = m->ve[i].x;
m->ymin = m->ve[i].y;
m->ymax = m->ve[i].y;
m->zmin = m->ve[i].z;
m->zmax = m->ve[i].z;
}
else
{
if (m->xmin > m->ve[i].x)
m->xmin = m->ve[i].x;
if (m->xmax < m->ve[i].x)
m->xmax = m->ve[i].x;
if (m->ymin > m->ve[i].y)
m->ymin = m->ve[i].y;
if (m->ymax < m->ve[i].y)
m->ymax = m->ve[i].y;
if (m->zmin > m->ve[i].z)
m->zmin = m->ve[i].z;
if (m->zmax < m->ve[i].z)
m->zmax = m->ve[i].z;
}
}
}
/**
Rotation d'un modèle en radian suivant l'axe Y de centre (cx,cy,cz)
@param v pointeur sur le modèle
@param angle angle de rotation du modèle en radian
@param centre pointeur sur le point3d servant de centre à la rotation
@return aucun
*/
void
a2ri_vef_rotateY_radian_center (
vef_model * m,
double angle,
const point3d * const centre)
{
//rotation de tous les sommets
for (int i = 0; i < m->nbvertex; i++)
{
vef_vertex_rotateY_center_radian (&(m->ve[i]), angle, centre);
//mis à jour de la bounding box
if (i == 0)
{
m->xmin = m->ve[i].x;
m->xmax = m->ve[i].x;
m->ymin = m->ve[i].y;
m->ymax = m->ve[i].y;
m->zmin = m->ve[i].z;
m->zmax = m->ve[i].z;
}
else
{
if (m->xmin > m->ve[i].x)
m->xmin = m->ve[i].x;
if (m->xmax < m->ve[i].x)
m->xmax = m->ve[i].x;
if (m->ymin > m->ve[i].y)
m->ymin = m->ve[i].y;
if (m->ymax < m->ve[i].y)
m->ymax = m->ve[i].y;
if (m->zmin > m->ve[i].z)
m->zmin = m->ve[i].z;
if (m->zmax < m->ve[i].z)
m->zmax = m->ve[i].z;
}
}
}
/**
Rotation d'un modèle en degre suivant l'axe Y de centre (cx,cy,cz)
@param v pointeur sur le modèle
@param angle angle de rotation du modèle en degre
@param centre pointeur sur le point3d servant de centre à la rotation
@return aucun
*/
void
a2ri_vef_rotateY_degre_center (
vef_model * m,
double angle,
const point3d * const centre)
{
//rotation de tous les sommets
for (int i = 0; i < m->nbvertex; i++)
{
vef_vertex_rotateY_center_degre (&(m->ve[i]), angle, centre);
//mis à jour de la bounding box
if (i == 0)
{
m->xmin = m->ve[i].x;
m->xmax = m->ve[i].x;
m->ymin = m->ve[i].y;
m->ymax = m->ve[i].y;
m->zmin = m->ve[i].z;
m->zmax = m->ve[i].z;
}
else
{
if (m->xmin > m->ve[i].x)
m->xmin = m->ve[i].x;
if (m->xmax < m->ve[i].x)
m->xmax = m->ve[i].x;
if (m->ymin > m->ve[i].y)
m->ymin = m->ve[i].y;
if (m->ymax < m->ve[i].y)
m->ymax = m->ve[i].y;
if (m->zmin > m->ve[i].z)
m->zmin = m->ve[i].z;
if (m->zmax < m->ve[i].z)
m->zmax = m->ve[i].z;
}
}
}
/**
Rotation d'un modèle en radian autour de l'axe Z
@param v pointeur sur le modèle
@param angle angle de rotation du modèle en radian
@return aucun
*/
void
a2ri_vef_rotateZ_radian (
vef_model * m,
double angle)
{
//rotation de tous les sommets
for (int i = 0; i < m->nbvertex; i++)
{
vef_vertex_rotateZ_radian (&(m->ve[i]), angle);
//mis à jour de la bounding box
if (i == 0)
{
m->xmin = m->ve[i].x;
m->xmax = m->ve[i].x;
m->ymin = m->ve[i].y;
m->ymax = m->ve[i].y;
m->zmin = m->ve[i].z;
m->zmax = m->ve[i].z;
}
else
{
if (m->xmin > m->ve[i].x)
m->xmin = m->ve[i].x;
if (m->xmax < m->ve[i].x)
m->xmax = m->ve[i].x;
if (m->ymin > m->ve[i].y)
m->ymin = m->ve[i].y;
if (m->ymax < m->ve[i].y)
m->ymax = m->ve[i].y;
if (m->zmin > m->ve[i].z)
m->zmin = m->ve[i].z;
if (m->zmax < m->ve[i].z)
m->zmax = m->ve[i].z;
}
}
}
/**
Rotation d'un modèle en degré autour de l'axe Z
@param v pointeur sur le modèle
@param angle angle de rotation du modèle en degré
@return aucun
*/
void
a2ri_vef_rotateZ_degre (
vef_model * m,
double angle)
{
//rotation de tous les sommets
for (int i = 0; i < m->nbvertex; i++)
{
vef_vertex_rotateZ_degre (&(m->ve[i]), angle);
//mis à jour de la bounding box
if (i == 0)
{
m->xmin = m->ve[i].x;
m->xmax = m->ve[i].x;
m->ymin = m->ve[i].y;
m->ymax = m->ve[i].y;
m->zmin = m->ve[i].z;
m->zmax = m->ve[i].z;
}
else
{
if (m->xmin > m->ve[i].x)
m->xmin = m->ve[i].x;
if (m->xmax < m->ve[i].x)
m->xmax = m->ve[i].x;
if (m->ymin > m->ve[i].y)
m->ymin = m->ve[i].y;
if (m->ymax < m->ve[i].y)
m->ymax = m->ve[i].y;
if (m->zmin > m->ve[i].z)
m->zmin = m->ve[i].z;
if (m->zmax < m->ve[i].z)
m->zmax = m->ve[i].z;
}
}
}
/**
Rotation d'un modèle en radian suivant l'axe Z de centre (cx,cy,cz)
@param v pointeur sur le modèle
@param angle angle de rotation du modèle en radian
@param centre pointeur sur le point3d servant de centre à la rotation
@return aucun
*/
void
a2ri_vef_rotateZ_radian_center (
vef_model * m,
double angle,
const point3d * const centre)
{
//rotation de tous les sommets
for (int i = 0; i < m->nbvertex; i++)
{
vef_vertex_rotateZ_center_radian (&(m->ve[i]), angle, centre);
//mis à jour de la bounding box
if (i == 0)
{
m->xmin = m->ve[i].x;
m->xmax = m->ve[i].x;
m->ymin = m->ve[i].y;
m->ymax = m->ve[i].y;
m->zmin = m->ve[i].z;
m->zmax = m->ve[i].z;
}
else
{
if (m->xmin > m->ve[i].x)
m->xmin = m->ve[i].x;
if (m->xmax < m->ve[i].x)
m->xmax = m->ve[i].x;
if (m->ymin > m->ve[i].y)
m->ymin = m->ve[i].y;
if (m->ymax < m->ve[i].y)
m->ymax = m->ve[i].y;
if (m->zmin > m->ve[i].z)
m->zmin = m->ve[i].z;
if (m->zmax < m->ve[i].z)
m->zmax = m->ve[i].z;
}
}
}
/**
Rotation d'un modèle en degre suivant l'axe Z de centre (cx,cy,cz)
@param v pointeur sur le modèle
@param angle angle de rotation du modèle en degre
@param centre pointeur sur le point3d servant de centre à la rotation
@return aucun
*/
void
a2ri_vef_rotateZ_degre_center (
vef_model * m,
double angle,
const point3d * const centre)
{
//rotation de tous les sommets
for (int i = 0; i < m->nbvertex; i++)
{
vef_vertex_rotateZ_center_degre (&(m->ve[i]), angle, centre);
//mis à jour de la bounding box
if (i == 0)
{
m->xmin = m->ve[i].x;
m->xmax = m->ve[i].x;
m->ymin = m->ve[i].y;
m->ymax = m->ve[i].y;
m->zmin = m->ve[i].z;
m->zmax = m->ve[i].z;
}
else
{
if (m->xmin > m->ve[i].x)
m->xmin = m->ve[i].x;
if (m->xmax < m->ve[i].x)
m->xmax = m->ve[i].x;
if (m->ymin > m->ve[i].y)
m->ymin = m->ve[i].y;
if (m->ymax < m->ve[i].y)
m->ymax = m->ve[i].y;
if (m->zmin > m->ve[i].z)
m->zmin = m->ve[i].z;
if (m->zmax < m->ve[i].z)
m->zmax = m->ve[i].z;
}
}
}
/**
Rotation d'un modèle en degré suivant l'axe donnée
@param m pointeur sur le modèle
@param angle angle de rotation du modèle en degre
@param axe l'axe de rotation
@return aucun
*/
void
a2ri_vef_rotate_axe_radian (
vef_model * m,
double angle,
const vector3d * const axe)
{
gsl_matrix *identity3,
*A,
*B,
*M;
double x = axe->dx;
double y = axe->dy;
double z = axe->dz;
identity3 = gsl_matrix_alloc (3, 3);
gsl_matrix_set_identity (identity3);
A = gsl_matrix_alloc (3, 3);
gsl_matrix_set (A, 0, 0, x * x);
gsl_matrix_set (A, 0, 1, x * y);
gsl_matrix_set (A, 0, 2, x * z);
gsl_matrix_set (A, 1, 0, x * y);
gsl_matrix_set (A, 1, 1, y * y);
gsl_matrix_set (A, 1, 2, y * z);
gsl_matrix_set (A, 2, 0, x * z);
gsl_matrix_set (A, 2, 1, y * z);
gsl_matrix_set (A, 2, 2, z * z);
B = gsl_matrix_alloc (3, 3);
gsl_matrix_set (B, 0, 0, 0);
gsl_matrix_set (B, 0, 1, -z);
gsl_matrix_set (B, 0, 2, y);
gsl_matrix_set (B, 1, 0, z);
gsl_matrix_set (B, 1, 1, 0);
gsl_matrix_set (B, 1, 2, -x);
gsl_matrix_set (B, 2, 0, -y);
gsl_matrix_set (B, 2, 1, x);
gsl_matrix_set (B, 2, 2, 0);
M =
matrix_add (matrix_add
(matrix_mul_scale (identity3, cos (angle)),
matrix_mul_scale (A, 1 - cos (angle))), matrix_mul_scale (B,
sin
(angle)));
//rotation de tous les sommets
for (int i = 0; i < m->nbvertex; i++)
{
vef_vertex_rotate_axe_radian (&(m->ve[i]), M);
//mis à jour de la bounding box
if (i == 0)
{
m->xmin = m->ve[i].x;
m->xmax = m->ve[i].x;
m->ymin = m->ve[i].y;
m->ymax = m->ve[i].y;
m->zmin = m->ve[i].z;
m->zmax = m->ve[i].z;
}
else
{
if (m->xmin > m->ve[i].x)
m->xmin = m->ve[i].x;
if (m->xmax < m->ve[i].x)
m->xmax = m->ve[i].x;
if (m->ymin > m->ve[i].y)
m->ymin = m->ve[i].y;
if (m->ymax < m->ve[i].y)
m->ymax = m->ve[i].y;
if (m->zmin > m->ve[i].z)
m->zmin = m->ve[i].z;
if (m->zmax < m->ve[i].z)
m->zmax = m->ve[i].z;
}
}
gsl_matrix_free (A);
gsl_matrix_free (B);
gsl_matrix_free (M);
gsl_matrix_free (identity3);
}
/**
Calcul de l'aire totale d'un modèle
@param m le modèle
@return aire totale du modèle
*/
double
a2ri_vef_area (
const vef_model * const m)
{
int ve1,
ve2,
ve3;
double sumarea = 0.0;
point3d A,
B,
C;
//somme des aires de toutes les faces
for (int i = 0; i < m->nbface; i++)
{
vef_face_get_vertices (&(m->fa[i]), m->ed, &ve1, &ve2, &ve3);
point3d_init (&A, m->ve[ve1].x, m->ve[ve1].y, m->ve[ve1].z);
point3d_init (&B, m->ve[ve2].x, m->ve[ve2].y, m->ve[ve2].z);
point3d_init (&C, m->ve[ve3].x, m->ve[ve3].y, m->ve[ve3].z);
sumarea += point3d_area (&A, &B, &C);
}
return sumarea;
}
/**
Ajout des points d'un vef_model dans une partition de l'espace
@param m le modèle
@param sp la partition de l'espace
@return aucun
*/
void
a2ri_vef_space_partition (
const vef_model * const m,
space_partition * sp)
{
point3d p;
for (int i = 0; i < m->nbvertex; i++)
{
point3d_init (&p, m->ve[i].x, m->ve[i].y, m->ve[i].z);
p.att_int = i;
space_partition_add_point (sp, &p);
}
}
/**
Conversion d'un vef_model en liste de point3d
@param m le modèle
@return la liste de point3d
**/
point3d *
a2ri_vef_to_list_point3d(
const vef_model * const m)
{
point3d *retour=(point3d*)malloc(m->nbvertex*sizeof(point3d));
a2ri_erreur_critique_si(retour==NULL,"(a2ri_vf_to_list_point3d) - erreur allocation mémoire pour retour\n");
for(int i=0;inbvertex;i++)
point3d_init(&retour[i],m->ve[i].x,m->ve[i].y,m->ve[i].z);
return retour;
}
/**
Conversion d'un vef_model en vf_model
@param m le modèle à convertir
@return un pointeur sur le vf_model
**/
vf_model *
a2ri_vef_to_vf (
const vef_model * const m)
{
vf_model *retour=(vf_model*)malloc(sizeof(vf_model));
a2ri_erreur_critique_si(retour==NULL,"erreur allocation mémoire pour retour dans a2ri_vef_to_vf");
a2ri_vf_init(retour);
for(int i=0;inbvertex;i++)
a2ri_vf_add_vertex(retour,m->ve[i].x,m->ve[i].y,m->ve[i].z);
int ve1,ve2,ve3;
for(int i=0;inbface;i++)
{
vef_face_get_vertices(&(m->fa[i]),m->ed,&ve1,&ve2,&ve3);
a2ri_vf_add_face(retour,ve1,ve2,ve3);
}
retour->xmin=m->xmin;
retour->xmax=m->xmax;
retour->ymin=m->ymin;
retour->ymax=m->ymax;
retour->zmin=m->zmin;
retour->zmax=m->zmax;
return retour;
}