mirror of
https://bitbucket.org/cosmicvoids/vide_public.git
synced 2025-07-04 15:21:11 +00:00
245 lines
7.7 KiB
C
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;
|
|
}
|