1"""
2/******************************************************************************
3 * $Id$
4 *
5 * Project:  libLAS - http://liblas.org - A BSD library for LAS format data.
6 * Purpose:  Python VLR implementation
7  * Author:   Howard Butler, hobu.inc@gmail.com
8 *
9 ******************************************************************************
10 * Copyright (c) 2009, Howard Butler
11 *
12 * All rights reserved.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following
16 * conditions are met:
17 *
18 *     * Redistributions of source code must retain the above copyright
19 *       notice, this list of conditions and the following disclaimer.
20 *     * Redistributions in binary form must reproduce the above copyright
21 *       notice, this list of conditions and the following disclaimer in
22 *       the documentation and/or other materials provided
23 *       with the distribution.
24 *     * Neither the name of the Martin Isenburg or Iowa Department
25 *       of Natural Resources nor the names of its contributors may be
26 *       used to endorse or promote products derived from this software
27 *       without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
32 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
33 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
34 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
35 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
36 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
37 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
38 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
39 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
40 * OF SUCH DAMAGE.
41 ****************************************************************************/
42 """
43
44from . import core
45import ctypes
46
47
48class VLR(object):
49    def __init__(self, owned=True, handle=None):
50        """
51        :keyword owned: flag to denote whether or not the VLR owns itself.  \
52                        If it is owned, the underlying C object will be \
53                        destroyed once it goes out of scope.
54        :keyword handle: raw ctypes object
55
56        From the specification_:
57
58            The Public Header Block is followed by one or more Variable Length
59            Records (There is one mandatory Variable Length Record,
60            GeoKeyDirectoryTag). The number of Variable Length Records is
61            specified in the "Number of Variable Length Records"
62            (:obj:`liblas.header.Header.records_count`) field in the Public
63            Header Block. The Variable Length Records must be accessed
64            sequentially since the size of each variable length record is
65            contained in the Variable Length Record Header. Each Variable
66            Length Record Header is 60 bytes in length.
67
68        >>> from liblas import vlr
69        >>> v = vlr.VLR()
70        >>> v.reserved
71        0
72        >>> v.recordid
73        0
74        >>> v.recordid = 2
75        >>> v.recordid
76        2
77        >>> v.userid
78        ''
79        >>> v.userid = 'liblas.org'
80        >>> v.userid
81        'liblas.org'
82
83        >>> v.description
84        ''
85        >>> v.description = 'libLAS'
86        >>> v.description
87        'libLAS'
88
89        """
90        if handle:
91            self.handle = handle
92        else:
93            self.handle = core.las.LASVLR_Create()
94        self.owned = owned
95
96    def __del__(self):
97        if self.owned:
98            if self.handle and core:
99                core.las.LASVLR_Destroy(self.handle)
100
101    def get_userid(self):
102        return core.las.LASVLR_GetUserId(self.handle)
103
104    def set_userid(self, value):
105        return core.las.LASVLR_SetUserId(self.handle, value)
106    doc = """User ID key for this VLR (clipped to 16 bytes long)
107
108    The User ID for libLAS is ``liblas``, and it will be used
109    for all extra VLRs that libLAS itself can interpret.
110
111    .. seealso::
112        :ref:`liblas_vlr_key` has more detail on the key and name.
113
114    From the specification_:
115        The User ID field is ASCII character data that identifies the user
116        which created the variable length record. It is possible to have many
117        Variable Length Records from different sources with different User
118        IDs. If the character data is less than 16 characters, the remaining
119        data must be null. The User ID must be registered with the LAS
120        specification managing body. The management of these User IDs ensures
121        that no two individuals accidentally use the same User ID. The
122        specification will initially use two IDs: one for globally specified
123        records (LASF_Spec), and another for projection types
124        (LASF_Projection). Keys may be requested at
125        http://www.asprs.org/lasform/keyform.html
126
127    """
128    userid = property(get_userid, set_userid, None, doc)
129    user = userid
130
131    def get_description(self):
132        return core.las.LASVLR_GetDescription(self.handle)
133
134    def set_description(self, value):
135        return core.las.LASVLR_SetDescription(self.handle, value)
136    doc = """Description of this VLR instance (clipped to 32 bytes long)
137
138    From the specification_:
139        Optional, null terminated text description of the data. Any remaining
140        characters not used must be null.
141    """
142    description = property(get_description, set_description, None, doc)
143
144    def get_recordlength(self):
145        return core.las.LASVLR_GetRecordLength(self.handle)
146
147    def set_recordlength(self, value):
148        return core.las.LASVLR_SetRecordLength(self.handle, value)
149    doc = """The number of bytes long the VLR is"""
150    recordlength = property(get_recordlength, set_recordlength, None, doc)
151
152    def __len__(self):
153        return self.recordlength
154
155    def get_recordid(self):
156        return core.las.LASVLR_GetRecordId(self.handle)
157
158    def set_recordid(self, value):
159        return core.las.LASVLR_SetRecordId(self.handle, value)
160    doc = """Record ID for the VLR
161
162    From the specification_:
163        The Record ID is dependent upon the User ID. There can be 0 to 65535
164        Record IDs for every User ID. The LAS specification manages its own
165        Record IDs (User IDs owned by the specification), otherwise Record IDs
166        will be managed by the owner of the given User ID. Thus each User ID
167        is allowed to assign 0 to 65535 Record IDs in any manner they desire.
168        Publicizing the meaning of a given Record ID is left to the owner of
169        the given User ID. Unknown User ID/Record ID combinations should be
170        ignore
171    """
172    recordid = property(get_recordid, set_recordid, None, doc)
173
174    def get_reserved(self):
175        return core.las.LASVLR_GetReserved(self.handle)
176
177    def set_reserved(self, value):
178        return core.las.LASVLR_SetReserved(self.handle, value)
179    doc = """Reserved value for the VLR.  Currently unused."""
180    reserved = property(get_reserved, set_reserved, None, doc)
181
182    def get_data(self):
183        length = self.recordlength
184        data = (ctypes.c_ubyte * length)()
185        core.las.LASVLR_GetData(self.handle, data)
186        return data
187
188    def set_data(self, data):
189        self.recordlength = len(data)
190        pdata = ctypes.cast(data, ctypes.POINTER(ctypes.c_ubyte))
191        core.las.LASVLR_SetData(self.handle, pdata, self.recordlength)
192    doc = """Raw data (in the form of an array of :class:`ctypes.c_ubyte`)"""
193    data = property(get_data, set_data, None, doc)
194