예제 #1
0
//-------------------------------------------------------------------
void SearchZones::addShiftedPrimitiveSearchZone(uint finger_id,vertexT const* curr_vtx)
{
  setT *neighbor_facets=curr_vtx->neighbors;
  PrimitiveSearchZone* p_search_zone = new PrimitiveSearchZone();
  p_search_zone->hyperplane_ids_.reserve(qh_setsize(neighbor_facets));

  for(uint i=0; i < (uint)qh_setsize(neighbor_facets); i++)
    p_search_zone->hyperplane_ids_.push_back(((facetT*)neighbor_facets->e[i].p)->id);

  search_zones_[finger_id]->push_back(p_search_zone);
}
예제 #2
0
파일: testqset.c 프로젝트: xelda1988/qhull
void testSetcompactCopy(int numInts, int *intarray, int checkEvery)
{
    setT *ints= qh_setnew(20);
    setT *ints2= NULL;
    int i,j,k;

    qh_fprintf(stderr, 8017, "\n\nTesting qh_setcompact and qh_setcopy 0..%d. Test", numInts-1);
    for(j=0; j<numInts; j++){
        if(log_i(ints, "j", j, numInts, checkEvery)){
            for(i= qh_setsize(ints); i<j; i++){  /* Test i<j to test the empty set */
                for(k= 0; k<i%7; k++){
                    qh_setappend(&ints, NULL);
                }
                qh_setappend(&ints, intarray+i);
            }
            qh_setfree(&ints2);
            ints2= qh_setcopy(ints, 0);
            qh_setcompact(ints);
            qh_setcompact(ints2);
            checkSetContents("qh_setcompact", ints, j, 0, 0, -1);
            checkSetContents("qh_setcompact", ints2, j, 0, 0, -1);
            qh_setcompact(ints);
            checkSetContents("qh_setcompact", ints, j, 0, 0, -1);
        }
    }
    qh_setfree(&ints);
    qh_setfree(&ints2);
}/*testSetcompactCopy*/
예제 #3
0
파일: testqset.c 프로젝트: xelda1988/qhull
void testSetdelSetadd(int numInts, int *intarray, int checkEvery)
{
    setT *ints=qh_setnew(1);
    int i,j,isCheck;

    qh_fprintf(stderr, 8003, "\n\nTesting qh_setdelnthsorted and qh_setaddnth 1..%d. Test", numInts-1);
    for(j=1; j<numInts; j++){  /* size 0 not valid */
        if(log_i(ints, "j", j, numInts, MAXint)){
            for(i= qh_setsize(ints); i<j; i++){
                qh_setappend(&ints, intarray+i);
            }
            checkSetContents("qh_setappend", ints, j, 0, -1, -1);
            for(i= 0; i<j && i<100; i++){  /* otherwise too slow */
                isCheck= log_i(ints, "", i, numInts, checkEvery);
                (void)isCheck; /* unused */
                qh_setdelnthsorted(ints, i);
                qh_setaddnth(&ints, i, intarray+i);
                if(checkEvery==1){
                    checkSetContents("qh_setdelnthsorted qh_setaddnth", ints, j, 0, -1, -1);
                }
            }
            checkSetContents("qh_setdelnthsorted qh_setaddnth 2", ints, j, 0, -1, -1);
        }
    }
    qh_setfree(&ints);
}/*testSetdelSetadd*/
예제 #4
0
파일: stat.c 프로젝트: jmainpri/libmove3d
/*-<a                             href="qh-stat.htm#TOC"
  >-------------------------------</a><a name="collectstatistics">-</a>

  qh_collectstatistics()
    collect statistics for qh.facet_list

*/
void qh_collectstatistics(void) {
  facetT *facet, *neighbor, **neighborp;
  vertexT *vertex, **vertexp;
  realT dotproduct, dist;
  int sizneighbors, sizridges, sizvertices, i;

  qh old_randomdist= qh RANDOMdist;
  qh RANDOMdist= False;
  zval_(Zmempoints)= qh num_points * qh normal_size +
                             sizeof(qhT) + sizeof(qhstatT);
  zval_(Zmemfacets)= 0;
  zval_(Zmemridges)= 0;
  zval_(Zmemvertices)= 0;
  zval_(Zangle)= 0;
  wval_(Wangle)= 0.0;
  zval_(Znumridges)= 0;
  zval_(Znumfacets)= 0;
  zval_(Znumneighbors)= 0;
  zval_(Znumvertices)= 0;
  zval_(Znumvneighbors)= 0;
  zval_(Znummergetot)= 0;
  zval_(Znummergemax)= 0;
  zval_(Zvertices)= qh num_vertices - qh_setsize(qh del_vertices);
  if (qh MERGING || qh APPROXhull || qh JOGGLEmax < REALmax/2)
    wmax_(Wmaxoutside, qh max_outside);
  if (qh MERGING)
    wmin_(Wminvertex, qh min_vertex);
  FORALLfacets
    facet->seen= False;
  if (qh DELAUNAY) {
    FORALLfacets {
      if (facet->upperdelaunay != qh UPPERdelaunay)
        facet->seen= True; /* remove from angle statistics */
    }
  }
예제 #5
0
파일: testqset.c 프로젝트: xelda1988/qhull
void testSetdelsortedEtc(int numInts, int *intarray, int checkEvery)
{
    setT *ints= qh_setnew(1);
    setT *ints2= NULL;
    int i,j;

    qh_fprintf(stderr, 8018, "\n\nTesting qh_setdel*, qh_setaddsorted, and  0..%d. Test", numInts-1);
    for(j=0; j<numInts; j++){
        if(log_i(ints, "j", j, numInts, checkEvery)){
            for(i= qh_setsize(ints); i<j; i++){  /* Test i<j to test the empty set */
                qh_setaddsorted(&ints, intarray+i);
            }
            checkSetContents("qh_setaddsorted", ints, j, 0, 0, -1);
            if(j>3){
                qh_setdelsorted(ints, intarray+i/2);
                checkSetContents("qh_setdelsorted", ints, j-1, 0, i/2+1, -1);
                qh_setaddsorted(&ints, intarray+i/2);
                checkSetContents("qh_setaddsorted i/2", ints, j, 0, 0, -1);
            }
            qh_setdellast(ints);
            checkSetContents("qh_setdellast", ints, (j ? j-1 : 0), 0, -1, -1);
            if(j>0){
                qh_setaddsorted(&ints, intarray+j-1);
                checkSetContents("qh_setaddsorted j-1", ints, j, 0, -1, -1);
            }
            if(j>4){
                qh_setdelnthsorted(ints, i/2);
                if (checkEvery==1)
                  checkSetContents("qh_setdelnthsorted", ints, j-1, 0, i/2+1, -1);
                /* test qh_setdelnth and move-to-front */
                qh_setdelsorted(ints, intarray+i/2+1);
                checkSetContents("qh_setdelsorted 2", ints, j-2, 0, i/2+2, -1);
                qh_setaddsorted(&ints, intarray+i/2+1);
                if (checkEvery==1)
                  checkSetContents("qh_setaddsorted i/2+1", ints, j-1, 0, i/2+1, -1);
                qh_setaddsorted(&ints, intarray+i/2);
                checkSetContents("qh_setaddsorted i/2 again", ints, j, 0, -1, -1);
            }
            qh_setfree(&ints2);
            ints2= qh_setcopy(ints, 0);
            qh_setcompact(ints);
            qh_setcompact(ints2);
            checkSetContents("qh_setcompact", ints, j, 0, 0, -1);
            checkSetContents("qh_setcompact 2", ints2, j, 0, 0, -1);
            qh_setcompact(ints);
            checkSetContents("qh_setcompact 3", ints, j, 0, 0, -1);
            qh_setfree(&ints2);
        }
    }
    qh_setfreelong(&ints);
    if(ints){
        qh_setfree(&ints); /* Was quick memory */
    }
}/*testSetdelsortedEtc*/
예제 #6
0
파일: testqset.c 프로젝트: xelda1988/qhull
void testSetappendSet(int numInts, int *intarray, int checkEvery)
{
    setT *ints=qh_setnew(1);
    setT *ints2;
    int i,j,k;

    qh_fprintf(stderr, 8016, "\n\nTesting qh_setappend_set 0..%d. Test", numInts-1);
    for(j=0; j<numInts; j++){
        if(log_i(ints, "j", j, numInts, numInts)){
            for(i= qh_setsize(ints); i<j; i++){
                qh_setappend(&ints, intarray+i);
            }
            if(checkEvery==1){
                checkSetContents("qh_setappend", ints, j, 0, -1, -1);
            }
            ints2= qh_setnew(j==0 ? 0 : j-1);  /* One less than needed */
            for(i= 0; i<=j && i<=20; i++){  /* otherwise too slow */
                if(log_i(ints, "", i, numInts, numInts)){
                    for(k= qh_setsize(ints2); k<i; k++){
                        qh_setappend(&ints2, intarray+k);
                    }
                    if(checkEvery==1){
                        checkSetContents("qh_setappend 2", ints2, i, 0, -1, -1);
                    }
                    qh_setappend_set(&ints, ints2);
                    checkSetContents("qh_setappend_set", ints, i+j, 0, (j==0 ? -1 : 0), -1);
                    qh_settruncate(ints, j);
                    if(checkEvery==1){
                        checkSetContents("qh_settruncate", ints, j, 0, -1, -1);
                    }
                }
            }
            qh_setfree(&ints2);
        }
    }
    qh_setfree(&ints);
}/*testSetappendSet*/
예제 #7
0
bool QhullCalc::Calc(
	const std::vector<v3d> &pin,
	std::vector<v3d> &pout,
	std::vector<std::vector<int> > &fout)const
{
	if(pin.size() < 4)
		return false;

	try
	{
		char cmd[]="qhull ";
		if(qh_new_qhull(3,int(pin.size()),const_cast<double*>(&pin[0].x),false,cmd,NULL,NULL))
			return false;
		pointT *point, *pointtemp;
		FORALLpoints
		{
			pout.push_back(v3d(point[0],point[1],point[2]));
		}
		facetT *facet;
		vertexT *vertex, **vertexp;
		FORALLfacets
		{
			std::vector<int> idx;
			setT *vertices=qh_facet3vertex(facet);
			qh_setsize(vertices);
			FOREACHvertex_(vertices)
			{
				idx.push_back(qh_pointid(vertex->point));
			}
			fout.push_back(idx);
			qh_settempfree(&vertices);
		}
		qh_freeqhull(!qh_ALL);
		int curlong, totlong;
		qh_memfreeshort(&curlong, &totlong);
		if(curlong || totlong)
		{
			return false;
		}
		return true;
	}
	catch(...)
	{
		return false;
	}
}
예제 #8
0
파일: testqset.c 프로젝트: xelda1988/qhull
void testSettemp(int numInts, int *intarray, int checkEvery)
{
    setT *ints= NULL;
    setT *ints2= NULL;
    setT *ints3= NULL;
    int i,j;

    qh_fprintf(stderr, 8021, "\n\nTesting qh_settemp* 0..%d. Test", numInts-1);
    for(j=0; j<numInts; j++){
        if(log_i(ints, "j", j, numInts, checkEvery)){
            if(j<20){
                for(i=0; i<j; i++){
                    ints2= qh_settemp(j);
                }
                qh_settempfree_all();
            }
            for(i= qh_setsize(ints); i<j; i++){  /* Test i<j to test the empty set */
                qh_setappend(&ints, intarray+i);
            }
            ints2= qh_settemp(j);
            if(j>0){
                qh_settemppush(ints);
                ints3= qh_settemppop();
                if(ints!=ints3){
                    qh_fprintf(stderr, 6343, "qh_settemppop: didn't pop the push\n");
                    error_count++;
                }
            }
            qh_settempfree(&ints2);
        }
    }
    qh_setfreelong(&ints);
    if(ints){
        qh_setfree(&ints); /* Was quick memory */
    }
}/*testSettemp*/
예제 #9
0
파일: testqset.c 프로젝트: xelda1988/qhull
void testSetlastEtc(int numInts, int *intarray, int checkEvery)
{
    setT *ints= NULL;
    setT *ints2= NULL;
    int i,j,prepend;

    qh_fprintf(stderr, 8020, "\n\nTesting qh_setlast, qh_setnew_delnthsorted, qh_setunique, and qh_setzero 0..%d. Test", numInts-1);
    for(j=0; j<numInts; j++){
        if(log_i(ints, "j", j, numInts, checkEvery)){
            for(i= qh_setsize(ints); i<j; i++){  /* Test i<j to test the empty set */
                if(!qh_setunique(&ints, intarray+i)){
                    qh_fprintf(stderr, 6340, "qh_setunique: not able to append next element %d\n", i);
                    error_count++;
                }
                if(checkEvery==1){
                    checkSetContents("qh_setunique", ints, i+1, 0, -1, -1);
                }
                if(qh_setunique(&ints, intarray+i)){
                    qh_fprintf(stderr, 6341, "qh_setunique: appended next element twice %d\n", i);
                    error_count++;
                }
                if(qh_setunique(&ints, intarray+i/2)){
                    qh_fprintf(stderr, 6346, "qh_setunique: appended middle element twice %d/2\n", i);
                    error_count++;
                }
            }
            checkSetContents("qh_setunique 2", ints, j, 0, -1, -1);
            if(j==0 && NULL!=qh_setlast(ints)){
                qh_fprintf(stderr, 6339, "qh_setlast: returned last element of empty set\n");
                error_count++;
            }
            if(j>0){
                if(intarray+j-1!=qh_setlast(ints)){
                    qh_fprintf(stderr, 6338, "qh_setlast: wrong last element\n");
                    error_count++;
                }
                prepend= (j<100 ? j/4 : 0);
                ints2= qh_setnew_delnthsorted(ints, qh_setsize(ints), j/2, prepend);
                if(qh_setsize(ints2)!=j+prepend-1){
                    qh_fprintf(stderr, 6345, "qh_setnew_delnthsorted: Expecting %d elements, got %d\n", j+prepend-1, qh_setsize(ints2));
                    error_count++;
                }
                /* Define prepended elements.  Otherwise qh_setdelnthsorted may fail */
                for(i= 0; i<prepend; i++){
                    void **p= &SETelem_(ints2, i);
                    *p= intarray+0;
                }
                for(i= 0; i<prepend; i++){
                    qh_setdelnthsorted(ints2, 0);  /* delete undefined prefix */
                }
                checkSetContents("qh_setnew_delnthsorted", ints2, j-1, 0, j/2+1, -1);
                if(j>2){
                    qh_setzero(ints2, j/2, j-1);  /* max size may be j-1 */
                    if(qh_setsize(ints2)!=j-1){
                        qh_fprintf(stderr, 6342, "qh_setzero: Expecting %d elements, got %d\n", j, qh_setsize(ints2));
                        error_count++;
                    }
                    qh_setcompact(ints2);
                    checkSetContents("qh_setzero", ints2, j/2, 0, -1, -1);
                }
            }
            qh_setfree(&ints2);
        }
    }
    qh_setfreelong(&ints);
    if(ints){
        qh_setfree(&ints); /* Was quick memory */
    }
}/*testSetlastEtc*/
예제 #10
0
파일: testqset.c 프로젝트: xelda1988/qhull
void testSetequalInEtc(int numInts, int *intarray, int checkEvery)
{
    setT *ints= NULL;
    setT *ints2= NULL;
    setT *ints3= NULL;
    int i,j,n;

    qh_fprintf(stderr, 8019, "\n\nTesting qh_setequal*, qh_setin*, qh_setdel, qh_setdelnth, and qh_setlarger 0..%d. Test", numInts-1);
    for(j=0; j<numInts; j++){
        if(log_i(ints, "j", j, numInts, checkEvery)){
            n= qh_setsize(ints);
            qh_setlarger(&ints);
            checkSetContents("qh_setlarger", ints, n, 0, -1, -1);
            for(i= qh_setsize(ints); i<j; i++){  /* Test i<j to test the empty set */
                qh_setappend(&ints, intarray+i);
            }
            checkSetContents("qh_setappend", ints, j, 0, -1, -1);
            if(!qh_setequal(ints, ints)){
                qh_fprintf(stderr, 6300, "testSetequalInEtc: set not equal to itself at length %d\n", j);
                error_count++;
            }
            if(j==0 && !qh_setequal(ints, ints2)){
                qh_fprintf(stderr, 6323, "testSetequalInEtc: empty set not equal to null set\n");
                error_count++;
            }
            if(j>0){
                if(qh_setequal(ints, ints2)){
                    qh_fprintf(stderr, 6324, "testSetequalInEtc: non-empty set equal to empty set\n", j);
                    error_count++;
                }
                qh_setfree(&ints3);
                ints3= qh_setcopy(ints, 0);
                checkSetContents("qh_setreplace", ints3, j, 0, -1, -1);
                qh_setreplace(ints3, intarray+j/2, intarray+j/2+1);
                if(j==1){
                    checkSetContents("qh_setreplace 2", ints3, j, j/2+1, -1, -1);
                }else if(j==2){
                    checkSetContents("qh_setreplace 3", ints3, j, 0, j/2+1, -1);
                }else{
                    checkSetContents("qh_setreplace 3", ints3, j, 0, j/2+1, j/2+1);
                }
                if(qh_setequal(ints, ints3)){
                    qh_fprintf(stderr, 6325, "testSetequalInEtc: modified set equal to original set at %d/2\n", j);
                    error_count++;
                }
                if(!qh_setequal_except(ints, intarray+j/2, ints3, intarray+j/2+1)){
                    qh_fprintf(stderr, 6326, "qh_setequal_except: modified set not equal to original set except modified\n", j);
                    error_count++;
                }
                if(qh_setequal_except(ints, intarray+j/2, ints3, intarray)){
                    qh_fprintf(stderr, 6327, "qh_setequal_except: modified set equal to original set with wrong excepts\n", j);
                    error_count++;
                }
                if(!qh_setequal_skip(ints, j/2, ints3, j/2)){
                    qh_fprintf(stderr, 6328, "qh_setequal_skip: modified set not equal to original set except modified\n", j);
                    error_count++;
                }
                if(j>2 && qh_setequal_skip(ints, j/2, ints3, 0)){
                    qh_fprintf(stderr, 6329, "qh_setequal_skip: modified set equal to original set with wrong excepts\n", j);
                    error_count++;
                }
                if(intarray+j/2+1!=qh_setdel(ints3, intarray+j/2+1)){
                    qh_fprintf(stderr, 6330, "qh_setdel: failed to find added element\n", j);
                    error_count++;
                }
                checkSetContents("qh_setdel", ints3, j-1, 0, j-1, (j==1 ? -1 : j/2+1));  /* swaps last element with deleted element */
                if(j>3){
                    qh_setdelnth(ints3, j/2); /* Delete at the same location as the original replace, for only one out-of-order element */
                    checkSetContents("qh_setdelnth", ints3, j-2, 0, j-2, (j==2 ? -1 : j/2+1));
                }
                if(qh_setin(ints3, intarray+j/2)){
                    qh_fprintf(stderr, 6331, "qh_setin: found deleted element\n");
                    error_count++;
                }
                if(j>4 && !qh_setin(ints3, intarray+1)){
                    qh_fprintf(stderr, 6332, "qh_setin: did not find second element\n");
                    error_count++;
                }
                if(j>4 && !qh_setin(ints3, intarray+j-2)){
                    qh_fprintf(stderr, 6333, "qh_setin: did not find last element\n");
                    error_count++;
                }
                if(-1!=qh_setindex(ints2, intarray)){
                    qh_fprintf(stderr, 6334, "qh_setindex: found element in empty set\n");
                    error_count++;
                }
                if(-1!=qh_setindex(ints3, intarray+j/2)){
                    qh_fprintf(stderr, 6335, "qh_setindex: found deleted element in set\n");
                    error_count++;
                }
                if(0!=qh_setindex(ints, intarray)){
                    qh_fprintf(stderr, 6336, "qh_setindex: did not find first in set\n");
                    error_count++;
                }
                if(j-1!=qh_setindex(ints, intarray+j-1)){
                    qh_fprintf(stderr, 6337, "qh_setindex: did not find last in set\n");
                    error_count++;
                }
            }
            qh_setfree(&ints2);
        }
    }
    qh_setfree(&ints3);
    qh_setfreelong(&ints);
    if(ints){
        qh_setfree(&ints); /* Was quick memory */
    }
}/*testSetequalInEtc*/
/*! Uses the \a projCoords and \a fixedCoordSet (which identifies the indices
	of the fixed coordinates) to project the 6D hyperplanes of the Grasp Wrench 
	Space into 3D. The \a projCoords is an array of 6 values, but only 3 are used.  
	It then calls qhull to perform a halfspace intersection to get the vertices 
	of the 3D volume.  These vertices are stored in \a hullCoords, and indices 
	of the individual faces that make up the volume are stored in \a hullIndices 
	(an Indexed Face Set).
*/
int
GWS::projectTo3D(double *projCoords, std::set<int> fixedCoordSet,
				 std::vector<position> &hullCoords, std::vector<int> &hullIndices)
{
  int i,j,k,validPlanes,numCoords,numInLoop;
  double **planes;
  int freeCoord[3],fixedCoord[3];

  // qhull variables
  boolT ismalloc;
  int curlong,totlong,exitcode;
  char options[200];  
  facetT *facet;

  if (numHyperPlanes == 0) {
	  DBGP("No hyperplanes");
	  return SUCCESS;
  }

  planes = (double **) malloc(numHyperPlanes * sizeof(double *));
  if (!planes) {
#ifdef GRASPITDBG
    pr_error("GWS::ProjectTo3D,Out of memory allocating planes array");
    printf("NumHyperplanes: %d\n",numHyperPlanes);
#endif
    return FAILURE;
  }

  validPlanes = 0;

  // determine which dimensions are free and which are fixed
  // the set keeps things ordered
  for (i=0,j=0,k=0;i<6;i++) {
    if (fixedCoordSet.find(i) == fixedCoordSet.end()) {
      freeCoord[k++] = i;
	} else {
      fixedCoord[j++] = i;
	}
  }

  // project the hyperplanes to three dimensional planes
  for (i=0;i<numHyperPlanes;i++) {
    double len = sqrt(hyperPlanes[i][freeCoord[0]]*hyperPlanes[i][freeCoord[0]] +
                      hyperPlanes[i][freeCoord[1]]*hyperPlanes[i][freeCoord[1]] +
                      hyperPlanes[i][freeCoord[2]]*hyperPlanes[i][freeCoord[2]]);

    if (len>1e-11) {
      planes[validPlanes] = (double *) malloc(4 * sizeof(double));
      if (!planes[validPlanes]) {
		pr_error("Out of memory allocating planes array");
	    DBGP("Out of memory allocating planes array");
		return FAILURE;
	  }
      planes[validPlanes][0] = hyperPlanes[i][freeCoord[0]]/len;
      planes[validPlanes][1] = hyperPlanes[i][freeCoord[1]]/len;
      planes[validPlanes][2] = hyperPlanes[i][freeCoord[2]]/len;
      planes[validPlanes][3] = (hyperPlanes[i][6] + 
	                            hyperPlanes[i][fixedCoord[0]]*projCoords[fixedCoord[0]] +
		                        hyperPlanes[i][fixedCoord[1]]*projCoords[fixedCoord[1]] +
		                        hyperPlanes[i][fixedCoord[2]]*projCoords[fixedCoord[2]])/len;
      
      validPlanes++;
	}
  }

  if (validPlanes<numHyperPlanes) {
	  DBGP("Ignored " << numHyperPlanes-validPlanes << 
		   " hyperplanes which did not intersect this 3-space");
  }
  if (!validPlanes) {
	  DBGA("No valid planes in 3D projection!");
	  return FAILURE;
  }
	   

  //
  // call qhull to do the halfspace intersection
  //
  coordT *array = new coordT[validPlanes*3];
  coordT *p = &array[0];
  
  boolT zerodiv;
  coordT *point, *normp, *coordp, **pointp, *feasiblep;
  vertexT *vertex, **vertexp;

#ifdef GRASPITDBG
  printf("Calling qhull to perform a 3D halfspace intersection of %d planes...\n",validPlanes);
#endif

  ismalloc = False; 	// True if qh_freeqhull should 'free(array)'

  // I want to get rid of this but qh_init needs some sort of file pointer
  // for stdout and stderr
  FILE *qhfp = fopen("logfile","w");

  if (!qhfp) {
	fprintf(stderr,"Could not open qhull logfile!\n");
	qh_init_A(NULL, stdout, stderr, 0, NULL);
  }
  else
   qh_init_A(NULL, qhfp, qhfp, 0, NULL);

  if ((exitcode = setjmp(qh errexit))) {
    delete [] array;
	qh NOerrexit= True;
	qh_freeqhull(!qh_ALL);
	qh_memfreeshort (&curlong, &totlong);
	if (curlong || totlong)  	/* optional */
	   fprintf (stderr, "qhull internal warning (main): did not free %d bytes of long memory (%d pieces)\n",
		 totlong, curlong);
    for (i=0;i<validPlanes;i++)
      free(planes[i]);
    free(planes);
	if (qhfp) fclose(qhfp);
	DBGP("Qhull forces the exit; probably no valid intersection");
    return FAILURE; //exit(exitcode);
  }
  sprintf(options, "qhull -H0,0,0 Pp");
  qh_initflags(options);
  qh_setfeasible(3);
  if (!(qh feasible_point)) printf("why is qh_qh NULL?\n");
  for(i=0;i<validPlanes;i++) {
    qh_sethalfspace (3, p, &p, planes[i],&(planes[i][3]), qh feasible_point);
  }

  qh_init_B(&array[0], validPlanes, 3, ismalloc);
  qh_qhull();
  qh_check_output();
  if (qhfp) fclose(qhfp);

  //
  // Collect the vertices of the volume
  //
  hullCoords.clear();
  numCoords = qh num_facets;
  hullCoords.reserve(numCoords);
  int *indices = new int[numCoords];

  double scale = grasp->getMaxRadius(); // Hmm, is this right?

  point= (pointT*)qh_memalloc (qh normal_size);

  FORALLfacets {
    coordp = point;
	if (facet->offset > 0)
      goto LABELprintinfinite;
	
    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) {
          goto LABELprintinfinite;
        }
      }
    }    
    hullCoords.push_back(position(point[0]*scale,point[1]*scale,
				  point[2]*scale));
    continue;
    LABELprintinfinite:
    hullCoords.push_back(position(qh_INFINITE,qh_INFINITE,qh_INFINITE));
    fprintf(stderr,"intersection at infinity!\n");
  }
  qh_memfree (point, qh normal_size);


  //
  // use adjacency information to build faces of the volume
  //
  double dot;
  vec3 testNormal, refNormal;

  int numfacets, numsimplicial, numridges, totneighbors, numneighbors, numcoplanars;
  setT *vertices, *vertex_points, *coplanar_points;
  int numpoints= qh num_points + qh_setsize (qh other_points);
  int vertex_i, vertex_n;
  facetT *neighbor, **neighborp;
  int unused_numnumtricoplanarsp; //added because countfacets takes more arguments in qhull 2012
								  //FIXME - understand what this argument does. 
  qh_countfacets (qh facet_list, NULL, !qh_ALL, &numfacets, &numsimplicial, 
      &totneighbors, &numridges, &numcoplanars, &unused_numnumtricoplanarsp);  /* sets facet->visitid */

  qh_vertexneighbors();
  vertices= qh_facetvertices (qh facet_list, NULL, !qh_ALL);
  vertex_points= qh_settemp (numpoints);
  coplanar_points= qh_settemp (numpoints);
  qh_setzero (vertex_points, 0, numpoints);
  qh_setzero (coplanar_points, 0, numpoints);
  FOREACHvertex_(vertices)
    qh_point_add (vertex_points, vertex->point, vertex);
  FORALLfacet_(qh facet_list) {
    FOREACHpoint_(facet->coplanarset)
      qh_point_add (coplanar_points, point, facet);
  }