point_count_t BpfReader::readDimMajor(PointBuffer& data, point_count_t count) { PointId idx(0); PointId startId = data.size(); point_count_t numRead = 0; for (size_t d = 0; d < m_dims.size(); ++d) { idx = m_index; PointId nextId = startId; numRead = 0; seekDimMajor(d, idx); for (; numRead < count && idx < numPoints(); idx++, numRead++, nextId++) { float f; m_stream >> f; data.setField(m_dims[d].m_id, nextId, f + m_dims[d].m_offset); } } m_index = idx; // Transformation only applies to X, Y and Z for (PointId idx = startId; idx < data.size(); idx++) { double x = data.getFieldAs<double>(Dimension::Id::X, idx); double y = data.getFieldAs<double>(Dimension::Id::Y, idx); double z = data.getFieldAs<double>(Dimension::Id::Z, idx); m_header.m_xform.apply(x, y, z); data.setField(Dimension::Id::X, idx, x); data.setField(Dimension::Id::Y, idx, y); data.setField(Dimension::Id::Z, idx, z); } return numRead; }
point_count_t BpfReader::readPointMajor(PointBuffer& data, point_count_t count) { PointId nextId = data.size(); PointId idx = m_index; point_count_t numRead = 0; seekPointMajor(idx); while (numRead < count && idx < numPoints()) { for (size_t d = 0; d < m_dims.size(); ++d) { float f; m_stream >> f; data.setField(m_dims[d].m_id, nextId, f + m_dims[d].m_offset); } // Transformation only applies to X, Y and Z double x = data.getFieldAs<double>(Dimension::Id::X, nextId); double y = data.getFieldAs<double>(Dimension::Id::Y, nextId); double z = data.getFieldAs<double>(Dimension::Id::Z, nextId); m_header.m_xform.apply(x, y, z); data.setField(Dimension::Id::X, nextId, x); data.setField(Dimension::Id::Y, nextId, y); data.setField(Dimension::Id::Z, nextId, z); idx++; numRead++; nextId++; } m_index = idx; return numRead; }
point_count_t BpfReader::readByteMajor(PointBuffer& data, point_count_t count) { PointId idx(0); PointId startId = data.size(); point_count_t numRead = 0; // We need a temp buffer for the point data. union uu { float f; uint32_t u32; }; std::unique_ptr<union uu> uArr( new uu[std::min(count, numPoints() - m_index)]); for (size_t d = 0; d < m_dims.size(); ++d) { for (size_t b = 0; b < sizeof(float); ++b) { idx = m_index; numRead = 0; PointId nextId = startId; seekByteMajor(d, b, idx); for (;numRead < count && idx < numPoints(); idx++, numRead++, nextId++) { union uu& u = *(uArr.get() + numRead); if (b == 0) u.u32 = 0; uint8_t u8; m_stream >> u8; u.u32 |= ((uint32_t)u8 << (b * CHAR_BIT)); if (b == 3) { u.f += m_dims[d].m_offset; data.setField(m_dims[d].m_id, nextId, u.f); } } } } m_index = idx; // Transformation only applies to X, Y and Z for (PointId idx = startId; idx < data.size(); idx++) { double x = data.getFieldAs<double>(Dimension::Id::X, idx); double y = data.getFieldAs<double>(Dimension::Id::Y, idx); double z = data.getFieldAs<double>(Dimension::Id::Z, idx); m_header.m_xform.apply(x, y, z); data.setField(Dimension::Id::X, idx, x); data.setField(Dimension::Id::Y, idx, y); data.setField(Dimension::Id::Z, idx, z); } return numRead; }
PointBuffer* makeTestBuffer() { Dimension d1("Classification", dimension::UnsignedInteger, 1); Dimension d2("X", dimension::SignedInteger, 4); Dimension d3("Y", dimension::Float, 8); Schema schema; schema.appendDimension(d1); schema.appendDimension(d2); schema.appendDimension(d3); std::size_t offX = schema.getDimension(0).getByteOffset(); BOOST_CHECK(offX==0); std::size_t offY = schema.getDimension(1).getByteOffset(); BOOST_CHECK(offY==1); std::size_t offZ = schema.getDimension(2).getByteOffset(); BOOST_CHECK(offZ==5); boost::uint32_t capacity = 17; PointBuffer* data = new PointBuffer(schema, capacity); BOOST_CHECK(data->getCapacity() == capacity); Dimension const& dimC = data->getSchema().getDimension("Classification"); Dimension const& dimX = data->getSchema().getDimension("X"); Dimension const& dimY = data->getSchema().getDimension("Y"); // write the data into the buffer for (boost::uint32_t i=0; i<data->getCapacity(); i++) { const boost::uint8_t x = static_cast<boost::uint8_t>(i)+1; const boost::int32_t y = i*10; const double z = i * 100; data->setField(dimC, i, x); data->setField(dimX, i, y); data->setField(dimY, i, z); data->setNumPoints(i+1); } BOOST_CHECK(data->getCapacity() ==17); BOOST_CHECK(data->getNumPoints() ==17); return data; }
void IteratorBase::fillUserBuffer(PointBuffer& user_buffer) { Schema const& user_schema = user_buffer.getSchema(); schema::index_by_index const& idx = user_schema.getDimensions().get<schema::index>(); boost::int32_t numUserSpace = user_buffer.getCapacity() - user_buffer.getNumPoints(); if (numUserSpace < 0) throw pdal_error("We ran out of space!"); boost::int32_t numOraclePoints = m_active_buffer->getNumPoints() - m_buffer_position; schema::index_by_index::size_type i(0); for (i = 0; i < idx.size(); ++i) { copyDatabaseData(*m_active_buffer, user_buffer, idx[i], m_buffer_position, user_buffer.getNumPoints(), (std::min)(numOraclePoints,numUserSpace)); } bool bSetPointSourceId = getReader().getOptions().getValueOrDefault<bool>("populate_pointsourceid", false); if (bSetPointSourceId) { Dimension const* point_source_field = &(user_buffer.getSchema().getDimensionOptional("PointSourceId").get()); if (point_source_field) { for (boost::int32_t i = 0; i < numUserSpace; ++i) { if (i < 0) throw sqlite_driver_error("point_source_field point index is less than 0!"); user_buffer.setField(*point_source_field, i, m_active_cloud_id); } } } if (numOraclePoints > numUserSpace) m_buffer_position = m_buffer_position + numUserSpace; else if (numOraclePoints < numUserSpace) m_buffer_position = 0; boost::uint32_t howManyThisRead = (std::min)(numUserSpace, numOraclePoints); user_buffer.setNumPoints(howManyThisRead + user_buffer.getNumPoints()); }
void AttributeFilter::filter(PointBuffer& buffer) { for (auto& dim_par : m_dimensions) { if (dim_par.second.isogr) { UpdateGEOSBuffer(buffer, dim_par.second); } else { for (PointId i = 0; i < buffer.size(); ++i) { double v = boost::lexical_cast<double>(dim_par.second.value); buffer.setField(dim_par.second.dim, i, v); } } } }
point_count_t SbetReader::read(PointBuffer& buf, point_count_t count) { PointId nextId = buf.size(); PointId idx = m_index; point_count_t numRead = 0; seek(idx); Dimension::IdList dims = getDefaultDimensions(); while (numRead < count && idx < m_numPts) { for (auto di = dims.begin(); di != dims.end(); ++di) { double d; *m_stream >> d; Dimension::Id::Enum dim = *di; buf.setField(dim, nextId, d); } idx++; nextId++; numRead++; } m_index = idx; return numRead; }
void BufferedInvocation::end(PointBuffer& buffer) { // for each entry in the script's outs dictionary, // look up that entry's name in the schema and then // copy the data into the right dimension spot in the // buffer std::vector<std::string> names; getOutputNames(names); PointContext ctx = buffer.m_context; Dimension::IdList const& dims = ctx.dims(); for (auto di = dims.begin(); di != dims.end(); ++di) { Dimension::Id::Enum d = *di; Dimension::Detail *dd = ctx.dimDetail(d); std::string name = ctx.dimName(*di); auto found = std::find(names.begin(), names.end(), name); if (found == names.end()) continue; // didn't have this dim in the names assert(name == *found); assert(hasOutputVariable(name)); size_t size = dd->size(); void *data = extractResult(name, dd->type()); char *p = (char *)data; for (PointId idx = 0; idx < buffer.size(); ++idx) { buffer.setField(d, dd->type(), idx, (void *)p); p += size; } } for (auto bi = m_buffers.begin(); bi != m_buffers.end(); ++bi) free(*bi); m_buffers.clear(); }
point_count_t GreyhoundReader::setPoints( PointBuffer& pointBuffer, const char* data, const point_count_t pointsToRead) const { PointId nextId(pointBuffer.size()); std::size_t dataOffset(0); point_count_t numRead(0); while (numRead < pointsToRead) { for (auto dim : m_dimData) { pointBuffer.setField(dim.id, dim.type, nextId, data + dataOffset); dataOffset += Dimension::size(dim.type); } ++nextId; ++numRead; } return numRead; }
void AttributeFilter::UpdateGEOSBuffer(PointBuffer& buffer, AttributeInfo& info) { QuadIndex idx(buffer); idx.build(); if (!info.lyr) // wake up the layer { if (info.layer.size()) info.lyr = OGR_DS_GetLayerByName(info.ds.get(), info.layer.c_str()); else if (info.query.size()) { info.lyr = OGR_DS_ExecuteSQL(info.ds.get(), info.query.c_str(), 0, 0); } else info.lyr = OGR_DS_GetLayer(info.ds.get(), 0); if (!info.lyr) { std::ostringstream oss; oss << "Unable to select layer '" << info.layer << "'"; throw pdal_error(oss.str()); } } OGRFeaturePtr feature = OGRFeaturePtr(OGR_L_GetNextFeature(info.lyr), OGRFeatureDeleter()); int field_index(1); // default to first column if nothing was set if (info.column.size()) { field_index = OGR_F_GetFieldIndex(feature.get(), info.column.c_str()); if (field_index == -1) { std::ostringstream oss; oss << "No column name '" << info.column << "' was found."; throw pdal_error(oss.str()); } } while(feature) { OGRGeometryH geom = OGR_F_GetGeometryRef(feature.get()); OGRwkbGeometryType t = OGR_G_GetGeometryType(geom); int f_count = OGR_F_GetFieldCount (feature.get()); if (!(t == wkbPolygon || t == wkbMultiPolygon || t == wkbPolygon25D || t == wkbMultiPolygon25D)) { std::ostringstream oss; oss << "Geometry is not Polygon or MultiPolygon!"; throw pdal::pdal_error(oss.str()); } OGRGeometry* ogr_g = (OGRGeometry*) geom; GEOSGeometry* geos_g (0); if (!m_geosEnvironment) { #if (GDAL_VERSION_MINOR < 11) && (GDAL_VERSION_MAJOR == 1) geos_g = ogr_g->exportToGEOS(); #else m_geosEnvironment = ogr_g->createGEOSContext(); geos_g = ogr_g->exportToGEOS(m_geosEnvironment); #endif } GEOSPreparedGeometry const* geos_pg = GEOSPrepare_r(m_geosEnvironment, geos_g); if (!geos_pg) throw pdal_error("unable to prepare geometry for index-accelerated intersection"); // Compute a total bounds for the geometry. Query the QuadTree to // find out the points that are inside the bbox. Then test each // point in the bbox against the prepared geometry. BOX3D box = computeBounds(m_geosEnvironment, geos_g); std::vector<std::size_t> ids = idx.getPoints(box); for (const auto& i : ids) { double x = buffer.getFieldAs<double>(Dimension::Id::X, i); double y = buffer.getFieldAs<double>(Dimension::Id::Y, i); double z = buffer.getFieldAs<double>(Dimension::Id::Z, i); GEOSGeometry* p = createGEOSPoint(m_geosEnvironment, x, y ,z); if (static_cast<bool>(GEOSPreparedContains_r(m_geosEnvironment, geos_pg, p))) { // We're in the poly, write the attribute value int32_t v = OGR_F_GetFieldAsInteger(feature.get(), field_index); buffer.setField(info.dim, i, v); // log()->get(LogLevel::Debug) << "Setting value: " << v << std::endl; } GEOSGeom_destroy_r(m_geosEnvironment, p); } feature = OGRFeaturePtr(OGR_L_GetNextFeature(info.lyr), OGRFeatureDeleter()); } }
point_count_t QfitReader::read(PointBuffer& data, point_count_t count) { if (!m_istream->good()) { throw pdal_error("QFIT file stream is no good!"); } if (m_istream->eof()) { throw pdal_error("QFIT file stream is eof!"); } count = std::min(m_numPoints - m_index, count); uint8_t *buf = new uint8_t[m_size]; PointId nextId = data.size(); point_count_t numRead = 0; while (count--) { Utils::read_n(buf, *m_istream, m_size); uint8_t* p = buf; // always read the base fields { int32_t time = Utils::read_field<int32_t>(p); if (!m_littleEndian) QFIT_SWAP_BE_TO_LE(time); data.setField(Dimension::Id::OffsetTime, nextId, time); int32_t y = Utils::read_field<int32_t>(p); if (!m_littleEndian) QFIT_SWAP_BE_TO_LE(y); data.setField(Dimension::Id::Y, nextId, y / 1000000.0); int32_t xi = Utils::read_field<int32_t>(p); if (!m_littleEndian) QFIT_SWAP_BE_TO_LE(xi); double x = xi / 1000000.0; if (m_flip_x && x > 180) x -= 360; data.setField(Dimension::Id::X, nextId, x); int32_t z = Utils::read_field<int32_t>(p); if (!m_littleEndian) QFIT_SWAP_BE_TO_LE(z); data.setField(Dimension::Id::Z, nextId, z * m_scale_z); int32_t start_pulse = Utils::read_field<int32_t>(p); if (!m_littleEndian) QFIT_SWAP_BE_TO_LE(start_pulse); data.setField(Dimension::Id::StartPulse, nextId, start_pulse); int32_t reflected_pulse = Utils::read_field<int32_t>(p); if (!m_littleEndian) QFIT_SWAP_BE_TO_LE(reflected_pulse); data.setField(Dimension::Id::ReflectedPulse, nextId, reflected_pulse); int32_t scan_angle = Utils::read_field<int32_t>(p); if (!m_littleEndian) QFIT_SWAP_BE_TO_LE(scan_angle); data.setField(Dimension::Id::ScanAngleRank, nextId, scan_angle / 1000.0); int32_t pitch = Utils::read_field<int32_t>(p); if (!m_littleEndian) QFIT_SWAP_BE_TO_LE(pitch); data.setField(Dimension::Id::Pitch, nextId, pitch / 1000.0); int32_t roll = Utils::read_field<int32_t>(p); if (!m_littleEndian) QFIT_SWAP_BE_TO_LE(roll); data.setField(Dimension::Id::Roll, nextId, roll / 1000.0); } if (m_format == QFIT_Format_12) { int32_t pdop = Utils::read_field<int32_t>(p); if (!m_littleEndian) QFIT_SWAP_BE_TO_LE(pdop); data.setField(Dimension::Id::Pdop, nextId, pdop / 10.0); int32_t pulse_width = Utils::read_field<int32_t>(p); if (!m_littleEndian) QFIT_SWAP_BE_TO_LE(pulse_width); data.setField(Dimension::Id::PulseWidth, nextId, pulse_width); } else if (m_format == QFIT_Format_14) { int32_t passive_signal = Utils::read_field<int32_t>(p); if (!m_littleEndian) QFIT_SWAP_BE_TO_LE(passive_signal); data.setField(Dimension::Id::PassiveSignal, nextId, passive_signal); int32_t passive_y = Utils::read_field<int32_t>(p); if (!m_littleEndian) QFIT_SWAP_BE_TO_LE(passive_y); data.setField(Dimension::Id::PassiveY, nextId, passive_y / 1000000.0); int32_t passive_x = Utils::read_field<int32_t>(p); if (!m_littleEndian) QFIT_SWAP_BE_TO_LE(passive_x); double x = passive_x / 1000000.0; if (m_flip_x && x > 180) x -= 360; data.setField(Dimension::Id::PassiveX, nextId, x); int32_t passive_z = Utils::read_field<int32_t>(p); if (!m_littleEndian) QFIT_SWAP_BE_TO_LE(passive_z); data.setField(Dimension::Id::PassiveZ, nextId, passive_z * m_scale_z); } // GPS time is really a GPS offset from the start of the GPS day // encoded in this odd way: 153320100 = 15 hours 33 minutes // 20 seconds 100 milliseconds. // Not sure why we have that AND the other offset time. For now // we'll just extract this time and drop it. int32_t gpstime = Utils::read_field<int32_t>(p); numRead++; nextId++; } delete[] buf; m_index += numRead; return numRead; }
point_count_t FauxReader::read(PointBuffer& buf, point_count_t count) { const double numDeltas = (double)count - 1.0; const double delX = (m_maxX - m_minX) / numDeltas; const double delY = (m_maxY - m_minY) / numDeltas; const double delZ = (m_maxZ - m_minZ) / numDeltas; log()->get(LogLevel::Debug5) << "Reading a point buffer of " << count << " points." << std::endl; boost::uint64_t time = count; boost::uint32_t seed = static_cast<boost::uint32_t>(std::time(NULL)); for (PointId idx = 0; idx < count; ++idx) { double x; double y; double z; switch (m_mode) { case Random: x = Utils::random(m_minX, m_maxX); y = Utils::random(m_minY, m_maxY); z = Utils::random(m_minZ, m_maxZ); break; case Constant: x = m_minX; y = m_minY; z = m_minZ; break; case Ramp: x = m_minX + delX * idx; y = m_minY + delY * idx; z = m_minZ + delZ * idx; break; case Uniform: x = Utils::uniform(m_minX, m_maxX, seed++); y = Utils::uniform(m_minY, m_maxY, seed++); z = Utils::uniform(m_minZ, m_maxZ, seed++); break; case Normal: x = Utils::normal(m_mean_x, m_stdev_x, seed++); y = Utils::normal(m_mean_y, m_stdev_y, seed++); z = Utils::normal(m_mean_z, m_stdev_z, seed++); break; default: throw pdal_error("invalid mode in FauxReader"); break; } buf.setField(Dimension::Id::X, idx, x); buf.setField(Dimension::Id::Y, idx, y); buf.setField(Dimension::Id::Z, idx, z); buf.setField(Dimension::Id::OffsetTime, idx, m_time++); if (m_numReturns > 0) { buf.setField(Dimension::Id::ReturnNumber, idx, m_returnNum); buf.setField(Dimension::Id::NumberOfReturns, idx, m_numReturns); m_returnNum = (m_returnNum % m_numReturns) + 1; } } return count; }
void IteratorBase::fillUserBuffer(PointBuffer& user_buffer) { Schema const& user_schema = user_buffer.getSchema(); schema::index_by_index const& idx = user_schema.getDimensions().get<schema::index>(); boost::int32_t numOraclePoints = m_oracle_buffer->getNumPoints() - m_buffer_position; boost::int32_t numUserSpace = user_buffer.getCapacity() - user_buffer.getNumPoints(); boost::int32_t howManyThisRead = (std::min)(numUserSpace, numOraclePoints); if (numUserSpace < 0) { std::ostringstream oss; oss << "numUserSpace < 0! : " << numUserSpace; throw pdal_error(oss.str()); } if (numOraclePoints < 0) { std::ostringstream oss; oss << "numOraclePoints < 0! : " << numOraclePoints; throw pdal_error(oss.str()); } if (user_buffer.getNumPoints() + howManyThisRead > user_buffer.getCapacity()) { std::ostringstream oss; oss << "user_buffer.getNumPoints() + howManyThisRead == " << user_buffer.getNumPoints() + howManyThisRead << " but user_buffer.getCapacity() == " << user_buffer.getCapacity(); throw pdal_error(oss.str()); } PointBuffer::copyLikeDimensions(*m_oracle_buffer, user_buffer, *m_dimension_map, m_buffer_position, user_buffer.getNumPoints(), howManyThisRead); Schema const& src = m_oracle_buffer->getSchema(); Dimension const& src_x = src.getDimension("drivers.oci.reader.X"); Dimension const& src_y = src.getDimension("drivers.oci.reader.Y"); Dimension const& src_z = src.getDimension("drivers.oci.reader.Z"); Schema const& dst = user_buffer.getSchema(); Dimension const& dst_x = dst.getDimension("drivers.oci.reader.X"); Dimension const& dst_y = dst.getDimension("drivers.oci.reader.Y"); Dimension const& dst_z = dst.getDimension("drivers.oci.reader.Z"); bool bDifferentScales = (!pdal::Utils::compare_distance(dst_x.getNumericScale(), src_x.getNumericScale()) || !pdal::Utils::compare_distance(dst_y.getNumericScale(), src_y.getNumericScale()) || !pdal::Utils::compare_distance(dst_z.getNumericScale(), src_z.getNumericScale())); bool bDifferentOffsets = (!pdal::Utils::compare_distance(dst_x.getNumericOffset(), src_x.getNumericOffset()) || !pdal::Utils::compare_distance(dst_y.getNumericOffset(), src_y.getNumericOffset()) || !pdal::Utils::compare_distance(dst_z.getNumericOffset(), src_z.getNumericOffset())); bool bNormalizeXYZ = getReader().getOptions().getValueOrDefault<bool>("do_normalize_xyz", true); if ((bDifferentScales || bDifferentOffsets) && bNormalizeXYZ) { for (unsigned i = m_buffer_position; i < howManyThisRead; ++i) { double x = m_oracle_buffer->applyScaling(src_x, i); boost::int32_t xi = dst_x.removeScaling<boost::int32_t>(x); user_buffer.setField<boost::int32_t>(dst_x, user_buffer.getNumPoints()+i, xi); double y = m_oracle_buffer->applyScaling(src_y, i); boost::int32_t yi = dst_y.removeScaling<boost::int32_t>(y); user_buffer.setField<boost::int32_t>(dst_y, user_buffer.getNumPoints()+i, yi); double z = m_oracle_buffer->applyScaling(src_z, i); boost::int32_t zi = dst_z.removeScaling<boost::int32_t>(z); user_buffer.setField<boost::int32_t>(dst_z, user_buffer.getNumPoints()+i, zi); } } getReader().log()->get(logDEBUG2) << "IteratorBase::fillUserBuffer m_buffer_position: " << m_buffer_position << std::endl; if (numOraclePoints > numUserSpace) m_buffer_position = m_buffer_position + numUserSpace; else if (numOraclePoints < numUserSpace) m_buffer_position = 0; getReader().log()->get(logDEBUG2) << "IteratorBase::fillUserBuffer m_buffer_position: " << m_buffer_position << std::endl; bool bSetPointSourceId = getReader().getOptions().getValueOrDefault<bool>("populate_pointsourceid", false); if (bSetPointSourceId) { Dimension const* point_source_field = user_buffer.getSchema().getDimensionPtr("PointSourceId"); if (point_source_field) { for (boost::int32_t i = m_buffer_position; i < howManyThisRead; ++i) { assert(user_buffer.getNumPoints() + i < user_buffer.getCapacity()); if (point_source_field->getByteSize() == 2) user_buffer.setField(*point_source_field, user_buffer.getNumPoints() + i, static_cast<boost::uint16_t>(m_active_cloud_id)); else if (point_source_field->getByteSize() == 4) { user_buffer.setField(*point_source_field, user_buffer.getNumPoints() + i, m_active_cloud_id); } } } } user_buffer.setNumPoints(howManyThisRead + user_buffer.getNumPoints()); }
point_count_t TerrasolidReader::read(PointBuffer& data, point_count_t count) { count = std::min(count, getNumPoints() - m_index); uint8_t *buf = new uint8_t[m_size * count]; Utils::read_n(buf, *m_istream, m_size * count); //See https://www.terrasolid.com/download/tscan.pdf // This spec is awful, but it's something. // The scaling adjustments are different than what we used to do and // seem wrong (scaling the offset is odd), but that's what the document // says. // Also modified the fetch of time/color based on header flag (rather // than just not write the data into the buffer). PointId nextId = data.size(); while (!eof()) { uint8_t* p = buf + m_size * m_index; if (m_format == TERRASOLID_Format_1) { uint8_t classification = Utils::read_field<uint8_t>(p); data.setField(Dimension::Id::Classification, nextId, classification); uint8_t flight_line = Utils::read_field<uint8_t>(p); data.setField(Dimension::Id::PointSourceId, nextId, flight_line); uint16_t echo_int = Utils::read_field<uint16_t>(p); data.setField(Dimension::Id::ReturnNumber, nextId, echo_int); int32_t x = Utils::read_field<int32_t>(p); data.setField(Dimension::Id::X, nextId, (x - m_header->OrgX) / m_header->Units); int32_t y = Utils::read_field<int32_t>(p); data.setField(Dimension::Id::Y, nextId, (y - m_header->OrgY) / m_header->Units); int32_t z = Utils::read_field<int32_t>(p); data.setField(Dimension::Id::Z, nextId, (z - m_header->OrgZ) / m_header->Units); } if (m_format == TERRASOLID_Format_2) { int32_t x = Utils::read_field<int32_t>(p); data.setField(Dimension::Id::X, nextId, (x - m_header->OrgX) / m_header->Units); int32_t y = Utils::read_field<int32_t>(p); data.setField(Dimension::Id::Y, nextId, (y - m_header->OrgY) / m_header->Units); int32_t z = Utils::read_field<int32_t>(p); data.setField(Dimension::Id::Z, nextId, (z - m_header->OrgZ) / m_header->Units); uint8_t classification = Utils::read_field<uint8_t>(p); data.setField(Dimension::Id::Classification, nextId, classification); uint8_t return_number = Utils::read_field<uint8_t>(p); data.setField(Dimension::Id::ReturnNumber, nextId, return_number); uint8_t flag = Utils::read_field<uint8_t>(p); data.setField(Dimension::Id::Flag, nextId, flag); uint8_t mark = Utils::read_field<uint8_t>(p); data.setField(Dimension::Id::Mark, nextId, mark); uint16_t flight_line = Utils::read_field<uint16_t>(p); data.setField(Dimension::Id::PointSourceId, nextId, flight_line); uint16_t intensity = Utils::read_field<uint16_t>(p); data.setField(Dimension::Id::Intensity, nextId, intensity); } if (m_haveTime) { uint32_t t = Utils::read_field<uint32_t>(p); if (m_index == 0) m_baseTime = t; t -= m_baseTime; //Offset from the beginning of the read. //instead of GPS week. t /= 5; //5000ths of a second to milliseconds data.setField(Dimension::Id::OffsetTime, nextId, t); } if (m_haveColor) { uint8_t red = Utils::read_field<uint8_t>(p); data.setField(Dimension::Id::Red, nextId, red); uint8_t green = Utils::read_field<uint8_t>(p); data.setField(Dimension::Id::Green, nextId, green); uint8_t blue = Utils::read_field<uint8_t>(p); data.setField(Dimension::Id::Blue, nextId, blue); uint8_t alpha = Utils::read_field<uint8_t>(p); data.setField(Dimension::Id::Alpha, nextId, alpha); } nextId++; } delete[] buf; return count; }
point_count_t Reader::read(PointBuffer& buf, point_count_t count) { //All data we read for icebridge is currently 4 bytes wide, so // just allocate once and forget it. //This could be a huge allocation. Perhaps we should do something // in the icebridge handler? PointId startId = buf.size(); point_count_t remaining = m_hdf5Handler.getNumPoints() - m_index; count = std::min(count, remaining); std::unique_ptr<unsigned char> rawData(new unsigned char[count * sizeof(float)]); //Not loving the position-linked data, but fine for now. Dimension::IdList dims = getDefaultDimensions(); auto di = dims.begin(); for (auto ci = hdf5Columns.begin(); ci != hdf5Columns.end(); ++ci, ++di) { PointId nextId = startId; PointId idx = m_index; const hdf5::Hdf5ColumnData& column = *ci; try { m_hdf5Handler.getColumnEntries(rawData.get(), column.name, count, m_index); void *p = (void *)rawData.get(); // This is ugly but avoids a test in a tight loop. if (column.predType == H5::PredType::NATIVE_FLOAT) { // Offset time is in ms but icebridge stores in seconds. if (*di == Dimension::Id::OffsetTime) { float *fval = (float *)p; for (PointId i = 0; i < count; ++i) { buf.setField(*di, nextId++, *fval * 1000); fval++; } } else { float *fval = (float *)p; for (PointId i = 0; i < count; ++i) buf.setField(*di, nextId++, *fval++); } } else if (column.predType == H5::PredType::NATIVE_INT) { int32_t *ival = (int32_t *)p; for (PointId i = 0; i < count; ++i) buf.setField(*di, nextId++, *ival++); } } catch(...) { throw icebridge_error("Error fetching column data"); } } return count; }