From 39ea55f0733333b7ccc899918ba9fafe03921eb2 Mon Sep 17 00:00:00 2001 From: Howard Butler Date: Wed, 26 Oct 2016 12:40:45 -0500 Subject: [PATCH] add a dimensions page. Update the tutorials to match current source code --- doc/conf.py | 21 +++++ doc/dimensions.rst | 15 ++++ doc/index.rst | 6 ++ doc/references.rst | 20 +++++ doc/stages/filters.dartsample.rst | 5 -- doc/stages/filters.ground.rst | 2 - doc/stages/filters.outlier.rst | 25 +++--- doc/stages/filters.pmf.rst | 2 - doc/stages/filters.sample.rst | 5 -- doc/stages/filters.statisticaloutlier.rst | 2 +- doc/stages/readers.rst | 2 +- doc/tutorial/writing-filter.rst | 100 ++++++++++++++++------ doc/tutorial/writing-kernel.rst | 2 +- doc/tutorial/writing-reader.rst | 95 ++++++++++++-------- doc/tutorial/writing-writer.rst | 40 +++++---- 15 files changed, 231 insertions(+), 111 deletions(-) create mode 100644 doc/dimensions.rst create mode 100644 doc/references.rst diff --git a/doc/conf.py b/doc/conf.py index 5b8d6b2cee..041b27aac9 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -21,6 +21,27 @@ year = datetime.datetime.now().year + +def process_dimensions(): + import json, csv + + data = open('../src/Dimension.json','rb').read() + + data = json.loads(data)['dimensions'] + + output = [] + for dim in data: + output.append([dim['name'], dim['type'], dim['description']]) + + output = sorted(output,key=lambda x: x[0]) + + with open('dimension-table.csv','wb') as fp: + a = csv.writer(fp, delimiter=',', quotechar='"', quoting=csv.QUOTE_ALL) + a.writerows(output) + + +process_dimensions() + # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. diff --git a/doc/dimensions.rst b/doc/dimensions.rst new file mode 100644 index 0000000000..e83827ef5e --- /dev/null +++ b/doc/dimensions.rst @@ -0,0 +1,15 @@ +.. _dimensions: + +=============================================================================== +Dimensions +=============================================================================== + +PDAL dimensions describe the combination of data's type, size, and meaning. The +following table provides a list of known dimension names you can use in +:ref:`filters`, :ref:`writers`, and :ref:`readers` descriptions. + + +.. csv-table:: + :file: ./dimension-table.csv + :header: "Name", "Type", "Description" + :widths: 10, 5, 40 diff --git a/doc/index.rst b/doc/index.rst index 7f7b42b773..d5788ab043 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -81,6 +81,7 @@ Drivers stages/readers stages/writers stages/filters + dimensions Tutorials -------------------------------------------------------------------------------- @@ -110,6 +111,11 @@ Development faq copyright +.. toctree:: + :includehidden: + + references + diff --git a/doc/references.rst b/doc/references.rst new file mode 100644 index 0000000000..d9adcbdf0a --- /dev/null +++ b/doc/references.rst @@ -0,0 +1,20 @@ +.. _references: + +****************************************************************************** +References +****************************************************************************** + +.. index:: References + + +.. [Cook1986] Cook, Robert L. "Stochastic sampling in computer graphics." *ACM Transactions on Graphics (TOG)* 5.1 (1986): 51-72. + +.. [Dippe1985] Dippé, Mark AZ, and Erling Henry Wold. "Antialiasing through stochastic sampling." *ACM Siggraph Computer Graphics* 19.3 (1985): 69-78. + +.. [Mesh2009] ALoopingIcon. "Meshing Point Clouds." *MESHLAB STUFF*. n.p., 7 Sept. 2009. Web. 13 Nov. 2015. + +.. [Rusu2008] Rusu, Radu Bogdan, et al. "Towards 3D point cloud based object maps for household environments." Robotics and Autonomous Systems 56.11 (2008): 927-941. + +.. [Zhang2003] Zhang, Keqi, et al. "A progressive morphological filter for removing nonground measurements from airborne LIDAR data." Geoscience and Remote Sensing, IEEE Transactions on 41.4 (2003): 872-882. + + diff --git a/doc/stages/filters.dartsample.rst b/doc/stages/filters.dartsample.rst index e73988074d..ff1b7a2470 100644 --- a/doc/stages/filters.dartsample.rst +++ b/doc/stages/filters.dartsample.rst @@ -17,11 +17,6 @@ is kept in tact (the same cannot be said for :ref:`filters.voxelgrid`). :ref:`filters.decimation` and :ref:`filters.voxelgrid` also perform decimation. -.. [Cook1986] Cook, Robert L. "Stochastic sampling in computer graphics." *ACM Transactions on Graphics (TOG)* 5.1 (1986): 51-72. - -.. [Dippe1985] Dippé, Mark AZ, and Erling Henry Wold. "Antialiasing through stochastic sampling." *ACM Siggraph Computer Graphics* 19.3 (1985): 69-78. - -.. [Mesh2009] ALoopingIcon. "Meshing Point Clouds." *MESHLAB STUFF*. n.p., 7 Sept. 2009. Web. 13 Nov. 2015. Options ------------------------------------------------------------------------------- diff --git a/doc/stages/filters.ground.rst b/doc/stages/filters.ground.rst index d0c871120f..cea7d92f3a 100644 --- a/doc/stages/filters.ground.rst +++ b/doc/stages/filters.ground.rst @@ -9,8 +9,6 @@ ProgressiveMorphologicalFilter algorithm. ProgressiveMorphologicalFilter is an implementation of the method described in [Zhang2003]_. -.. [Zhang2003] Zhang, Keqi, et al. "A progressive morphological filter for removing nonground measurements from airborne LIDAR data." Geoscience and Remote Sensing, IEEE Transactions on 41.4 (2003): 872-882. - .. _`PCL`: http://www.pointclouds.org diff --git a/doc/stages/filters.outlier.rst b/doc/stages/filters.outlier.rst index 7f71a9e891..3367ad016e 100644 --- a/doc/stages/filters.outlier.rst +++ b/doc/stages/filters.outlier.rst @@ -15,30 +15,30 @@ The default method for identifying outlier points is the statistical outlier met In the first pass, for each point :math:`p_i` in the input ``PointView``, compute the mean distance :math:`\mu_i` to each of the :math:`k` nearest neighbors (where :math:`k` is configurable and specified by ``mean_k``). Then, .. math:: - + \overline{\mu} = \frac{1}{N} \sum_{i=1}^N \mu_i - + .. math:: - + \sigma = \sqrt{\frac{1}{N-1} \sum_{i=1}^N (\mu_i - \overline{\mu})^2} A global mean :math:`\overline{\mu}` of these mean distances is then computed along with the standard deviation :math:`\sigma`. From this, the threshold is computed as .. math:: - + t = \mu + m\sigma - + where :math:`m` is a user-defined multiplier specified by ``multiplier``. We now interate over the pre-computed mean distances :math:`\mu_i` and compare to computed threshold value. If :math:`\mu_i` is greater than the threshold, it is marked as an outlier. .. math:: - + outlier_i = \begin{cases} \text{true,} \phantom{false,} \text{if } \mu_i >= t \\ \text{false,} \phantom{true,} \text{otherwise} \\ \end{cases} - + The ``classify`` and ``extract`` options are used to control whether outlier points are labeled as noise, or removed from the output ``PointView`` completely. @@ -59,7 +59,6 @@ After outlier removal, the noise points are removed. See [Rusu2008]_ for more information. -.. [Rusu2008] Rusu, Radu Bogdan, et al. "Towards 3D point cloud based object maps for household environments." Robotics and Autonomous Systems 56.11 (2008): 927-941. Example ................................................................................ @@ -81,7 +80,7 @@ of the 12 nearest neighbors is below the computed threshold. "output.las" ] } - + Radius Method ------------------------------------------------------------------------------- @@ -91,12 +90,12 @@ number of neighboring points :math:`k_i` within radius :math:`r` (specified by of neighbors specified by ``min_k``, it is marked as an outlier. .. math:: - + outlier_i = \begin{cases} \text{true,} \phantom{false,} \text{if } k_i < k_{min} \\ \text{false,} \phantom{true,} \text{otherwise} \\ \end{cases} - + The ``classify`` and ``extract`` options are used to control whether outlier points are labeled as noise, or removed from the output ``PointView`` completely. @@ -121,7 +120,7 @@ four neighbors within a radius of 1.0. "output.las" ] } - + Options ------------------------------------------------------------------------------- @@ -139,7 +138,7 @@ mean_k multiplier Standard deviation threshold (statistical method only). [Default: **2.0**] - + classify Apply classification value of 18 (LAS high noise)? [Default: **true**] diff --git a/doc/stages/filters.pmf.rst b/doc/stages/filters.pmf.rst index a5bccef99a..7b2f17efa6 100644 --- a/doc/stages/filters.pmf.rst +++ b/doc/stages/filters.pmf.rst @@ -7,8 +7,6 @@ The Progressive Morphological Filter (PMF) is a method of segmenting ground and non-ground returns. This filter is an implementation of the method described in [Zhang2003]_. -.. [Zhang2003] Zhang, Keqi, et al. "A progressive morphological filter for removing nonground measurements from airborne LIDAR data." Geoscience and Remote Sensing, IEEE Transactions on 41.4 (2003): 872-882. - Example ------- diff --git a/doc/stages/filters.sample.rst b/doc/stages/filters.sample.rst index 6113dc634f..dc97df0c9c 100644 --- a/doc/stages/filters.sample.rst +++ b/doc/stages/filters.sample.rst @@ -21,11 +21,6 @@ is kept in tact (the same cannot be said for :ref:`filters.voxelgrid`). :ref:`filters.decimation` and :ref:`filters.voxelgrid` also perform decimation. -.. [Cook1986] Cook, Robert L. "Stochastic sampling in computer graphics." *ACM Transactions on Graphics (TOG)* 5.1 (1986): 51-72. - -.. [Dippe1985] Dippé, Mark AZ, and Erling Henry Wold. "Antialiasing through stochastic sampling." *ACM Siggraph Computer Graphics* 19.3 (1985): 69-78. - -.. [Mesh2009] ALoopingIcon. "Meshing Point Clouds." *MESHLAB STUFF*. n.p., 7 Sept. 2009. Web. 13 Nov. 2015. Options ------------------------------------------------------------------------------- diff --git a/doc/stages/filters.statisticaloutlier.rst b/doc/stages/filters.statisticaloutlier.rst index adf5aa3297..1cfe77eb4f 100644 --- a/doc/stages/filters.statisticaloutlier.rst +++ b/doc/stages/filters.statisticaloutlier.rst @@ -31,7 +31,7 @@ but a value other than 2 can be chosen using :math:`\tt multiplier`. See [Rusu2008]_ for more information. -.. [Rusu2008] Rusu, Radu Bogdan, et al. "Towards 3D point cloud based object maps for household environments." Robotics and Autonomous Systems 56.11 (2008): 927-941. + .. _`PCL`: http://www.pointclouds.org diff --git a/doc/stages/readers.rst b/doc/stages/readers.rst index c56ffce956..f77a453537 100644 --- a/doc/stages/readers.rst +++ b/doc/stages/readers.rst @@ -9,7 +9,7 @@ a network service like :ref:`readers.greyhound`. .. note:: - Readers provide :cpp:class:`pdal::Dimension` to :ref:`pipeline`. PDAL attempts + Readers provide :ref:`dimensions` to :ref:`pipeline`. PDAL attempts to normalize common dimension types, like X, Y, Z, or Intensity, which are often found in LiDAR point clouds. Not all dimension types need to be fixed, however. Database drivers typically return unstructured lists of dimensions. diff --git a/doc/tutorial/writing-filter.rst b/doc/tutorial/writing-filter.rst index 0e9d0266c5..68b74a56ea 100644 --- a/doc/tutorial/writing-filter.rst +++ b/doc/tutorial/writing-filter.rst @@ -6,7 +6,7 @@ Writing a filter :Author: Bradley Chambers :Contact: brad.chambers@gmail.com -:Date: 11/11/2015 +:Date: 10/26/2016 PDAL can be extended through the development of filter functions. @@ -16,9 +16,16 @@ PDAL can be extended through the development of filter functions. For more on filters and their role in PDAL, please refer to :ref:`overview`. -Every filter stage in PDAL is implemented as a plugin (sometimes referred to as a "driver"). Filters native to PDAL, such as :ref:`filters.ferry`, are implemented as _static_ filters and are statically linked into the PDAL library. Filters that require extra/optional dependencies, or are external to the core PDAL codebase altogether, such as :ref:`filters.ground`, are implemented as _shared_ filters, and are built as individual shared libraries, discoverable by PDAL at runtime. +Every filter stage in PDAL is implemented as a plugin (sometimes referred to as +a "driver"). Filters native to PDAL, such as :ref:`filters.ferry`, are +implemented as _static_ filters and are statically linked into the PDAL +library. Filters that require extra/optional dependencies, or are external to +the core PDAL codebase altogether, such as :ref:`filters.ground`, are +implemented as _shared_ filters, and are built as individual shared libraries, +discoverable by PDAL at runtime. -In this tutorial, we will give a brief example of a filter, with notes on how to make it static or shared. +In this tutorial, we will give a brief example of a filter, with notes on how +to make it static or shared. The header @@ -28,14 +35,18 @@ First, we provide a full listing of the filter header. .. literalinclude:: ../../examples/writing-filter/MyFilter.hpp :language: cpp + :linenos: -This header should be relatively straightforward, but we will point out three methods that must be declared for the plugin interface to be satisfied. +This header should be relatively straightforward, but we will point out three +methods that must be declared for the plugin interface to be satisfied. .. literalinclude:: ../../examples/writing-filter/MyFilter.hpp :language: cpp :lines: 23-25 -In many instances, you should be able to copy this header template verbatim, changing only the filter class name, includes, and member functions/variables as required by your implementation. +In many instances, you should be able to copy this header template verbatim, +changing only the filter class name, includes, and member functions/variables +as required by your implementation. The source ............................................................................... @@ -44,63 +55,96 @@ Again, we start with a full listing of the filter source. .. literalinclude:: ../../examples/writing-filter/MyFilter.cpp :language: cpp + :linenos: -For your filter to be available to PDAL at runtime, it must adhere to the PDAL plugin interface. As a convenience, we provide the macros in ``pdal_macros.hpp`` to do just this. +For your filter to be available to PDAL at runtime, it must adhere to the PDAL +plugin interface. As a convenience, we provide the macros in +``pdal_macros.hpp`` to do just this. -We begin by creating a ``PluginInfo`` struct containing three identifying elements - the filter name, description, and a link to documentation. +We begin by creating a ``PluginInfo`` struct containing three identifying +elements - the filter name, description, and a link to documentation. .. literalinclude:: ../../examples/writing-filter/MyFilter.cpp :language: cpp - :lines: 14-16 + :lines: 15-18 + :linenos: -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``). +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_PLUGIN`` macro, in order: +PDAL plugin ABI major version, PDAL plugin ABI minor version, filter class +name, stage type (``Filter``), and our ``PluginInfo`` struct. .. literalinclude:: ../../examples/writing-filter/MyFilter.cpp :language: cpp - :lines: 18 + :lines: 19 -To create a shared plugin, we simply change ``CREATE_STATIC_PLUGIN`` to ``CREATE_SHARED_PLUGIN``. +To create a shared plugin, we simply change ``CREATE_STATIC_PLUGIN`` to +``CREATE_SHARED_PLUGIN``. -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. +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. .. literalinclude:: ../../examples/writing-filter/MyFilter.cpp :language: cpp - :lines: 20-23 + :lines: 21-24 + :linenos: -Now that the filter has implemented the proper plugin interface, we will begin to implement some methods that actually implement the filter. First, ``getDefaultOptions()`` is used to advertise those options that the filter provides. Within PDAL, this is primarily used as a means of displaying options via the PDAL CLI with the ``--options`` argument. It provides the user with the option names, descriptions, and default values. +Now that the filter has implemented the proper plugin interface, we will begin +to implement some methods that actually implement the filter. First, +``getDefaultOptions()`` is used to advertise those options that the filter +provides. Within PDAL, this is primarily used as a means of displaying options +via the PDAL CLI with the ``--options`` argument. It provides the user with the +option names, descriptions, and default values. .. literalinclude:: ../../examples/writing-filter/MyFilter.cpp :language: cpp - :lines: 25-30 + :lines: 26-29 + :linenos: -The ``processOptions()`` method is used to parse any provided options. Here, we get the value of ``param``, if provided, else we populate ``m_value`` with the default value of ``1.0``. +The ``addArgs()`` method is used to register and bind any provided options to +the stage. Here, we get the value of ``param``, if provided, else we populate +``m_value`` with the default value of ``1.0``. .. literalinclude:: ../../examples/writing-filter/MyFilter.cpp :language: cpp - :lines: 32-35 + :lines: 31-36 + :linenos: -In ``addDimensions()`` we make sure that the known ``Intensity`` dimension is registered. We can also add a custom dimension, ``MyDimension``, which will be populated within ``run()``. +In ``addDimensions()`` we make sure that the known ``Intensity`` dimension is +registered. We can also add a custom dimension, ``MyDimension``, which will be +populated within ``run()``. .. literalinclude:: ../../examples/writing-filter/MyFilter.cpp :language: cpp - :lines: 37-41 + :lines: 38-43 + :linenos: -Finally, we define ``run()``, which takes as input a ``PointViewPtr`` and returns a ``PointViewSet``. It is here that we can transform existing dimensions, add data to new dimensions, or selectively add/remove individual points. +Finally, we define ``run()``, which takes as input a ``PointViewPtr`` and +returns a ``PointViewSet``. It is here that we can transform existing +dimensions, add data to new dimensions, or selectively add/remove individual +points. -.. literalinclude:: ../../examples/writing-filter/MyFilter.cpp - :language: cpp - :lines: 43-48 - -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! +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. +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). +First, add the following line to the beginning of ``StageFactory.cpp`` +(adjusting the path and filename as necessary). .. code-block:: cpp diff --git a/doc/tutorial/writing-kernel.rst b/doc/tutorial/writing-kernel.rst index e004ef71a3..c7b78f98ee 100644 --- a/doc/tutorial/writing-kernel.rst +++ b/doc/tutorial/writing-kernel.rst @@ -6,7 +6,7 @@ Writing a kernel :Author: Bradley Chambers :Contact: brad.chambers@gmail.com -:Date: 01/21/2015 +:Date: 10/16/2016 PDAL's command-line application can be extended through the development of diff --git a/doc/tutorial/writing-reader.rst b/doc/tutorial/writing-reader.rst index ca1883ab21..af5a92181a 100644 --- a/doc/tutorial/writing-reader.rst +++ b/doc/tutorial/writing-reader.rst @@ -6,7 +6,7 @@ Writing a reader :Authors: Bradley Chambers, Scott Lewis :Contact: brad.chambers@gmail.com -:Date: 11/13/2015 +:Date: 10/26/2016 PDAL's command-line application can be extended through the development of @@ -19,6 +19,7 @@ First, we provide a full listing of the reader header. .. literalinclude:: ../../examples/writing-reader/MyReader.hpp :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. @@ -26,18 +27,22 @@ 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: 20-21 + :lines: 20 + :linenos: -These methods are used for setting various defaults for the Reader. +``getDefaultDimensions`` returns a list of :ref:`dimensions` that the +reader provides. .. literalinclude:: ../../examples/writing-reader/MyReader.hpp :language: cpp - :lines: 24-26 + :lines: 23-25 + :linenos: ``m_stream`` is used to process the input, while ``m_index`` is used to track the index of the records. ``m_scale_z`` is specific to MyReader, and will @@ -45,11 +50,17 @@ be described later. .. literalinclude:: ../../examples/writing-reader/MyReader.hpp :language: cpp - :lines: 28-32 + :lines: 27-31 + :linenos: Various other override methods for the stage. There are a few others that could be overridden, which will not be discussed in this tutorial. +.. note:: + + See ``./include/pdal/Reader.hpp`` of the source tree for more methods + that a reader can override or implement. + The source ------------------------------------------------------------------------------- @@ -57,16 +68,18 @@ Again, we start with a full listing of the reader source. .. literalinclude:: ../../examples/writing-reader/MyReader.cpp :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: 7-12 + :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 instalation. The macro is supplied with a version number +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. @@ -76,35 +89,39 @@ in this tutorial. .. literalinclude:: ../../examples/writing-reader/MyReader.cpp :language: cpp - :lines: 16-22 + :lines: 18-21 + :linenos: -This method will process a set of default options for the reader. In this +This method will process a options for the reader. In this example, we are setting the z_scale value to a default of 1.0, indicating that the Z values we read should remain as-is. (In our reader, this could be changed if, for example, the Z values in the file represented mm values, -and we want to represent them as m in the storage model). - -The options will then be processed elsewhere and will be supplied values from -the pipeline configuration, etc. +and we want to represent them as m in the storage model). ``addArgs`` will +bind values given for the argument to the ``m_scale_z`` variable of the +stage. .. literalinclude:: ../../examples/writing-reader/MyReader.cpp :language: cpp - :lines: 24-27 + :lines: 23-29 + :linenos: -This method takes an Options object and populates the reader's private -variables with values found in the options object. +This method registers the various dimensions the reader will use. In our case, +we are using the X, Y, and Z built-in dimensions, as well as a custom +dimension MyData. .. literalinclude:: ../../examples/writing-reader/MyReader.cpp :language: cpp - :lines: 29-35 + :lines: 31-40 + :linenos: + +This method returns the list of :ref:`dimensions` that the reader can +provide. -This method registers the various dimensions the reader will use. In our case, -we are using the X, Y, and Z built-in dimensions, as well as a custom -dimension MyData. .. literalinclude:: ../../examples/writing-reader/MyReader.cpp :language: cpp - :lines: 48-52 + :lines: 42-46 + :linenos: This method is called when the Reader is ready for use. It will only be called once, regardless of the number of PointViews that are to be @@ -112,15 +129,18 @@ processed. .. literalinclude:: ../../examples/writing-reader/MyReader.cpp :language: cpp - :lines: 55-68 + :lines: 49-62 + :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: 71-78 + :lines: 65 + :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 @@ -128,34 +148,40 @@ 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 being read, but this should serve as a good start for how to build the -PointView ojbect. +PointView object. .. literalinclude:: ../../examples/writing-reader/MyReader.cpp :language: cpp - :lines: 80-82 + :lines: 74-76 + :linenos: -In prepration for reading the file, we prepare to skip some header lines. In +In preparation for reading the file, we prepare to skip some header lines. In our case, the header is only a single line. .. literalinclude:: ../../examples/writing-reader/MyReader.cpp :language: cpp - :lines: 83-87 + :lines: 77-82 + :linenos: Here we begin our main loop. In our example file, the first line is a header, 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: 91-99 + :lines: 85-94 + :linenos: Here we take the line we read in the for block header, split it, and make sure that we have the proper number of fields. .. literalinclude:: ../../examples/writing-reader/MyReader.cpp :language: cpp - :lines: 101-112 + :lines: 96-109 + :linenos: + Here we take the values we read and put them into the PointView object. The X and Y fields are simply converted from the file and put into the respective @@ -169,17 +195,15 @@ each iteration of the loop), and the dimension value. .. literalinclude:: ../../examples/writing-reader/MyReader.cpp :language: cpp - :lines: 111-122 + :lines: 111-113 + :linenos: -Finally, we increment the nextId. After the loop is done, we set the index +Finally, we increment the nextId and make a call into the progress callback +if we have one with our nextId. After the loop is done, we set the index 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: 124-127 - 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. @@ -190,6 +214,7 @@ The MyReader.cpp code can be compiled. For this example, we'll use cmake. Here is the CMakeLists.txt file we will use: .. literalinclude:: ../../examples/writing-reader/CMakeLists.txt + :linenos: If this file is in the directory containing MyReader.hpp and MyReader.cpp, simply run ``cmake .``, followed by ``make``. This will generate a file called diff --git a/doc/tutorial/writing-writer.rst b/doc/tutorial/writing-writer.rst index f16ec52b18..a4c99db8f8 100644 --- a/doc/tutorial/writing-writer.rst +++ b/doc/tutorial/writing-writer.rst @@ -6,7 +6,7 @@ Writing a writer :Authors: Bradley Chambers, Scott Lewis :Contact: brad.chambers@gmail.com -:Date: 11/18/2015 +:Date: 10/26/2016 PDAL's command-line application can be extended through the development of @@ -19,6 +19,7 @@ First, we provide a full listing of the writer header. .. literalinclude:: ../../examples/writing-writer/MyWriter.hpp :language: cpp + :linenos: In your MyWriter class, you will declare the necessary methods and variables needed to make the writer work and meet the plugin specifications. @@ -26,6 +27,7 @@ needed to make the writer work and meet the plugin specifications. .. literalinclude:: ../../examples/writing-writer/MyWriter.hpp :language: cpp :lines: 11 + :linenos: FileStreamPtr is defined to make the declaration of the stream easier to manage later on. @@ -36,22 +38,17 @@ later on. These three methods are required to fulfill the specs for defining a new plugin. -.. literalinclude:: ../../examples/writing-writer/MyWriter.hpp - :language: cpp - :lines: 23 - -This method will be used to specify default options for the Writer. .. literalinclude:: ../../examples/writing-writer/MyWriter.hpp :language: cpp - :lines: 26-29 + :lines: 24-28 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: 31-37 + :lines: 30-36 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 @@ -68,13 +65,14 @@ We will start with a full listing of the writer source. .. literalinclude:: ../../examples/writing-writer/MyWriter.cpp :language: cpp + :linenos: In the writer implementation, we will use a macro defined in pdal_macros, which is included in the include chain we are using. .. literalinclude:: ../../examples/writing-writer/MyWriter.cpp :language: cpp - :lines: 11-16 + :lines: 10-15 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 @@ -88,27 +86,30 @@ also possible, but requires some extra steps and will not be covered here. .. literalinclude:: ../../examples/writing-writer/MyWriter.cpp :language: cpp - :lines: 20-31 + :lines: 19-30 + :linenos: This struct is used for helping with the FileStreamPtr for cleanup. .. literalinclude:: ../../examples/writing-writer/MyWriter.cpp :language: cpp - :lines: 34-44 + :lines: 33-40 + :linenos: -This method sets various default parameters. They can be overridden via the -pipeline, if desired. +This method defines the arguments the writer provides and binds them to +private variables. .. literalinclude:: ../../examples/writing-writer/MyWriter.cpp :language: cpp :lines: 47-63 -This method processes the options, including the default options given, and in -this case also opens the output file stream for use. +This method initializes our file stream in preparation for writing. + .. literalinclude:: ../../examples/writing-writer/MyWriter.cpp :language: cpp - :lines: 66-82 + :lines: 55-70 + :linenos: The ready method is used to prepare the writer for any number of PointViews that may be passed in. In this case, we are setting the precision for our double @@ -117,7 +118,8 @@ and writing the header of the output file. .. literalinclude:: ../../examples/writing-writer/MyWriter.cpp :language: cpp - :lines: 85-101 + :lines: 74-90 + :linenos: This method is the main method for writing. In our case, we are writing a very simple file, with data in the format of X:Y:Z:MyData. We loop through each @@ -136,7 +138,8 @@ to the output stream. .. literalinclude:: ../../examples/writing-writer/MyWriter.cpp :language: cpp - :lines: 104-107 + :lines: 93-96 + :linenos: This method is called when the writing is done. In this case, it simply cleans up the output stream by resetting it. @@ -148,6 +151,7 @@ To compile this reader, we will use cmake. Here is the CMakeLists.txt file we will use for this process: .. literalinclude:: ../../examples/writing-writer/CMakeLists.txt + :linenos: If this file is in the directory with the MyWriter.hpp and MyWriter.cpp files, simply run ``cmake .`` followed by ``make``. This will generate a file called