Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
    inline void clipEdge( bool closePolygon,
                          PointBuffer<Point> &points, PointBuffer<Point> &clippedPoints ) const
    {
        clippedPoints.reset();

        if ( points.size() < 2 )
        {
            if ( points.size() == 1 )
                clippedPoints.add( points[0] );
            return;
        }

        const Edge edge( d_clipRect.x(), d_clipRect.x() + d_clipRect.width(),
                         d_clipRect.y(), d_clipRect.y() + d_clipRect.height() );

        int lastPos, start;
        if ( closePolygon )
        {
            start = 0;
            lastPos = points.size() - 1;
        }
        else
        {
            start = 1;
            lastPos = 0;

            if ( edge.isInside( points[0] ) )
                clippedPoints.add( points[0] );
        }

        const uint nPoints = points.size();
        for ( uint i = start; i < nPoints; i++ )
        {
            const Point &p1 = points[i];
            const Point &p2 = points[lastPos];

            if ( edge.isInside( p1 ) )
            {
                if ( edge.isInside( p2 ) )
                {
                    clippedPoints.add( p1 );
                }
                else
                {
                    clippedPoints.add( edge.intersection( p1, p2 ) );
                    clippedPoints.add( p1 );
                }
            }
            else
            {
                if ( edge.isInside( p2 ) )
                {
                    clippedPoints.add( edge.intersection( p1, p2 ) );
                }
            }
            lastPos = i;
        }
    }
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
void Crop::crop(PointBuffer& input, PointBuffer& output)
{
    bool logOutput = (log()->getLevel() > LogLevel::Debug4);
    if (logOutput)
        log()->floatPrecision(8);

    for (PointId idx = 0; idx < input.size(); ++idx)
    {
        double x = input.getFieldAs<double>(Dimension::Id::X, idx);
        double y = input.getFieldAs<double>(Dimension::Id::Y, idx);
        double z = input.getFieldAs<double>(Dimension::Id::Z, idx);

        if (logOutput)
        {
            log()->floatPrecision(10);
            log()->get(LogLevel::Debug5) << "input: " << x << " y: " << y <<
                " z: " << z << std::endl;
        }

        if (m_poly.empty())
        {
            // We don't have a polygon, just a bounds. Filter on that
            // by itself.
            if (!m_cropOutside && m_bounds.contains(x, y, z))
                output.appendPoint(input, idx);
        }
#ifdef PDAL_HAVE_GEOS
        else
        {
            int ret(0);

            // precise filtering based on the geometry
            GEOSCoordSequence* coords =
                GEOSCoordSeq_create_r(m_geosEnvironment, 1, 3);
            if (!coords)
                throw pdal_error("unable to allocate coordinate sequence");
            ret = GEOSCoordSeq_setX_r(m_geosEnvironment, coords, 0, x);
            if (!ret)
                throw pdal_error("unable to set x for coordinate sequence");
            ret = GEOSCoordSeq_setY_r(m_geosEnvironment, coords, 0, y);
            if (!ret)
                throw pdal_error("unable to set y for coordinate sequence");
            ret = GEOSCoordSeq_setZ_r(m_geosEnvironment, coords, 0, z);
            if (!ret)
                throw pdal_error("unable to set z for coordinate sequence");

            GEOSGeometry* p = GEOSGeom_createPoint_r(m_geosEnvironment, coords);
            if (!p)
                throw pdal_error("unable to allocate candidate test point");

            if (static_cast<bool>(GEOSPreparedContains_r(m_geosEnvironment,
                m_geosPreparedGeometry, p)) != m_cropOutside)
                output.appendPoint(input, idx);
            GEOSGeom_destroy_r(m_geosEnvironment, p);
        }
#endif
    }
}
Ejemplo n.º 6
0
void BufferedInvocation::begin(PointBuffer& buffer)
{
    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);
        void *data = malloc(dd->size() * buffer.size());
        m_buffers.push_back(data);  // Hold pointer for deallocation
        char *p = (char *)data;
        for (PointId idx = 0; idx < buffer.size(); ++idx)
        {
            buffer.getFieldInternal(d, idx, (void *)p);
            p += dd->size();
        }
        std::string name = ctx.dimName(*di);
        insertArgument(name, (uint8_t *)data, dd->type(), buffer.size());
    }
}
Ejemplo n.º 7
0
point_count_t PgReader::read(PointBuffer& buffer, point_count_t count)
{
    if (eof())
        return 0;

    log()->get(LogLevel::Debug) << "readBufferImpl called with "
        "PointBuffer filled to " << buffer.size() << " points" <<
        std::endl;

    point_count_t totalNumRead = 0;
    while (totalNumRead < count)
    {
        if (m_patch.remaining == 0)
            if (!NextBuffer())
                return totalNumRead;
        PointId bufBegin = buffer.size();
        point_count_t numRead = readPgPatch(buffer, count - totalNumRead);
        PointId bufEnd = bufBegin + numRead;
        totalNumRead += numRead;
    }
    return totalNumRead;
}
Ejemplo n.º 8
0
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);
            }

        }
    }
}
Ejemplo n.º 9
0
point_count_t PgReader::readPgPatch(PointBuffer& buffer, point_count_t numPts)
{
    point_count_t numRemaining = m_patch.remaining;
    PointId nextId = buffer.size();
    point_count_t numRead = 0;

    size_t offset = ((m_patch.count - m_patch.remaining) * m_point_size);
    char *pos = (char *)(m_patch.binary.data() + offset);

    while (numRead < numPts && numRemaining > 0)
    {
        writePoint(buffer, nextId, pos);
        pos += m_point_size;
        numRemaining--;
        nextId++;
        numRead++;
    }
    m_patch.remaining = numRemaining;
    return numRead;
}
Ejemplo n.º 10
0
void Diff::checkPoints(const PointBuffer& source_data,
    const PointBuffer& candidate_data, ptree& errors)
{
    uint32_t i(0);
    uint32_t MAX_BADBYTES(20);
    uint32_t badbytes(0);

    // Both schemas have already been determined to be equal, so are the
    // same size and in the same order.
    Dimension::IdList const& sourceDims = source_data.dims();
    Dimension::IdList const& candidateDims = candidate_data.dims();

    char sbuf[8];
    char cbuf[8];
    for (PointId idx = 0; idx < source_data.size(); ++idx)
    {
        for (size_t d = 0; d < sourceDims.size(); ++d)
        {
            Dimension::Id::Enum sd = sourceDims[d];
            Dimension::Id::Enum cd = candidateDims[d];

            source_data.getRawField(sd, idx, (void *)sbuf);
            candidate_data.getRawField(cd, idx, (void *)cbuf);
            Dimension::Type::Enum t = Dimension::defaultType(cd);
            size_t size = Dimension::size(t);
            if (memcmp(sbuf, cbuf, size))
            {
                std::ostringstream oss;

                oss << "Point " << idx << " differs for dimension \"" <<
                    Dimension::name(sd) << "\" for source and candidate";
                errors.put<std::string>("data.error", oss.str());
                badbytes++;
            }
        }
        if (badbytes > MAX_BADBYTES )
            break;
    }
}
Ejemplo n.º 11
0
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;
}
Ejemplo n.º 12
0
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();
}
Ejemplo n.º 13
0
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;
}
Ejemplo n.º 14
0
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;
}
Ejemplo n.º 15
0
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;
}
Ejemplo n.º 16
0
void P2gWriter::write(const PointBuffer& buf)
{
    std::string z_name = getOptions().getValueOrDefault<std::string>("Z", "Z");


    for (point_count_t idx = 0; idx < buf.size(); idx++)
    {
        double x = buf.getFieldAs<double>(Dimension::Id::X, idx);
        double y = buf.getFieldAs<double>(Dimension::Id::Y, idx);
        double z = buf.getFieldAs<double>(Dimension::Id::Z, idx);
        m_coordinates.push_back(boost::tuple<double, double, double>(x, y, z));
    }

    m_bounds = buf.calculateBounds();

    m_GRID_SIZE_X = (int)(ceil((m_bounds.maxx - m_bounds.minx)/m_GRID_DIST_X)) + 1;
    m_GRID_SIZE_Y = (int)(ceil((m_bounds.maxy - m_bounds.miny)/m_GRID_DIST_Y)) + 1;

    log()->get(LogLevel::Debug) << "X grid size: " << m_GRID_SIZE_X << std::endl;
    log()->get(LogLevel::Debug) << "Y grid size: " << m_GRID_SIZE_Y << std::endl;


    log()->floatPrecision(6);
    log()->get(LogLevel::Debug) << "X grid distance: " << m_GRID_DIST_X << std::endl;
    log()->get(LogLevel::Debug) << "Y grid distance: " << m_GRID_DIST_Y << std::endl;
    log()->clearFloat();

    boost::scoped_ptr<OutCoreInterp> p(new OutCoreInterp(m_GRID_DIST_X,
                                       m_GRID_DIST_Y,
                                       m_GRID_SIZE_X,
                                       m_GRID_SIZE_Y,
                                       m_RADIUS_SQ,
                                       m_bounds.minx,
                                       m_bounds.maxx,
                                       m_bounds.miny,
                                       m_bounds.maxy,
                                       m_fill_window_size));
    m_interpolator.swap(p);

    if (m_interpolator->init() < 0)
    {
        throw p2g_error("unable to initialize interpolator");
    }

    int rc(0);

    std::vector<boost::tuple<double, double, double> >::const_iterator i;
    for (i = m_coordinates.begin(); i!= m_coordinates.end(); ++i)
    {
        double x = i->get<0>();
        double y = i->get<1>();
        x = x - m_bounds.minx;
        y = y - m_bounds.miny;

        rc = m_interpolator->update(x, y, i->get<2>());
        if (rc < 0)
        {
            throw p2g_error("interp->update() error while processing ");
        }
    }

    double adfGeoTransform[6];
    adfGeoTransform[0] = m_bounds.minx;
    adfGeoTransform[1] = m_GRID_DIST_X;
    adfGeoTransform[2] = 0.0;
    adfGeoTransform[3] = m_bounds.maxy;
    adfGeoTransform[4] = 0.0;
    adfGeoTransform[5] = -1 * m_GRID_DIST_Y;

    SpatialReference const& srs = getSpatialReference();

    if ((rc = m_interpolator->finish(const_cast<char*>(m_filename.c_str()), m_outputFormat, m_outputTypes, adfGeoTransform, srs.getWKT().c_str())) < 0)
    {
        throw p2g_error("interp->finish() error");
    }

    return;
}
Ejemplo n.º 17
0
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;
}