[pdal] Migrating from libLAS

Andrew Bell andrew.bell.ia at gmail.com
Wed Sep 2 14:16:08 PDT 2015


Here's an example from the test code where I've removed all the stuff
that actually tests.  First we create a point table that's a subclass
of PointTable.  It only supports x, y, and z.  Then we register a
callback to be invoked each time a point is read (it does nothing
other than fetch the data).  I've also annotated the code.

TEST(PointTable, userView)
{
    class UserTable : public PointTable
    {

    // Local members to contain X, Y and Z
    private:
        double m_x;
        double m_y;
        double m_z;

    public:
        // addPoint() normally allocates memory for a point when
necessary and returns the PointId of the
        // latest point added.  In this case, we're not allocating
memory at all since we're not storing point data.
        // We return 0 as the PointId.
        PointId addPoint()
            { return 0; }

        // getPoint() provides raw access to point data.  Nobody
normally need call it, but it's there and we
        // redefine it to return NULL so that's it's clear that if you
DO call it, you've probably done something
        // wrong.
        char *getPoint(PointId idx)
            { return NULL; }

        // setField() gets called for data field as points are read.
The data is passed in based on the registered
        // type.  This type can be determined from the
Dimension::Detail if necessary, but X, Y and Z
        // are always registered as doubles, so we just cast.  Even if
they weren't stored as doubles,
        // we might well know the data type based on registration.
Note that if this function is called for
        // dimensions other than X, Y or Z, it's a noop.  Also note
that we ignore the PointId since we're not
        // storing points.
        // IMPORTANT NOTE:  The registered data type may be something
different than that read from a
        // file depending on what you're doing.  PDAL promotes type as
necessary to accommodate all the
        // stages in the pipeline.  HOWEVER, if you're simply reading
LAS, the type will be that registered
        // by the LasReader.  See LasReader::addDimensions().  If the
registration of a dimension doesn't
        // specify a type, the default type of the dimension is used
(see Dimension.hpp).
        void setField(const Dimension::Detail *d, PointId idx,
            const void *value)
        {
            if (d->id() == Dimension::Id::X)
               m_x = *(const double *)value;
            else if (d->id() == Dimension::Id::Y)
               m_y = *(const double *)value;
            else if (d->id() == Dimension::Id::Z)
               m_z = *(const double *)value;
        }

        // This is just the reverse of the above.
        void getField(const Dimension::Detail *d, PointId idx, void *value)
        {
            if (d->id() == Dimension::Id::X)
               *(double *)value = m_x;
            else if (d->id() == Dimension::Id::Y)
               *(double *)value = m_y;
            else if (d->id() == Dimension::Id::Z)
               *(double *)value = m_z;
        }
    };

    LasReader reader;

    Options opts;
    opts.add("filename", Support::datapath("las/simple.las"));

    reader.setOptions(opts);

    // This is a callback to be invoked when storage of a point is
complete (setField() has been called for all
    // fields in a point.  In this case we just read the data from the
PointTable through the provided PointView.
    auto readCb = [](PointView& customView, PointId id)
    {
        double x = customView.getFieldAs<double>(Dimension::Id::X, id);
        double y = customView.getFieldAs<double>(Dimension::Id::Y, id);
        double z = customView.getFieldAs<double>(Dimension::Id::Z, id);
    };

    // This sets the callback into the reader.  Note that you may not
need to use a callback at all with
    // a custom PointTable.  You may be able to do all the work you
need as the fields are stored.  But it may also
    // be easier to wait until the point is fully populated in order
to do your custom processing.
    reader.setReadCb(readCb);

    UserTable table;

    // Go...
    reader.prepare(table);
    reader.execute(table);
}

On Wed, Sep 2, 2015 at 2:47 PM, Vaclav Petras <wenzeslaus at gmail.com> wrote:
>
>
> On Wed, Sep 2, 2015 at 10:27 AM, Andrew Bell <andrew.bell.ia at gmail.com>
> wrote:
>>
>> On Wed, Sep 2, 2015 at 9:24 AM, Andrew Bell <andrew.bell.ia at gmail.com>
>> wrote:
>> > There is an example in PointViewTest.cpp called userView that shows
>> > how you might implement a custom PointTable and callback.  It
>> > allocates no memory other than a bit for each field.  There are lots
>> > of options on how you might do this.
>>
>> I take that back.  It looks incomplete.  I'll fix.
>
>
> This would be great I was looking at PointTableTest.cpp and I'm not able to
> make sense out of that. I wanted to run the tests but with make test I'm not
> sure if this one passed or not (I see only pdal_point_table_test).
>
> Thanks for the feedback on the transition guide. I incorporated your answers
> there. I'm almost finished with it. I just need to answer one more question
> (I'll send a separate email).
>
> Thanks,
> Vaclav



-- 
Andrew Bell
andrew.bell.ia at gmail.com


More information about the pdal mailing list