/*
  ---------------------------------

   poly.h 
   header file for poly.c and poly2.c

   see qh-poly.htm, qhull.h and poly.c

   copyright (c) 1993-2002, The Geometry Center
*/

#ifndef qhDEFpoly
#define qhDEFpoly 1

/*===============   constants ========================== */

/*----------------------------------
  
  ALGORITHMfault   
    use as argument to checkconvex() to report errors during buildhull
*/
#define qh_ALGORITHMfault 0

/*----------------------------------
  
  DATAfault        
    use as argument to checkconvex() to report errors during initialhull
*/
#define qh_DATAfault 1

/*----------------------------------
  
  DUPLICATEridge
    special value for facet->neighbor to indicate a duplicate ridge
  
  notes:
    set by matchneighbor, used by matchmatch and mark_dupridge
*/
#define qh_DUPLICATEridge ( facetT * ) 1L

/*----------------------------------
  
  MERGEridge       flag in facet
    special value for facet->neighbor to indicate a merged ridge
  
  notes:
    set by matchneighbor, used by matchmatch and mark_dupridge
*/
#define qh_MERGEridge ( facetT * ) 2L


/*============ -structures- ====================*/

/*=========== -macros- =========================*/

/*----------------------------------
  
  FORALLfacet_( facetlist ) { ... }
    assign 'facet' to each facet in facetlist
    
  notes:
    uses 'facetT *facet;'
    assumes last facet is a sentinel
    
  see:
    FORALLfacets
*/
#define FORALLfacet_( facetlist ) if ( facetlist ) for( facet=( facetlist );facet && facet->next;facet=facet->next )

/*----------------------------------
  
  FORALLnew_facets { ... } 
    assign 'newfacet' to each facet in qh.newfacet_list
    
  notes:
    uses 'facetT *newfacet;'
    at exit, newfacet==NULL
*/
#define FORALLnew_facets for( newfacet=qh newfacet_list;newfacet && newfacet->next;newfacet=newfacet->next )

/*----------------------------------
  
  FORALLvertex_( vertexlist ) { ... }
    assign 'vertex' to each vertex in vertexlist
    
  notes:
    uses 'vertexT *vertex;'
    at exit, vertex==NULL
*/
#define FORALLvertex_( vertexlist ) for ( vertex=( vertexlist );vertex && vertex->next;vertex= vertex->next )

/*----------------------------------
  
  FORALLvisible_facets { ... }
    assign 'visible' to each visible facet in qh.visible_list
    
  notes:
    uses 'vacetT *visible;'
    at exit, visible==NULL
*/
#define FORALLvisible_facets for (visible=qh visible_list; visible && visible->visible; visible= visible->next)

/*----------------------------------
  
  FORALLsame_( newfacet ) { ... } 
    assign 'same' to each facet in newfacet->f.samecycle
    
  notes:
    uses 'facetT *same;'
    stops when it returns to newfacet
*/
#define FORALLsame_(newfacet) for (same= newfacet->f.samecycle; same != newfacet; same= same->f.samecycle)

/*----------------------------------
  
  FORALLsame_cycle_( newfacet ) { ... } 
    assign 'same' to each facet in newfacet->f.samecycle
    
  notes:
    uses 'facetT *same;'
    at exit, same == NULL
*/
#define FORALLsame_cycle_(newfacet) \
     for (same= newfacet->f.samecycle; \
         same; same= (same == newfacet ?  NULL : same->f.samecycle))

/*----------------------------------
  
  FOREACHneighborA_( facet ) { ... }
    assign 'neighborA' to each neighbor in facet->neighbors
  
  FOREACHneighborA_( vertex ) { ... }
    assign 'neighborA' to each neighbor in vertex->neighbors
  
  declare:
    facetT *neighborA, **neighborAp;

  see:
    FOREACHsetelement_
*/
#define FOREACHneighborA_(facet)  FOREACHsetelement_(facetT, facet->neighbors, neighborA)

/*----------------------------------
  
  FOREACHvisible_( facets ) { ... } 
    assign 'visible' to each facet in facets
    
  notes:
    uses 'facetT *facet, *facetp;'
    see FOREACHsetelement_
*/
#define FOREACHvisible_(facets) FOREACHsetelement_(facetT, facets, visible)

/*----------------------------------
  
  FOREACHnewfacet_( facets ) { ... } 
    assign 'newfacet' to each facet in facets
    
  notes:
    uses 'facetT *newfacet, *newfacetp;'
    see FOREACHsetelement_
*/
#define FOREACHnewfacet_(facets) FOREACHsetelement_(facetT, facets, newfacet)

/*----------------------------------
  
  FOREACHvertexA_( vertices ) { ... } 
    assign 'vertexA' to each vertex in vertices
    
  notes:
    uses 'vertexT *vertexA, *vertexAp;'
    see FOREACHsetelement_
*/
#define FOREACHvertexA_(vertices) FOREACHsetelement_(vertexT, vertices, vertexA)

/*----------------------------------
  
  FOREACHvertexreverse12_( vertices ) { ... } 
    assign 'vertex' to each vertex in vertices
    reverse order of first two vertices
    
  notes:
    uses 'vertexT *vertex, *vertexp;'
    see FOREACHsetelement_
*/
#define FOREACHvertexreverse12_(vertices) FOREACHsetelementreverse12_(vertexT, vertices, vertex)


/*=============== prototypes poly.c in alphabetical order ================*/

void    qh_appendfacet(facetT *facet);
void    qh_appendvertex(vertexT *vertex);
void 	qh_attachnewfacets (void);
boolT   qh_checkflipped (facetT *facet, realT *dist, boolT allerror);
void	qh_delfacet(facetT *facet);
void 	qh_deletevisible(void /*qh visible_list, qh horizon_list*/);
setT   *qh_facetintersect (facetT *facetA, facetT *facetB, int *skipAp,int *skipBp, int extra);
unsigned qh_gethash (int hashsize, setT *set, int size, int firstindex, void *skipelem);
facetT *qh_makenewfacet(setT *vertices, boolT toporient, facetT *facet);
void    qh_makenewplanes ( void /* newfacet_list */);
facetT *qh_makenew_nonsimplicial (facetT *visible, vertexT *apex, int *numnew);
facetT *qh_makenew_simplicial (facetT *visible, vertexT *apex, int *numnew);
void    qh_matchneighbor (facetT *newfacet, int newskip, int hashsize,
			  int *hashcount);
void	qh_matchnewfacets (void);
boolT   qh_matchvertices (int firstindex, setT *verticesA, int skipA, 
			  setT *verticesB, int *skipB, boolT *same);
facetT *qh_newfacet(void);
ridgeT *qh_newridge(void);
int     qh_pointid (pointT *point);
void 	qh_removefacet(facetT *facet);
void 	qh_removevertex(vertexT *vertex);
void    qh_updatevertices (void);


/*========== -prototypes poly2.c in alphabetical order ===========*/

void    qh_addhash (void* newelem, setT *hashtable, int hashsize, unsigned hash);
void 	qh_check_bestdist (void);
void    qh_check_maxout (void);
void    qh_check_output (void);
void    qh_check_point (pointT *point, facetT *facet, realT *maxoutside, realT *maxdist, facetT **errfacet1, facetT **errfacet2);
void   	qh_check_points(void);
void 	qh_checkconvex(facetT *facetlist, int fault);
void    qh_checkfacet(facetT *facet, boolT newmerge, boolT *waserrorp);
void 	qh_checkflipped_all (facetT *facetlist);
void 	qh_checkpolygon(facetT *facetlist);
void    qh_checkvertex (vertexT *vertex);
void 	qh_clearcenters (qh_CENTER type);
void 	qh_createsimplex(setT *vertices);
void 	qh_delridge(ridgeT *ridge);
void    qh_delvertex (vertexT *vertex);
setT   *qh_facet3vertex (facetT *facet);
facetT *qh_findbestfacet (pointT *point, boolT bestoutside,
           realT *bestdist, boolT *isoutside);
facetT *qh_findfacet_all (pointT *point, realT *bestdist, boolT *isoutside,
			  int *numpart);
int 	qh_findgood (facetT *facetlist, int goodhorizon);
void 	qh_findgood_all (facetT *facetlist);
void    qh_furthestnext (void /* qh facet_list */);
void    qh_furthestout (facetT *facet);
void    qh_infiniteloop (facetT *facet);
void 	qh_initbuild(void);
void 	qh_initialhull(setT *vertices);
setT   *qh_initialvertices(int dim, setT *maxpoints, pointT *points, int numpoints);
vertexT *qh_isvertex (pointT *point, setT *vertices);
vertexT *qh_makenewfacets (pointT *point /*horizon_list, visible_list*/);
void    qh_matchduplicates (facetT *atfacet, int atskip, int hashsize, int *hashcount);
void    qh_nearcoplanar ( void /* qh.facet_list */);
vertexT *qh_nearvertex (facetT *facet, pointT *point, realT *bestdistp);
int 	qh_newhashtable(int newsize);
vertexT *qh_newvertex(pointT *point);
ridgeT *qh_nextridge3d (ridgeT *atridge, facetT *facet, vertexT **vertexp);
void    qh_outcoplanar (void /* facet_list */);
pointT *qh_point (int id);
void 	qh_point_add (setT *set, pointT *point, void *elem);
setT   *qh_pointfacet (void /*qh facet_list*/);
setT   *qh_pointvertex (void /*qh facet_list*/);
void 	qh_prependfacet(facetT *facet, facetT **facetlist);
void	qh_printhashtable(FILE *fp);
void    qh_printlists (void);
void    qh_resetlists (boolT stats, boolT resetVisible /*qh newvertex_list newfacet_list visible_list*/);
void    qh_setvoronoi_all (void);
void	qh_triangulate (void /*qh facet_list*/);
void    qh_triangulate_facet (facetT *facetA, vertexT **first_vertex);
void    qh_triangulate_link (facetT *oldfacetA, facetT *facetA, facetT *oldfacetB, facetT *facetB);
void	qh_triangulate_mirror (facetT *facetA, facetT *facetB);
void    qh_triangulate_null (facetT *facetA);
void    qh_vertexintersect(setT **vertexsetA,setT *vertexsetB);
setT   *qh_vertexintersect_new(setT *vertexsetA,setT *vertexsetB);
void    qh_vertexneighbors (void /*qh facet_list*/);
boolT 	qh_vertexsubset(setT *vertexsetA, setT *vertexsetB);


#endif /* qhDEFpoly */