123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665 |
- /*************************************/
- /* Auteur : Rémi Synave */
- /* Date de création : 01/03/07 */
- /* Date de modification : 15/03/15 */
- /* Version : 0.4 */
- /*************************************/
- /***************************************************************************/
- /* 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 <http://www.gnu.org/licenses/>. */
- /***************************************************************************/
- #include "topology.h"
- /********** INTERMEDIATE TYPES AND FUNCTIONS **********/
- /* Les fonctions intermédiaires sont préfixées de IF */
- /* et les types intermédiaires de IT */
- typedef struct
- {
- int *list;
- int nbelt;
- } ITlistecouple;
- void
- IFstar_byedge (
- const vf_model * const m,
- int ** list,
- int * size,
- int depth,
- const hashtable * const table)
- {
- int sizetemp = *size;
- vf_edge *edgetemp;
- if (depth == 0)
- return;
- for (int i = 0; i < sizetemp; i++)
- {
- int ve1 = m->fa[(*list)[i]].ve1;
- int ve2 = m->fa[(*list)[i]].ve2;
- int ve3 = m->fa[(*list)[i]].ve3;
- //1ere arete
- edgetemp = hashtable_look_for (table, ve1, ve2);
- if (edgetemp->nbsharedfaces == 2)
- {
- if (edgetemp->sharedfaces[0] == (*list)[i])
- list_int_add (list, size, edgetemp->sharedfaces[1],
- WITHOUT_REDUNDANCE);
- else
- list_int_add (list, size, edgetemp->sharedfaces[0],
- WITHOUT_REDUNDANCE);
- }
- //2eme arete
- edgetemp = hashtable_look_for (table, ve1, ve3);
- if (edgetemp->nbsharedfaces == 2)
- {
- if (edgetemp->sharedfaces[0] == (*list)[i])
- list_int_add (list, size, edgetemp->sharedfaces[1],
- WITHOUT_REDUNDANCE);
- else
- list_int_add (list, size, edgetemp->sharedfaces[0],
- WITHOUT_REDUNDANCE);
- }
- //3eme arete
- edgetemp = hashtable_look_for (table, ve2, ve3);
- if (edgetemp->nbsharedfaces == 2)
- {
- if (edgetemp->sharedfaces[0] == (*list)[i])
- list_int_add (list, size, edgetemp->sharedfaces[1],
- WITHOUT_REDUNDANCE);
- else
- list_int_add (list, size, edgetemp->sharedfaces[0],
- WITHOUT_REDUNDANCE);
- }
- }
- IFstar_byedge (m, list, size, depth - 1, table);
- }
- void
- IFstar_byvertex (
- const vf_model * const m,
- int **list,
- int *size,
- int depth,
- const hashtable * const table)
- {
- int sizetemp = *size;
- vf_edge *edgetemp;
- int ve[3];
- if (depth == 0)
- return;
- for (int i = 0; i < sizetemp; i++)
- {
- ve[0] = m->fa[(*list)[i]].ve1;
- ve[1] = m->fa[(*list)[i]].ve2;
- ve[2] = m->fa[(*list)[i]].ve3;
- for (int j = 0; j < 3; j++)
- {
- for (int k = 0; k < m->ve[ve[j]].nbincidentvertices; k++)
- {
- edgetemp =
- hashtable_look_for (table, ve[j],
- m->ve[ve[j]].incidentvertices[k]);
- for (int l = 0; l < edgetemp->nbsharedfaces; l++)
- if (edgetemp->sharedfaces[l] != (*list)[i])
- list_int_add (list, size, edgetemp->sharedfaces[l],
- WITHOUT_REDUNDANCE);
- }
- }
- }
- IFstar_byvertex (m, list, size, depth - 1, table);
- }
- //on cherche les aretes qui ne partagent qu'une seule face et on ajoute leur sommet dans une liste
- //résultat : la liste des sommets appartenant au bord du maillage
- void
- IFlook_for_border (
- int key,
- vf_edge * value,
- void *user_data)
- {
- ITlistecouple *list = user_data;
- if (value->nbsharedfaces == 1)
- {
- list_int_add (&(list->list), &(list->nbelt), value->ve1,
- WITH_REDUNDANCE);
- list_int_add (&(list->list), &(list->nbelt), value->ve2,
- WITH_REDUNDANCE);
- }
- }
- //on cherche à retrouver un cycle dans la liste des sommets appartenant au bord du maillage
- void
- IFcycle (
- ITlistecouple * list,
- ITlistecouple * cycle)
- {
- int trouve = 1;
- int next = (*list).list[1];
- //on ajoute le premier et le second sommet
- list_int_add (&(cycle->list), &(cycle->nbelt), (*list).list[0],
- WITH_REDUNDANCE);
- list_int_add (&(cycle->list), &(cycle->nbelt), (*list).list[1],
- WITH_REDUNDANCE);
- while (next != (*list).list[0] && trouve)
- {
- trouve = 0;
- //dans le reste de la liste, on cherche le couple dont le premier element correspond au dernier element ajouté
- for (int i = 0; i < (*list).nbelt / 2; i++)
- {
- if ((*list).list[i * 2] == cycle->list[(cycle->nbelt) - 1])
- {
- //on a correspondance entre le premier element du couple et le dernier element ajouté
- if ((*list).list[i * 2 + 1] != (*list).list[0])
- {
- //l'element trouvé ne correpond pas au premier element
- //on ajoute donc le sommet suivant
- list_int_add (&(cycle->list), &(cycle->nbelt),
- (*list).list[i * 2 + 1], WITH_REDUNDANCE);
- next = (*list).list[i * 2 + 1];
- list_int_remove (&((*list).list), &((*list).nbelt),
- i * 2 + 1);
- list_int_remove (&((*list).list), &((*list).nbelt), i * 2);
- }
- else
- {
- //on a correpondance entre l'element à ajouter et le premier élément donc nous avons trouvé un cycle
- next = (*list).list[0];
- list_int_add (&(cycle->list), &(cycle->nbelt),
- -1, WITH_REDUNDANCE);
- //on termine l'algorithme en mettant next à la valeur du premier element
- list_int_remove (&((*list).list), &((*list).nbelt),
- i * 2 + 1);
- list_int_remove (&((*list).list), &((*list).nbelt), i * 2);
- }
- trouve = 1;
- }
- }
- }
- list_int_remove (&((*list).list), &((*list).nbelt), 1);
- list_int_remove (&((*list).list), &((*list).nbelt), 0);
- }
- void
- IFvf_complete_partie_connexe (
- const vf_model * const m,
- const hashtable * const table,
- int *list,
- int numface,
- int numpartie,
- int *nbaffect,
- int *nbrecurs)
- {
- int p1,
- p2;
- printf("nbrecurs : %d\n",*nbrecurs);
- *nbrecurs=*nbrecurs+1;
-
- if (list[numface] != -1)
- return;
- //la première face est affectée du numéro de partie
- list[numface] = numpartie;
- *nbaffect = (*nbaffect) + 1;
- //pour la premiere arete de la face,
- p1 = m->fa[numface].ve1;
- p2 = m->fa[numface].ve2;
- //printf("blop3.5 - %d %d\n",p1,p2);
- vf_edge *edgetemp = hashtable_look_for (table, p1, p2);
- //printf("blop4\n");
- //on regarde si elle partage deux faces
- if (edgetemp->nbsharedfaces == 2)
- {
- //dans ce cas, on relance la fonction avec le meme modele, les memes aretes, la meme list de parties, le numero de la face partagée, le meme numéro de parties et le meme nombre de faces affecté
- if (edgetemp->sharedfaces[0] == numface)
- IFvf_complete_partie_connexe (m, table, list,
- edgetemp->sharedfaces[1], numpartie,
- nbaffect,nbrecurs);
- else
- IFvf_complete_partie_connexe (m, table, list,
- edgetemp->sharedfaces[0], numpartie,
- nbaffect,nbrecurs);
- }
- //printf("blop5\n");
- //on recommence l'opération précédente avec la seconde et la troisième arete de la face
- p1 = m->fa[numface].ve2;
- p2 = m->fa[numface].ve3;
- //printf("blop5.5 - %d %d\n",p1,p2);
- edgetemp = hashtable_look_for (table, p1, p2);
- //printf("blop6\n");
- if (edgetemp->nbsharedfaces == 2)
- {
- if (edgetemp->sharedfaces[0] == numface)
- IFvf_complete_partie_connexe (m, table, list,
- edgetemp->sharedfaces[1], numpartie,
- nbaffect,nbrecurs);
- else
- IFvf_complete_partie_connexe (m, table, list,
- edgetemp->sharedfaces[0], numpartie,
- nbaffect,nbrecurs);
- }
- //printf("blop7\n");
- p1 = m->fa[numface].ve3;
- p2 = m->fa[numface].ve1;
- //printf("blop7.5 - %d %d\n",p1,p2);
- edgetemp = hashtable_look_for (table, p1, p2);
- //printf("blop8\n");
- if (edgetemp->nbsharedfaces == 2)
- {
- if (edgetemp->sharedfaces[0] == numface)
- IFvf_complete_partie_connexe (m, table, list,
- edgetemp->sharedfaces[1], numpartie,
- nbaffect,nbrecurs);
- else
- IFvf_complete_partie_connexe (m, table, list,
- edgetemp->sharedfaces[0], numpartie,
- nbaffect,nbrecurs);
- }
- }
- void
- IFvef_complete_partie_connexe (
- const vef_model * const m,
- int *list,
- int numface,
- int numpartie,
- int *nbaffect)
- {
- int ed1 = m->fa[numface].ed1,
- ed2 = m->fa[numface].ed2,
- ed3 = m->fa[numface].ed3;
- char *temp = NULL;
- if (list[numface] != -1)
- return;
- temp = (char *) malloc (20 * sizeof (char));
- a2ri_erreur_critique_si (temp == NULL,
- "erreur allocation memoire pour temp\nIFvef_complete_partie_connexe");
- //la première face est affecté du numéro de partie
- list[numface] = numpartie;
- *nbaffect = (*nbaffect) + 1;
- //pour la premiere arete de la face,
- //on regarde si elle partage deux faces
- if (m->ed[ed1].nbsharedfaces == 2)
- {
- //dans ce cas, on relance la fonction avec le meme modele, les memes aretes, la meme list de parties, le numero de la face partagée, le meme numéro de parties et le meme nombre de faces affecté
- if (m->ed[ed1].sharedfaces[0] == numface)
- IFvef_complete_partie_connexe (m, list, m->ed[ed1].sharedfaces[1],
- numpartie, nbaffect);
- else
- IFvef_complete_partie_connexe (m, list, m->ed[ed1].sharedfaces[0],
- numpartie, nbaffect);
- }
- //on recommence l'opération précédente avec la seconde et la troisième arete de la face
- if (m->ed[ed2].nbsharedfaces == 2)
- {
- if (m->ed[ed2].sharedfaces[0] == numface)
- IFvef_complete_partie_connexe (m, list, m->ed[ed2].sharedfaces[1],
- numpartie, nbaffect);
- else
- IFvef_complete_partie_connexe (m, list, m->ed[ed2].sharedfaces[0],
- numpartie, nbaffect);
- }
- if (m->ed[ed3].nbsharedfaces == 2)
- {
- if (m->ed[ed3].sharedfaces[0] == numface)
- IFvef_complete_partie_connexe (m, list, m->ed[ed3].sharedfaces[1],
- numpartie, nbaffect);
- else
- IFvef_complete_partie_connexe (m, list, m->ed[ed3].sharedfaces[0],
- numpartie, nbaffect);
- }
- free (temp);
- }
- /********** MAIN FUNCTIONS **********/
- /**
- Recherche du voisinage pour une liste de faces et à une profondeur donnée
- @param type BYVERTEX ou BYEDGE <BR> BYVERTEX : recherche du voisinage par sommet <BR> BYEDGE : recherche du voisinage par arete.
- @param m le modèle
- @param faces tableau contenant les numéros des faces de d\303\251part
- @param nbfaces taille du tableau
- @param list pointeur sur le tableau des faces contenu dans le voisinage
- @param size pointeur sur le nombre de faces dans le voisinage
- @param depth profondeur du voisinage
- @return aucun
- */
- void
- a2ri_vf_star (
- int type,
- const vf_model * const m,
- const int * const faces,
- int nbfaces,
- int **list,
- int *size,
- int depth)
- {
- int *listclone = NULL;
- hashtable *table = a2ri_vf_construction_edge_table (m, NULL, 0);
- list_int_clone (faces, nbfaces, &listclone);
- *size = nbfaces;
- if (type == BYEDGE)
- {
- IFstar_byedge (m, &listclone, size, depth, table);
- *list = listclone;
- }
- else
- {
- IFstar_byvertex (m, &listclone, size, depth, table);
- *list = listclone;
- }
- hashtable_free (table);
- free (table);
- }
- /**
- Calcul du nombre de trous/nombre de limites dans le modèle
- @param m le modèle
- @return nombre de trous/limites
- */
- int
- a2ri_vf_nb_hole (
- const vf_model * const m)
- {
- int nbtrou = 0;
- ITlistecouple lescouples,
- lescycles;
- lescouples.list = NULL;
- lescouples.nbelt = 0;
- lescycles.list = NULL;
- lescycles.nbelt = 0;
- hashtable *table = a2ri_vf_construction_edge_table (m, NULL, 0);
- hashtable_foreach (table, IFlook_for_border, &lescouples);
- //si on ne trouve aucun sommet sur le bord du maillage
- if (lescouples.nbelt == 0)
- {
- hashtable_free (table);
- free (table);
- free (lescouples.list);
- free (lescycles.list);
- //il n'y a pas de trou
- return nbtrou;
- }
- #ifdef _DEBUG
- printf("--> lescouples\n");
- list_int_display(lescouples.list,lescouples.nbelt);
- #endif
- //sinon tant qu'on a des elements dans la liste, on cherche un nouveau cycle
- while (lescouples.nbelt != 0)
- {
- IFcycle (&lescouples, &lescycles);
- //le nombre de cycle correspond au nombre de trou
- nbtrou++;
- }
- #ifdef _DEBUG
- printf("--> lescycles\n");
- list_int_display(lescycles.list,lescycles.nbelt);
- #endif
- hashtable_free (table);
- free (table);
- free (lescouples.list);
- free (lescycles.list);
- return nbtrou;
- }
- /**
- Calcul du nombre de trous/nombre de limites dans le modèle
- @param m le modèle
- @return nombre de trous/limites
- */
- int
- a2ri_vef_nb_hole (
- const vef_model * const m)
- {
- int nbtrou = 0;
- ITlistecouple lescouples,
- lescycles;
- lescouples.list = NULL;
- lescouples.nbelt = 0;
- lescycles.list = NULL;
- lescycles.nbelt = 0;
- for (int i = 0; i < m->nbedge; i++)
- if (m->ed[i].nbsharedfaces == 1)
- {
- list_int_add (&(lescouples.list), &(lescouples.nbelt), m->ed[i].ve1,
- WITH_REDUNDANCE);
- list_int_add (&(lescouples.list), &(lescouples.nbelt), m->ed[i].ve2,
- WITH_REDUNDANCE);
- }
- //si on ne trouve aucun sommet sur le bord du maillage
- if (lescouples.nbelt == 0)
- //il n'y a pas de trou
- return nbtrou;
- //sinon tant qu'on a des elements dans la liste, on cherche un nouveau cycle
- while (lescouples.nbelt != 0)
- {
- IFcycle (&lescouples, &lescycles);
- //le nombre de cycle correspond au nombre de trou
- nbtrou++;
- }
- free (lescouples.list);
- free (lescycles.list);
- return nbtrou;
- }
- /**
- Calcul du nombre de parties connexes contenu dans le modèle
- @param m le modèle
- @param list tableau d'entier représentant les faces du modèle et contenant le numéro de la partie à laquelle la face appartient.
- @return nombre de parties connexes
- */
- int
- a2ri_vf_nb_connected_part (
- const vf_model * const m,
- int **list)
- {
- int nbpart = 0,
- nbaffect = 0,
- nbrecurs=0,
- j;
- int *parties = NULL;
- parties = (int *) malloc (m->nbface * sizeof (int));
- a2ri_erreur_critique_si (parties == NULL,
- "erreur allocation memoire pour parties\na2ri_vf_nb_connected_part");
- //parties sera le tableau qui donnera le numero de la parties à laquelle apparient la face du meme index
- // les parties sont initialisées à -1
- for (int i = 0; i < m->nbface; i++)
- parties[i] = -1;
- hashtable *table = a2ri_vf_construction_edge_table (m, NULL, 0);
- //tant que toutes les faces n'ont pas trouvées de numéro de parties, on continu
- while (nbaffect != m->nbface)
- {
- nbrecurs=0;
- j = 0;
- //on cherche la première face n'ayant pas de numéro de parties donc ne faisant parties d'aucun groupe
- while (parties[j] != -1)
- j++;
- //on appelle la fonction avec le modèle, les aretes, le tableau des parties, le numéro de la première face, le numéro de la nouvelle partie et enfin le nombre de face deja affecté d'un numéro de parties
- IFvf_complete_partie_connexe (m, table, parties, j, nbpart,
- &nbaffect,&nbrecurs);
- //nous avons trouvé une nouvelle partie
- nbpart++;
- }
- *list = parties;
- hashtable_free (table);
- free (table);
- return nbpart;
- }
- /**
- Calcul du nombre de parties connexes contenu dans le modèle
- @param m le modèle
- @param list tableau d'entier représentant les faces du modèle et contenant le numéro de la partie à laquelle la face appartient.
- @return nombre de parties connexes
- */
- int
- a2ri_vef_nb_connected_part (
- const vef_model * const m,
- int **list)
- {
- int nbpart = 0,
- nbaffect = 0,
- j;
- int *parties = NULL;
- parties = (int *) malloc (m->nbface * sizeof (int));
- a2ri_erreur_critique_si (parties == NULL,
- "erreur allocation memoire pour parties\na2ri_vef_nb_connected_part");
- //parties sera le tableau qui donnera le numero de la parties à laquelle apparient la face du meme index
- // les parties sont initialisées à -1
- for (int i = 0; i < m->nbface; i++)
- parties[i] = -1;
- //tant que toutes les faces n'ont pas trouvées de numéro de parties, on continu
- while (nbaffect != m->nbface)
- {
- j = 0;
- //on cherche la première face n'ayant pas de numéro de parties donc ne faisant parties d'aucun groupe
- while (parties[j] != -1)
- j++;
- //on appelle la fonction avec le modèle, les aretes, le tableau des parties, le numéro de la première face, le numéro de la nouvelle partie et enfin le nombre de face deja affecté d'un numéro de parties
- IFvef_complete_partie_connexe (m, parties, j, nbpart, &nbaffect);
- //nous avons trouvé une nouvelle partie
- nbpart++;
- }
- *list = parties;
- return nbpart;
- }
- /**
- Cherche un trou/cycle dans le maillage contenant les deux sommets
- @param m le modele
- @param ve1 premier sommet qui doit etre contenu dans le cycle
- @param ve2 second sommet qui doit etre contenu dans le cycle
- @param list liste des sommets formant le cycle
- @param size taille de la liste
- **/
- void
- a2ri_vf_search_hole_contains (
- const vf_model * const m,
- int ve1,
- int ve2,
- int ** list,
- int * size)
- {
- ITlistecouple lescouples,
- lescycles;
- lescouples.list = NULL;
- lescouples.nbelt = 0;
- lescycles.list = NULL;
- lescycles.nbelt = 0;
- hashtable *table = a2ri_vf_construction_edge_table (m, NULL, 0);
- hashtable_foreach (table, IFlook_for_border, &lescouples);
- //si on ne trouve aucun sommet sur le bord du maillage
- if (lescouples.nbelt == 0)
- {
- hashtable_free (table);
- free (table);
- free (lescouples.list);
- free (lescycles.list);
- //il n'y a pas de trou
- *list = NULL;
- *size = 0;
- return;
- }
- //sinon tant qu'on a des elements dans la liste, on cherche un nouveau cycle
- while (lescouples.nbelt != 0)
- {
- IFcycle (&lescouples, &lescycles);
- //le nombre de cycle correspond au nombre de trou
- if (list_int_contains (lescycles.list, lescycles.nbelt, ve1) != -1 &&
- list_int_contains (lescycles.list, lescycles.nbelt, ve2) != -1)
- {
- *list = lescycles.list;
- *size = lescycles.nbelt;
- free (lescouples.list);
- hashtable_free (table);
- free (table);
- return;
- }
- free (lescycles.list);
- lescycles.list = NULL;
- lescycles.nbelt = 0;
- }
- hashtable_free (table);
- free (table);
- free (lescouples.list);
- free (lescycles.list);
- *list = NULL;
- *size = 0;
- return;
- }
|