void ccPointListPickingDlg::exportToASCII(ExportFormat format) { if (!m_associatedCloud) return; //get all labels std::vector<cc2DLabel*> labels; unsigned count = getPickedPoints(labels); if (count == 0) return; QSettings settings; settings.beginGroup("PointListPickingDlg"); QString filename = settings.value("filename", "picking_list.txt").toString(); settings.endGroup(); filename = QFileDialog::getSaveFileName(this, "Export to ASCII", filename, AsciiFilter::GetFileFilter()); if (filename.isEmpty()) return; settings.beginGroup("PointListPickingDlg"); settings.setValue("filename", filename); settings.endGroup(); FILE* fp = fopen(qPrintable(filename),"wt"); if (!fp) { ccLog::Error(QString("Failed to open file '%1' for saving!").arg(filename)); return; } //if a global shift exists, ask the user if it should be applied CCVector3d shift = m_associatedCloud->getGlobalShift(); double scale = m_associatedCloud->getGlobalScale(); if (shift.norm2() != 0 || scale != 1.0) { if (QMessageBox::warning( this, "Apply global shift", "Do you want to apply global shift/scale to exported points?", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes ) == QMessageBox::No) { //reset shift shift = CCVector3d(0,0,0); scale = 1.0; } } //starting index int startIndex = startIndexSpinBox->value(); for (unsigned i=0; i<count; ++i) { assert(labels[i]->size() == 1); const cc2DLabel::PickedPoint& PP = labels[i]->getPoint(0); const CCVector3* P = PP.cloud->getPoint(PP.index); if (format == PLP_ASCII_EXPORT_IXYZ) fprintf(fp,"%i,",i+startIndex); fprintf(fp,"%.12f,%.12f,%.12f\n", static_cast<double>(P->x)/scale - shift.x, static_cast<double>(P->y)/scale - shift.y, static_cast<double>(P->z)/scale - shift.z); } fclose(fp); ccLog::Print(QString("[I/O] File '%1' saved successfully").arg(filename)); }
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; }