void QhullVertexSet:: freeQhSetTemp() { if(qhsettemp_defined){ UsingLibQhull q(qhsettemp_qhull, QhullError::NOthrow); if(q.defined()){ int exitCode = setjmp(qh errexit); if(!exitCode){ // no object creation -- destructors skipped on longjmp() qh_settempfree(referenceSetT()); // errors if not top of tempstack or if qhmem corrupted } q.maybeThrowQhullMessage(exitCode, QhullError::NOthrow); } } }//freeQhSetTemp
void Compute_Convex_Hull( const SWIFT_Real* vs, int vn, int*& fs, int& fn ) { int i; // qhull variables int exitcode; facetT *facet; vertexT *vertex; vertexT **vertexp; setT *vertices; coordT *qhv = (coordT*)malloc( sizeof(coordT)*vn*3 ); coordT *p = qhv; const SWIFT_Real* vsp = vs; // Load the coordinates into the vertex array for qhull since SWIFT_Real // may not be the same type. for( i = 0; i < vn; i++ ) { *p++ = *vsp++; *p++ = *vsp++; *p++ = *vsp++; } qh_init_A( stdin, stdout, stderr, 0, NULL ); if( (exitcode = setjmp (qh errexit)) ) exit(exitcode); qh_initflags( options ); qh_init_B( qhv, vn, 3, True ); qh_qhull(); #ifdef SWIFT_DEBUG qh_check_output(); #endif fs = new int[((vn<<1) + 4)*3]; fn = 0; FORALLfacets { setT *vertices = qh_facet3vertex(facet); FOREACHvertex_( vertices ) { fs[fn++] = qh_pointid(vertex->point); } // Swap the face vertex indices back i = fs[fn-1]; fs[fn-1] = fs[fn-2]; fs[fn-2] = i; qh_settempfree(&vertices); } //qh NOerrexit = True; qh_freeqhull(qh_ALL); fn /= 3; }
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; } }
void Compute_Convex_Hull( coordT* vs, int vn, int*& fs, int& fn ) { int i; // qhull variables int exitcode; facetT *facet; vertexT *vertex; vertexT **vertexp; setT *vertices; qh_init_A( stdin, stdout, stderr, 0, NULL ); if( (exitcode = setjmp (qh errexit)) ) exit(exitcode); qh_initflags( options ); qh_init_B( vs, vn, 3, True ); qh_qhull(); #ifdef SWIFT_DEBUG qh_check_output(); #endif fs = new int[((vn<<1) + 4)*3]; fn = 0; FORALLfacets { setT *vertices = qh_facet3vertex(facet); FOREACHvertex_( vertices ) { fs[fn++] = qh_pointid(vertex->point); } // Swap the face vertex indices back i = fs[fn-1]; fs[fn-1] = fs[fn-2]; fs[fn-2] = i; qh_settempfree(&vertices); } //qh_freeqhull(qh_ALL); qh_freeqhull(!qh_ALL); int i1, i2; qh_memfreeshort(&i1, &i2); fn /= 3; }
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*/
CCLib::ReferenceCloud* qHPR::removeHiddenPoints(CCLib::GenericIndexedCloudPersist* theCloud, const CCVector3d& viewPoint, double fParam) { assert(theCloud); unsigned nbPoints = theCloud->size(); if (nbPoints == 0) return 0; //less than 4 points? no need for calculation, we return the whole cloud if (nbPoints < 4) { CCLib::ReferenceCloud* visiblePoints = new CCLib::ReferenceCloud(theCloud); if (!visiblePoints->addPointIndex(0,nbPoints)) //well even for less than 4 points we never know ;) { //not enough memory! delete visiblePoints; visiblePoints = 0; } return visiblePoints; } double maxRadius = 0; //convert point cloud to an array of double triplets (for qHull) coordT* pt_array = new coordT[(nbPoints+1)*3]; { coordT* _pt_array = pt_array; for (unsigned i=0; i<nbPoints; ++i) { CCVector3d P = CCVector3d::fromArray(theCloud->getPoint(i)->u) - viewPoint; *_pt_array++ = static_cast<coordT>(P.x); *_pt_array++ = static_cast<coordT>(P.y); *_pt_array++ = static_cast<coordT>(P.z); //we keep track of the highest 'radius' double r2 = P.norm2(); if (maxRadius < r2) maxRadius = r2; } //we add the view point (Cf. HPR) *_pt_array++ = 0; *_pt_array++ = 0; *_pt_array++ = 0; maxRadius = sqrt(maxRadius); } //apply spherical flipping { maxRadius *= pow(10.0,fParam) * 2; coordT* _pt_array = pt_array; for (unsigned i=0; i<nbPoints; ++i) { CCVector3d P = CCVector3d::fromArray(theCloud->getPoint(i)->u) - viewPoint; double r = (maxRadius/P.norm()) - 1.0; *_pt_array++ *= r; *_pt_array++ *= r; *_pt_array++ *= r; } } //array to flag points on the convex hull std::vector<bool> pointBelongsToCvxHull; static char qHullCommand[] = "qhull QJ Qci"; if (!qh_new_qhull(3,nbPoints+1,pt_array,False,qHullCommand,0,stderr)) { try { pointBelongsToCvxHull.resize(nbPoints+1,false); } catch (const std::bad_alloc&) { //not enough memory! delete[] pt_array; return 0; } vertexT *vertex = 0,**vertexp = 0; facetT *facet = 0; FORALLfacets { //if (!facet->simplicial) // error("convhulln: non-simplicial facet"); // should never happen with QJ setT* vertices = qh_facet3vertex(facet); FOREACHvertex_(vertices) { pointBelongsToCvxHull[qh_pointid(vertex->point)] = true; } qh_settempfree(&vertices); } } delete[] pt_array; pt_array = 0; qh_freeqhull(!qh_ALL); //free long memory int curlong, totlong; qh_memfreeshort (&curlong, &totlong); //free short memory and memory allocator if (!pointBelongsToCvxHull.empty()) { //compute the number of points belonging to the convex hull unsigned cvxHullSize = 0; { for (unsigned i=0; i<nbPoints; ++i) if (pointBelongsToCvxHull[i]) ++cvxHullSize; } CCLib::ReferenceCloud* visiblePoints = new CCLib::ReferenceCloud(theCloud); if (cvxHullSize!=0 && visiblePoints->reserve(cvxHullSize)) { for (unsigned i=0; i<nbPoints; ++i) if (pointBelongsToCvxHull[i]) visiblePoints->addPointIndex(i); //can't fail, see above return visiblePoints; } else //not enough memory { delete visiblePoints; visiblePoints = 0; } } return 0; }
/*------------------------------------------------- -qhull- hull_dim convex hull of num_points starting at first_point returns: returns facet_list, numfacets, etc. */ void qh_qhull (void) { setT *maxpoints, *vertices; facetT *facet; int numpart, i, numoutside; realT dist; boolT isoutside; qh hulltime= qh_CPUclock; if (qh DELAUNAY && qh upper_threshold[qh hull_dim-1] > REALmax/2 && qh lower_threshold[qh hull_dim-1] < -REALmax/2) { for (i= qh_PRINTEND; i--; ) { if (qh PRINTout[i] == qh_PRINTgeom && qh DROPdim < 0 && !qh GOODthreshold && !qh SPLITthresholds) break; /* in this case, don't set upper_threshold */ } if (i < 0) { if (qh UPPERdelaunay) qh lower_threshold[qh hull_dim-1]= 0.0; else qh upper_threshold[qh hull_dim-1]= 0.0; if (!qh GOODthreshold) qh SPLITthresholds= True; /* build upper-convex hull even if Qg */ /* qh_initqhull_globals errors if Qg without Pdk/etc. */ } } maxpoints= qh_maxmin(qh first_point, qh num_points, qh hull_dim); /* qh_maxmin sets DISTround and other precision constants */ vertices= qh_initialvertices(qh hull_dim, maxpoints, qh first_point, qh num_points); qh_initialhull (vertices); /* initial qh facet_list */ qh_partitionall (vertices, qh first_point, qh num_points); qh_resetlists (False /*qh visible_list newvertex_list newfacet_list */); qh facet_next= qh facet_list; qh_furthestnext (/* qh facet_list */); if (qh PREmerge) { qh cos_max= qh premerge_cos; qh centrum_radius= qh premerge_centrum; } if (qh ONLYgood) { if (qh GOODvertex > 0 && qh MERGING) { fprintf (qh ferr, "qhull input error: 'Qg QVn' (only good vertex) does not work with merging. Use 'Q0'\n"); qh_errexit (qh_ERRinput, NULL, NULL); } if (!(qh GOODthreshold || qh GOODpoint)) { fprintf (qh ferr, "qhull input error: 'Qg' (ONLYgood) needs a good threshold ('Pd0D0'), a\n\ good point (QGn or QG-n), or a good vertex with 'Q0' (QVn).\n"); qh_errexit (qh_ERRinput, NULL, NULL); } if (qh GOODvertex > 0 && !qh MERGING /* matches qh_partitionall */ && !qh_isvertex (qh GOODvertexp, vertices)) { facet= qh_findbestnew (qh GOODvertexp, qh facet_list, &dist, &isoutside, &numpart); zadd_(Zdistgood, numpart); if (!isoutside) { fprintf (qh ferr, "qhull input error: point for QV%d is inside initial simplex\n", qh_pointid(qh GOODvertexp)); qh_errexit (qh_ERRinput, NULL, NULL); } if (!qh_addpoint (qh GOODvertexp, facet, False)) { qh_settempfree(&vertices); qh_settempfree(&maxpoints); return; } } qh_findgood (qh facet_list, 0); }
CCLib::ReferenceCloud* qHPR::removeHiddenPoints(CCLib::GenericIndexedCloudPersist* theCloud, float viewPoint[], float fParam) { assert(theCloud); unsigned i,nbPoints = theCloud->size(); if (nbPoints==0) return 0; CCLib::ReferenceCloud* newCloud = new CCLib::ReferenceCloud(theCloud); //less than 4 points ? no need for calculation, we return the whole cloud if (nbPoints<4) { if (!newCloud->reserve(nbPoints)) //well, we never know ;) { //not enough memory! delete newCloud; return 0; } newCloud->addPointIndex(0,nbPoints); return newCloud; } //view point coordT Cx = viewPoint[0]; coordT Cy = viewPoint[1]; coordT Cz = viewPoint[2]; float* radius = new float[nbPoints]; if (!radius) { //not enough memory! delete newCloud; return 0; } float r,maxRadius = 0.0; //table of points coordT* pt_array = new coordT[(nbPoints+1)*3]; coordT* _pt_array = pt_array; theCloud->placeIteratorAtBegining(); //#define BACKUP_PROJECTED_CLOUDS #ifdef BACKUP_PROJECTED_CLOUDS FILE* fp = fopen("output_centered.asc","wt"); #endif double x,y,z; for (i=0;i<nbPoints;++i) { const CCVector3* P = theCloud->getNextPoint(); *(_pt_array++)=x=coordT(P->x)-Cx; *(_pt_array++)=y=coordT(P->y)-Cy; *(_pt_array++)=z=coordT(P->z)-Cz; //we pre-compute the radius ... r = (float)sqrt(x*x+y*y+z*z); //in order to determine the max radius if (maxRadius<r) maxRadius = r; radius[i] = r; #ifdef BACKUP_PROJECTED_CLOUDS fprintf(fp,"%f %f %f %f\n",x,y,z,r); #endif } //we add the view point (Cf. HPR) *(_pt_array++)=0.0; *(_pt_array++)=0.0; *(_pt_array++)=0.0; #ifdef BACKUP_PROJECTED_CLOUDS fprintf(fp,"%f %f %f %f\n",0,0,0,0); fclose(fp); #endif maxRadius *= 2.0f*pow(10.0f,fParam); _pt_array = pt_array; #ifdef BACKUP_PROJECTED_CLOUDS fp = fopen("output_transformed.asc","wt"); #endif for (i=0;i<nbPoints;++i) { //Spherical flipping r = maxRadius/radius[i]-1.0f; #ifndef BACKUP_PROJECTED_CLOUDS *(_pt_array++) *= double(r); *(_pt_array++) *= double(r); *(_pt_array++) *= double(r); #else x = *_pt_array * double(r); *(_pt_array++) = x; y = *_pt_array * double(r); *(_pt_array++) = y; z = *_pt_array * double(r); *(_pt_array++) = z; fprintf(fp,"%f %f %f %f\n",x,y,z,r); #endif } #ifdef BACKUP_PROJECTED_CLOUDS fclose(fp); #endif //we re-use the radius to record if each point belongs to the convex hull //delete[] radius; //uchar* pointBelongsToCvxHull = new uchar[nbPoints]; uchar* pointBelongsToCvxHull = (uchar*)radius; memset(pointBelongsToCvxHull,0,sizeof(uchar)*(nbPoints+1)); if (!qh_new_qhull(3,nbPoints+1,pt_array,False,(char*)"qhull QJ s Qci Tcv",0,stderr)) { vertexT *vertex,**vertexp; facetT *facet; setT *vertices; int j, i = 0; FORALLfacets { /*if (!facet->simplicial) error("convhulln: non-simplicial facet"); // should never happen with QJ */ j = 0; vertices = qh_facet3vertex (facet); FOREACHvertex_(vertices) { pointBelongsToCvxHull[qh_pointid(vertex->point)]=1; ++j; } qh_settempfree(&vertices); if (j < 3) printf("Warning, facet %d only has %d vertices\n",i,j); // likewise but less fatal i++; } }