XYZPointReader(string file, string format, vector<double> colorRange, vector<double> intensityRange) : stream(file, std::ios::in | std::ios::binary) { this->format = format; pointsRead = 0; linesSkipped = 0; pointCount = 0; colorScale = -1; if(intensityRange.size() == 2){ intensityOffset = (float)intensityRange[0]; intensityScale = (float)intensityRange[1]-(float)intensityRange[0]; }else if(intensityRange.size() == 1){ intensityOffset = 0.0f; intensityScale = (float)intensityRange[0]; }else{ intensityOffset = 0.0f; intensityScale = 1.0f; } if(colorRange.size() == 2){ colorOffset = (float)colorRange[0]; colorScale = (float)colorRange[1]; }else if(colorRange.size() == 1){ colorOffset = 0.0f; colorScale = (float)colorRange[0]; }else if(colorRange.size() == 0){ colorOffset = 0.0f; // try to find color range by evaluating the first x points. float max = 0; int j = 0; string line; while(getline(stream, line) && j < 1000){ trim(line); vector<string> tokens = split(line, { '\t', ' ', ',' }); if(this->format == "" && tokens.size() >= 3){ string f(tokens.size(), 's'); f.replace(0, 3, "xyz"); if(tokens.size() >= 6){ f.replace(tokens.size() - 3, 3, "rgb"); } this->format = f; cout << "using format: '" << this->format << "'" << endl; } if(tokens.size() < this->format.size()){ continue; } int i = 0; for(const auto &f : format) { string token = tokens[i++]; if(f == 'r'){ max = std::max(max, stof(token)); }else if(f == 'g'){ max = std::max(max, stof(token)); }else if(f == 'b'){ max = std::max(max, stof(token)); } } j++; } if(max <= 1.0f){ colorScale = 1.0f; } else if(max <= 255){ colorScale = 255.0f; }else if(max <= pow(2, 16) - 1){ colorScale =(float)pow(2, 16) - 1; }else{ colorScale = (float)max; } stream.clear(); stream.seekg(0, stream.beg); } // read through once to calculate aabb and number of points while(readNextPoint()){ Point p = getPoint(); aabb.update(p.position); pointCount++; } stream.clear(); stream.seekg(0, stream.beg); }
int main(int argc, char* argv[]) { if (argc < 3) { return 1; } std::string inFile(argv[1]); std::string outFile(argv[2]); auto reader = (Potree::LASPointReader*)Proxy::createPointReader(inFile); if (!reader) { // TODO return 1; } auto aabb = reader->getAABB(); aabb.size = aabb.max - aabb.min; aabb.makeCubic(); uint64_t pointNum = 0; uint64_t flushNum = 0; FILE* fp = nullptr; fopen_s(&fp, outFile.c_str(), "wb"); fseek(fp, sizeof(TMPHeader), SEEK_SET); std::vector<Point> points; points.reserve(reader->numPoints()); static const uint32_t FLUSH_NUM = 10000; while (reader->readNextPoint()) { auto point = reader->getPoint(); pointNum++; flushNum++; Point pt; pt.pos[0] = point.position.x; pt.pos[1] = point.position.y; pt.pos[2] = point.position.z; pt.rgba[0] = point.color.x; pt.rgba[1] = point.color.y; pt.rgba[2] = point.color.z; pt.rgba[3] = 0xff; points.push_back(pt); if (flushNum == FLUSH_NUM) { printf("%d\n", pointNum); fwrite(&points[0], sizeof(Point), flushNum, fp); points.clear(); flushNum = 0; } } if (flushNum > 0) { printf("%d\n", pointNum); fwrite(&points[0], sizeof(Point), flushNum, fp); points.clear(); flushNum = 0; } // Write header. { TMPHeader header; header.fileSize = ftell(fp); header.vtxFormat = VtxFormat::Position | VtxFormat::Color; header.vtxNum = pointNum; auto& aabbMin = aabb.min; auto& aabbMax = aabb.max; header.aabbMin[0] = aabbMin.x; header.aabbMin[1] = aabbMin.y; header.aabbMin[2] = aabbMin.z; header.aabbMax[0] = aabbMax.x; header.aabbMax[1] = aabbMax.y; header.aabbMax[2] = aabbMax.z; fseek(fp, 0, SEEK_SET); fwrite(&header, sizeof(header), 1, fp); } fclose(fp); return 0; }