vide_public/c_source/zobov/vozutil.c
2024-05-22 16:15:14 -04:00

245 lines
7.7 KiB
C

#include "libqhull/qhull_a.h"
#include "voz.h"
#define FOREACHvertex2_(vertices) FOREACHsetelement_(vertexT, vertices2,vertex2)
/*char qh_version[] = "user_eg 3.1 2001/10/04"; */
int compar(const void * n1, const void * n2) {
int i1,i2;
i1 = *(int *)n1;
i2 = *(int *)n2;
return 2*(i1 > i2) - 1 + (i1 == i2);
}
/* Finds Delaunay adjacencies of a set of points */
int delaunadj (coordT *points, int nvp, int nvpbuf, int nvpall, PARTADJ **adjs) {
int dim= 3; /* dimension of points */
boolT ismalloc= False; /* True if qhull should free points in qh_freeqhull() or reallocation */
char flags[250]; /* option flags for qhull, see qh_opt.htm */
FILE *outfile= stdout; /* output from qh_produce_output()
use NULL to skip qh_produce_output() */
FILE *errfile= stderr; /* error messages from qhull code */
int exitcode; /* 0 if no error from qhull */
int curlong, totlong; /* memory remaining after qh_memfreeshort */
int i, ver, count;
int numfacets, numsimplicial, numridges, totneighbors, numneighbors,
numcoplanars, numtricoplanars;
setT *vertices, *vertices2, *vertex_points, *coplanar_points;
vertexT *vertex, **vertexp;
vertexT *vertex2, **vertex2p;
int vertex_i, vertex_n;
facetT *facet, **facetp, *neighbor, **neighborp;
pointT *point, **pointp;
int numdiv;
PARTADJ adjst;
int errorReported = 0;
adjst.adj = (int *)malloc(MAXVERVER*sizeof(int));
if (adjst.adj == NULL) {
printf("Unable to allocate adjst.adj\n");
exit(0);
}
/* Delaunay triangulation*/
sprintf (flags, "qhull s d Qt");
exitcode= qh_new_qhull (dim, nvpall, points, ismalloc,
flags, outfile, errfile);
if (!exitcode) { /* if no error */
/* 'qh facet_list' contains the convex hull */
/* From qh_printvneighbors */
qh_countfacets(qh facet_list, NULL, 0, &numfacets, &numsimplicial,
&totneighbors, &numridges, &numcoplanars, &numtricoplanars);
qh_vertexneighbors();
vertices= qh_facetvertices (qh facet_list, NULL, 0);
vertex_points= qh_settemp (nvpall);
coplanar_points= qh_settemp (nvpall);
qh_setzero (vertex_points, 0, nvpall);
qh_setzero (coplanar_points, 0, nvpall);
FOREACHvertex_(vertices)
qh_point_add (vertex_points, vertex->point, vertex);
FORALLfacet_(qh facet_list) {
FOREACHpoint_(facet->coplanarset)
qh_point_add (coplanar_points, point, facet);
}
ver = 0;
FOREACHvertex_i_(vertex_points) {
(*adjs)[ver].nadj = 0;
if (vertex) {
/* Count the neighboring vertices, check that all are real
neighbors */
adjst.nadj = 0;
FOREACHneighbor_(vertex) {
if ((*adjs)[ver].nadj > -1) {
if (neighbor->visitid) {
vertices2 = neighbor->vertices;
FOREACHvertex2_(vertices2) {
if (ver != qh_pointid(vertex2->point)) {
adjst.adj[adjst.nadj] = (int)qh_pointid(vertex2->point);
adjst.nadj ++;
if (adjst.nadj > MAXVERVER) {
printf("Increase MAXVERVER to at least %d!\n",adjst.nadj);
exit(0);
}
}
}
} else {
printf(" %d",ver);
(*adjs)[ver].nadj = -1; /* There are unreal vertices here */
}
}
}
} else (*adjs)[ver].nadj = -2;
/* Enumerate the unique adjacencies*/
if (adjst.nadj >= 4) {
qsort((void *)adjst.adj, adjst.nadj, sizeof(int), &compar);
count = 1;
for (i=1; i<adjst.nadj; i++)
if (adjst.adj[i] != adjst.adj[i-1]) {
if (adjst.adj[i] >= nvpbuf && !errorReported) {
errorReported = 1;
printf("Guard point encountered. Increase border and/or nguard.\n");
printf("P:(%f,%f,%f), G: (%f,%f,%f)\n",points[3*ver],points[3*ver+1],points[3*ver+2],
points[3*adjst.adj[i]],points[3*adjst.adj[i]+1],points[3*adjst.adj[i]+2]);
}
count++;
}
(*adjs)[ver].adj = (int *)malloc(count*sizeof(int));
if ((*adjs)[ver].adj == NULL) {
printf("Unable to allocate (*adjs)[ver].adj\n");
exit(0);
}
(*adjs)[ver].adj[0] = adjst.adj[0];
count = 1;
for (i=1; i<adjst.nadj; i++)
if (adjst.adj[i] != adjst.adj[i-1]) {
(*adjs)[ver].adj[count] = adjst.adj[i];
count++;
}
(*adjs)[ver].nadj = count;
} else {
printf("Number of adjacencies %d < 4, particle %d -> %d\n",adjst.nadj,ver,ver);
exit(0);
}
ver++;
if (ver == nvp) break;
}
qh_settempfree (&coplanar_points);
qh_settempfree (&vertex_points);
qh_settempfree (&vertices);
}
qh_freeqhull(!qh_ALL); /* free long memory */
qh_memfreeshort (&curlong, &totlong); /* free short memory and memory allocator */
if (curlong || totlong)
fprintf (errfile, "qhull internal warning (delaunadj): did not free %d bytes of long memory (%d pieces)\n", totlong, curlong);
free(adjst.adj);
return exitcode;
}
/* Calculates the Voronoi volume from a set of Delaunay adjacencies */
int vorvol (coordT *deladjs, coordT *points, pointT *intpoints, int numpoints, float *vol) {
int dim= 3; /* dimension of points */
boolT ismalloc= False; /* True if qhull should free points in qh_freeqhull() or reallocation */
char flags[250]; /* option flags for qhull, see qh_opt.htm */
FILE *outfile= NULL; /* output from qh_produce_output()
use NULL to skip qh_produce_output() */
FILE *errfile= stderr; /* error messages from qhull code */
int exitcode; /* 0 if no error from qhull */
facetT *facet; /* set by FORALLfacets */
int curlong, totlong; /* memory remaining after qh_memfreeshort */
coordT *point, *normp, *coordp, *feasiblep, *deladj;
int i, j, k;
boolT zerodiv;
float runsum;
char region;
/*coordT *points;
pointT *intpoints;*/
/* make point array from adjacency coordinates (add offset)*/
/*points = (coordT *)malloc(4*numpoints*sizeof(coordT));
if (points == NULL) {
printf("Unable to allocate points\n");
exit(0);
}*/
for (i=0; i<numpoints; i++) {
runsum = 0.;
deladj = deladjs + 3*i;
point = points + 4*i;
for (j=0;j<3;j++) {
runsum += deladj[j]*deladj[j];
point[j] = deladj[j];
}
point[3] = -0.5*runsum;
}
sprintf (flags, "qhull H0");
exitcode= qh_new_qhull (4, numpoints, points, ismalloc,
flags, outfile, errfile);
numpoints = 0;
if (!exitcode) { /* if no error */
FORALLfacets {
numpoints++;
}
/* Now we know how many points */
/*intpoints = (pointT *)malloc(dim*numpoints*sizeof(pointT));
if (intpoints == NULL) {
printf("Unable to allocate intpoints\n");
exit(0);
}*/
j = 0;
FORALLfacets {
if (!qh feasible_point) {
fprintf (stdout, "qhull input error (qh_printafacet): option 'Fp' needs qh feasible_point\n");
qh_errexit( qh_ERRinput, NULL, NULL);
}
point= coordp= intpoints + j*3;
j++;
normp= facet->normal;
feasiblep= qh feasible_point;
if (facet->offset < -qh MINdenom) {
for (k= qh hull_dim; k--; )
*(coordp++)= (*(normp++) / - facet->offset) + *(feasiblep++);
}else {
for (k= qh hull_dim; k--; ) {
*(coordp++)= qh_divzero (*(normp++), facet->offset, qh MINdenom_1,
&zerodiv) + *(feasiblep++);
if (zerodiv) {
qh_memfree (point, qh normal_size);
printf("LABELprintinfinite\n");
exit(0);
}
}
}
}
}
qh_freeqhull (!qh_ALL);
qh_memfreeshort (&curlong, &totlong);
/* Now we calculate the volume */
sprintf (flags, "qhull FA");
exitcode= qh_new_qhull (dim, numpoints, intpoints, ismalloc,
flags, outfile, errfile);
qh_getarea(qh facet_list);
*vol = qh totvol;
qh_freeqhull (!qh_ALL);
qh_memfreeshort (&curlong, &totlong);
if (curlong || totlong)
fprintf (errfile, "qhull internal warning (vorvol): did not free %d bytes of long memory (%d pieces)\n", totlong, curlong);
/*free(points); free(intpoints);*/
return exitcode;
}