/** * Loads the contents of an X-Com set of PCK/TAB image files * into the surface. The PCK file contains an RLE compressed * image, while the TAB file contains the offsets to each * frame in the image. * @param pck Filename of the PCK image. * @param tab Filename of the TAB offsets. * @sa http://www.ufopaedia.org/index.php?title=Image_Formats#PCK */ void SurfaceSet::loadPck(const std::string &pck, const std::string &tab) { int nframes = 0; // Load TAB and get image offsets std::ifstream offsetFile (tab.c_str(), std::ios::in | std::ios::binary); if (!offsetFile) { nframes = 1; Surface *surface = new Surface(_width, _height); _frames[0] = surface; } else { Uint16 off; while (offsetFile.read((char*)&off, sizeof(off))) { off = SDL_SwapLE16(off); Surface *surface = new Surface(_width, _height); _frames[nframes] = surface; nframes++; } } // Load PCX and put pixels in surfaces std::ifstream imgFile (pck.c_str(), std::ios::in | std::ios::binary); if (!imgFile) { throw Exception(pck + " not found"); } Uint8 value; for (int frame = 0; frame < nframes; frame++) { int x = 0, y = 0; // Lock the surface _frames[frame]->lock(); imgFile.read((char*)&value, 1); for (int i = 0; i < value; ++i) { for (int j = 0; j < _width; ++j) { _frames[frame]->setPixelIterative(&x, &y, 0); } } while (imgFile.read((char*)&value, 1) && value != 255) { if (value == 254) { imgFile.read((char*)&value, 1); for (int i = 0; i < value; ++i) { _frames[frame]->setPixelIterative(&x, &y, 0); } } else { _frames[frame]->setPixelIterative(&x, &y, value); } } // Unlock the surface _frames[frame]->unlock(); } imgFile.close(); offsetFile.close(); }
ScanRLEArrayIterator::ScanRLEArrayIterator(const RLEArray * const source, AttributeID attId, string path, size_t maxChunkNo) : currChunk(NULL), logger(log4cxx::Logger::getLogger("scidb.query.ops.ScanRQArrayIterator")), _attId(attId), _dirPath(path), _chunkNo(0), _maxChunkNo(maxChunkNo), _desc(&source->getArrayDesc()), _currPos(_desc->getDimensions().size(), 0) { if (_desc->getAttributes()[attId].getFlags() & AttributeDesc::IS_NULLABLE) { throw SYSTEM_EXCEPTION(SCIDB_SE_INTERNAL, SCIDB_LE_NOT_IMPLEMENTED) << "nullable attributes"; } if (_desc->getAttributes()[attId].getSize() == 0) { throw SYSTEM_EXCEPTION(SCIDB_SE_INTERNAL, SCIDB_LE_NOT_IMPLEMENTED) << "variable size attributes"; } // set up the file offsets and chunk sizes uint8_t attrBytes, chunkBytes, offsetBytes; stringstream chunkFileName, offsetFileName; chunkId lhs0, lhs1; chunkFileInfo rhs0, rhs1; chunkFileName << path << "/chunks"; offsetFileName << path << "/offsets"; ifstream offsetFile(offsetFileName.str().c_str(), ios_base::binary | ios_base::in | ios_base::ate); _chunkFile.open(chunkFileName.str().c_str(), ios_base::binary | ios_base::in | ios_base::ate); size_t offsetFileSize = offsetFile.tellg(); size_t chunkFileSize = _chunkFile.tellg(); offsetFile.seekg(0, ios_base::beg); offsetFile.read((char *) &attrBytes, 1); offsetFile.read((char *) &chunkBytes, 1); offsetBytes = sizeof(size_t); size_t offsetChunks = offsetFileSize / (attrBytes + chunkBytes + offsetBytes); // init them all rhs0.first = rhs0.second = rhs1.first = rhs1.second = lhs0.first = lhs0.second = lhs1.first = lhs1.second = 0; // read starter chunk offsetFile.read((char *) &lhs0.first, attrBytes); offsetFile.read((char *) &lhs0.second, chunkBytes); offsetFile.read((char *) &rhs0.first, offsetBytes); // the chunk size is wrong because it will be off by one for (size_t i = 1; i < offsetChunks; ++i) { // read in tuple 1 offsetFile.read((char *) &lhs1.first, attrBytes); offsetFile.read((char *) &lhs1.second, chunkBytes); offsetFile.read((char *) &rhs1.first, offsetBytes); // calculate chunk offset of predecessor rhs0.second = rhs1.first - rhs0.first; // commit it _chunkFileData[lhs0] = rhs0; // roll over to the next one lhs0 = lhs1; rhs0 = rhs1; } // output the last one rhs0.second = chunkFileSize - rhs0.first; _chunkFileData[lhs0] = rhs0; reset(); }
LidarProcessOctree::LidarProcessOctree(const char* lidarFileName,size_t sCacheSize) :indexFile(getLidarPartFileName(lidarFileName,"Index").c_str()), pointsFile(getLidarPartFileName(lidarFileName,"Points").c_str()), offset(OffsetVector::zero), numSubdivideCalls(0),numLoadedNodes(0), lruHead(0),lruTail(0) { indexFile.setEndianness(Misc::LittleEndian); pointsFile.setEndianness(Misc::LittleEndian); /* Read the octree file header: */ LidarOctreeFileHeader ofh(indexFile); /* Initialize the root node's domain: */ root.domain=ofh.domain; /* Initialize the tree structure: */ maxNumPointsPerNode=ofh.maxNumPointsPerNode; /* Calculate the memory and GPU cache sizes: */ size_t memNodeSize=sizeof(Node)+size_t(maxNumPointsPerNode)*sizeof(LidarPoint); cacheSize=(unsigned int)(sCacheSize/memNodeSize); if(cacheSize==0U) Misc::throwStdErr("LidarProcessOctree::LidarProcessOctree: Specified memory cache size too small"); std::cout<<"Cache size: "<<cacheSize<<" memory nodes"<<std::endl; /* Read the root node's structure: */ LidarOctreeFileNode rootfn; rootfn.read(indexFile); root.childrenOffset=rootfn.childrenOffset; root.numPoints=rootfn.numPoints; root.dataOffset=rootfn.dataOffset; root.detailSize=rootfn.detailSize; /* Get the total number of nodes by dividing the index file's size by the size of one octree node: */ numNodes=size_t((indexFile.getSize()-LidarOctreeFileHeader::getFileSize())/LidarFile::Offset(LidarOctreeFileNode::getFileSize())); /* Read the point file's header: */ LidarDataFileHeader dfh(pointsFile); pointsRecordSize=LidarFile::Offset(dfh.recordSize); if(root.numPoints>0) { /* Load the root node's points: */ root.points=new LidarPoint[maxNumPointsPerNode]; // Always allocate maximum to prevent memory fragmentation pointsFile.setReadPosAbs(LidarDataFileHeader::getFileSize()+pointsRecordSize*root.dataOffset); pointsFile.read(root.points,root.numPoints); } ++numLoadedNodes; /* Try loading an offset file: */ try { IO::FilePtr offsetFile(IO::openFile(getLidarPartFileName(lidarFileName,"Offset").c_str())); offsetFile->setEndianness(Misc::LittleEndian); /* Read the original offset vector: */ offsetFile->read<OffsetVector::Scalar>(offset.getComponents(),3); /* Invert the offset transformation: */ offset=-offset; } catch(IO::File::OpenError err) { /* Ignore the error */ } /* Initialize the node cache: */ numCachedNodes=1U; }
int main(int argc,char* argv[]) { /* Set default values for all parameters: */ unsigned int memoryCacheSize=512; unsigned int tempOctreeMaxNumPointsPerNode=4096; std::string tempOctreeFileNameTemplate="/tmp/LidarPreprocessorTempOctree"; unsigned int maxNumPointsPerNode=4096; int numThreads=1; std::string tempPointFileNameTemplate="/tmp/LidarPreprocessorTempPoints"; try { /* Open LidarViewer's configuration file: */ Misc::ConfigurationFile configFile(LIDARVIEWER_CONFIGFILENAME); Misc::ConfigurationFileSection cfg=configFile.getSection("/LidarPreprocessor"); /* Override program settings from configuration file: */ memoryCacheSize=cfg.retrieveValue<unsigned int>("./memoryCacheSize",memoryCacheSize); tempOctreeMaxNumPointsPerNode=cfg.retrieveValue<unsigned int>("./tempOctreeMaxNumPointsPerNode",tempOctreeMaxNumPointsPerNode); tempOctreeFileNameTemplate=cfg.retrieveValue<std::string>("./tempOctreeFileNameTemplate",tempOctreeFileNameTemplate); maxNumPointsPerNode=cfg.retrieveValue<unsigned int>("./maxNumPointsPerNode",maxNumPointsPerNode); numThreads=cfg.retrieveValue<int>("./numThreads",numThreads); tempPointFileNameTemplate=cfg.retrieveValue<std::string>("./tempPointFileNameTemplate",tempPointFileNameTemplate); } catch(std::runtime_error err) { /* Just ignore the error */ } /* Parse the command line and load the input files: */ unsigned baseMemoryCacheSize=64; // Memory cache size for base octree in MB LidarProcessOctree* basePoints=0; // Octree containing the base point data const char* subtractFileName=0; // Name of ASCII file containing the point set to subtract int asciiColumnIndices[3]={0,1,2}; // Column indices of x, y, z point components in ASCII file Scalar epsilon=Scalar(1.0e-7); // Maximum match point distance PointAccumulator pa; // Point accumulator holding the subtracted point set pa.setMemorySize(memoryCacheSize,tempOctreeMaxNumPointsPerNode); pa.setTempOctreeFileNameTemplate(tempOctreeFileNameTemplate+"XXXXXX"); PointAccumulator::Vector pointOffset=PointAccumulator::Vector::zero; // Offset vector added to points during octree creation const char* outputFileName=0; // Name of resulting LiDAR octree file bool haveOffset=false; // Flag whether an explicit point offset was specified on the command line for(int i=1;i<argc;++i) { if(argv[i][0]=='-') { if(strcasecmp(argv[i]+1,"o")==0) { ++i; if(i<argc) outputFileName=argv[i]; else std::cerr<<"Dangling -o flag on command line"<<std::endl; } else if(strcasecmp(argv[i]+1,"np")==0) { ++i; if(i<argc) maxNumPointsPerNode=(unsigned int)(atoi(argv[i])); else std::cerr<<"Dangling -np flag on command line"<<std::endl; } else if(strcasecmp(argv[i]+1,"nt")==0) { ++i; if(i<argc) numThreads=atoi(argv[i]); else std::cerr<<"Dangling -nt flag on command line"<<std::endl; } else if(strcasecmp(argv[i]+1,"ooc")==0) { ++i; if(i<argc) { memoryCacheSize=(unsigned int)(atoi(argv[i])); pa.setMemorySize(memoryCacheSize,tempOctreeMaxNumPointsPerNode); } else std::cerr<<"Dangling -ooc flag on command line"<<std::endl; } else if(strcasecmp(argv[i]+1,"to")==0) { ++i; if(i<argc) { tempOctreeFileNameTemplate=argv[i]; pa.setTempOctreeFileNameTemplate(tempOctreeFileNameTemplate+"XXXXXX"); } else std::cerr<<"Dangling -to flag on command line"<<std::endl; } else if(strcasecmp(argv[i]+1,"tp")==0) { ++i; if(i<argc) tempPointFileNameTemplate=argv[i]; else std::cerr<<"Dangling -tp flag on command line"<<std::endl; } else if(strcasecmp(argv[i]+1,"lasOffset")==0) { if(i+3<argc) { for(int j=0;j<3;++j) { ++i; pointOffset[j]=atof(argv[i]); } haveOffset=true; } else std::cerr<<"Dangling -lasOffset flag on command line"<<std::endl; } else if(strcasecmp(argv[i]+1,"lasOffsetFile")==0) { ++i; if(i<argc) { /* Read the point offset from a binary file: */ try { IO::FilePtr offsetFile=IO::openFile(argv[i]); offsetFile->setEndianness(Misc::LittleEndian); offsetFile->read(pointOffset.getComponents(),3); haveOffset=true; } catch(std::runtime_error err) { /* Print a warning and carry on: */ std::cerr<<"Ignoring lasOffsetFile argument due to error "<<err.what()<<" when reading file "<<argv[i]<<std::endl; } } else std::cerr<<"Dangling -lasOffsetFile flag on command line"<<std::endl; } else if(strcasecmp(argv[i]+1,"eps")==0) { ++i; if(i<argc) epsilon=Scalar(atof(argv[i])); else std::cerr<<"Dangling -eps flag on command line"<<std::endl; } else if(strcasecmp(argv[i]+1,"booc")==0) { ++i; if(i<argc) baseMemoryCacheSize=(unsigned int)(atoi(argv[i])); else std::cerr<<"Dangling -booc flag on command line"<<std::endl; } else if(strcasecmp(argv[i]+1,"columns")==0) { if(i+3<argc) { for(int j=0;j<3;++j) { ++i; asciiColumnIndices[j]=atoi(argv[i]); } } else std::cerr<<"Dangling -columns flag on command line"<<std::endl; } } else if(basePoints==0) { try { /* Create a processing octree: */ basePoints=new LidarProcessOctree(argv[i],size_t(baseMemoryCacheSize)*size_t(1024*1024)); } catch(std::runtime_error err) { std::cerr<<"Cannot open LiDAR file "<<argv[i]<<" due to exception "<<err.what()<<"; terminating"<<std::endl; return 1; } } else if(subtractFileName==0) { /* Store the subtraction file name: */ subtractFileName=argv[i]; } else std::cerr<<"Ignoring command line argument "<<argv[i]<<std::endl; } if(!haveOffset) { /* Use the base point set's point offset for the resulting file: */ pointOffset=-basePoints->getOffset(); } else { PointAccumulator::Vector totalOffset=pointOffset-PointAccumulator::Vector(basePoints->getOffset()); if(totalOffset!=PointAccumulator::Vector::zero) pa.setPointOffset(totalOffset); } /* Load the subtraction point set into a kd-tree: */ std::vector<Point> subtractPoints; try { std::cout<<"Loading subtraction points from "<<subtractFileName<<"..."<<std::flush; IO::ValueSource subtractSource(new IO::ReadAheadFilter(IO::openFile(subtractFileName))); subtractSource.setWhitespace(',',true); subtractSource.setPunctuation('\n',true); subtractSource.skipWs(); const LidarProcessOctree::OffsetVector& offset=basePoints->getOffset(); while(!subtractSource.eof()) { /* Read the next point and subtract the base file's point offset: */ Point p; for(int i=0;i<3;++i) p[i]=Scalar(subtractSource.readNumber()-offset[i]); subtractPoints.push_back(p); /* Skip the rest of the line: */ subtractSource.skipLine(); subtractSource.skipWs(); } std::cout<<" done"<<std::endl; } catch(std::runtime_error err) { std::cout<<" failed"<<std::endl; std::cerr<<"Caught exception "<<err.what()<<"while reading subtraction file "<<subtractFileName<<"; terminating"<<std::endl; return 1; } std::cout<<"Creating kd-tree of "<<subtractPoints.size()<<" subtraction points..."<<std::flush; Geometry::ArrayKdTree<Point>* subtractPointTree=new Geometry::ArrayKdTree<Point>(subtractPoints.size()); Point* points=subtractPointTree->accessPoints(); for(size_t i=0;i<subtractPoints.size();++i) points[i]=subtractPoints[i]; subtractPointTree->releasePoints(numThreads); std::cout<<" done"<<std::endl; /* Process the base point set: */ { std::cout<<"Subtracting points..."<<std::flush; NodePointSubtractor nps(*basePoints,*subtractPointTree,epsilon,pa); basePoints->processNodesPostfix(nps); pa.finishReading(); std::cout<<" done"<<std::endl; } /* Clear input data structures: */ delete basePoints; delete subtractPointTree; /* Construct an octree with less than maxPointsPerNode points per leaf: */ LidarOctreeCreator tree(pa.getMaxNumCacheablePoints(),maxNumPointsPerNode,numThreads,pa.getTempOctrees(),tempPointFileNameTemplate+"XXXXXX"); /* Delete the temporary point octrees: */ pa.deleteTempOctrees(); /* Write the octree structure and data to the destination LiDAR file: */ tree.write(outputFileName); /* Check if a point offset was defined: */ if(pointOffset!=PointAccumulator::Vector::zero) { /* Write the point offsets to an offset file: */ std::string offsetFileName=outputFileName; offsetFileName.append("/Offset"); IO::FilePtr offsetFile(IO::openFile(offsetFileName.c_str(),IO::File::WriteOnly)); offsetFile->setEndianness(Misc::LittleEndian); offsetFile->write(pointOffset.getComponents(),3); } return 0; }