[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