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*/
/*! 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); }