******************************************************************************
 libLAS RFC 2: SpatialReference Overhaul
******************************************************************************

:Author: Frank Warmerdam
:Contact: warmerdam@pobox.com
:Date: 11/19/10
:Status: Implemented
:Version: libLAS 1.6

.. contents::
    :depth: 1

This RFC addresses several areas of change to the liblas::SpatialReference 
class and associated services.  The objectives are:

 * Minimize the default exposure of libLAS applications to definitions 
   from the GeoTIFF library.
 * Minimize the default exposure of libLAS applications to definitions
   from the GDAL library.
 * Provide a mechanism to capture coordinate system definitions in a LAS
   file that cannot be represented via GeoTIFF tags via a liblas 
   vendor proprietary WKT VLR.  
 * Ensure that the liblas::SpatialReference class can hold such a non
   GeoTIFF definition.


Justification for Minimized GeoTIFF / GDAL Include Flow Through
------------------------------------------------------------------------------

Currently the lasspatialreference.hpp and a few other include files
pull in libgeotiff, and GDAL include files somewhat gratuitously if
these sublibraries are enabled in the build. 

This introduces a lot of cruft into the global namespace.  Also due to the
"C" style includes of these sublibraries, it introduces a lot of junk that
might interfere in surprising ways and in contrast to how the rest of 
libLAS in very careful to put things into namespaces and otherwise be
somewhat sparing of includes. 

The cleanup should help avoid conflicts and namespace pollution for
applications primarily linking against libLAS and not wanting to use
libgeotiff or GDAL services directly.  It should also make building somewhat
less fragile in some cases.


Justification for WKT Coordinate System Representation
------------------------------------------------------------------------------

There are a significant number of coordinate systems, and options that 
cannot be represented in GeoTIFF tags.  This includes TOWGS84 parameters, 
options to use particular horizontal and vertical grid shift files, and
support for projection methods that don't have CT\_ definitions for 
GeoTIFF.

Currently the liblas::SpatialReference class converts passed in WKT 
coordinate system definitions into a GeoTIFF VLR and future requests for
the WKT are created by converting the GeoTIFF VLR back into WKT.  This 
makes it essentially impossible currently for :ref:`las2las <las2las>` to perform 
transformations between coordinate systems not representable in GeoTIFF
terms even if the source and destination are provided on the command-line in 
WKT format. 

Also, it seems with future versions of LAS format some variation of OGC
WKT in a VLR will become a supported, or even the preferred way of 
representing coordinate systems. 

Given these points it seems reasonable to make liblas::SpatialReference 
less GeoTIFF VLR oriented now.


Include File Overhaul
------------------------------------------------------------------------------

The basic plan is to remove includes of all GeoTIFF include files from
any public liblas include files.  For objects, like liblas::SpatialReference,
that depend on GeoTIFF definitions like GTIF, ST_TIFF or GTIFDefn we will
substitute dummy types if the corresponding GeoTIFF include files have
not already been included in advance by the application.  This looks something
like::

  // Fake out the compiler if we don't have libgeotiff includes already
  #if !defined(__geotiff_h_)
  typedef struct GTIFS *GTIF;
  #endif
  #if !defined(__geo_simpletags_h_)
  typedef struct ST_TIFFS *ST_TIFF;
  #endif

Thus libLAS library code, and application code that wants "proper" 
GTIF and ST_TIFF types will need to include the corresponding libgeotiff
include files *before* including lasspatialreference.hpp.  Any attempt to 
include these libgeotiff include files *after* including lasspatialreference.hpp
will cause conflicts.  Yes, this is somewhat unfortunate and will be an
unobvious requirement to new folks.  Some existing application code will
likely need a bit of include reordering before it will work. 

It is intended that similar approach might be used for GDAL and OGR
dependencies.  The primary place where this is a concern seems to be 
lastransform.hpp. 

It is also planned to move the lasversion.hpp function implementations into a
.cpp file to avoid having to include libgeotiff and GDAL include files right
in lasversion.hpp.  This should have the added benefit of not making what
lasversion.hpp returns depend on what extra macros (like `HAVE_GDAL`) are defined
when it is included vs. when libLAS itself is compiled and linked.


SpatialReference WKT Updates
------------------------------------------------------------------------------

Additions to SpatialReference Class::

  public
    enum GeoVLRType
    {
        eGeoTIFF = 1,
        eOGRWKT = 2
    };

    void ClearVLRs( GeoVLRType eType );

  private:
    std::string m_wkt;

The GeoVLRType enumeration is currently used just to define what information
should be wiped in a call to ClearVLRs() but in the future it might also 
be used for other purposes.

The ClearVLRs() method clears either the WKT VLR + m_vlr, or the GeoTIFF
VLRs and the associated m_gtiff, m_tiff objects. 

The m_wkt is used internally to cache the current WKT string associated
with the spatial reference.  

The SpatialReference class is updated to:

 * Generated both GeoTIFF and WKT VLRs in the ResetVLRs() method.  

 * GetWKT() now just returns the WKT definition if it is available, otherwise 
   it computes the WKT from the GeoTIFF definition. 

 * SetWKT() now caches the WKT as well as creating the GeoTIFF definition
   from it.  Then the WKT and GeoTIFF VLRs are generated.

.. note::
    A liblas::SpatialReference instance that was read/generated from VLRs containing 
    only GeoTIFF keys will continue to only have GeoTIFF keys until you 
    issue a call to SetWKT().  You can simply do the following to WKT-enable 
    a liblas::SpatialReference in that case:
    
    ::
    
        reference.SetWKT(reference.GetWKT());
    

.. warning::

    If you want *only* GeoTIFF VLRs you should normally generate the
    SpatialReference and then call "ClearVLRs(eOGRWKT);" before setting the
    SpatialReference on the header being written. If you want *only* a WKT VLR
    then you should call "ClearVLRs(eGeotIFF);" at the same point.



WKT VLR
------------------------------------------------------------------------------


Currently the OGR WKT VLR is currently being written with a UserId of
"liblas" and with a RecordId of 2112 to 
distinguish it from the GeoTIFF VLRs.  

The data is the OGR WKT string with a terminating zero byte. An exception 
is thrown if the size of the WKT is larger than a VLR record can hold.

Is there any scheme to assign RecordIds?  Perhaps we should pick a value
outside the normal legal range for TIFF tags?  Or perhaps we should be
using a different UserId? 

.. note::

    It is anticipated at some point in the future there will be a
    WKT VLR definition as part of the LAS specification and that it's contents
    may be more accurately defined as OGC WKT rather than OGR WKT which can
    contain a variety of extensions to the specification.


