bool PointArray::loadLas(QString fileName, size_t maxPointCount, std::vector<GeomField>& fields, V3d& offset, size_t& npoints, uint64_t& totPoints, Imath::Box3d& bbox, V3d& centroid) { V3d Psum(0); #ifdef DISPLAZ_USE_PDAL // Open file if (!pdal::FileUtils::fileExists(fileName.toAscii().constData())) { g_logger.info("File \"%s\" does not exist", fileName.toStdString() ); return false; } std::unique_ptr<pdal::PipelineManager> manager(new pdal::PipelineManager); pdal::StageFactory factory; std::string driver = factory.inferReaderDriver(fileName.toStdString()); manager->addReader(driver); pdal::Stage* reader = static_cast<pdal::Reader*>(manager->getStage()); pdal::Options options; pdal::Option fname("filename", fileName.toStdString()); options.add(fname); reader->setOptions(options); manager->execute(); pdal::PointBufferSet pbSet = manager->buffers(); pdal::PointContext context = manager->context(); bool hasColor = context.hasDim(pdal::Dimension::Id::Red); pdal::QuickInfo quickinfo = reader->preview(); // Figure out how much to decimate the point cloud. totPoints = quickinfo.m_pointCount; size_t decimate = totPoints == 0 ? 1 : 1 + (totPoints - 1) / maxPointCount; if(decimate > 1) { g_logger.info("Decimating \"%s\" by factor of %d", fileName.toStdString(), decimate); } npoints = (totPoints + decimate - 1) / decimate; pdal::BOX3D pdal_bounds = quickinfo.m_bounds; offset = V3d(0.5*(pdal_bounds.minx + pdal_bounds.maxx), 0.5*(pdal_bounds.miny + pdal_bounds.maxy), 0.5*(pdal_bounds.minz + pdal_bounds.maxz)); // Attempt to place all data on the same vertical scale, but allow // other offsets if the magnitude of z is too large (and we would // therefore loose noticable precision by storing the data as floats) if (fabs(offset.z) < 10000) offset.z = 0; // Allocate all arrays fields.push_back(GeomField(TypeSpec::vec3float32(), "position", npoints)); fields.push_back(GeomField(TypeSpec::uint16_i(), "intensity", npoints)); fields.push_back(GeomField(TypeSpec::uint8_i(), "returnNumber", npoints)); fields.push_back(GeomField(TypeSpec::uint8_i(), "numberOfReturns", npoints)); fields.push_back(GeomField(TypeSpec::uint8_i(), "pointSourceId", npoints)); fields.push_back(GeomField(TypeSpec::uint8_i(), "classification", npoints)); // Output iterators for the output arrays V3f* position = (V3f*)fields[0].as<float>(); uint16_t* intensity = fields[1].as<uint16_t>(); uint8_t* returnNumber = fields[2].as<uint8_t>(); uint8_t* numReturns = fields[3].as<uint8_t>(); uint8_t* pointSourceId = fields[4].as<uint8_t>(); uint8_t* classification = fields[5].as<uint8_t>(); uint16_t* color = 0; if (hasColor) { fields.push_back(GeomField(TypeSpec(TypeSpec::Uint,2,3,TypeSpec::Color), "color", npoints)); color = fields.back().as<uint16_t>(); } size_t readCount = 0; size_t storeCount = 0; size_t nextDecimateBlock = 1; size_t nextStore = 1; for (auto st = pbSet.begin(); st != pbSet.end(); ++st) // while (size_t numRead = chunkIter->read(buf)) { pdal::PointBufferPtr buf = *st; for (size_t i = 0; i < buf->size(); ++i) { ++readCount; V3d P = V3d(buf->getFieldAs<double>(pdal::Dimension::Id::X, i), buf->getFieldAs<double>(pdal::Dimension::Id::Y, i), buf->getFieldAs<double>(pdal::Dimension::Id::Z, i)); // V3d P = V3d(xDim.applyScaling(buf.getField<int32_t>(xDim, i)), // yDim.applyScaling(buf.getField<int32_t>(yDim, i)), // zDim.applyScaling(buf.getField<int32_t>(zDim, i))); bbox.extendBy(P); Psum += P; if(readCount < nextStore) continue; ++storeCount; // Store the point *position++ = P - offset; *intensity++ = buf->getFieldAs<uint16_t>(pdal::Dimension::Id::Intensity, i); *returnNumber++ = buf->getFieldAs<uint8_t>(pdal::Dimension::Id::ReturnNumber, i); *numReturns++ = buf->getFieldAs<uint8_t>(pdal::Dimension::Id::NumberOfReturns, i); *pointSourceId++ = buf->getFieldAs<uint8_t>(pdal::Dimension::Id::PointSourceId, i); *classification++ = buf->getFieldAs<uint8_t>(pdal::Dimension::Id::Classification, i); // Extract point RGB if (hasColor) { *color++ = buf->getFieldAs<uint16_t>(pdal::Dimension::Id::Red, i); *color++ = buf->getFieldAs<uint16_t>(pdal::Dimension::Id::Green, i); *color++ = buf->getFieldAs<uint16_t>(pdal::Dimension::Id::Blue, i); } // Figure out which point will be the next stored point. nextDecimateBlock += decimate; nextStore = nextDecimateBlock; if(decimate > 1) { // Randomize selected point within block to avoid repeated patterns nextStore += (qrand() % decimate); if(nextDecimateBlock <= totPoints && nextStore > totPoints) nextStore = totPoints; } } emit loadProgress(100*readCount/totPoints); } #else LASreadOpener lasReadOpener; #ifdef _WIN32 // Hack: liblas doesn't like forward slashes as path separators on windows fileName = fileName.replace('/', '\\'); #endif lasReadOpener.set_file_name(fileName.toAscii().constData()); std::unique_ptr<LASreader> lasReader(lasReadOpener.open()); if(!lasReader) { g_logger.error("Couldn't open file \"%s\"", fileName); return false; } //std::ofstream dumpFile("points.txt"); // Figure out how much to decimate the point cloud. totPoints = std::max<uint64_t>(lasReader->header.extended_number_of_point_records, lasReader->header.number_of_point_records); size_t decimate = totPoints == 0 ? 1 : 1 + (totPoints - 1) / maxPointCount; if(decimate > 1) { g_logger.info("Decimating \"%s\" by factor of %d", fileName.toStdString(), decimate); } npoints = (totPoints + decimate - 1) / decimate; offset = V3d(lasReader->header.min_x, lasReader->header.min_y, 0); // Attempt to place all data on the same vertical scale, but allow other // offsets if the magnitude of z is too large (and we would therefore loose // noticable precision by storing the data as floats) if (fabs(lasReader->header.min_z) > 10000) offset.z = lasReader->header.min_z; fields.push_back(GeomField(TypeSpec::vec3float32(), "position", npoints)); fields.push_back(GeomField(TypeSpec::uint16_i(), "intensity", npoints)); fields.push_back(GeomField(TypeSpec::uint8_i(), "returnNumber", npoints)); fields.push_back(GeomField(TypeSpec::uint8_i(), "numberOfReturns", npoints)); fields.push_back(GeomField(TypeSpec::uint8_i(), "pointSourceId", npoints)); fields.push_back(GeomField(TypeSpec::uint8_i(), "classification", npoints)); if (totPoints == 0) { g_logger.warning("File %s has zero points", fileName); return true; } // Iterate over all points & pull in the data. V3f* position = (V3f*)fields[0].as<float>(); uint16_t* intensity = fields[1].as<uint16_t>(); uint8_t* returnNumber = fields[2].as<uint8_t>(); uint8_t* numReturns = fields[3].as<uint8_t>(); uint8_t* pointSourceId = fields[4].as<uint8_t>(); uint8_t* classification = fields[5].as<uint8_t>(); uint64_t readCount = 0; uint64_t nextDecimateBlock = 1; uint64_t nextStore = 1; size_t storeCount = 0; if (!lasReader->read_point()) return false; const LASpoint& point = lasReader->point; uint16_t* color = 0; if (point.have_rgb) { fields.push_back(GeomField(TypeSpec(TypeSpec::Uint,2,3,TypeSpec::Color), "color", npoints)); color = fields.back().as<uint16_t>(); } do { // Read a point from the las file ++readCount; if(readCount % 10000 == 0) emit loadProgress(100*readCount/totPoints); V3d P = V3d(point.get_x(), point.get_y(), point.get_z()); bbox.extendBy(P); Psum += P; if(readCount < nextStore) continue; ++storeCount; // Store the point *position++ = P - offset; // float intens = float(point.scan_angle_rank) / 40; *intensity++ = point.intensity; *returnNumber++ = point.return_number; # if LAS_TOOLS_VERSION >= 140315 *numReturns++ = point.number_of_returns; # else *numReturns++ = point.number_of_returns_of_given_pulse; # endif *pointSourceId++ = point.point_source_ID; // Put flags back in classification byte to avoid memory bloat *classification++ = point.classification | (point.synthetic_flag << 5) | (point.keypoint_flag << 6) | (point.withheld_flag << 7); // Extract point RGB if (color) { *color++ = point.rgb[0]; *color++ = point.rgb[1]; *color++ = point.rgb[2]; } // Figure out which point will be the next stored point. nextDecimateBlock += decimate; nextStore = nextDecimateBlock; if(decimate > 1) { // Randomize selected point within block to avoid repeated patterns nextStore += (qrand() % decimate); if(nextDecimateBlock <= totPoints && nextStore > totPoints) nextStore = totPoints; } } while(lasReader->read_point()); lasReader->close(); #endif if (readCount < totPoints) { g_logger.warning("Expected %d points in file \"%s\", got %d", totPoints, fileName, readCount); npoints = storeCount; // Shrink all fields to fit - these will have wasted space at the end, // but that will be fixed during reordering. for (size_t i = 0; i < fields.size(); ++i) fields[i].size = npoints; totPoints = readCount; } if (totPoints > 0) centroid = (1.0/totPoints)*Psum; return true; }
bool OSLCompilerImpl::compile (const std::string &filename, const std::vector<std::string> &options, const std::string &stdoslpath) { if (! OIIO::Filesystem::exists (filename)) { error (ustring(), 0, "Input file \"%s\" not found", filename.c_str()); return false; } std::string stdinclude; #ifdef USE_BOOST_WAVE std::vector<std::string> defines; std::vector<std::string> includepaths; #else std::string cppoptions; #endif m_cwd = boost::filesystem::initial_path().string(); m_main_filename = filename; // Determine where the installed shader include directory is, and // look for ../shaders/stdosl.h and force it to include. if (stdoslpath.empty()) { std::string program = OIIO::Sysutil::this_program_path (); if (program.size()) { boost::filesystem::path path (program); // our program path = path.parent_path (); // now the bin dir of our program path = path.parent_path (); // now the parent dir path = path / "shaders"; bool found = false; if (OIIO::Filesystem::exists (path.string())) { #ifdef USE_BOOST_WAVE includepaths.push_back(path.string()); #else // pass along to cpp cppoptions += "\"-I"; cppoptions += path.string(); cppoptions += "\" "; #endif path = path / "stdosl.h"; if (OIIO::Filesystem::exists (path.string())) { stdinclude = path.string(); found = true; } } if (! found) warning (ustring(filename), 0, "Unable to find \"%s\"", path.string().c_str()); } } else stdinclude = stdoslpath; m_output_filename.clear (); bool preprocess_only = false; for (size_t i = 0; i < options.size(); ++i) { if (options[i] == "-v") { // verbose mode m_verbose = true; } else if (options[i] == "-q") { // quiet mode m_quiet = true; } else if (options[i] == "-d") { // debug mode m_debug = true; } else if (options[i] == "-E") { preprocess_only = true; } else if (options[i] == "-o" && i < options.size()-1) { ++i; m_output_filename = options[i]; } else if (options[i] == "-O0") { m_optimizelevel = 0; } else if (options[i] == "-O" || options[i] == "-O1") { m_optimizelevel = 1; } else if (options[i] == "-O2") { m_optimizelevel = 2; #ifdef USE_BOOST_WAVE } else if (options[i].c_str()[0] == '-' && options[i].size() > 2) { // options meant for the preprocessor if (options[i].c_str()[1] == 'D' || options[i].c_str()[1] == 'U') defines.push_back(options[i].substr(2)); else if (options[i].c_str()[1] == 'I') includepaths.push_back(options[i].substr(2)); #else } else { // something meant for the cpp command cppoptions += "\""; cppoptions += options[i]; cppoptions += "\" "; #endif } } std::string preprocess_result; #ifdef USE_BOOST_WAVE if (! preprocess(filename, stdinclude, defines, includepaths, preprocess_result)) { #else if (! preprocess(filename, stdinclude, cppoptions, preprocess_result)) { #endif return false; } else if (preprocess_only) { std::cout << preprocess_result; } else { std::istringstream in (preprocess_result); oslcompiler = this; // Create a lexer, parse the file, delete the lexer m_lexer = new oslFlexLexer (&in); oslparse (); bool parseerr = error_encountered(); delete m_lexer; if (! parseerr) { if (shader()) shader()->typecheck (); else error (ustring(), 0, "No shader function defined"); } // Print the parse tree if there were no errors if (m_debug) { symtab().print (); if (shader()) shader()->print (std::cout); } if (! error_encountered()) { shader()->codegen (); // add_useparam (); track_variable_dependencies (); track_variable_lifetimes (); check_for_illegal_writes (); // if (m_optimizelevel >= 1) // coalesce_temporaries (); } if (! error_encountered()) { if (m_output_filename.size() == 0) m_output_filename = default_output_filename (); write_oso_file (m_output_filename); } oslcompiler = NULL; } return ! error_encountered(); } struct GlobalTable { const char *name; TypeSpec type; }; void OSLCompilerImpl::initialize_globals () { static GlobalTable globals[] = { { "P", TypeDesc::TypePoint }, { "I", TypeDesc::TypeVector }, { "N", TypeDesc::TypeNormal }, { "Ng", TypeDesc::TypeNormal }, { "u", TypeDesc::TypeFloat }, { "v", TypeDesc::TypeFloat }, { "dPdu", TypeDesc::TypeVector }, { "dPdv", TypeDesc::TypeVector }, #if 0 // Light variables -- we don't seem to be on a route to support this // kind of light shader, so comment these out for now. { "L", TypeDesc::TypeVector }, { "Cl", TypeDesc::TypeColor }, { "Ns", TypeDesc::TypeNormal }, { "Pl", TypeDesc::TypePoint }, { "Nl", TypeDesc::TypeNormal }, #endif { "Ps", TypeDesc::TypePoint }, { "Ci", TypeSpec (TypeDesc::TypeColor, true) }, { "time", TypeDesc::TypeFloat }, { "dtime", TypeDesc::TypeFloat }, { "dPdtime", TypeDesc::TypeVector }, { NULL } }; for (int i = 0; globals[i].name; ++i) { Symbol *s = new Symbol (ustring(globals[i].name), globals[i].type, SymTypeGlobal); symtab().insert (s); } } std::string OSLCompilerImpl::default_output_filename () { if (m_shader && shader_decl()) return shader_decl()->shadername().string() + ".oso"; return std::string(); } void OSLCompilerImpl::write_oso_metadata (const ASTNode *metanode) const { ASSERT (metanode->nodetype() == ASTNode::variable_declaration_node); const ASTvariable_declaration *metavar = static_cast<const ASTvariable_declaration *>(metanode); Symbol *metasym = metavar->sym(); ASSERT (metasym); TypeSpec ts = metasym->typespec(); oso ("%%meta{%s,%s,", ts.string().c_str(), metasym->name().c_str()); const ASTNode *init = metavar->init().get(); ASSERT (init); if (ts.is_string() && init->nodetype() == ASTNode::literal_node) oso ("\"%s\"", ((const ASTliteral *)init)->strval()); else if (ts.is_int() && init->nodetype() == ASTNode::literal_node) oso ("%d", ((const ASTliteral *)init)->intval()); else if (ts.is_float() && init->nodetype() == ASTNode::literal_node) oso ("%.8g", ((const ASTliteral *)init)->floatval()); // FIXME -- what about type constructors? else { std::cout << "Error, don't know how to print metadata " << ts.string() << " with node type " << init->nodetypename() << "\n"; ASSERT (0); // FIXME } oso ("} "); }