/*************************************/
/* Auteur : Rémi Synave              */
/* Date de création : 10/03/10       */
/* Date de modification : 10/12/14   */
/* Version : 0.3                     */
/*************************************/

/***************************************************************************/
/* 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 "io.h"

/********** INTERMEDIATE TYPES AND FUNCTIONS **********/
/* Les fonctions intermédiaires sont préfixées de IF  */
/* et les types intermédiaires de IT                  */

void
IFaffichage_chargement (
		      FILE * is,
		      long posmax)
{
  long poscur;

  poscur = ftell (is);
  printf ("%c%c%c%c%c%c%c%c%c%c%c%c%c%lf %c", 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
	  8, 8, ((poscur) * 100.0) / (posmax * 1.0), 37);
}

//fonction qui ecrit les aretes dans un fichier vef
void IFsave_vef_write_edge (
			  vf_model * m,
			  hashtable * table,
			  FILE * os)
{
  int p1,
    p2;
  int indexarete = 0;
  
  //pour toute les faces, on regarde si l'arete existe deja dans la table de hachage
  //si oui, on ne fait rien 
  //sinon on entre l'arete dans la table et on l'ecrit dans le fichier. 
  //on enregistre également son index pour l'écriture des faces définies par trois aretes
  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\nIFsave_vef_write_edge");
	  edgetemp->ve1 = p1;
	  edgetemp->ve2 = p2;
	  edgetemp->att_int = indexarete;
	  indexarete++;
	  fprintf (os, "%d %d\n", p1, p2);
	  hashtable_add (table, edgetemp);
	}
      
      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\nIFsave_vef_write_edge");
	  edgetemp->ve1 = p1;
	  edgetemp->ve2 = p2;
	  edgetemp->att_int = indexarete;
	  indexarete++;
	  fprintf (os, "%d %d\n", p1, p2);
	  hashtable_add (table, edgetemp);
	}
      
      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\nIFsave_vef_write_edge");
	  edgetemp->ve1 = p1;
	  edgetemp->ve2 = p2;
	  edgetemp->att_int = indexarete;
	  indexarete++;
	  fprintf (os, "%d %d\n", p1, p2);
	  hashtable_add (table, edgetemp);
	}
    }
}

//fonction qui ecrit les aretes dans un fichier gts
void IFsave_gts_write_edge (
			  vf_model * m,
			  hashtable * table,
			  FILE * os)
{
  int p1,
    p2;
  int indexarete = 0;
  
  //pour toute les faces, on regarde si l'arete existe deja dans la table de hachage
  //si oui, on ne fait rien 
  //sinon on entre l'arete dans la table et on l'ecrit dans le fichier. 
  //on enregistre également son index pour l'écriture des faces définies par trois aretes
  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\nIFsave_gts_write_edge");
	  edgetemp->ve1 = p1;
	  edgetemp->ve2 = p2;
	  edgetemp->att_int = indexarete;
	  indexarete++;
	  fprintf (os, "%d %d\n", p1 + 1, p2 + 1);
	  hashtable_add (table, edgetemp);
	}
      
      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\nIFsave_gts_write_edge");
	  edgetemp->ve1 = p1;
	  edgetemp->ve2 = p2;
	  edgetemp->att_int = indexarete;
	  indexarete++;
	  fprintf (os, "%d %d\n", p1 + 1, p2 + 1);
	  hashtable_add (table, edgetemp);
	}
      
      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\nIFsave_gts_write_edge");
	  edgetemp->ve1 = p1;
	  edgetemp->ve2 = p2;
	  edgetemp->att_int = indexarete;
	  indexarete++;
	  fprintf (os, "%d %d\n", p1 + 1, p2 + 1);
	  hashtable_add (table, edgetemp);
	}
    }
}

/********** MAIN FUNCTIONS **********/

/**
   Ouverture d'un fichier contenant un modèle
   @param file chemin du fichier à ouvrir
   @param m pointeur sur le modèle
   @return 1 si succès, 0 sinon
*/
int
a2ri_vf_open_file (
		   char *file,
		   vf_model * m)
{
  char ext[5];
  
  memcpy (ext, file + (strlen (file) - 4), 4);
  ext[4] = 0;

  //appel de la bonne fonction en fonction de l'extension du fichier
  if (!strcmp (ext, ".wrl"))
    return (a2ri_vf_load_wrl (file, m));

  if (!strcmp (ext, ".asc"))
    return (a2ri_vf_load_asc (file, m));

  if (!strcmp (ext, ".vef"))
    return (a2ri_vf_load_vef (file, m));

  if (!strcmp (ext, ".pgn"))
    return (a2ri_vf_load_pgn (file, m));

  if (!strcmp (ext, ".ply"))
    return (a2ri_vf_load_ply (file, m));

  if (!strcmp (ext, ".off"))
    return (a2ri_vf_load_off (file, m));

  if (!strcmp (ext, ".obj"))
    return (a2ri_vf_load_obj (file, m));

  if (!strcmp (ext, ".gts"))
    return (a2ri_vf_load_gts (file, m));

  if (!strcmp (ext, ".stl"))
    return (a2ri_vf_load_stl (file, m));

  return 0;

}

/**
   Ouverture d'un fichier asc contenant un nuage de point
   @param file chemin du fichier à ouvrir
   @param m pointeur sur le modèle
   @return 1 si succès, 0 sinon
*/
int
a2ri_vf_load_asc (
		  char *file,
		  vf_model * m)
{

  FILE *is = NULL;
  double coordx,
    coordy,
    coordz;
  int i;

  setlocale(LC_NUMERIC,"C");

  is = fopen (file, "r");
  if (is == NULL)
    return 0;

  i=0;
  fscanf (is, "%lf %lf %lf", &coordx, &coordy, &coordz);
  while(!feof(is))
    {
      //fscanf (is, "%lf %lf %lf", &coordx, &coordy, &coordz);
      a2ri_vf_add_vertex (m, coordx, coordy, coordz);
      if (i == 0)
	{
	  m->xmin = coordx;
	  m->xmax = coordx;
	  m->ymin = coordy;
	  m->ymax = coordy;
	  m->zmin = coordz;
	  m->zmax = coordz;
	}
      else
	{
	  //mis à jour de la bounding box du modèle
	  if (coordx < m->xmin)
	    m->xmin = coordx;
	  if (coordx > m->xmax)
	    m->xmax = coordx;
	  if (coordy < m->ymin)
	    m->ymin = coordy;
	  if (coordy > m->ymax)
	    m->ymax = coordy;
	  if (coordz < m->zmin)
	    m->zmin = coordz;
	  if (coordz > m->zmax)
	    m->zmax = coordz;
	}
      fscanf (is, "%lf %lf %lf", &coordx, &coordy, &coordz);
      fscanf (is, "%lf %lf %lf", &coordx, &coordy, &coordz);
      i=1;
    }

  fclose (is);

  setlocale(LC_NUMERIC,"");

  return 1;

}

/**
   Ouverture d'un fichier pgn contenant un modèle
   @param file chemin du fichier à ouvrir
   @param m pointeur sur le modèle
   @return 1 si succès, 0 sinon
*/
int
a2ri_vf_load_pgn (
		  char *file,
		  vf_model * m)
{

  FILE *is = NULL;
  int nbvertex,
    nbface,
    ve1,
    ve2,
    ve3;
  double coordx,
    coordy,
    coordz;

  setlocale(LC_NUMERIC,"C");

  is = fopen (file, "r");
  if (is == NULL)
    return 0;

  //lecture du nombre de sommets et de faces
  fscanf (is, "%d %d", &nbvertex, &nbface);

  //lecture des sommets
  for (int i = 0; i < nbvertex; i++)
    {
      fscanf (is, "%lf %lf %lf", &coordx, &coordy, &coordz);
      a2ri_vf_add_vertex (m, coordx, coordy, coordz);
      if (i == 0)
	{
	  m->xmin = coordx;
	  m->xmax = coordx;
	  m->ymin = coordy;
	  m->ymax = coordy;
	  m->zmin = coordz;
	  m->zmax = coordz;
	}
      else
	{
	  //mis à jour de la bounding box du modèle
	  if (coordx < m->xmin)
	    m->xmin = coordx;
	  if (coordx > m->xmax)
	    m->xmax = coordx;
	  if (coordy < m->ymin)
	    m->ymin = coordy;
	  if (coordy > m->ymax)
	    m->ymax = coordy;
	  if (coordz < m->zmin)
	    m->zmin = coordz;
	  if (coordz > m->zmax)
	    m->zmax = coordz;
	}
    }

  //lecture des faces
  for (int i = 0; i < nbface; i++)
    {
      fscanf (is, "%d %d %d", &ve1, &ve2, &ve3);
      a2ri_vf_add_face (m, ve1, ve2, ve3);

      fscanf (is, "%d", &ve1);
    }

  fclose (is);

  setlocale(LC_NUMERIC,"");

  return 1;

}

/**
   Ouverture d'un fichier obj contenant un modèle
   @param file chemin du fichier à ouvrir
   @param m pointeur sur le modèle
   @return 1 si succès, 0 sinon
*/
int
a2ri_vf_load_obj (
		  char *file,
		  vf_model * m)
{

  FILE *is = NULL;
  int ve1,
    ve2,
    ve3;
  double coordx,
    coordy,
    coordz;
  char str[250],
    str_ve1[20],
    str_ve2[20],
    str_ve3[20];

  setlocale(LC_NUMERIC,"C");

  is = fopen (file, "r");
  if (is == NULL)
    return 0;

  fscanf (is, "%s", str);


  while (strcmp (str, "v") != 0)
    fscanf (is, "%s", str);

  //lecture des sommets
  while (strcmp (str, "v") == 0  && !feof (is))
    {
      fscanf (is, "%lf %lf %lf", &coordx, &coordy, &coordz);
      //ajout d'un sommet
      a2ri_vf_add_vertex (m, coordx, coordy, coordz);
      fscanf (is, "%s", str);
      //mis à jour de la bounding box
      if (m->nbvertex == 1)
	{
	  m->xmin = coordx;
	  m->xmax = coordx;
	  m->ymin = coordy;
	  m->ymax = coordy;
	  m->zmin = coordz;
	  m->zmax = coordz;
	}
      else
	{
	  if (coordx < m->xmin)
	    m->xmin = coordx;
	  if (coordx > m->xmax)
	    m->xmax = coordx;
	  if (coordy < m->ymin)
	    m->ymin = coordy;
	  if (coordy > m->ymax)
	    m->ymax = coordy;
	  if (coordz < m->zmin)
	    m->zmin = coordz;
	  if (coordz > m->zmax)
	    m->zmax = coordz;
	}
    }

  while (strcmp (str, "f") != 0  && !feof (is))
    {
      fscanf (is, "%s", str);
    }

  //lecture des faces
  while (strcmp (str, "f") == 0 && !feof (is))
    {
      fscanf (is, "%s %s %s", str_ve1, str_ve2, str_ve3);
      ve1 = atoi (str_ve1);
      ve2 = atoi (str_ve2);
      ve3 = atoi (str_ve3);
      ve1--;
      ve2--;
      ve3--;
      //ajout d'une face
      a2ri_vf_add_face (m, ve1, ve2, ve3);

      fscanf (is, "%s", str);
      if (str[0] >= '0' && str[0] <= '9')
	{
	  ve2 = atoi (str);
	  ve2--;
	  a2ri_vf_add_face (m, ve3, ve2, ve1);
	  fscanf (is, "%s", str);
	}
    }

  fclose (is);

  setlocale(LC_NUMERIC,"");

  return 1;

}

/**
   Ouverture d'un fichier wrl contenant un modèle
   @param file chemin du fichier à ouvrir
   @param m pointeur sur le modèle
   @return 1 si succès, 0 sinon
*/
int
a2ri_vf_load_wrl1 (
		   char *file,
		   vf_model * m)
{
  FILE *is = NULL;
  char str[20];
  char coordx[15],
    coordy[15],
    coordz[15];

  setlocale(LC_NUMERIC,"C");

  is = fopen (file, "r");
  if (is == NULL)
    return 0;

  fscanf (is, "%s", str);

  while (strcmp (str, "point") && strcmp (str, "point["))
    fscanf (is, "%s", str);

  if (!strcmp (str, "point"))
    fscanf (is, "%s", str);

  //lecture des sommets
  fscanf (is, "%s", coordx);
  int i = 0;
  while (strcmp (coordx, "}") && strcmp (coordx, "]"))
    {
      fscanf (is, "%s", coordy);
      fscanf (is, "%s", coordz);
      if (coordz[strlen (coordz) - 1] == ',')
	{
	  memcpy (coordz, coordz, strlen (coordz) - 1);
	  coordz[strlen (coordz)] = '\0';
	}
      //ajout d'un sommet
      a2ri_vf_add_vertex (m, atof (coordx), atof (coordy), atof (coordz));
      //mis à jour de la bounding box
      if (i == 0)
	{
	  i++;
	  m->xmin = atof (coordx);
	  m->xmax = atof (coordx);
	  m->ymin = atof (coordy);
	  m->ymax = atof (coordy);
	  m->zmin = atof (coordz);
	  m->zmax = atof (coordz);
	}
      else
	{
	  if (atof (coordx) < m->xmin)
	    m->xmin = atof (coordx);
	  if (atof (coordx) > m->xmax)
	    m->xmax = atof (coordx);
	  if (atof (coordy) < m->ymin)
	    m->ymin = atof (coordy);
	  if (atof (coordy) > m->ymax)
	    m->ymax = atof (coordy);
	  if (atof (coordz) < m->zmin)
	    m->zmin = atof (coordz);
	  if (atof (coordz) > m->zmax)
	    m->zmax = atof (coordz);
	}
      fscanf (is, "%s", coordx);
    }

  fscanf (is, "%s", str);

  while (strcmp (str, "coordIndex") && strcmp (str, "coordIndex["))
    fscanf (is, "%s", str);

  if (!strcmp (str, "coordIndex"))
    fscanf (is, "%s", str);

  //lecture des faces
  fscanf (is, "%s", coordx);
  while (strcmp (coordx, "}") && strcmp (coordx, "]"))
    {
      fscanf (is, "%s", coordy);
      fscanf (is, "%s", coordz);

      if (coordx[strlen (coordx) - 1] == ',')
	{
	  memcpy (coordx, coordx, strlen (coordx) - 1);
	  coordz[strlen (coordx)] = '\0';
	}
      if (coordy[strlen (coordy) - 1] == ',')
	{
	  memcpy (coordy, coordy, strlen (coordy) - 1);
	  coordy[strlen (coordy)] = '\0';
	}
      if (coordz[strlen (coordz) - 1] == ',')
	{
	  memcpy (coordz, coordz, strlen (coordz) - 1);
	  coordz[strlen (coordz)] = '\0';
	}
      //ajout d'une face
      a2ri_vf_add_face (m, atoi (coordx), atoi (coordy), atoi (coordz));
      // reading the -1
      fscanf (is, "%s", coordy);

      if (coordy[strlen (coordy) - 1] == ',')
	{
	  memcpy (coordy, coordy, strlen (coordy) - 1);
	  coordy[strlen (coordy)] = '\0';
	}
      if (atoi (coordy) != -1)
	{
	  a2ri_vf_add_face (m, atoi (coordz), atoi (coordy), atoi (coordx));
	  fscanf (is, "%s", coordx);
	}


      fscanf (is, "%s", coordx);
    }

  fclose (is);

  setlocale(LC_NUMERIC,"");

  return 1;
}

/**
   Ouverture d'un fichier wrl contenant un modèle
   @param file chemin du fichier à ouvrir
   @param m pointeur sur le modèle
   @return 1 si succès, 0 sinon
*/
int
a2ri_vf_load_wrl2 (
		   char *file,
		   vf_model * m)
{
  FILE *is = NULL;
  char str[20];
  char coordx[15],
    coordy[15],
    coordz[15];

  setlocale(LC_NUMERIC,"C");

  is = fopen (file, "r");
  if (is == NULL)
    return 0;

  fscanf (is, "%s", str);

  while (strcmp (str, "point") && strcmp (str, "point["))
    fscanf (is, "%s", str);

  if (!strcmp (str, "point"))
    fscanf (is, "%s", str);

  //lecture des sommets
  fscanf (is, "%s", coordx);
  int i = 0;
  while (strcmp (coordx, "}") && strcmp (coordx, "]"))
    {
      fscanf (is, "%s", coordy);
      fscanf (is, "%s", coordz);

      if (coordz[strlen (coordz) - 1] == ',')
	{
	  memcpy (coordz, coordz, strlen (coordz) - 1);
	  coordz[strlen (coordz)] = '\0';
	}
      //ajout d'un sommet
      a2ri_vf_add_vertex (m, atof (coordx), atof (coordy), atof (coordz));
      //mis à jour de la bounding box
      if (i == 0)
	{
	  i++;
	  m->xmin = atof (coordx);
	  m->xmax = atof (coordx);
	  m->ymin = atof (coordy);
	  m->ymax = atof (coordy);
	  m->zmin = atof (coordz);
	  m->zmax = atof (coordz);
	}
      else
	{
	  if (atof (coordx) < m->xmin)
	    m->xmin = atof (coordx);
	  if (atof (coordx) > m->xmax)
	    m->xmax = atof (coordx);
	  if (atof (coordy) < m->ymin)
	    m->ymin = atof (coordy);
	  if (atof (coordy) > m->ymax)
	    m->ymax = atof (coordy);
	  if (atof (coordz) < m->zmin)
	    m->zmin = atof (coordz);
	  if (atof (coordz) > m->zmax)
	    m->zmax = atof (coordz);
	}
      fscanf (is, "%s", coordx);
    }

  fscanf (is, "%s", str);

  while (strcmp (str, "coordIndex") && strcmp (str, "coordIndex["))
    fscanf (is, "%s", str);

  if (!strcmp (str, "coordIndex"))
    fscanf (is, "%s", str);

  //lecture des faces
  fscanf (is, "%s", coordx);
  while (strcmp (coordx, "}") && strcmp (coordx, "]"))
    {
      fscanf (is, "%s", coordy);
      fscanf (is, "%s", coordz);
      //ajout d'une face
      a2ri_vf_add_face (m, atoi (coordx), atoi (coordy), atoi (coordz));
      // reading the -1
      fscanf (is, "%s", coordx);
      fscanf (is, "%s", coordx);
    }

  fclose (is);
  
  setlocale(LC_NUMERIC,"");

  return 1;
}


/**
   Ouverture d'un fichier wrl contenant un modèle
   @param file chemin du fichier à ouvrir
   @param m pointeur sur le modèle
   @return 1 si succès, 0 sinon
*/
int
a2ri_vf_load_wrl (
		  char *file,
		  vf_model * m)
{
  FILE *is = NULL;
  char str[20];

  is = fopen (file, "r");
  if (is == NULL)
    return 0;

  fscanf (is, "%s", str);
  fscanf (is, "%s", str);

  if (!strcmp (str, "v1.0") || !strcmp (str, "V1.0"))
    return a2ri_vf_load_wrl1 (file, m);

  if (!strcmp (str, "v2.0") || !strcmp (str, "V2.0"))
    return a2ri_vf_load_wrl2 (file, m);

  return 0;
}

/**
   Ouverture d'un fichier vef contenant un modèle
   @param file chemin du fichier à ouvrir
   @param m pointeur sur le modèle
   @return 1 si succès, 0 sinon
*/
int
a2ri_vf_load_vef (
		  char *file,
		  vf_model * m)
{
  FILE *is = NULL;
  int nbvertex,
    nbedge,
    nbface,
    ve1,
    ve2,
    ve3,
    ed1,
    ed2,
    ed3,
    classif;
  double coordx,
    coordy,
    coordz;

  setlocale(LC_NUMERIC,"C");

  is = fopen (file, "r");
  if (is == NULL)
    return 0;

  a2ri_vf_init (m);

  //lecture du nombre de sommets
  fscanf (is, "%d", &nbvertex);

  //lecture du nombre d'aretes
  fscanf (is, "%d", &nbedge);

  //lecture du nombre de faces
  fscanf (is, "%d", &nbface);


  //lecture des sommets
  for (int i = 0; i < nbvertex; i++)
    {
      fscanf (is, "%lf", &coordx);
      fscanf (is, "%lf", &coordy);
      fscanf (is, "%lf", &coordz);
      //ajout d'un sommet
      a2ri_vf_add_vertex (m, coordx, coordy, coordz);
      //mis à jour de la bounding box
      if (i == 0)
	{
	  m->xmin = coordx;
	  m->xmax = coordx;
	  m->ymin = coordy;
	  m->ymax = coordy;
	  m->zmin = coordz;
	  m->zmax = coordz;
	}
      else
	{
	  if (coordx < m->xmin)
	    m->xmin = coordx;
	  if (coordx > m->xmax)
	    m->xmax = coordx;
	  if (coordy < m->ymin)
	    m->ymin = coordy;
	  if (coordy > m->ymax)
	    m->ymax = coordy;
	  if (coordz < m->zmin)
	    m->zmin = coordz;
	  if (coordz > m->zmax)
	    m->zmax = coordz;
	}
    }

  //lecture des aretes et enregistrement dans un tableau temporaire
  vf_edge *temp = (vf_edge *) malloc (nbedge * sizeof (vf_edge));
  a2ri_erreur_critique_si (temp == NULL,
			"erreur allocation memoire pour temp\na2ri_vf_load_vef");
  for (int i = 0; i < nbedge; i++)
    {
      fscanf (is, "%d", &ve1);
      fscanf (is, "%d", &ve2);
      temp[i].ve1 = ve1;
      temp[i].ve2 = ve2;
    }

  //lecture des faces
  for (int i = 0; i < nbface; i++)
    {
      fscanf (is, "%d", &ed1);
      fscanf (is, "%d", &ed2);
      fscanf (is, "%d", &ed3);

      //recherche des trois sommets contenu dans les trois aretes
      if (temp[ed1].ve1 == temp[ed2].ve1 || temp[ed1].ve1 == temp[ed2].ve2)
	{
	  ve1 = temp[ed1].ve1;
	  ve3 = temp[ed1].ve2;
	}
      else
	{
	  ve1 = temp[ed1].ve2;
	  ve3 = temp[ed1].ve1;
	}

      if (temp[ed2].ve1 == temp[ed3].ve1 || temp[ed2].ve1 == temp[ed3].ve2)
	ve2 = temp[ed2].ve1;
      else
	ve2 = temp[ed2].ve2;

      //ajout de la face
      a2ri_vf_add_face (m, ve1, ve2, ve3);
    }

  //lecture des classification si disponible
  for (int i = 0; i < nbface; i++)
    {
      if (!feof (is))
	{
	  fscanf (is, "%d", &classif);
	  m->fa[i].type = classif;
	}
    }

  fclose (is);
  
  setlocale(LC_NUMERIC,"");

  return 1;
}

/**
   Ouverture d'un fichier gts contenant un modèle
   @param file chemin du fichier à ouvrir
   @param m pointeur sur le modèle
   @return 1 si succès, 0 sinon
*/
int
a2ri_vf_load_gts (
		  char *file,
		  vf_model * m)
{
  FILE *is = NULL;
  int nbvertex,
    nbedge,
    nbface,
    ve1,
    ve2,
    ve3,
    ed1,
    ed2,
    ed3,
    classif;
  double coordx,
    coordy,
    coordz;

  setlocale(LC_NUMERIC,"C");

  is = fopen (file, "r");
  if (is == NULL)
    return 0;

  a2ri_vf_init (m);

  //lecture du nombre de sommets
  fscanf (is, "%d", &nbvertex);

  //lecture du nombre d'aretes
  fscanf (is, "%d", &nbedge);

  //lecture du nombre de faces
  fscanf (is, "%d", &nbface);


  //lecture des sommets
  for (int i = 0; i < nbvertex; i++)
    {
      fscanf (is, "%lf", &coordx);
      fscanf (is, "%lf", &coordy);
      fscanf (is, "%lf", &coordz);
      //ajout d'un sommet
      a2ri_vf_add_vertex (m, coordx, coordy, coordz);
      //mis à jour de la bounding box
      if (i == 0)
	{
	  m->xmin = coordx;
	  m->xmax = coordx;
	  m->ymin = coordy;
	  m->ymax = coordy;
	  m->zmin = coordz;
	  m->zmax = coordz;
	}
      else
	{
	  if (coordx < m->xmin)
	    m->xmin = coordx;
	  if (coordx > m->xmax)
	    m->xmax = coordx;
	  if (coordy < m->ymin)
	    m->ymin = coordy;
	  if (coordy > m->ymax)
	    m->ymax = coordy;
	  if (coordz < m->zmin)
	    m->zmin = coordz;
	  if (coordz > m->zmax)
	    m->zmax = coordz;
	}
    }

  //lecture des aretes et enregistrement dans un tableau temporaire
  vf_edge *temp = (vf_edge *) malloc (nbedge * sizeof (vf_edge));
  a2ri_erreur_critique_si (temp == NULL,
			"erreur allocation memoire pour temp\na2ri_vf_load_gts");
  for (int i = 0; i < nbedge; i++)
    {
      fscanf (is, "%d", &ve1);
      fscanf (is, "%d", &ve2);
      ve1--;
      ve2--;
      temp[i].ve1 = ve1;
      temp[i].ve2 = ve2;
    }

  //lecture des faces
  for (int i = 0; i < nbface; i++)
    {
      fscanf (is, "%d", &ed1);
      fscanf (is, "%d", &ed2);
      fscanf (is, "%d", &ed3);
      ed1--;
      ed2--;
      ed3--;

      //recherche des trois sommets contenu dans les trois aretes
      if (temp[ed1].ve1 == temp[ed2].ve1 || temp[ed1].ve1 == temp[ed2].ve2)
	{
	  ve1 = temp[ed1].ve1;
	  ve3 = temp[ed1].ve2;
	}
      else
	{
	  ve1 = temp[ed1].ve2;
	  ve3 = temp[ed1].ve1;
	}

      if (temp[ed2].ve1 == temp[ed3].ve1 || temp[ed2].ve1 == temp[ed3].ve2)
	ve2 = temp[ed2].ve1;
      else
	ve2 = temp[ed2].ve2;

      //ajout de la face
      a2ri_vf_add_face (m, ve1, ve2, ve3);
    }

  //lecture des classification si disponible
  for (int i = 0; i < nbface; i++)
    {
      if (!feof (is))
	{
	  fscanf (is, "%d", &classif);
	  m->fa[i].type = classif;
	}
    }

  fclose (is);

  setlocale(LC_NUMERIC,"");

  return 1;
}

/**
   Ouverture d'un fichier ply contenant un modèle
   @param file chemin du fichier à ouvrir
   @param m pointeur sur le modèle
   @return 1 si succès, 0 sinon
*/
int
a2ri_vf_load_ply (
		  char *file,
		  vf_model * m)
{
  int prop = 0,
    nbpropvertex = 0,
    nbpropface = 0,
    nbvertex,
    nbface,
    ve1,
    ve2,
    ve3;
  char str[20];
  double coordx,
    coordy,
    coordz;

  FILE *is = NULL;

  setlocale(LC_NUMERIC,"C");

  is = fopen (file, "r");
  if (is == NULL)
    return 0;

  fscanf (is, "%s", str);

  if (strcmp (str, "ply"))
    return 0;

  while (strcmp (str, "end_header"))
    {
      fscanf (is, "%s", str);
      if (prop == 1 && !strcmp (str, "property"))
	nbpropvertex++;
      if (prop == 2 && !strcmp (str, "property"))
	nbpropface++;

      if (!strcmp (str, "element"))
	{
	  fscanf (is, "%s", str);
	  //lecture du nombre de sommets
	  if (!strcmp (str, "vertex"))
	    {
	      prop = 1;
	      fscanf (is, "%d", &nbvertex);
	    }
	  //lecture du nombre de face
	  else
	    {
	      if (!strcmp (str, "face"))
		{
		  prop = 1;
		  fscanf (is, "%d", &nbface);
		}
	    }
	}
    }

  //lecture des sommets
  for (int i = 0; i < nbvertex; i++)
    {
      fscanf (is, "%lf %lf %lf", &coordx, &coordy, &coordz);
      //ajout d'un sommet
      a2ri_vf_add_vertex (m, coordx, coordy, coordz);
      //mis à jour de la bounding box
      if (i == 0)
	{
	  m->xmin = coordx;
	  m->xmax = coordx;
	  m->ymin = coordy;
	  m->ymax = coordy;
	  m->zmin = coordz;
	  m->zmax = coordz;
	}
      else
	{
	  if (coordx < m->xmin)
	    m->xmin = coordx;
	  if (coordx > m->xmax)
	    m->xmax = coordx;
	  if (coordy < m->ymin)
	    m->ymin = coordy;
	  if (coordy > m->ymax)
	    m->ymax = coordy;
	  if (coordz < m->zmin)
	    m->zmin = coordz;
	  if (coordz > m->zmax)
	    m->zmax = coordz;
	}
      for (int j = 0; j < nbpropvertex - 4; j++)
	fscanf (is, "%s", str);

    }

  //lecture des faces
  for (int i = 0; i < nbface; i++)
    {
      fscanf (is, "%d", &ve1);
      fscanf (is, "%d %d %d", &ve1, &ve2, &ve3);
      //ajout d'une face
      a2ri_vf_add_face (m, ve1, ve2, ve3);
    }

  fclose (is);

  setlocale(LC_NUMERIC,"");

  return 1;
}

/**
   Ouverture d'un fichier off contenant un modèle
   @param file chemin du fichier à ouvrir
   @param m pointeur sur le modèle
   @return 1 si succès, 0 sinon
*/
int
a2ri_vf_load_off (
		  char *file,
		  vf_model * m)
{

  FILE *is = NULL;
  int nbvertex,
    nbface,
    ve1,
    ve2,
    ve3;
  double coordx,
    coordy,
    coordz;
  char str[250];

  setlocale(LC_NUMERIC,"C");

  is = fopen (file, "r");
  if (is == NULL)
    return 0;

  fscanf (is, "%s", str);

  if (strcmp (str, "OFF"))
    return 0;

  //lecture du nombre de sommets et de faces
  fscanf (is, "%d %d %d", &nbvertex, &nbface, &ve1);

  //lecture des sommets
  for (int i = 0; i < nbvertex; i++)
    {
      fscanf (is, "%lf %lf %lf", &coordx, &coordy, &coordz);
      //ajout du sommet
      a2ri_vf_add_vertex (m, coordx, coordy, coordz);
      //mis à jour de la bounding box
      if (i == 0)
	{
	  m->xmin = coordx;
	  m->xmax = coordx;
	  m->ymin = coordy;
	  m->ymax = coordy;
	  m->zmin = coordz;
	  m->zmax = coordz;
	}
      else
	{
	  if (coordx < m->xmin)
	    m->xmin = coordx;
	  if (coordx > m->xmax)
	    m->xmax = coordx;
	  if (coordy < m->ymin)
	    m->ymin = coordy;
	  if (coordy > m->ymax)
	    m->ymax = coordy;
	  if (coordz < m->zmin)
	    m->zmin = coordz;
	  if (coordz > m->zmax)
	    m->zmax = coordz;
	}
    }

  //lecture des faces
  for (int i = 0; i < nbface; i++)
    {
      fscanf (is, "%d", &ve1);
      fscanf (is, "%d %d %d", &ve1, &ve2, &ve3);
      //ajout d'une face
      a2ri_vf_add_face (m, ve1, ve2, ve3);
    }

  fclose (is);

  setlocale(LC_NUMERIC,"");

  return 1;

}

/**
   Ouverture d'un fichier stl contenant un modèle
   @param file chemin du fichier ÃÂ  ouvrir
   @param m pointeur sur le modèle
   @return 1 si succÃÂ¨s, 0 sinon
*/
int
a2ri_vf_load_stl (
		  char *file,
		  vf_model * m)
{
  FILE *is = NULL;
  char str[250];

  is = fopen (file, "r");
  if (is == NULL)
    return 0;


  fscanf (is, "%s", str);

  fclose (is);

  if (!strcmp (str, "solid"))
    return a2ri_vf_load_ascii_stl (file, m);
  else
    return a2ri_vf_load_binary_stl (file, m);
}

/**
   Ouverture d'un fichier stl binaire contenant un modèle
   @param file chemin du fichier ÃÂ  ouvrir
   @param m pointeur sur le modèle
   @return 1 si succÃÂ¨s, 0 sinon
*/
int
a2ri_vf_load_binary_stl (
			 char *file,
			 vf_model * m)
{
  FILE *is = NULL;
  char str[80];
  unsigned int nbface;
  unsigned char finligne;
  float coordx,
    coordy,
    coordz;
  int ve1 = 0,
    ve2 = 0,
    ve3 = 0;
  point3d ptmin,
    ptmax;
  space_partition sp;

  setlocale(LC_NUMERIC,"C");

  is = fopen (file, "rb");
  if (is == NULL)
    return 0;

  fread (&str, sizeof (char), 80, is);

  fread (&nbface, sizeof (unsigned int), 1, is);

  //recherche de la bounding box du modele numerique
  for (unsigned int i = 0; i < nbface; i++)
    {
      fread (&coordx, sizeof (float), 1, is);
      fread (&coordy, sizeof (float), 1, is);
      fread (&coordz, sizeof (float), 1, is);
      for (unsigned int j = 0; j < 3; j++)
	{
	  //read the vertex
	  fread (&coordx, sizeof (float), 1, is);
	  fread (&coordy, sizeof (float), 1, is);
	  fread (&coordz, sizeof (float), 1, is);

	  if (i == 0 && j == 0)
	    {
	      m->xmin = coordx;
	      m->xmax = coordx;
	      m->ymin = coordy;
	      m->ymax = coordy;
	      m->zmin = coordz;
	      m->zmax = coordz;
	    }
	  else
	    {
	      if (coordx < m->xmin)
		m->xmin = coordx;
	      if (coordx > m->xmax)
		m->xmax = coordx;
	      if (coordy < m->ymin)
		m->ymin = coordy;
	      if (coordy > m->ymax)
		m->ymax = coordy;
	      if (coordz < m->zmin)
		m->zmin = coordz;
	      if (coordz > m->zmax)
		m->zmax = coordz;
	    }
	}

      fread (&finligne, 1, 1, is);
      fread (&finligne, 1, 1, is);
    }

  point3d_init (&ptmin, m->xmin, m->ymin, m->zmin);
  point3d_init (&ptmax, m->xmax, m->ymax, m->zmax);

  int nb_part = (int) (pow (nbface/22.0, (1.0 / 3.0))) + 1;

  space_partition_new (&sp, ptmin, ptmax, nb_part, nb_part, nb_part);

  //retour au debut du fichier
  fseek (is, 0, SEEK_SET);
  fread (&str, sizeof (char), 80, is);
  fread (&nbface, sizeof (unsigned int), 1, is);

  for (unsigned int i = 0; i < nbface; i++)
    {
      fread (&coordx, sizeof (float), 1, is);
      fread (&coordy, sizeof (float), 1, is);
      fread (&coordz, sizeof (float), 1, is);
      for (unsigned int j = 0; j < 3; j++)
	{
	  fread (&coordx, sizeof (float), 1, is);
	  fread (&coordy, sizeof (float), 1, is);
	  fread (&coordz, sizeof (float), 1, is);	//read the vertex
	  point3d_init (&ptmin, coordx, coordy, coordz);
	  if (i == 0 && j == 0)
	    {
	      ve1 = 0;
	      ptmin.att_int = space_partition_nb_points (&sp);
	      space_partition_add_point (&sp, ptmin);
	      a2ri_vf_add_vertex (m, ptmin.x, ptmin.y, ptmin.z);
	    }
	  else
	    {
	      point3d *ret=space_partition_contains_point (&sp, ptmin);
	      if (ret!=NULL)
		{
		  switch (j)
		    {
		    case 0:
		      ve1 = ret->att_int;
		      break;
		    case 1:
		      ve2 = ret->att_int;
		      break;
		    default:
		      ve3 = ret->att_int;
		    }
		}
	      else
		{
		  ptmin.att_int = space_partition_nb_points (&sp);
		  switch (j)
		    {
		    case 0:
		      ve1 = ptmin.att_int;
		      break;
		    case 1:
		      ve2 = ptmin.att_int;
		      break;
		    default:
		      ve3 = ptmin.att_int;
		    }
		  space_partition_add_point (&sp, ptmin);
		  a2ri_vf_add_vertex (m, ptmin.x, ptmin.y, ptmin.z);
		}
	    }
	}
      a2ri_vf_add_face (m, ve1, ve2, ve3);
      fread (&finligne, 1, 1, is);
      fread (&finligne, 1, 1, is);
    }

  fclose (is);

  setlocale(LC_NUMERIC,"");

  return 1;
}

/**
   Ouverture d'un fichier stl ascii contenant un modèle
   @param file chemin du fichier ÃÂ  ouvrir
   @param m pointeur sur le modèle
   @return 1 si succÃÂ¨s, 0 sinon
*/
int
a2ri_vf_load_ascii_stl (
			char *file,
			vf_model * m)
{
  FILE *is = NULL;
  int ve1,
    ve2,
    ve3,
    i = 0,
    fin = 0;
  double coordx,
    coordy,
    coordz;
  char str[250];

  setlocale(LC_NUMERIC,"C");

  is = fopen (file, "r");
  if (is == NULL)
    return 0;

  fscanf (is, "%s", str);
  while (strcmp (str, "facet"))
    fscanf (is, "%s", str);

  while (!fin)
    {
      fscanf (is, "%s", str);	//read normal
      fscanf (is, "%s", str);
      fscanf (is, "%s", str);
      fscanf (is, "%s", str);	//read the 3 values of the normal
      fscanf (is, "%s", str);
      fscanf (is, "%s", str);	//outer loop
      fscanf (is, "%s", str);	//read vertex
      fscanf (is, "%s", str);
      coordx = atof (str);	//coordx
      fscanf (is, "%s", str);
      coordy = atof (str);	//coordy
      fscanf (is, "%s", str);
      coordz = atof (str);	//coordz
      ve1 = a2ri_vf_search_vertex (*m, coordx, coordy, coordz);
      if (ve1 == -1)
	{
	  ve1 = m->nbvertex;
	  a2ri_vf_add_vertex (m, coordx, coordy, coordz);
	}
      if (i == 0)
	{
	  m->xmin = coordx;
	  m->xmax = coordx;
	  m->ymin = coordy;
	  m->ymax = coordy;
	  m->zmin = coordz;
	  m->zmax = coordz;
	  i++;
	}
      else
	{
	  if (coordx < m->xmin)
	    m->xmin = coordx;
	  if (coordx > m->xmax)
	    m->xmax = coordx;
	  if (coordy < m->ymin)
	    m->ymin = coordy;
	  if (coordy > m->ymax)
	    m->ymax = coordy;
	  if (coordz < m->zmin)
	    m->zmin = coordz;
	  if (coordz > m->zmax)
	    m->zmax = coordz;
	}
      fscanf (is, "%s", str);	//read vertex
      fscanf (is, "%s", str);
      coordx = atof (str);	//coordx
      fscanf (is, "%s", str);
      coordy = atof (str);	//coordy
      fscanf (is, "%s", str);
      coordz = atof (str);	//coordz
      ve2 = a2ri_vf_search_vertex (*m, coordx, coordy, coordz);
      if (ve2 == -1)
	{
	  ve2 = m->nbvertex;
	  a2ri_vf_add_vertex (m, coordx, coordy, coordz);
	}
      if (coordx < m->xmin)
	m->xmin = coordx;
      if (coordx > m->xmax)
	m->xmax = coordx;
      if (coordy < m->ymin)
	m->ymin = coordy;
      if (coordy > m->ymax)
	m->ymax = coordy;
      if (coordz < m->zmin)
	m->zmin = coordz;
      if (coordz > m->zmax)
	m->zmax = coordz;
      fscanf (is, "%s", str);	//read vertex
      fscanf (is, "%s", str);
      coordx = atof (str);	//coordx
      fscanf (is, "%s", str);
      coordy = atof (str);	//coordy
      fscanf (is, "%s", str);
      coordz = atof (str);	//coordz;
      ve3 = a2ri_vf_search_vertex (*m, coordx, coordy, coordz);
      if (ve3 == -1)
	{
	  ve3 = m->nbvertex;
	  a2ri_vf_add_vertex (m, coordx, coordy, coordz);
	}
      if (coordx < m->xmin)
	m->xmin = coordx;
      if (coordx > m->xmax)
	m->xmax = coordx;
      if (coordy < m->ymin)
	m->ymin = coordy;
      if (coordy > m->ymax)
	m->ymax = coordy;
      if (coordz < m->zmin)
	m->zmin = coordz;
      if (coordz > m->zmax)
	m->zmax = coordz;

      a2ri_vf_add_face (m, ve1, ve2, ve3);

      fscanf (is, "%s", str);	//read endloop
      fscanf (is, "%s", str);	//read endfacet
      fscanf (is, "%s", str);	//read facet ou endsolid
      fin = !strcmp (str, "endsolid");
    }

  fclose (is);

  setlocale(LC_NUMERIC,"");

  return 1;
}

/**
   Enregistrement d'un modèle dans un format défini par l'extension du nom de fichier
   @param file nom du fichier
   @param m le modèle
   @return aucun
*/
int
a2ri_vf_save_file (
		   char *file,
		   vf_model m)
{
  char ext[4];

  memcpy (ext, file + (strlen (file) - 3), 3);
  ext[3] = 0;

  //enregistrement du modèle en fonction de l'extension
  if (!strcmp (ext, "wrl"))
    {
      return a2ri_vf_save_wrl (file, m);
    }

  if (!strcmp (ext, "vef"))
    {
      return a2ri_vf_save_vef (file, m);
    }

  if (!strcmp (ext, "pgn"))
    {
      return a2ri_vf_save_pgn (file, m);
    }

  if (!strcmp (ext, "ply"))
    {
      return a2ri_vf_save_ply (file, m);
    }

  if (!strcmp (ext, "off"))
    {
      return a2ri_vf_save_off (file, m);
    }

  if (!strcmp (ext, "obj"))
    {
      return a2ri_vf_save_obj (file, m);
    }

  if (!strcmp (ext, "gts"))
    {
      return a2ri_vf_save_gts (file, m);
    }
  if (!strcmp (ext, "stl"))
    {
      return a2ri_vf_save_stl (file, m);
    }

  return 0;

}

/**
   Enregistrement d'un modèle dans un fichier wr@param file chemin du fichier
   @param m modèle à sauvegarder
   @return 1 si succès, 0 sinon
*/
int
a2ri_vf_save_wrl (
		  char *file,
		  vf_model m)
{
  setlocale(LC_NUMERIC,"C");
  
  if (strlen (file) < 4)
    {
      strcat (file, ".wrl");
    }

  char ext[5];

  memcpy (ext, file + (strlen (file) - 4), 4);
  ext[4] = '\0';

  if (strcmp (ext, ".wrl"))
    strcat (file, ".wrl");


  FILE *os = NULL;
  os = fopen (file, "w");
  if (os == NULL)
    return 0;

  //ecriture de l'en-tete
  fprintf (os, "#VRML V2.0 utf8\n");
  fprintf (os, "Shape{\n");
  fprintf (os, "appearance Appearance {\n");
  fprintf (os, "material Material {\n");
  fprintf (os, "}\n");
  fprintf (os, "}\n");
  fprintf (os, "geometry IndexedFaceSet{\n");
  fprintf (os, "coord Coordinate{\n");
  fprintf (os, "point[\n");

  //ecriture des sommets
  for (int i = 0; i < m.nbvertex; i++)
    fprintf (os, "%f %f %f,\n", m.ve[i].x, m.ve[i].y, m.ve[i].z);
  fprintf (os, "]\n");
  fprintf (os, "}\n");

  //ecriture des faces
  fprintf (os, "coordIndex[\n");
  for (int i = 0; i < m.nbface; i++)
    {
      int nb1 = m.fa[i].ve1;
      int nb2 = m.fa[i].ve2;
      int nb3 = m.fa[i].ve3;
      fprintf (os, "%d %d %d -1\n", nb1, nb2, nb3);
    }
  fprintf (os, "]\n");
  fprintf (os, "}\n");
  fprintf (os, "}\n");
  fclose (os);
  
  setlocale(LC_NUMERIC,"");

  return 1;
}

/**
   Enregistrement d'un modèle dans un fichier wrl version 1.0
   @param file chemin du fichier
   @param m modèle à sauvegarder
   @return 1 si succès, 0 sinon
*/
int
a2ri_vf_save_wrl_v1 (
		     char *file,
		     vf_model m)
{
  setlocale(LC_NUMERIC,"C");
  
  if (strlen (file) < 4)
    {
      strcat (file, ".wrl");
    }

  char ext[5];

  memcpy (ext, file + (strlen (file) - 4), 4);
  ext[4] = '\0';

  if (strcmp (ext, ".wrl"))
    strcat (file, ".wrl");


  FILE *os = NULL;
  os = fopen (file, "w");
  if (os == NULL)
    return 0;

  //ecriture de l'en-tete
  fprintf (os, "#VRML V1.0 ascii\n");
  fprintf (os, "Separator {\n");
  fprintf (os, "Switch {\n");
  fprintf (os, "DEF Pol{\n");
  fprintf (os, "Separator {\n");
  fprintf (os, "Coordinate3 {\n");
  fprintf (os, "point[\n");

  //ecriture des sommets
  for (int i = 0; i < m.nbvertex; i++)
    fprintf (os, "%f %f %f,\n", m.ve[i].x, m.ve[i].y, m.ve[i].z);
  fprintf (os, "]\n");
  fprintf (os, "}\n");

  //ecriture des faces
  fprintf (os, "IndexedFaceSet {\n");
  fprintf (os, "coordIndex [\n");
  for (int i = 0; i < m.nbface; i++)
    {
      int nb1 = m.fa[i].ve1;
      int nb2 = m.fa[i].ve2;
      int nb3 = m.fa[i].ve3;
      fprintf (os, "%d, %d, %d, -1,\n", nb1, nb2, nb3);
    }
  fprintf (os, "]\n");
  fprintf (os, "}\n");
  fprintf (os, "}\n");
  fprintf (os, "}\n");
  fclose (os);

  setlocale(LC_NUMERIC,"");

  return 1;
}

/**
   Enregistrement d'un modèle dans un fichier pgn
   @param file chemin du fichier
   @param m modèle à sauvegarder
   @return 1 si succès, 0 sinon
*/
int
a2ri_vf_save_pgn (
		  char *file,
		  vf_model m)
{
  setlocale(LC_NUMERIC,"C");

  if (strlen (file) < 4)
    {
      strcat (file, ".pgn");
    }

  char ext[5];

  memcpy (ext, file + (strlen (file) - 4), 4);
  ext[4] = '\0';

  if (strcmp (ext, ".pgn"))
    strcat (file, ".pgn");


  FILE *os = NULL;
  os = fopen (file, "w");
  if (os == NULL)
    return 0;

  //ecriture du nombre de sommets et de faces
  fprintf (os, "%d %d\n", m.nbvertex, m.nbface);

  //ecriture des sommets
  for (int i = 0; i < m.nbvertex; i++)
    fprintf (os, "%lf %lf %lf\n", m.ve[i].x, m.ve[i].y, m.ve[i].z);

  fprintf (os, "\n");

  //ecriture des faces
  for (int i = 0; i < m.nbface; i++)
    fprintf (os, "%d %d %d -1\n", m.fa[i].ve1, m.fa[i].ve2, m.fa[i].ve3);

  fclose (os);

  setlocale(LC_NUMERIC,"");

  return 1;

}

/**
   Enregistrement d'un modèle dans un fichier vef
   @param file chemin du fichier
   @param m modèle à sauvegarder
   @return 1 si succès, 0 sinon
**/
int
a2ri_vf_save_vef (
		  char *file,
		  vf_model m)
{
  hashtable *table = hashtable_new (m.nbvertex + m.nbface);
  hashtable *tabletemp = NULL;

  int p1,
    p2;

  setlocale(LC_NUMERIC,"C");

  if (strlen (file) < 4)
    {
      strcat (file, ".vef");
    }

  char ext[5];

  memcpy (ext, file + (strlen (file) - 4), 4);
  ext[4] = '\0';

  if (strcmp (ext, ".vef"))
    strcat (file, ".vef");


  FILE *os = NULL;
  os = fopen (file, "w");
  if (os == NULL)
    return 0;

  tabletemp = a2ri_vf_construction_edge_table (&m, NULL, 0);

  //ecriture du nombre de sommets, d'aretes et de faces
  fprintf (os, "%d %d %d\n", m.nbvertex, hashtable_size (tabletemp),
	   m.nbface);

  hashtable_free (tabletemp);

  //ecriture des sommets
  for (int i = 0; i < m.nbvertex; i++)
    fprintf (os, "%lf %lf %lf\n", m.ve[i].x, m.ve[i].y, m.ve[i].z);

  fprintf (os, "\n");

  //ecriture des aretes
  IFsave_vef_write_edge (&m, table, os);

  fprintf (os, "\n");

  //ecriture des faces
  for (int i = 0; i < m.nbface; i++)
    {
      p1 = m.fa[i].ve1;
      p2 = m.fa[i].ve2;
      //recherche de l'arete dans la table de hachage
      vf_edge *edgetemp = hashtable_look_for (table, p1, p2);
      fprintf (os, "%d ", edgetemp->att_int);

      p1 = m.fa[i].ve2;
      p2 = m.fa[i].ve3;
      edgetemp = hashtable_look_for (table, p1, p2);
      fprintf (os, "%d ", edgetemp->att_int);

      p1 = m.fa[i].ve3;
      p2 = m.fa[i].ve1;
      edgetemp = hashtable_look_for (table, p1, p2);
      fprintf (os, "%d\n", edgetemp->att_int);
    }

  hashtable_free (table);

  fclose (os);

  setlocale(LC_NUMERIC,"");

  return 0;
}

/**
   Enregistrement d'un modèle dans un fichier gts
   @param file chemin du fichier
   @param m modèle à sauvegarder
   @return 1 si succès, 0 sinon
**/
int
a2ri_vf_save_gts (
		  char *file,
		  vf_model m)
{
  hashtable *table = hashtable_new (m.nbvertex + m.nbface);
  hashtable *tabletemp = NULL;

  int p1,
    p2;

  setlocale(LC_NUMERIC,"C");

  if (strlen (file) < 4)
    {
      strcat (file, ".gts");
    }

  char ext[5];

  memcpy (ext, file + (strlen (file) - 4), 4);
  ext[4] = '\0';

  if (strcmp (ext, ".gts"))
    strcat (file, ".gts");


  FILE *os = NULL;
  os = fopen (file, "w");
  if (os == NULL)
    return 0;

  tabletemp = a2ri_vf_construction_edge_table (&m, NULL, 0);

  //ecriture du nombre de sommets, d'aretes et de faces
  fprintf (os, "%d %d %d\n", m.nbvertex, hashtable_size (tabletemp),
	   m.nbface);

  hashtable_free (tabletemp);

  //ecriture des sommets
  for (int i = 0; i < m.nbvertex; i++)
    fprintf (os, "%lf %lf %lf\n", m.ve[i].x, m.ve[i].y, m.ve[i].z);

  fprintf (os, "\n");


  //ecriture des aretes
  IFsave_gts_write_edge (&m, table, os);

  fprintf (os, "\n");

  //ecriture des faces
  for (int i = 0; i < m.nbface; i++)
    {
      p1 = m.fa[i].ve1;
      p2 = m.fa[i].ve2;
      //recherche de l'arete dans la table de hachage
      vf_edge *edgetemp = hashtable_look_for (table, p1, p2);
      fprintf (os, "%d ", edgetemp->att_int + 1);

      p1 = m.fa[i].ve2;
      p2 = m.fa[i].ve3;
      edgetemp = hashtable_look_for (table, p1, 2);
      fprintf (os, "%d ", edgetemp->att_int + 1);

      p1 = m.fa[i].ve3;
      p2 = m.fa[i].ve1;
      edgetemp = hashtable_look_for (table, p1, p2);
      fprintf (os, "%d\n", edgetemp->att_int + 1);
    }

  hashtable_free (table);

  fclose (os);

  setlocale(LC_NUMERIC,"");

  return 0;
}

/**
   Enregistrement d'un modèle dans un fichier off
   @param file chemin du fichier
   @param m modèle à sauvegarder
   @return 1 si succès, 0 sinon
*/
int
a2ri_vf_save_off (
		  char *file,
		  vf_model m)
{
  setlocale(LC_NUMERIC,"C");

  if (strlen (file) < 4)
    {
      strcat (file, ".off");
    }

  char ext[5];

  memcpy (ext, file + (strlen (file) - 4), 4);
  ext[4] = '\0';

  if (strcmp (ext, ".off"))
    strcat (file, ".off");


  FILE *os = NULL;
  os = fopen (file, "w");
  if (os == NULL)
    return 0;

  //ecriture du nombre de sommets et de faces
  fprintf (os, "OFF\n%d %d 0\n", m.nbvertex, m.nbface);

  //ecriture des sommets
  for (int i = 0; i < m.nbvertex; i++)
    fprintf (os, "%lf %lf %lf\n", m.ve[i].x, m.ve[i].y, m.ve[i].z);

  fprintf (os, "\n");

  //ecriture des faces
  for (int i = 0; i < m.nbface; i++)
    fprintf (os, "3 %d %d %d\n", m.fa[i].ve1, m.fa[i].ve2, m.fa[i].ve3);

  fclose (os);

  setlocale(LC_NUMERIC,"");

  return 1;
}

/**
   Enregistrement d'un modèle dans un fichier ply
   @param file chemin du fichier
   @param m modèle à sauvegarder
   @return 1 si succès, 0 sinon
*/
int
a2ri_vf_save_ply (
		  char *file,
		  vf_model m)
{
  int ve1,
    ve2,
    ve3;

  setlocale(LC_NUMERIC,"C");

  if (strlen (file) < 4)
    {
      strcat (file, ".ply");
    }

  char ext[5];

  memcpy (ext, file + (strlen (file) - 4), 4);
  ext[4] = '\0';

  if (strcmp (ext, ".ply"))
    strcat (file, ".ply");


  FILE *os = NULL;
  os = fopen (file, "w");
  if (os == NULL)
    return 0;

  //ecriture des en-tetes
  fprintf (os, "ply\nformat ascii 1.0\ncomment zipper output\n");
  fprintf (os,
	   "element vertex %d\nproperty float x\nproperty float y\nproperty float z\nelement face %d\n",
	   m.nbvertex, m.nbface);
  fprintf (os, "property list uchar int vertex_indices\nend_header\n");

  //ecriture des sommets
  for (int i = 0; i < m.nbvertex; i++)
    fprintf (os, "%f %f %f\n", m.ve[i].x, m.ve[i].y, m.ve[i].z);

  //ecriture des faces
  for (int i = 0; i < m.nbface; i++)
    {
      ve1 = m.fa[i].ve1;
      ve2 = m.fa[i].ve2;
      ve3 = m.fa[i].ve3;
      fprintf (os, "3 %d %d %d \n", ve1, ve2, ve3);
    }

  fclose (os);

  setlocale(LC_NUMERIC,"");

  return 1;

}

/**
   Enregistrement d'un modèle dans un fichier obj
   @param file chemin du fichier
   @param m modèle à sauvegarder
   @return 1 si succès, 0 sinon
*/
int
a2ri_vf_save_obj (
		  char *file,
		  vf_model m)
{
  setlocale(LC_NUMERIC,"C");

  if (strlen (file) < 4)
    {
      strcat (file, ".obj");
    }

  char ext[5];

  memcpy (ext, file + (strlen (file) - 4), 4);
  ext[4] = '\0';

  if (strcmp (ext, ".obj"))
    strcat (file, ".obj");


  FILE *os = NULL;
  os = fopen (file, "w");
  if (os == NULL)
    return 0;

  //ecriture des sommets
  for (int i = 0; i < m.nbvertex; i++)
    fprintf (os, "v %lf %lf %lf\n", m.ve[i].x, m.ve[i].y, m.ve[i].z);

  fprintf (os, "\n");

  //ecriture des faces
  for (int i = 0; i < m.nbface; i++)
    fprintf (os, "f %d %d %d\n", m.fa[i].ve1 + 1, m.fa[i].ve2 + 1,
	     m.fa[i].ve3 + 1);

  fclose (os);

  setlocale(LC_NUMERIC,"");

  return 1;

}

/**
   Enregistrement d'un modèle dans un fichier stl
   @param file chemin du fichier
   @param m modèle à sauvegarder
   @return 1 si succÃÂ¨s, 0 sinon
*/
int
a2ri_vf_save_stl (
		  char *file,
		  vf_model m)
{

  setlocale(LC_NUMERIC,"C");

  if (strlen (file) < 4)
    {
      strcat (file, ".stl");
    }

  char ext[5];

  memcpy (ext, file + (strlen (file) - 4), 4);
  ext[4] = '\0';

  if (strcmp (ext, ".stl"))
    strcat (file, ".stl");


  FILE *os = NULL;
  os = fopen (file, "wb");
  if (os == NULL)
    return 0;

    fwrite
    ("generated by A2RI                                                               ",
     1, 80, os);
  fwrite (&(m.nbface), sizeof (unsigned int), 1, os);
  for (int i = 0; i < m.nbface; i++)
    {
      vector3d AB,
        AC,
        normale;
      vector3d_init (&AB,
		     m.ve[m.fa[i].ve2].x - m.ve[m.fa[i].ve1].x,
		     m.ve[m.fa[i].ve2].y - m.ve[m.fa[i].ve1].y,
		     m.ve[m.fa[i].ve2].z - m.ve[m.fa[i].ve1].z);
      vector3d_init (&AC,
		     m.ve[m.fa[i].ve3].x - m.ve[m.fa[i].ve1].x,
		     m.ve[m.fa[i].ve3].y - m.ve[m.fa[i].ve1].y,
		     m.ve[m.fa[i].ve3].z - m.ve[m.fa[i].ve1].z);
      normale = vector3d_vectorialproduct (AB, AC);
      float x,
        y,
        z;
      x = normale.dx;
      y = normale.dy;
      z = normale.dz;
      fwrite (&x, sizeof (float), 1, os);
      fwrite (&y, sizeof (float), 1, os);
      fwrite (&z, sizeof (float), 1, os);
      x = m.ve[m.fa[i].ve1].x;
      y = m.ve[m.fa[i].ve1].y;
      z = m.ve[m.fa[i].ve1].z;
      fwrite (&x, sizeof (float), 1, os);
      fwrite (&y, sizeof (float), 1, os);
      fwrite (&z, sizeof (float), 1, os);
      x = m.ve[m.fa[i].ve2].x;
      y = m.ve[m.fa[i].ve2].y;
      z = m.ve[m.fa[i].ve2].z;
      fwrite (&x, sizeof (float), 1, os);
      fwrite (&y, sizeof (float), 1, os);
      fwrite (&z, sizeof (float), 1, os);
      x = m.ve[m.fa[i].ve3].x;
      y = m.ve[m.fa[i].ve3].y;
      z = m.ve[m.fa[i].ve3].z;
      fwrite (&x, sizeof (float), 1, os);
      fwrite (&y, sizeof (float), 1, os);
      fwrite (&z, sizeof (float), 1, os);
      fwrite ("  ", 1, 2, os);
    }

  fclose (os);

  setlocale(LC_NUMERIC,"");

  return 1;
}

/**
   Ouverture d'un fichier contenant un modèle
   @param file chemin du fichier à ouvrir
   @param m pointeur sur le modèle
   @return 1 si succès, 0 sinon
*/
int
a2ri_vef_open_file (
		    char *file,
		    vef_model * m)
{
  char ext[5];

  memcpy (ext, file + (strlen (file) - 4), 4);
  ext[4] = 0;

  //appel de la fonction correspondant à l'extension du fichier
  if (!strcmp (ext, ".wrl"))
    return (a2ri_vef_load_wrl (file, m));

  if (!strcmp (ext, ".vef"))
    return (a2ri_vef_load_vef (file, m));

  if (!strcmp (ext, ".pgn"))
    return (a2ri_vef_load_pgn (file, m));

  if (!strcmp (ext, ".ply"))
    return (a2ri_vef_load_ply (file, m));

  if (!strcmp (ext, ".off"))
    return (a2ri_vef_load_off (file, m));

  if (!strcmp (ext, ".obj"))
    return (a2ri_vef_load_obj (file, m));

  if (!strcmp (ext, ".gts"))
    return (a2ri_vef_load_gts (file, m));

  if (!strcmp (ext, ".stl"))
    return (a2ri_vef_load_stl (file, m));

  return 0;

}

/**
   Ouverture d'un fichier pgn contenant un modèle
   @param file chemin du fichier à ouvrir
   @param m pointeur sur le modèle
   @return 1 si succès, 0 sinon
*/
int
a2ri_vef_load_pgn (
		   char *file,
		   vef_model * m)
{

  FILE *is = NULL;
  double coordx,
    coordy,
    coordz;
  int classif,
    ar1,
    ar2,
    ar3,
    nbvertex,
    nbface;

  setlocale(LC_NUMERIC,"C");

  is = fopen (file, "r");
  if (is == NULL)
    return 0;
  a2ri_vef_init (m);

  //lecture du nombre de sommets
  fscanf (is, "%d", &nbvertex);

  //lecture du nombre de faces
  fscanf (is, "%d", &nbface);

  //lecture des sommets
  for (int i = 0; i < nbvertex; i++)
    {
      fscanf (is, "%lf", &coordx);
      fscanf (is, "%lf", &coordy);
      fscanf (is, "%lf", &coordz);
      a2ri_vef_add_vertex (m, coordx, coordy, coordz);
      //mis à jour de la bounding box
      if (i == 0)
	{
	  m->xmin = coordx;
	  m->xmax = coordx;
	  m->ymin = coordy;
	  m->ymax = coordy;
	  m->zmin = coordz;
	  m->zmax = coordz;
	}
      else
	{
	  if (coordx < m->xmin)
	    m->xmin = coordx;
	  if (coordx > m->xmax)
	    m->xmax = coordx;
	  if (coordy < m->ymin)
	    m->ymin = coordy;
	  if (coordy > m->ymax)
	    m->ymax = coordy;
	  if (coordz < m->zmin)
	    m->zmin = coordz;
	  if (coordz > m->zmax)
	    m->zmax = coordz;
	}
    }

  //lecture des faces
  for (int i = 0; i < nbface; i++)
    {
      //lecture des trois sommets composant la face
      fscanf (is, "%d", &ar1);
      fscanf (is, "%d", &ar2);
      fscanf (is, "%d", &ar3);
      //ajout des aretes avec vérification au préalable de leur existence
      a2ri_vef_add_edge (m, ar1, ar2, 1);
      a2ri_vef_add_edge (m, ar2, ar3, 1);
      a2ri_vef_add_edge (m, ar3, ar1, 1);
      //recherche des aretes
      int ed1 = a2ri_vef_search_edge (*m, ar1, ar2);
      int ed2 = a2ri_vef_search_edge (*m, ar2, ar3);
      int ed3 = a2ri_vef_search_edge (*m, ar3, ar1);
      //ajout de la faces avec les trois aretes
      a2ri_vef_add_face (m, ed1, ed2, ed3);
      // reading the -1
      fscanf (is, "%d", &ar1);
    }

  //lecture des classifications si disponible
  for (int i = 0; i < nbface; i++)
    {
      if (!feof (is))
	{
	  fscanf (is, "%d", &classif);
	  m->fa[i].type = classif;
	}
    }

  fclose (is);

  setlocale(LC_NUMERIC,"");

  return 1;

}

/**
   Ouverture d'un fichier stl binaire contenant un modèle
   @param file chemin du fichier ÃÂ  ouvrir
   @param m pointeur sur le modèle
   @return 1 si succÃÂ¨s, 0 sinon
*/
int
a2ri_vef_load_binary_stl (
			  char *file,
			  vef_model * m)
{
  FILE *is = NULL;
  char str[80];
  unsigned int nbface;
  unsigned char finligne;
  float coordx,
    coordy,
    coordz;
  int ve1,
    ve2,
    ve3,
    
    ed1,
    ed2,
    ed3;

  setlocale(LC_NUMERIC,"C");

  is = fopen (file, "rb");
  if (is == NULL)
    return 0;

  fread (&str, sizeof (char), 80, is);

  fread (&nbface, sizeof (unsigned int), 1, is);


  for (unsigned int i = 0; i < nbface; i++)
    {
      fread (&coordx, sizeof (float), 1, is);
      fread (&coordy, sizeof (float), 1, is);
      fread (&coordz, sizeof (float), 1, is);	//read the normal
      fread (&coordx, sizeof (float), 1, is);
      fread (&coordy, sizeof (float), 1, is);
      fread (&coordz, sizeof (float), 1, is);	//read the first vertex

      ve1 = a2ri_vef_search_vertex (*m, coordx, coordy, coordz);
      if (ve1 == -1)
	{
	  ve1 = m->nbvertex;
	  a2ri_vef_add_vertex (m, coordx, coordy, coordz);
	}
      if (i == 0)
	{
	  m->xmin = coordx;
	  m->xmax = coordx;
	  m->ymin = coordy;
	  m->ymax = coordy;
	  m->zmin = coordz;
	  m->zmax = coordz;
	}
      else
	{
	  if (coordx < m->xmin)
	    m->xmin = coordx;
	  if (coordx > m->xmax)
	    m->xmax = coordx;
	  if (coordy < m->ymin)
	    m->ymin = coordy;
	  if (coordy > m->ymax)
	    m->ymax = coordy;
	  if (coordz < m->zmin)
	    m->zmin = coordz;
	  if (coordz > m->zmax)
	    m->zmax = coordz;
	}
      fread (&coordx, sizeof (float), 1, is);
      fread (&coordy, sizeof (float), 1, is);
      fread (&coordz, sizeof (float), 1, is);	//read the second vertex
      ve2 = a2ri_vef_search_vertex (*m, coordx, coordy, coordz);
      if (ve2 == -1)
	{
	  ve2 = m->nbvertex;
	  a2ri_vef_add_vertex (m, coordx, coordy, coordz);
	}
      if (coordx < m->xmin)
	m->xmin = coordx;
      if (coordx > m->xmax)
	m->xmax = coordx;
      if (coordy < m->ymin)
	m->ymin = coordy;
      if (coordy > m->ymax)
	m->ymax = coordy;
      if (coordz < m->zmin)
	m->zmin = coordz;
      if (coordz > m->zmax)
	m->zmax = coordz;
      fread (&coordx, sizeof (float), 1, is);
      fread (&coordy, sizeof (float), 1, is);
      fread (&coordz, sizeof (float), 1, is);	//read the third vertex
      ve3 = a2ri_vef_search_vertex (*m, coordx, coordy, coordz);
      if (ve3 == -1)
	{
	  ve3 = m->nbvertex;
	  a2ri_vef_add_vertex (m, coordx, coordy, coordz);
	}
      if (coordx < m->xmin)
	m->xmin = coordx;
      if (coordx > m->xmax)
	m->xmax = coordx;
      if (coordy < m->ymin)
	m->ymin = coordy;
      if (coordy > m->ymax)
	m->ymax = coordy;
      if (coordz < m->zmin)
	m->zmin = coordz;
      if (coordz > m->zmax)
	m->zmax = coordz;

      ed1 = a2ri_vef_search_edge (*m, ve1, ve2);
      ed2 = a2ri_vef_search_edge (*m, ve1, ve3);
      ed3 = a2ri_vef_search_edge (*m, ve2, ve3);

      if (ed1 == -1)
	{
	  ed1 = m->nbedge;
	  a2ri_vef_add_edge (m, ve1, ve2, 0);
	}
      if (ed2 == -1)
	{
	  ed2 = m->nbedge;
	  a2ri_vef_add_edge (m, ve1, ve3, 0);
	}
      if (ed3 == -1)
	{
	  ed3 = m->nbedge;
	  a2ri_vef_add_edge (m, ve2, ve3, 0);
	}

      a2ri_vef_add_face (m, ed2, ed1, ed3);

      fread (&finligne, 1, 1, is);
      fread (&finligne, 1, 1, is);
    }

  fclose (is);

  setlocale(LC_NUMERIC,"");

  return 1;
}

/**
   Ouverture d'un fichier stl ascii contenant un modèle
   @param file chemin du fichier ÃÂ  ouvrir
   @param m pointeur sur le modèle
   @return 1 si succÃÂ¨s, 0 sinon
*/
int
a2ri_vef_load_ascii_stl (
			 char *file,
			 vef_model * m)
{
  FILE *is = NULL;
  int ve1,
    ve2,
    ve3,
    i = 0,
    fin = 0,
    ed1,
    ed2,
    ed3;
  double coordx,
    coordy,
    coordz;
  char str[250];

  setlocale(LC_NUMERIC,"C");

  is = fopen (file, "r");
  if (is == NULL)
    return 0;

  fscanf (is, "%s", str);
  while (strcmp (str, "facet"))
    fscanf (is, "%s", str);

  while (!fin)
    {
      fscanf (is, "%s", str);	//read normal
      fscanf (is, "%s", str);
      fscanf (is, "%s", str);
      fscanf (is, "%s", str);	//read the 3 values of the normal
      fscanf (is, "%s", str);
      fscanf (is, "%s", str);	//outer loop
      fscanf (is, "%s", str);	//read vertex
      fscanf (is, "%s", str);
      coordx = atof (str);	//coordx
      fscanf (is, "%s", str);
      coordy = atof (str);	//coordy
      fscanf (is, "%s", str);
      coordz = atof (str);	//coordz
      ve1 = a2ri_vef_search_vertex (*m, coordx, coordy, coordz);
      if (ve1 == -1)
	{
	  ve1 = m->nbvertex;
	  a2ri_vef_add_vertex (m, coordx, coordy, coordz);
	}
      if (i == 0)
	{
	  m->xmin = coordx;
	  m->xmax = coordx;
	  m->ymin = coordy;
	  m->ymax = coordy;
	  m->zmin = coordz;
	  m->zmax = coordz;
	  i++;
	}
      else
	{
	  if (coordx < m->xmin)
	    m->xmin = coordx;
	  if (coordx > m->xmax)
	    m->xmax = coordx;
	  if (coordy < m->ymin)
	    m->ymin = coordy;
	  if (coordy > m->ymax)
	    m->ymax = coordy;
	  if (coordz < m->zmin)
	    m->zmin = coordz;
	  if (coordz > m->zmax)
	    m->zmax = coordz;
	}
      fscanf (is, "%s", str);	//read vertex
      fscanf (is, "%s", str);
      coordx = atof (str);	//coordx
      fscanf (is, "%s", str);
      coordy = atof (str);	//coordy
      fscanf (is, "%s", str);
      coordz = atof (str);	//coordz
      ve2 = a2ri_vef_search_vertex (*m, coordx, coordy, coordz);
      if (ve2 == -1)
	{
	  ve2 = m->nbvertex;
	  a2ri_vef_add_vertex (m, coordx, coordy, coordz);
	}
      if (coordx < m->xmin)
	m->xmin = coordx;
      if (coordx > m->xmax)
	m->xmax = coordx;
      if (coordy < m->ymin)
	m->ymin = coordy;
      if (coordy > m->ymax)
	m->ymax = coordy;
      if (coordz < m->zmin)
	m->zmin = coordz;
      if (coordz > m->zmax)
	m->zmax = coordz;
      fscanf (is, "%s", str);	//read vertex
      fscanf (is, "%s", str);
      coordx = atof (str);	//coordx
      fscanf (is, "%s", str);
      coordy = atof (str);	//coordy
      fscanf (is, "%s", str);
      coordz = atof (str);	//coordz;
      ve3 = a2ri_vef_search_vertex (*m, coordx, coordy, coordz);
      if (ve3 == -1)
	{
	  ve3 = m->nbvertex;
	  a2ri_vef_add_vertex (m, coordx, coordy, coordz);
	}
      if (coordx < m->xmin)
	m->xmin = coordx;
      if (coordx > m->xmax)
	m->xmax = coordx;
      if (coordy < m->ymin)
	m->ymin = coordy;
      if (coordy > m->ymax)
	m->ymax = coordy;
      if (coordz < m->zmin)
	m->zmin = coordz;
      if (coordz > m->zmax)
	m->zmax = coordz;

      ed1 = a2ri_vef_search_edge (*m, ve1, ve2);
      ed2 = a2ri_vef_search_edge (*m, ve1, ve3);
      ed3 = a2ri_vef_search_edge (*m, ve2, ve3);

      if (ed1 == -1)
	{
	  ed1 = m->nbedge;
	  a2ri_vef_add_edge (m, ve1, ve2, 0);
	}
      if (ed2 == -1)
	{
	  ed2 = m->nbedge;
	  a2ri_vef_add_edge (m, ve1, ve3, 0);
	}
      if (ed3 == -1)
	{
	  ed3 = m->nbedge;
	  a2ri_vef_add_edge (m, ve2, ve3, 0);
	}

      a2ri_vef_add_face (m, ed2, ed1, ed3);

      fscanf (is, "%s", str);	//read endloop
      fscanf (is, "%s", str);	//read endfacet
      fscanf (is, "%s", str);	//read facet ou endsolid
      fin = !strcmp (str, "endsolid");
    }

  fclose (is);

  setlocale(LC_NUMERIC,"");

  return 1;
}

/**
   Ouverture d'un fichier stl contenant un modèle
   @param file chemin du fichier ÃÂ  ouvrir
   @param m pointeur sur le modèle
   @return 1 si succÃÂ¨s, 0 sinon
*/
int
a2ri_vef_load_stl (
		   char *file,
		   vef_model * m)
{
  FILE *is = NULL;
  char str[250];

  is = fopen (file, "r");
  if (is == NULL)
    return 0;


  fscanf (is, "%s", str);

  fclose (is);

  if (!strcmp (str, "solid"))
    return a2ri_vef_load_ascii_stl (file, m);
  else
    return a2ri_vef_load_binary_stl (file, m);
}

/**
   Ouverture d'un fichier obj contenant un modèle
   @param file chemin du fichier à ouvrir
   @param m pointeur sur le modèle
   @return 1 si succès, 0 sinon
*/
int
a2ri_vef_load_obj (
		   char *file,
		   vef_model * m)
{

  FILE *is = NULL;
  int ve1,
    ve2,
    ve3;
  double coordx,
    coordy,
    coordz;
  char str[250];

  setlocale(LC_NUMERIC,"C");

  is = fopen (file, "r");
  if (is == NULL)
    return 0;

  fscanf (is, "%s", str);

  while (strcmp (str, "v") != 0)
    fscanf (is, "%s", str);

  //lecture des sommets
  while (strcmp (str, "g") != 0)
    {
      fscanf (is, "%lf %lf %lf", &coordx, &coordy, &coordz);
      //ajout d'un sommet
      a2ri_vef_add_vertex (m, coordx, coordy, coordz);
      fscanf (is, "%s", str);
      //mis à jour de la bounding box
      if (m->nbvertex == 1)
	{
	  m->xmin = coordx;
	  m->xmax = coordx;
	  m->ymin = coordy;
	  m->ymax = coordy;
	  m->zmin = coordz;
	  m->zmax = coordz;
	}
      else
	{
	  if (coordx < m->xmin)
	    m->xmin = coordx;
	  if (coordx > m->xmax)
	    m->xmax = coordx;
	  if (coordy < m->ymin)
	    m->ymin = coordy;
	  if (coordy > m->ymax)
	    m->ymax = coordy;
	  if (coordz < m->zmin)
	    m->zmin = coordz;
	  if (coordz > m->zmax)
	    m->zmax = coordz;
	}
    }

  fscanf (is, "%s", str);
  fscanf (is, "%s", str);

  //lecture des faces
  while (!feof (is))
    {
      //lecture des trois sommets
      fscanf (is, "%d %d %d", &ve1, &ve2, &ve3);
      ve1--;
      ve2--;
      ve3--;
      //ajout des aretes avec vérification au préalable de leur existence
      a2ri_vef_add_edge (m, ve1, ve2, 1);
      a2ri_vef_add_edge (m, ve2, ve3, 1);
      a2ri_vef_add_edge (m, ve3, ve1, 1);
      //recherche des aretes
      int ed1 = a2ri_vef_search_edge (*m, ve1, ve2);
      int ed2 = a2ri_vef_search_edge (*m, ve2, ve3);
      int ed3 = a2ri_vef_search_edge (*m, ve3, ve1);
      //ajout de la faces avec les trois aretes
      a2ri_vef_add_face (m, ed1, ed2, ed3);

      fscanf (is, "%s", str);
      //si la face compte plus de trois sommets, on relit et on ajoute des aretes et une seconde face
      if (strcmp (str, "f") != 0)
	{
	  ve2 = atoi (str);
	  ve2--;

	  a2ri_vef_add_edge (m, ve1, ve2, 1);
	  a2ri_vef_add_edge (m, ve2, ve3, 1);
	  a2ri_vef_add_edge (m, ve3, ve1, 1);
	  int ed1 = a2ri_vef_search_edge (*m, ve1, ve2);
	  int ed2 = a2ri_vef_search_edge (*m, ve2, ve3);
	  int ed3 = a2ri_vef_search_edge (*m, ve3, ve1);
	  a2ri_vef_add_face (m, ed1, ed3, ed2);


	  fscanf (is, "%s", str);
	}
    }


  fclose (is);

  setlocale(LC_NUMERIC,"");

  return 1;

}

/**
   Ouverture d'un fichier wrl contenant un modèle
   @param file chemin du fichier à ouvrir
   @param m pointeur sur le modèle
   @return 1 si succès, 0 sinon
*/
int
a2ri_vef_load_wrl (
		   char *file,
		   vef_model * m)
{
  FILE *is = NULL;
  char str[20];
  char coordx[15],
    coordy[15],
    coordz[15];

  setlocale(LC_NUMERIC,"C");

  is = fopen (file, "r");
  if (is == NULL)
    return 0;

  fscanf (is, "%s", str);

  while (strcmp (str, "point") && strcmp (str, "point["))
    fscanf (is, "%s", str);

  if (!strcmp (str, "point"))
    fscanf (is, "%s", str);

  // reading the file until coordx = } or ]
  fscanf (is, "%s", coordx);
  int i = 0;
  //lecture des sommets
  while (strcmp (coordx, "}") && strcmp (coordx, "]"))
    {
      fscanf (is, "%s", coordy);
      fscanf (is, "%s", coordz);
      if (coordz[strlen (coordz) - 1] == ',')
	{
	  memcpy (coordz, coordz, strlen (coordz) - 1);
	  coordz[strlen (coordz)] = '\0';
	}
      a2ri_vef_add_vertex (m, atof (coordx), atof (coordy), atof (coordz));
      //mis à jour de la bounding box
      if (i == 0)
	{
	  i++;
	  m->xmin = atof (coordx);
	  m->xmax = atof (coordx);
	  m->ymin = atof (coordy);
	  m->ymax = atof (coordy);
	  m->zmin = atof (coordz);
	  m->zmax = atof (coordz);
	}
      else
	{
	  if (atof (coordx) < m->xmin)
	    m->xmin = atof (coordx);
	  if (atof (coordx) > m->xmax)
	    m->xmax = atof (coordx);
	  if (atof (coordy) < m->ymin)
	    m->ymin = atof (coordy);
	  if (atof (coordy) > m->ymax)
	    m->ymax = atof (coordy);
	  if (atof (coordz) < m->zmin)
	    m->zmin = atof (coordz);
	  if (atof (coordz) > m->zmax)
	    m->zmax = atof (coordz);
	}
      fscanf (is, "%s", coordx);
    }

  fscanf (is, "%s", str);

  while (strcmp (str, "coordIndex") && strcmp (str, "coordIndex["))
    fscanf (is, "%s", str);

  if (!strcmp (str, "coordIndex"))
    fscanf (is, "%s", str);

  //lecture des faces
  fscanf (is, "%s", coordx);
  while (strcmp (coordx, "}") && strcmp (coordx, "]"))
    {
      //lecture des trois sommets composant la face
      fscanf (is, "%s", coordy);
      fscanf (is, "%s", coordz);
      //ajout des aretes avec vérification au préalable de leur existence
      a2ri_vef_add_edge (m, atoi (coordx), atoi (coordy), 1);
      a2ri_vef_add_edge (m, atoi (coordy), atoi (coordz), 1);
      a2ri_vef_add_edge (m, atoi (coordz), atoi (coordx), 1);
      //recherche des aretes
      int ed1 = a2ri_vef_search_edge (*m, atoi (coordx), atoi (coordy));
      int ed2 = a2ri_vef_search_edge (*m, atoi (coordy), atoi (coordz));
      int ed3 = a2ri_vef_search_edge (*m, atoi (coordz), atoi (coordx));
      //ajout de la faces avec les trois aretes
      a2ri_vef_add_face (m, ed1, ed2, ed3);

      // reading the -1
      fscanf (is, "%s", coordx);
      fscanf (is, "%s", coordx);
    }

  fclose (is);

  setlocale(LC_NUMERIC,"");

  return 1;
}

/**
   Ouverture d'un fichier vef contenant un modèle
   @param file chemin du fichier à ouvrir
   @param m pointeur sur le modèle
   @return 1 si succès, 0 sinon
*/
int
a2ri_vef_load_vef (
		   char *file,
		   vef_model * m)
{
  FILE *is = NULL;
  int nbvertex,
    nbedge,
    nbface,
    ve1,
    ve2,
    ed1,
    ed2,
    ed3,
    classif;
  double coordx,
    coordy,
    coordz;

  setlocale(LC_NUMERIC,"C");

  is = fopen (file, "r");
  if (is == NULL)
    return 0;

  a2ri_vef_init (m);

  //lecture du nombre de sommets
  fscanf (is, "%d", &nbvertex);

  //lecture du nombre d'aretes
  fscanf (is, "%d", &nbedge);

  //lecture du nombre de face
  fscanf (is, "%d", &nbface);

  //lecture des sommets
  for (int i = 0; i < nbvertex; i++)
    {
      fscanf (is, "%lf", &coordx);
      fscanf (is, "%lf", &coordy);
      fscanf (is, "%lf", &coordz);
      a2ri_vef_add_vertex (m, coordx, coordy, coordz);
      //mis à jour de la bounding box
      if (i == 0)
	{
	  m->xmin = coordx;
	  m->xmax = coordx;
	  m->ymin = coordy;
	  m->ymax = coordy;
	  m->zmin = coordz;
	  m->zmax = coordz;
	}
      else
	{
	  if (coordx < m->xmin)
	    m->xmin = coordx;
	  if (coordx > m->xmax)
	    m->xmax = coordx;
	  if (coordy < m->ymin)
	    m->ymin = coordy;
	  if (coordy > m->ymax)
	    m->ymax = coordy;
	  if (coordz < m->zmin)
	    m->zmin = coordz;
	  if (coordz > m->zmax)
	    m->zmax = coordz;
	}
    }


  //lecture des aretes
  for (int i = 0; i < nbedge; i++)
    {

      fscanf (is, "%d", &ve1);
      fscanf (is, "%d", &ve2);
      a2ri_vef_add_edge (m, ve1, ve2, 0);
    }

  //lecture des faces
  for (int i = 0; i < nbface; i++)
    {
      fscanf (is, "%d", &ed1);
      fscanf (is, "%d", &ed2);
      fscanf (is, "%d", &ed3);
      a2ri_vef_add_face (m, ed1, ed2, ed3);
    }

  //lecture des classifications si disponible
  for (int i = 0; i < nbface; i++)
    {
      if (!feof (is))
	{
	  fscanf (is, "%d", &classif);
	  m->fa[i].type = classif;
	}
    }

  fclose (is);

  setlocale(LC_NUMERIC,"");

  return 1;
}

/**
   Ouverture d'un fichier gts contenant un modèle
   @param file chemin du fichier à ouvrir
   @param m pointeur sur le modèle
   @return 1 si succès, 0 sinon
*/
int
a2ri_vef_load_gts (
		   char *file,
		   vef_model * m)
{
  FILE *is = NULL;
  int nbvertex,
    nbedge,
    nbface,
    ve1,
    ve2,
    ed1,
    ed2,
    ed3,
    classif;
  double coordx,
    coordy,
    coordz;

  setlocale(LC_NUMERIC,"C");

  is = fopen (file, "r");
  if (is == NULL)
    return 0;

  a2ri_vef_init (m);

  //lecture du nombre de sommets
  fscanf (is, "%d", &nbvertex);

  //lecture du nombre d'aretes
  fscanf (is, "%d", &nbedge);

  //lecture du nombre de face
  fscanf (is, "%d", &nbface);

  //lecture des sommets
  for (int i = 0; i < nbvertex; i++)
    {
      fscanf (is, "%lf", &coordx);
      fscanf (is, "%lf", &coordy);
      fscanf (is, "%lf", &coordz);
      a2ri_vef_add_vertex (m, coordx, coordy, coordz);
      //mis à jour de la bounding box
      if (i == 0)
	{
	  m->xmin = coordx;
	  m->xmax = coordx;
	  m->ymin = coordy;
	  m->ymax = coordy;
	  m->zmin = coordz;
	  m->zmax = coordz;
	}
      else
	{
	  if (coordx < m->xmin)
	    m->xmin = coordx;
	  if (coordx > m->xmax)
	    m->xmax = coordx;
	  if (coordy < m->ymin)
	    m->ymin = coordy;
	  if (coordy > m->ymax)
	    m->ymax = coordy;
	  if (coordz < m->zmin)
	    m->zmin = coordz;
	  if (coordz > m->zmax)
	    m->zmax = coordz;
	}
    }


  //lecture des aretes
  for (int i = 0; i < nbedge; i++)
    {

      fscanf (is, "%d", &ve1);
      fscanf (is, "%d", &ve2);
      ve1--;
      ve2--;
      a2ri_vef_add_edge (m, ve1, ve2, 0);
    }

  //lecture des faces
  for (int i = 0; i < nbface; i++)
    {
      fscanf (is, "%d", &ed1);
      fscanf (is, "%d", &ed2);
      fscanf (is, "%d", &ed3);
      ed1--;
      ed2--;
      ed3--;
      a2ri_vef_add_face (m, ed1, ed2, ed3);
    }

  //lecture des classifications si disponible
  for (int i = 0; i < nbface; i++)
    {
      if (!feof (is))
	{
	  fscanf (is, "%d", &classif);
	  m->fa[i].type = classif;
	}
    }

  fclose (is);

  setlocale(LC_NUMERIC,"");

  return 1;
}

/**
   Ouverture d'un fichier ply contenant un modèle
   @param file chemin du fichier à ouvrir
   @param m pointeur sur le modèle
   @return 1 si succès, 0 sinon
*/
int
a2ri_vef_load_ply (
		   char *file,
		   vef_model * m)
{
  int prop = 0,
    nbpropvertex = 0,
    nbpropface = 0,
    nbvertex,
    nbface,
    ve1,
    ve2,
    ve3;
  char str[20];
  double coordx,
    coordy,
    coordz;

  FILE *is = NULL;

  setlocale(LC_NUMERIC,"C");

  is = fopen (file, "r");
  if (is == NULL)
    return 0;


  fscanf (is, "%s", str);

  if (strcmp (str, "ply"))
    return 0;

  while (strcmp (str, "end_header"))
    {
      fscanf (is, "%s", str);
      if (prop == 1 && !strcmp (str, "property"))
	nbpropvertex++;
      if (prop == 2 && !strcmp (str, "property"))
	nbpropface++;

      if (!strcmp (str, "element"))
	{
	  fscanf (is, "%s", str);
	  //lecture du nombre de sommets
	  if (!strcmp (str, "vertex"))
	    {
	      prop = 1;
	      fscanf (is, "%d", &nbvertex);
	    }
	  //lecture du nombre de faces
	  else
	    {
	      prop = 1;
	      fscanf (is, "%d", &nbface);
	    }
	}
    }

  //lecture des sommets
  for (int i = 0; i < nbvertex; i++)
    {
      fscanf (is, "%lf %lf %lf", &coordx, &coordy, &coordz);
      a2ri_vef_add_vertex (m, coordx, coordy, coordz);
      //mis à jour de la bounding box
      if (i == 0)
	{
	  m->xmin = coordx;
	  m->xmax = coordx;
	  m->ymin = coordy;
	  m->ymax = coordy;
	  m->zmin = coordz;
	  m->zmax = coordz;
	}
      else
	{
	  if (coordx < m->xmin)
	    m->xmin = coordx;
	  if (coordx > m->xmax)
	    m->xmax = coordx;
	  if (coordy < m->ymin)
	    m->ymin = coordy;
	  if (coordy > m->ymax)
	    m->ymax = coordy;
	  if (coordz < m->zmin)
	    m->zmin = coordz;
	  if (coordz > m->zmax)
	    m->zmax = coordz;
	}
      for (int j = 0; j < nbpropvertex - 4; j++)
	fscanf (is, "%s", str);
    }

  //lecture des faces
  for (int i = 0; i < nbface; i++)
    {
      fscanf (is, "%d", &ve1);
      //lecture des trois sommets composant la face
      fscanf (is, "%d %d %d", &ve1, &ve2, &ve3);
      //ajout des aretes avec vérification au préalable de leur existence
      a2ri_vef_add_edge (m, ve1, ve2, 1);
      a2ri_vef_add_edge (m, ve2, ve3, 1);
      a2ri_vef_add_edge (m, ve3, ve1, 1);
      //recherche des aretes
      int ed1 = a2ri_vef_search_edge (*m, ve1, ve2);
      int ed2 = a2ri_vef_search_edge (*m, ve2, ve3);
      int ed3 = a2ri_vef_search_edge (*m, ve3, ve1);
      //ajout de la faces avec les trois aretes
      a2ri_vef_add_face (m, ed1, ed2, ed3);
    }

  fclose (is);

  setlocale(LC_NUMERIC,"");

  return 1;
}

/**
   Ouverture d'un fichier off contenant un modèle
   @param file chemin du fichier à ouvrir
   @param m pointeur sur le modèle
   @return 1 si succès, 0 sinon
*/
int
a2ri_vef_load_off (
		   char *file,
		   vef_model * m)
{

  FILE *is = NULL;
  char str[20];
  double coordx,
    coordy,
    coordz;
  int classif,
    ar1,
    ar2,
    ar3,
    nbvertex,
    nbface;

  setlocale(LC_NUMERIC,"C");

  is = fopen (file, "r");
  if (is == NULL)
    return 0;
  a2ri_vef_init (m);

  fscanf (is, "%s", str);

  if (strcmp (str, "OFF"))
    return 0;

  //lecture du nombre de sommets
  fscanf (is, "%d", &nbvertex);

  //lecture du nombre de faces
  fscanf (is, "%d", &nbface);

  fscanf (is, "%d", &ar1);

  //lecture des sommets
  for (int i = 0; i < nbvertex; i++)
    {
      fscanf (is, "%lf", &coordx);
      fscanf (is, "%lf", &coordy);
      fscanf (is, "%lf", &coordz);
      a2ri_vef_add_vertex (m, coordx, coordy, coordz);
      //mis à jour de la bounding box
      if (i == 0)
	{
	  m->xmin = coordx;
	  m->xmax = coordx;
	  m->ymin = coordy;
	  m->ymax = coordy;
	  m->zmin = coordz;
	  m->zmax = coordz;
	}
      else
	{
	  if (coordx < m->xmin)
	    m->xmin = coordx;
	  if (coordx > m->xmax)
	    m->xmax = coordx;
	  if (coordy < m->ymin)
	    m->ymin = coordy;
	  if (coordy > m->ymax)
	    m->ymax = coordy;
	  if (coordz < m->zmin)
	    m->zmin = coordz;
	  if (coordz > m->zmax)
	    m->zmax = coordz;
	}
    }

  //lecture des faces
  for (int i = 0; i < nbface; i++)
    {
      //lecture des trois sommets composant la face
      fscanf (is, "%d", &ar1);
      fscanf (is, "%d", &ar1);
      fscanf (is, "%d", &ar2);
      fscanf (is, "%d", &ar3);
      //ajout des aretes avec vérification au préalable de leur existence
      a2ri_vef_add_edge (m, ar1, ar2, 1);
      a2ri_vef_add_edge (m, ar2, ar3, 1);
      a2ri_vef_add_edge (m, ar3, ar1, 1);
      //recherche des aretes
      int ed1 = a2ri_vef_search_edge (*m, ar1, ar2);
      int ed2 = a2ri_vef_search_edge (*m, ar2, ar3);
      int ed3 = a2ri_vef_search_edge (*m, ar3, ar1);
      //ajout de la faces avec les trois aretes
      a2ri_vef_add_face (m, ed1, ed2, ed3);
    }

  //lecture des classifications si disponible
  for (int i = 0; i < nbface; i++)
    {
      if (!feof (is))
	{
	  fscanf (is, "%d", &classif);
	  m->fa[i].type = classif;
	}
    }

  fclose (is);

  setlocale(LC_NUMERIC,"");

  return 1;

}

/**
   Enregistrement d'un modèle dans un format défini par l'extension du nom de fichier
   @param file nom du fichier
   @param m le modèle
   @return aucun
*/
int
a2ri_vef_save_file (
		    char *file,
		    vef_model m)
{
  char ext[4];
  
  memcpy (ext, file + (strlen (file) - 3), 3);
  ext[3] = 0;

  //appel de la fonction d'enregistrement en fonction du type de l'extension du fichier
  if (!strcmp (ext, "wrl"))
    return a2ri_vef_save_wrl (file, m);

  if (!strcmp (ext, "vef"))
    return a2ri_vef_save_vef (file, m);

  if (!strcmp (ext, "pgn"))
    return a2ri_vef_save_pgn (file, m);

  if (!strcmp (ext, "ply"))
    return a2ri_vef_save_ply (file, m);

  if (!strcmp (ext, "off"))
    return a2ri_vef_save_off (file, m);

  if (!strcmp (ext, "obj"))
    return a2ri_vef_save_obj (file, m);

  if (!strcmp (ext, "gts"))
    return a2ri_vef_save_gts (file, m);

  return 0;

}

/**
   Enregistrement d'un modèle dans un fichier wrl
   @param file chemin du fichier
   @param m modèle à sauvegarder
   @return 1 si succès, 0 sinon
*/
int
a2ri_vef_save_wrl (
		   char *file,
		   vef_model m)
{
  setlocale(LC_NUMERIC,"C");

  if (strlen (file) < 4)
    {
      strcat (file, ".wrl");
    }

  char ext[5];

  memcpy (ext, file + (strlen (file) - 4), 4);
  ext[4] = '\0';

  if (strcmp (ext, ".wrl"))
    strcat (file, ".wrl");


  FILE *os = NULL;
  os = fopen (file, "w");
  if (os == NULL)
    return 0;

  //ecriture de l'en-tete
  fprintf (os, "#VRML V2.0 utf8\n");
  fprintf (os, "Shape{\n");
  fprintf (os, "appearance Appearance {\n");
  fprintf (os, "material Material {\n");
  fprintf (os, "}\n");
  fprintf (os, "}\n");
  fprintf (os, "geometry IndexedFaceSet{\n");
  fprintf (os, "coord Coordinate{\n");
  fprintf (os, "point[\n");

  //ecriture des sommets
  for (int i = 0; i < m.nbvertex; i++)
    fprintf (os, "%f %f %f,\n", m.ve[i].x, m.ve[i].y, m.ve[i].z);
  fprintf (os, "]\n");
  fprintf (os, "}\n");

  //ecriture des faces
  fprintf (os, "coordIndex[\n");
  for (int i = 0; i < m.nbface; i++)
    {
      int nb1,
        nb2,
        nb3;
      vef_face_get_vertices (m.fa[i], m.ed, &nb1, &nb2, &nb3);
      fprintf (os, "%d %d %d -1\n", nb1, nb2, nb3);
    }
  fprintf (os, "]\n");
  fprintf (os, "}\n");
  fprintf (os, "}\n");
  fclose (os);
  
  setlocale(LC_NUMERIC,"");

  return 1;
}

/**
   Enregistrement d'un modèle dans un fichier pgn
   @param file chemin du fichier
   @param m modèle à sauvegarder
   @return 1 si succès, 0 sinon
*/
int
a2ri_vef_save_pgn (
		   char *file,
		   vef_model m)
{
  setlocale(LC_NUMERIC,"C");

  if (strlen (file) < 4)
    {
      strcat (file, ".pgn");
    }

  char ext[5];

  memcpy (ext, file + (strlen (file) - 4), 4);
  ext[4] = '\0';

  if (strcmp (ext, ".pgn"))
    strcat (file, ".pgn");


  FILE *os = NULL;
  os = fopen (file, "w");
  if (os == NULL)
    return 0;

  //ecriture du nombre de sommets et faces
  fprintf (os, "%d %d \n\n", m.nbvertex, m.nbface);

  //ecriture des sommets
  for (int i = 0; i < m.nbvertex; i++)
    fprintf (os, "%f %f %f\n", m.ve[i].x, m.ve[i].y, m.ve[i].z);

  //ecriture des faces
  for (int i = 0; i < m.nbface; i++)
    {
      int ve1,
        ve2,
        ve3;
      vef_face_get_vertices (m.fa[i], m.ed, &ve1, &ve2, &ve3);
      fprintf (os, "%d %d %d -1\n", ve1, ve2, ve3);
    }

  fclose (os);

  setlocale(LC_NUMERIC,"");

  return 1;
}

/**
   Enregistrement d'un modèle dans un fichier vef
   @param file chemin du fichier
   @param m modèle à sauvegarder
   @return 1 si succès, 0 sinon
*/
int
a2ri_vef_save_vef (
		   char *file,
		   vef_model m)
{
  setlocale(LC_NUMERIC,"C");

  if (strlen (file) < 4)
    {
      strcat (file, ".vef");
    }

  char ext[5];

  memcpy (ext, file + (strlen (file) - 4), 4);
  ext[4] = '\0';

  if (strcmp (ext, ".vef"))
    strcat (file, ".vef");


  FILE *os = NULL;
  os = fopen (file, "w");
  if (os == NULL)
    return 0;

  //ecriture des nombre de sommets, aretes et faces
  fprintf (os, "%d %d %d\n\n", m.nbvertex, m.nbedge, m.nbface);

  //ecriture des sommets
  for (int i = 0; i < m.nbvertex; i++)
    fprintf (os, "%f %f %f\n", m.ve[i].x, m.ve[i].y, m.ve[i].z);

  //ecriture des aretes
  for (int i = 0; i < m.nbedge; i++)
    fprintf (os, "%d %d\n", m.ed[i].ve1, m.ed[i].ve2);

  //ecriture des faces
  for (int i = 0; i < m.nbface; i++)
    fprintf (os, "%d %d %d\n", m.fa[i].ed1, m.fa[i].ed2, m.fa[i].ed3);

  fclose (os);

  setlocale(LC_NUMERIC,"");

  return 1;
}

/**
   Enregistrement d'un modèle dans un fichier gts
   @param file chemin du fichier
   @param m modèle à sauvegarder
   @return 1 si succès, 0 sinon
*/
int
a2ri_vef_save_gts (
		   char *file,
		   vef_model m)
{
  setlocale(LC_NUMERIC,"C");

  if (strlen (file) < 4)
    {
      strcat (file, ".gts");
    }

  char ext[5];

  memcpy (ext, file + (strlen (file) - 4), 4);
  ext[4] = '\0';

  if (strcmp (ext, ".gts"))
    strcat (file, ".gts");


  FILE *os = NULL;
  os = fopen (file, "w");
  if (os == NULL)
    return 0;

  //ecriture des nombre de sommets, aretes et faces
  fprintf (os, "%d %d %d\n\n", m.nbvertex, m.nbedge, m.nbface);

  //ecriture des sommets
  for (int i = 0; i < m.nbvertex; i++)
    fprintf (os, "%f %f %f\n", m.ve[i].x, m.ve[i].y, m.ve[i].z);

  //ecriture des aretes
  for (int i = 0; i < m.nbedge; i++)
    fprintf (os, "%d %d\n", m.ed[i].ve1 + 1, m.ed[i].ve2 + 1);

  //ecriture des faces
  for (int i = 0; i < m.nbface; i++)
    fprintf (os, "%d %d %d\n", m.fa[i].ed1 + 1, m.fa[i].ed2 + 1,
	     m.fa[i].ed3 + 1);

  fclose (os);

  setlocale(LC_NUMERIC,"");

  return 1;
}

/**
   Enregistrement d'un modèle dans un fichier off
   @param file chemin du fichier
   @param m modèle à sauvegarder
   @return 1 si succès, 0 sinon
*/
int
a2ri_vef_save_off (
		   char *file,
		   vef_model m)
{
  setlocale(LC_NUMERIC,"C");

  if (strlen (file) < 4)
    {
      strcat (file, ".off");
    }

  char ext[5];

  memcpy (ext, file + (strlen (file) - 4), 4);
  ext[4] = '\0';

  if (strcmp (ext, ".off"))
    strcat (file, ".off");


  FILE *os = NULL;
  os = fopen (file, "w");
  if (os == NULL)
    return 0;

  //ecriture de l'en-tete et des nombres de sommets et faces
  fprintf (os, "OFF\n%d %d 0\n\n", m.nbvertex, m.nbface);

  //ecriture des sommets
  for (int i = 0; i < m.nbvertex; i++)
    fprintf (os, "%f %f %f\n", m.ve[i].x, m.ve[i].y, m.ve[i].z);

  //ecriture des faces
  for (int i = 0; i < m.nbface; i++)
    {
      int ve1,
        ve2,
        ve3;
      vef_face_get_vertices (m.fa[i], m.ed, &ve1, &ve2, &ve3);
      fprintf (os, "3 %d %d %d \n", ve1, ve2, ve3);
    }

  fclose (os);

  setlocale(LC_NUMERIC,"");

  return 1;
}

/**
   Enregistrement d'un modèle dans un fichier ply
   @param file chemin du fichier
   @param m modèle à sauvegarder
   @return 1 si succès, 0 sinon
*/
int
a2ri_vef_save_ply (
		   char *file,
		   vef_model m)
{
  setlocale(LC_NUMERIC,"C");

  if (strlen (file) < 4)
    {
      strcat (file, ".ply");
    }
  char ext[5];

  memcpy (ext, file + (strlen (file) - 4), 4);
  ext[4] = '\0';

  if (strcmp (ext, ".ply"))
    strcat (file, ".ply");


  FILE *os = NULL;
  os = fopen (file, "w");
  if (os == NULL)
    return 0;

  //ecriture de l'en-tete avec le nombre de sommets et de faces
  fprintf (os, "ply\nformat ascii 1.0\ncomment zipper output\n");
  fprintf (os,
	   "element vertex %d\nproperty float x\nproperty float y\nproperty float z\nelement face %d\n",
	   m.nbvertex, m.nbface);
  fprintf (os, "property list uchar int vertex_indices\nend_header\n");

  //ecriture des sommets
  for (int i = 0; i < m.nbvertex; i++)
    fprintf (os, "%f %f %f\n", m.ve[i].x, m.ve[i].y, m.ve[i].z);

  //ecriture des faces
  for (int i = 0; i < m.nbface; i++)
    {
      int ve1,
        ve2,
        ve3;
      vef_face_get_vertices (m.fa[i], m.ed, &ve1, &ve2, &ve3);
      fprintf (os, "3 %d %d %d \n", ve1, ve2, ve3);
    }

  fclose (os);

  setlocale(LC_NUMERIC,"");

  return 1;
}

/**
   Enregistrement d'un modèle dans un fichier obj
   @param file chemin du fichier
   @param m modèle à sauvegarder
   @return 1 si succès, 0 sinon
*/
int
a2ri_vef_save_obj (
		   char *file,
		   vef_model m)
{
  setlocale(LC_NUMERIC,"C");

  if (strlen (file) < 4)
    {
      strcat (file, ".obj");
    }

  char ext[5];

  memcpy (ext, file + (strlen (file) - 4), 4);
  ext[4] = '\0';

  if (strcmp (ext, ".obj"))
    strcat (file, ".obj");


  FILE *os = NULL;
  os = fopen (file, "w");
  if (os == NULL)
    return 0;

  //ecriture des sommets
  for (int i = 0; i < m.nbvertex; i++)
    fprintf (os, "v %f %f %f\n", m.ve[i].x, m.ve[i].y, m.ve[i].z);

  fprintf (os, "\n");

  //ecriture des faces
  for (int i = 0; i < m.nbface; i++)
    {
      int ve1,
        ve2,
        ve3;
      vef_face_get_vertices (m.fa[i], m.ed, &ve1, &ve2, &ve3);
      fprintf (os, "f %d %d %d\n", ve1 + 1, ve2 + 1, ve3 + 1);
    }

  fclose (os);

  setlocale(LC_NUMERIC,"");

  return 1;
}
