diff --git a/doc/development/writing-filter.rst b/doc/development/writing-filter.rst index a197083dc1..a79797213a 100644 --- a/doc/development/writing-filter.rst +++ b/doc/development/writing-filter.rst @@ -73,16 +73,14 @@ PDAL requires that filter names always begin with ``filters.``, and end with a string that uniquely identifies the filter. The description will be displayed to users of the PDAL CLI (``pdal --drivers``). -Next, we pass the following to the ``CREATE_STATIC_PLUGIN`` macro, in order: -PDAL plugin ABI major version, PDAL plugin ABI minor version, filter class -name, stage type (``Filter``), and our ``PluginInfo`` struct. +Next, we pass the following to the ``CREATE_STATIC_STAGE`` macro, passin in the name of the stage and the ``PluginInfo`` struct. .. literalinclude:: ../../examples/writing-filter/MyFilter.cpp :language: cpp :lines: 19 -To create a shared plugin, we simply change ``CREATE_STATIC_PLUGIN`` to -``CREATE_SHARED_PLUGIN``. +To create a shared stage, we simply change ``CREATE_STATIC_STAGE`` to +``CREATE_SHARED_STAGE``. Finally, we implement a method to get the plugin name, which is primarily used by the PDAL CLI when using the ``--drivers`` or ``--options`` arguments. @@ -130,32 +128,6 @@ points. We suggest you take a closer look at our existing filters to get an idea of the power of the ``Filter`` stage and inspiration for your own filters! -StageFactory -............................................................................... - -As of this writing, users must also make a couple of changes to -``StageFactory.cpp`` to properly register static plugins only (this is not -required for shared plugins). It is our goal to eventually remove this -requirement to further streamline development of add-on plugins. - -.. note:: - - Modification of StageFactory is required for STATIC plugins only. - Dynamic plugins are registered at runtime. - -First, add the following line to the beginning of ``StageFactory.cpp`` -(adjusting the path and filename as necessary). - -.. code-block:: cpp - - #include - -Next, add the following line of code to the ``StageFactory`` constructor. - -.. code-block:: cpp - - PluginManager::initializePlugin(MyFilter_InitPlugin); - Compilation ............................................................................... diff --git a/doc/development/writing-kernel.rst b/doc/development/writing-kernel.rst index 1e53bb9ac8..ac2e6d5872 100644 --- a/doc/development/writing-kernel.rst +++ b/doc/development/writing-kernel.rst @@ -21,12 +21,11 @@ First, we provide a full listing of the kernel header. :language: cpp :linenos: -As with other plugins, the MyKernel class needs to have the following three -methods declared for the plugin interface to be satisfied: +As with other plugins, the MyKernel class needs to return a name. .. literalinclude:: ../../examples/writing-kernel/MyKernel.hpp :language: cpp - :lines: 16-18 + :lines: 17 The source @@ -39,67 +38,33 @@ Again, we start with a full listing of the kernel source. :linenos: In your kernel implementation, you will use a macro defined in pdal_macros. -This macro registers the plugin with the Kernel factory. It is -only required by plugins. +This macro registers the plugin with the PluginManager. .. literalinclude:: ../../examples/writing-kernel/MyKernel.cpp :language: cpp - :lines: 25-26 - -.. note:: - - A static plugin macro can also be used to integrate the kernel with the - main code. This will not be described here. Using this as a shared plugin - will be described later. + :lines: 23 To build up a processing pipeline in this example, we need to create two -objects: the :cpp:class:`pdal::PointTable` and the -:cpp:class:`pdal::StageFactory`. The latter is used to create the various -stages that will be used within the kernel. - -.. literalinclude:: ../../examples/writing-kernel/MyKernel.cpp - :language: cpp - :lines: 39-40 - -The :cpp:class:`pdal::Reader` is created from the -:cpp:class:`pdal::StageFactory`, and is specified by the stage name, in this -case an LAS reader. For brevity, we provide the reader a single option, the -filename of the file to be read. - -.. literalinclude:: ../../examples/writing-kernel/MyKernel.cpp - :language: cpp - :lines: 42-45 - -The :cpp:class:`pdal::Filter` is also created from the -:cpp:class:`pdal::StageFactory`. Here, we create a decimation filter that will -pass every tenth point to subsequent stages. We also specify the input to this -stage, which is the reader. - -.. literalinclude:: ../../examples/writing-kernel/MyKernel.cpp - :language: cpp - :lines: 47-51 - -Finally, the :cpp:class:`pdal::Writer` is created from the -:cpp:class:`pdal::StageFactory`. This :ref:`writers.text`, takes as input the previous -stage (the :ref:`filters.decimation`) and the output filename as its sole option. +objects: the :cpp:class:`pdal::PointTable`. .. literalinclude:: ../../examples/writing-kernel/MyKernel.cpp :language: cpp - :lines: 53-57 + :lines: 35-53 -The final two steps are to prepare and execute the pipeline. This is achieved -by calling prepare and execute on the final stage. +To implement the actual kernel logic we implement execute(). In this case, +the kernel reads a las file, decimates the data (eliminates some points) and +writes the result to a text file. The base kernel class provides functions +(makeReader, makeFilter, makeWriter) to create stages with options as desired. +The pipeline that has been created can be run by preparing and executing the +last stage in the pipeline. -.. literalinclude:: ../../examples/writing-kernel/MyKernel.cpp - :language: cpp - :lines: 58-59 When compiled, a dynamic library file will be created; in this case, ``libpdal_plugin_kernel_mykernel.dylib`` Put this file in whatever directory ``PDAL_DRIVER_PATH`` is pointing to. Then, -if you run ``pdal --help``, you should see ``mykernel`` listed in the possible -commands. +if you run ``pdal --drivers``, you should see ``mykernel`` listed in the +possible commands. To run this kernel, you would use ``pdal mykernel -i -o ``. diff --git a/doc/development/writing-reader.rst b/doc/development/writing-reader.rst index 63d89d01a5..c58205b28c 100644 --- a/doc/development/writing-reader.rst +++ b/doc/development/writing-reader.rst @@ -21,19 +21,9 @@ First, we provide a full listing of the reader header. :language: cpp :linenos: -In your MyReader class, you will declare the necessary methods and variables -needed to make the reader work and meet the plugin specifications. - -.. literalinclude:: ../../examples/writing-reader/MyReader.hpp - :language: cpp - :lines: 16-18 - :linenos: - -These methods are required to fulfill the specs for defining a new plugin. - .. literalinclude:: ../../examples/writing-reader/MyReader.hpp :language: cpp - :lines: 21-23 + :lines:18-20 :linenos: ``m_stream`` is used to process the input, while ``m_index`` is used to track @@ -42,7 +32,7 @@ be described later. .. literalinclude:: ../../examples/writing-reader/MyReader.hpp :language: cpp - :lines: 27-31 + :lines: 22-26 :linenos: Various other override methods for the stage. There are a few others that @@ -62,26 +52,17 @@ Again, we start with a full listing of the reader source. :language: cpp :linenos: -In your reader implementation, you will use a macro defined in pdal_macros. - -.. literalinclude:: ../../examples/writing-reader/MyReader.cpp - :language: cpp - :lines: 9-12 - :linenos: - -This macro registers the plugin with the PDAL code. In this case, we are -declaring this as a SHARED plugin, meaning that it will be located external -to the main PDAL installation. The macro is supplied with a version number -(major and minor), the class of the plugin, the parent class (in this case, -to identify it as a reader), and an object with information. This information -includes the name of the plugin, a description, and a link to documentation. - -Creating STATIC plugins requires a few more steps which will not be covered -in this tutorial. +In your reader implementation, you will use a macro to create the plugin. +This macro registers the plugin with the PDAL PluginManager. In this case, +we are declaring this as a SHARED stage, meaning that it will be loaded at +runtime instead of being linked +to the main PDAL installation. The macro is supplied with the class name +of the plugin and a PluginInfo object. The PluginInfo objection includes +the name of the plugin, a description, and a link to documentation. .. literalinclude:: ../../examples/writing-reader/MyReader.cpp :language: cpp - :lines: 18-21 + :lines: 8-15 :linenos: This method will process a options for the reader. In this @@ -94,7 +75,7 @@ stage. .. literalinclude:: ../../examples/writing-reader/MyReader.cpp :language: cpp - :lines: 23-29 + :lines: 19-22 :linenos: This method registers the various dimensions the reader will use. In our case, @@ -103,7 +84,7 @@ dimension MyData. .. literalinclude:: ../../examples/writing-reader/MyReader.cpp :language: cpp - :lines: 31-35 + :lines: 24-30 :linenos: This method is called when the Reader is ready for use. It will only be @@ -112,21 +93,20 @@ processed. .. literalinclude:: ../../examples/writing-reader/MyReader.cpp :language: cpp - :lines: 37-50 + :lines: 32-36 :linenos: This is a helper function, which will convert a string value into the type specified when it's called. In our example, it will be used to convert strings to doubles when reading from the input stream. - .. literalinclude:: ../../examples/writing-reader/MyReader.cpp :language: cpp - :lines: 53 + :lines: 38-52 :linenos: This method is the main processing method for the reader. It takes a -pointer to a Point View which we will build as we read from the file. We +pointer to a PointView which we will build as we read from the file. We initialize some variables as well, and then reset the input stream with the filename used for the reader. Note that in other readers, the contents of this method could be very different depending on the format of the file @@ -135,7 +115,7 @@ PointView object. .. literalinclude:: ../../examples/writing-reader/MyReader.cpp :language: cpp - :lines: 62-64 + :lines: 57-62 :linenos: In preparation for reading the file, we prepare to skip some header lines. In @@ -143,7 +123,7 @@ our case, the header is only a single line. .. literalinclude:: ../../examples/writing-reader/MyReader.cpp :language: cpp - :lines: 65-70 + :lines: 64-66 :linenos: Here we begin our main loop. In our example file, the first line is a header, @@ -151,10 +131,9 @@ and each line thereafter is a single point. If the file had a different format the method of looping and reading would have to change as appropriate. We make sure we are skipping the header lines here before moving on. - .. literalinclude:: ../../examples/writing-reader/MyReader.cpp :language: cpp - :lines: 73-82 + :lines: 67-72 :linenos: Here we take the line we read in the for block header, split it, and make sure @@ -162,7 +141,7 @@ that we have the proper number of fields. .. literalinclude:: ../../examples/writing-reader/MyReader.cpp :language: cpp - :lines: 84-97 + :lines: 75-84 :linenos: Here we take the values we read and put them into the PointView object. The @@ -177,7 +156,7 @@ each iteration of the loop), and the dimension value. .. literalinclude:: ../../examples/writing-reader/MyReader.cpp :language: cpp - :lines: 99-101 + :lines: 86-99 :linenos: Finally, we increment the nextId and make a call into the progress callback @@ -186,9 +165,19 @@ and number read, and return that value as the number of points read. This could differ in cases where we read multiple streams, but that won't be covered here. +.. literalinclude:: ../../examples/writing-reader/MyReader.cpp + :language: cpp + :lines: 101-108 + :linenos: + When the read method is finished, the done method is called for any cleanup. In this case, we simply make sure the stream is reset. +.. literalinclude:: ../../examples/writing-reader/MyReader.cpp + :language: cpp + :lines: 111-114 + :linenos: + Compiling and Usage ------------------------------------------------------------------------------- diff --git a/doc/development/writing-writer.rst b/doc/development/writing-writer.rst index 373c6a495f..2de2db4deb 100644 --- a/doc/development/writing-writer.rst +++ b/doc/development/writing-writer.rst @@ -34,21 +34,20 @@ later on. .. literalinclude:: ../../examples/writing-writer/MyWriter.hpp :language: cpp - :lines: 19-21 - -These three methods are required to fulfill the specs for defining a new plugin. + :lines: 19 +Every stage must return a unique name. .. literalinclude:: ../../examples/writing-writer/MyWriter.hpp :language: cpp - :lines: 24-28 + :lines: 22-26 These methods are used during various phases of the pipeline. There are also more methods, which will not be covered in this tutorial. .. literalinclude:: ../../examples/writing-writer/MyWriter.hpp :language: cpp - :lines: 30-36 + :lines: 28-34 These are variables our Writer will use, such as the file to write to, the newline character to use, the name of the data field to use to write the MyData @@ -72,21 +71,17 @@ which is included in the include chain we are using. .. literalinclude:: ../../examples/writing-writer/MyWriter.cpp :language: cpp - :lines: 10-15 + :lines: 9-16 Here we define a struct with information regarding the writer, such as the name, a description, and a path to documentation. We then use the macro -to create a SHARED plugin, which means it will be external to the main PDAL -installation. When using the macro, we specify the version (major and minor), -the class of the plugin, the class of the parent (Writer, in this case), and -the struct we defined earlier. - -Creating STATIC plugins, which would be part of the main PDAL installation, is -also possible, but requires some extra steps and will not be covered here. +to create a SHARED stage, which means it will be external to the main PDAL +installation. When using the macro, we specify the name of the Stage and +the PluginInfo struct we defined earlier. .. literalinclude:: ../../examples/writing-writer/MyWriter.cpp :language: cpp - :lines: 19-30 + :lines: 20-31 :linenos: This struct is used for helping with the FileStreamPtr for cleanup. @@ -101,14 +96,13 @@ private variables. .. literalinclude:: ../../examples/writing-writer/MyWriter.cpp :language: cpp - :lines: 47-63 + :lines: 42-53 This method initializes our file stream in preparation for writing. - .. literalinclude:: ../../examples/writing-writer/MyWriter.cpp :language: cpp - :lines: 55-70 + :lines: 56-72 :linenos: The ready method is used to prepare the writer for any number of PointViews that @@ -118,7 +112,7 @@ and writing the header of the output file. .. literalinclude:: ../../examples/writing-writer/MyWriter.cpp :language: cpp - :lines: 74-90 + :lines: 75-91 :linenos: This method is the main method for writing. In our case, we are writing a very @@ -138,7 +132,7 @@ to the output stream. .. literalinclude:: ../../examples/writing-writer/MyWriter.cpp :language: cpp - :lines: 93-96 + :lines: 94-97 :linenos: This method is called when the writing is done. In this case, it simply cleans diff --git a/examples/writing-kernel/MyKernel.cpp b/examples/writing-kernel/MyKernel.cpp index 7438034a88..652d33f3e4 100644 --- a/examples/writing-kernel/MyKernel.cpp +++ b/examples/writing-kernel/MyKernel.cpp @@ -13,13 +13,14 @@ namespace pdal { - static PluginInfo const s_info { + static PluginInfo const s_info + { "kernels.mykernel", "MyKernel", "http://link/to/documentation" }; - CREATE_SHARED_PLUGIN(1, 0, MyKernel, Kernel, s_info); + CREATE_SHARED_KERNEL(MyKernel, s_info); std::string MyKernel::getName() const { return s_info.name; } MyKernel::MyKernel() : Kernel() diff --git a/examples/writing-reader/MyReader.cpp b/examples/writing-reader/MyReader.cpp index 789ef1da93..5896075999 100644 --- a/examples/writing-reader/MyReader.cpp +++ b/examples/writing-reader/MyReader.cpp @@ -5,12 +5,14 @@ namespace pdal { - static PluginInfo const s_info = PluginInfo( + static PluginInfo const s_info + { "readers.myreader", "My Awesome Reader", - "http://link/to/documentation" ); + "http://link/to/documentation" + }; - CREATE_SHARED_PLUGIN(1, 0, MyReader, Reader, s_info) + CREATE_SHARED_STAGE(MyReader, s_info) std::string MyReader::getName() const { return s_info.name; } @@ -41,7 +43,8 @@ namespace pdal if (!bConverted) { std::stringstream oss; - oss << "Unable to convert " << name << ", " << s[fieldno] << ", to double"; + oss << "Unable to convert " << name << ", " << s[fieldno] << + ", to double"; throw pdal_error(oss.str()); } diff --git a/examples/writing-writer/MyWriter.cpp b/examples/writing-writer/MyWriter.cpp index 1fb1f3b792..7097e6ee22 100644 --- a/examples/writing-writer/MyWriter.cpp +++ b/examples/writing-writer/MyWriter.cpp @@ -6,12 +6,14 @@ namespace pdal { - static PluginInfo const s_info = PluginInfo( + static PluginInfo const s_info + { "writers.mywriter", "My Awesome Writer", - "http://path/to/documentation" ); + "http://path/to/documentation" + }; - CREATE_SHARED_PLUGIN(1, 0, MyWriter, Writer, s_info); + CREATE_SHARED_STAGE(MyWriter, s_info); std::string MyWriter::getName() const { return s_info.name; } @@ -28,7 +30,6 @@ namespace pdal } }; - void MyWriter::addArgs(ProgramArgs& args) { // setPositional() Makes the argument required. @@ -51,6 +52,7 @@ namespace pdal } } + void MyWriter::ready(PointTableRef table) { m_stream->precision(m_precision); @@ -93,5 +95,4 @@ namespace pdal { m_stream.reset(); } - }