/* topology.c: All things that have to do with conversion of a discretised 
 * scene to and from a Boundary REPresentation using the BREP library. */

#include "topology.h"

/* Adds topological information to VERTEXes and PATCHes. This information is
 * automatically freed when destroying the VERTEXes and PATCHes or
 * explicitely using brepCheckOut(). The
 * topoligical data for a VERTEX is a BREP_VERTEX with a pointer to the
 * vertex as client data. The data for a PATCH is a BREP_FACE with as client
 * data a pointer to the PATCH. This face contains one contour, with wings 
 * connecting the vertices of the patch in order. No client data is passed
 * when creating the BREP_CONTOURs or BREP_EDGEs. It is possible to connect
 * your own client data to the topological entities by setting a create callback
 * for the entities, see BREP/brep.h. */
void BrepCheckIn(PATCHLIST *patches)
{
  BREP_FACE *face;
  BREP_CONTOUR *contour;
  int i;

  for (; patches; patches = patches->next) {
    PATCH *patch = patches->patch;

    if (patch->brep_data)
      continue;

    /* Create a BREP_VERTEX for each VERTEX that didn't have one yet. */
    for (i=0; i<patch->nrvertices; i++) 
      if (!patch->vertex[i]->brep_data)
	patch->vertex[i]->brep_data = BrepCreateVertex(patch->vertex[i]);

    /* Create a BREP_FACE corresponding to the PATCH. */
    patch->brep_data = face = BrepCreateFace((BREP_SHELL *)NULL, patch);
    
    /* Create a BREP_CONTOUR in the face. No client data. */
    contour = BrepCreateContour(face, NULL);

    /* Create wings in the contour, connecting the vertices in order. */
    for (i=0; i<patch->nrvertices; i++) 
      BrepCreateWing(patch->vertex[i]->brep_data, 
		     patch->vertex[(i+1)%patch->nrvertices]->brep_data,
		     contour, NULL);

    /* This actually just makes sure that close callbacks for the face, 
     * its contour or its wings are called, if such callbacks have been 
     * installed. */
    BrepCloseFace(face);
  }
}

/* Destroys the topological information kept with the PATCHes and their 
 * VERTEXes. */
void BrepCheckOut(PATCHLIST *patches)
{
  int i;

  for (; patches; patches = patches->next) {
    PATCH *patch = patches->patch;

    if (patch->brep_data) {
      BrepDestroyFace(patch->brep_data);
      patch->brep_data = (BREP_FACE *)NULL;
    }

    for (i=0; i<patch->nrvertices; i++) {
      if (patch->vertex[i]->brep_data &&
	  !patch->vertex[i]->brep_data->wing_ring) {
	/* Only set the pointer to NULL if the BREP_VERTEX will
	 * really be destroyed. BrepDestroyVertex() does not destroy
	 * the BREP_VERTEX if it is still used in one more contours. */
	BrepDestroyVertex(patch->vertex[i]->brep_data);
	patch->vertex[i]->brep_data = (BREP_VERTEX *)NULL;
      }
    }
  }
}
