CC_FILE_ERROR BinFilter::LoadFileV1(QFile& in, ccHObject& container, unsigned nbScansTotal, const LoadParameters& parameters) { ccLog::Print("[BIN] Version 1.0"); if (nbScansTotal > 99) { if (QMessageBox::question(0, QString("Oups"), QString("Hum, do you really expect %1 point clouds?").arg(nbScansTotal), QMessageBox::Yes, QMessageBox::No) == QMessageBox::No) return CC_FERR_WRONG_FILE_TYPE; } else if (nbScansTotal == 0) { return CC_FERR_NO_LOAD; } ccProgressDialog pdlg(true, parameters.parentWidget); pdlg.setMethodTitle(QObject::tr("Open Bin file (old style)")); for (unsigned k=0; k<nbScansTotal; k++) { HeaderFlags header; unsigned nbOfPoints = 0; if (ReadEntityHeader(in, nbOfPoints, header) < 0) { return CC_FERR_READING; } //Console::print("[BinFilter::loadModelFromBinaryFile] Entity %i : %i points, color=%i, norms=%i, dists=%i\n",k,nbOfPoints,color,norms,distances); if (nbOfPoints == 0) { //Console::print("[BinFilter::loadModelFromBinaryFile] rien a faire !\n"); continue; } //progress for this cloud CCLib::NormalizedProgress nprogress(&pdlg, nbOfPoints); if (parameters.alwaysDisplayLoadDialog) { pdlg.reset(); pdlg.setInfo(QObject::tr("cloud %1/%2 (%3 points)").arg(k + 1).arg(nbScansTotal).arg(nbOfPoints)); pdlg.start(); QApplication::processEvents(); } //Cloud name char cloudName[256] = "unnamed"; if (header.name) { for (int i=0; i<256; ++i) { if (in.read(cloudName+i,1) < 0) { //Console::print("[BinFilter::loadModelFromBinaryFile] Error reading the cloud name!\n"); return CC_FERR_READING; } if (cloudName[i] == 0) { break; } } //we force the end of the name in case it is too long! cloudName[255] = 0; } else { sprintf(cloudName,"unnamed - Cloud #%u",k); } //Cloud name char sfName[1024] = "unnamed"; if (header.sfName) { for (int i=0; i<1024; ++i) { if (in.read(sfName+i,1) < 0) { //Console::print("[BinFilter::loadModelFromBinaryFile] Error reading the cloud name!\n"); return CC_FERR_READING; } if (sfName[i] == 0) break; } //we force the end of the name in case it is too long! sfName[1023] = 0; } else { strcpy(sfName,"Loaded scalar field"); } //Creation ccPointCloud* loadedCloud = new ccPointCloud(cloudName); if (!loadedCloud) return CC_FERR_NOT_ENOUGH_MEMORY; unsigned fileChunkPos = 0; unsigned fileChunkSize = std::min(nbOfPoints,CC_MAX_NUMBER_OF_POINTS_PER_CLOUD); loadedCloud->reserveThePointsTable(fileChunkSize); if (header.colors) { loadedCloud->reserveTheRGBTable(); loadedCloud->showColors(true); } if (header.normals) { loadedCloud->reserveTheNormsTable(); loadedCloud->showNormals(true); } if (header.scalarField) loadedCloud->enableScalarField(); unsigned lineRead = 0; int parts = 0; const ScalarType FORMER_HIDDEN_POINTS = (ScalarType)-1.0; //lecture du fichier for (unsigned i=0; i<nbOfPoints; ++i) { if (lineRead == fileChunkPos+fileChunkSize) { if (header.scalarField) loadedCloud->getCurrentInScalarField()->computeMinAndMax(); container.addChild(loadedCloud); fileChunkPos = lineRead; fileChunkSize = std::min(nbOfPoints-lineRead,CC_MAX_NUMBER_OF_POINTS_PER_CLOUD); char partName[64]; ++parts; sprintf(partName,"%s.part_%i",cloudName,parts); loadedCloud = new ccPointCloud(partName); loadedCloud->reserveThePointsTable(fileChunkSize); if (header.colors) { loadedCloud->reserveTheRGBTable(); loadedCloud->showColors(true); } if (header.normals) { loadedCloud->reserveTheNormsTable(); loadedCloud->showNormals(true); } if (header.scalarField) loadedCloud->enableScalarField(); } float Pf[3]; if (in.read((char*)Pf,sizeof(float)*3) < 0) { //Console::print("[BinFilter::loadModelFromBinaryFile] Error reading the %ith entity point !\n",k); return CC_FERR_READING; } loadedCloud->addPoint(CCVector3::fromArray(Pf)); if (header.colors) { unsigned char C[3]; if (in.read((char*)C,sizeof(ColorCompType)*3) < 0) { //Console::print("[BinFilter::loadModelFromBinaryFile] Error reading the %ith entity colors !\n",k); return CC_FERR_READING; } loadedCloud->addRGBColor(C); } if (header.normals) { CCVector3 N; if (in.read((char*)N.u,sizeof(float)*3) < 0) { //Console::print("[BinFilter::loadModelFromBinaryFile] Error reading the %ith entity norms !\n",k); return CC_FERR_READING; } loadedCloud->addNorm(N); } if (header.scalarField) { double D; if (in.read((char*)&D,sizeof(double)) < 0) { //Console::print("[BinFilter::loadModelFromBinaryFile] Error reading the %ith entity distance!\n",k); return CC_FERR_READING; } ScalarType d = static_cast<ScalarType>(D); loadedCloud->setPointScalarValue(i,d); } lineRead++; if (parameters.alwaysDisplayLoadDialog && !nprogress.oneStep()) { loadedCloud->resize(i+1-fileChunkPos); k=nbScansTotal; i=nbOfPoints; } } if (parameters.alwaysDisplayLoadDialog) { pdlg.stop(); QApplication::processEvents(); } if (header.scalarField) { CCLib::ScalarField* sf = loadedCloud->getCurrentInScalarField(); assert(sf); sf->setName(sfName); //replace HIDDEN_VALUES by NAN_VALUES for (unsigned i=0; i<sf->currentSize(); ++i) { if (sf->getValue(i) == FORMER_HIDDEN_POINTS) sf->setValue(i,NAN_VALUE); } sf->computeMinAndMax(); loadedCloud->setCurrentDisplayedScalarField(loadedCloud->getCurrentInScalarFieldIndex()); loadedCloud->showSF(true); } container.addChild(loadedCloud); } return CC_FERR_NO_ERROR; }
CC_FILE_ERROR LASFilter::saveToFile(ccHObject* entity, const char* filename) { if (!entity || !filename) return CC_FERR_BAD_ARGUMENT; ccHObject::Container clouds; if (entity->isKindOf(CC_POINT_CLOUD)) clouds.push_back(entity); else entity->filterChildren(clouds, true, CC_POINT_CLOUD); if (clouds.empty()) { ccConsole::Error("No point cloud in input selection!"); return CC_FERR_BAD_ENTITY_TYPE; } else if (clouds.size()>1) { ccConsole::Error("Can't save more than one cloud per LAS file!"); return CC_FERR_BAD_ENTITY_TYPE; } //the cloud to save ccGenericPointCloud* theCloud = static_cast<ccGenericPointCloud*>(clouds[0]); unsigned numberOfPoints = theCloud->size(); if (numberOfPoints==0) { ccConsole::Error("Cloud is empty!"); return CC_FERR_BAD_ENTITY_TYPE; } //colors bool hasColor = theCloud->hasColors(); //classification (as a scalar field) CCLib::ScalarField* classifSF = 0; if (theCloud->isA(CC_POINT_CLOUD)) { ccPointCloud* pc = static_cast<ccPointCloud*>(theCloud); int sfIdx = pc->getScalarFieldIndexByName(CC_LAS_CLASSIFICATION_FIELD_NAME); if (sfIdx>=0) { classifSF = pc->getScalarField(sfIdx); if (/*classifSF->getMax()>(ScalarType)liblas::Classification::class_table_size ||*/ classifSF->getMin()<0) { ccConsole::Warning("[LASFilter] Found a 'classification' scalar field, but its values outbounds LAS specifications (0-255)..."); classifSF = 0; } else { //we check that it's only integer values! unsigned i,count=classifSF->currentSize(); classifSF->placeIteratorAtBegining(); double integerPart = 0.0; for (i=0;i<count;++i) { if (modf(classifSF->getCurrentValue(),&integerPart) != 0.0) { ccConsole::Warning("[LASFilter] Found a 'classification' scalar field, but its values are not pure integers..."); classifSF = 0; break; } } } } } //open binary file for writing std::ofstream ofs; ofs.open(filename, std::ios::out | std::ios::binary); if (ofs.fail()) return CC_FERR_WRITING; const double* shift = theCloud->getOriginalShift(); liblas::Writer* writer = 0; try { liblas::Header header; //LAZ support based on extension! if (QFileInfo(filename).suffix().toUpper() == "LAZ") { header.SetCompressed(true); } //header.SetDataFormatId(liblas::ePointFormat3); ccBBox bBox = theCloud->getBB(); if (bBox.isValid()) { header.SetMin(-shift[0]+(double)bBox.minCorner().x,-shift[1]+(double)bBox.minCorner().y,-shift[2]+(double)bBox.minCorner().z); header.SetMax(-shift[0]+(double)bBox.maxCorner().x,-shift[1]+(double)bBox.maxCorner().y,-shift[2]+(double)bBox.maxCorner().z); CCVector3 diag = bBox.getDiagVec(); //Set offset & scale, as points will be stored as boost::int32_t values (between 0 and 4294967296) //int_value = (double_value-offset)/scale header.SetOffset(-shift[0]+(double)bBox.minCorner().x,-shift[1]+(double)bBox.minCorner().y,-shift[2]+(double)bBox.minCorner().z); header.SetScale(1.0e-9*std::max<double>(diag.x,ZERO_TOLERANCE), //result must fit in 32bits?! 1.0e-9*std::max<double>(diag.y,ZERO_TOLERANCE), 1.0e-9*std::max<double>(diag.z,ZERO_TOLERANCE)); } header.SetPointRecordsCount(numberOfPoints); //header.SetDataFormatId(Header::ePointFormat1); writer = new liblas::Writer(ofs, header); } catch (...) { return CC_FERR_WRITING; } //progress dialog ccProgressDialog pdlg(true); //cancel available CCLib::NormalizedProgress nprogress(&pdlg,numberOfPoints); pdlg.setMethodTitle("Save LAS file"); char buffer[256]; sprintf(buffer,"Points: %i",numberOfPoints); pdlg.setInfo(buffer); pdlg.start(); //liblas::Point point(boost::shared_ptr<liblas::Header>(new liblas::Header(writer->GetHeader()))); liblas::Point point(&writer->GetHeader()); for (unsigned i=0; i<numberOfPoints; i++) { const CCVector3* P = theCloud->getPoint(i); { double x=-shift[0]+(double)P->x; double y=-shift[1]+(double)P->y; double z=-shift[2]+(double)P->z; point.SetCoordinates(x, y, z); } if (hasColor) { const colorType* rgb = theCloud->getPointColor(i); point.SetColor(liblas::Color(rgb[0]<<8,rgb[1]<<8,rgb[2]<<8)); //DGM: LAS colors are stored on 16 bits! } if (classifSF) { liblas::Classification classif; classif.SetClass((boost::uint32_t)classifSF->getValue(i)); point.SetClassification(classif); } writer->WritePoint(point); if (!nprogress.oneStep()) break; } delete writer; //ofs.close(); return CC_FERR_NO_ERROR; }