~ubuntu-branches/ubuntu/trusty/liblas/trusty-proposed

« back to all changes in this revision

Viewing changes to python/scripts/oci2las.py

  • Committer: Package Import Robot
  • Author(s): Francesco Paolo Lovergine
  • Date: 2014-01-05 17:00:29 UTC
  • mfrom: (7.1.2 sid)
  • Revision ID: package-import@ubuntu.com-20140105170029-ddtp0j63x5jvck2u
Tags: 1.7.0+dfsg-2
Fixed missing linking of system boost component.
(closes: #733282)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python
 
2
 
 
3
from liblas import file as lasfile
 
4
from liblas import header
 
5
from liblas import point
 
6
from liblas import srs
 
7
 
 
8
import glob
 
9
import struct
 
10
 
 
11
import os, sys
 
12
 
 
13
 
 
14
import cx_Oracle as oci
 
15
 
 
16
# big-endian DOUBLE, DOUBLE, DOUBLE, LONG, LONG
 
17
format = '>dddddll'
 
18
ptsize = struct.calcsize(format)
 
19
 
 
20
 
 
21
class Translator(object):
 
22
 
 
23
    def construct_parser(self):
 
24
        from optparse import OptionParser, OptionGroup
 
25
        usage = "usage: %prog [options] arg"
 
26
        parser = OptionParser(usage)
 
27
        g = OptionGroup(parser, "Base options", "Basic Translation Options")
 
28
        g.add_option("-c", "--connection", dest="connection",
 
29
                          help="OCI connection string", metavar="CONNECTION")
 
30
        g.add_option("-o", "--output", dest='output',
 
31
                          help="LAS file to write", metavar="OUTPUT")
 
32
        g.add_option("-s", "--sql", dest='sql',
 
33
                          help="SQL to select the point cloud ", metavar="SQL")
 
34
        g.add_option("-l", "--column", dest='column',
 
35
                          help="Column name containing the point cloud object ", metavar="COLUMN")
 
36
 
 
37
        g.add_option("-p", "--precision", dest='precision',
 
38
                          help="Numeric precision (# of digits) to maintain for the output file ", metavar="PRECISION")
 
39
 
 
40
        g.add_option("-r", "--srs", dest='srs',
 
41
                          help="Coordinate system override", metavar="SRS")
 
42
                          
 
43
        g.add_option("-w", "--overwrite",
 
44
                          action="store_true", dest="overwrite", 
 
45
                          help="overwrite the existing file")
 
46
 
 
47
        g.add_option("-m", "--min-offset",
 
48
                          action="store_true", dest="offset", default=False,
 
49
                          help="Use the minimum values as base for offset")
 
50
                          
 
51
        g.add_option("-q", "--quiet",
 
52
                          action="store_false", dest="verbose", default=False,
 
53
                          help="Don't say what we're doing on stdout")
 
54
        
 
55
        g.add_option("--compressed", action="store_true", dest="compressed",
 
56
                          default=False)
 
57
                  
 
58
        parser.add_option_group(g)
 
59
 
 
60
        if self.opts:
 
61
            g = OptionGroup(parser, "Special Options", "Special options")
 
62
            for o in self.opts:
 
63
                g.add_option(o)
 
64
            parser.add_option_group(g)
 
65
            
 
66
        parser.set_defaults(verbose=True, precision = 6)
 
67
 
 
68
        self.parser = parser
 
69
        
 
70
    def __init__(self, arguments, options=None):
 
71
        self.connection = None
 
72
        self.output = None
 
73
        self.sql = None
 
74
        
 
75
        self.opts = options
 
76
        self.construct_parser()
 
77
        self.options, self.args = self.parser.parse_args(args=arguments)
 
78
        
 
79
        if self.args:
 
80
            self.options.connection = self.args[0]
 
81
            
 
82
        if not self.options.output:
 
83
            try:
 
84
                self.options.output = self.args[1]
 
85
            except IndexError:
 
86
                self.options.output = 'output.las'
 
87
                
 
88
        if not self.options.sql:
 
89
            try:
 
90
                self.options.sql = self.args[2]
 
91
            except IndexError:
 
92
                raise self.parser.error("No SQL was provided to select the point cloud!")           
 
93
 
 
94
        if self.options.output:
 
95
            self.options.output = os.path.abspath(self.options.output)
 
96
            if os.path.isdir(self.options.output):
 
97
                raise self.parser.error("Output '%s' is a directory, not a file " % self.options.output)
 
98
            
 
99
            if os.path.exists(self.options.output):
 
100
                if not self.options.overwrite:
 
101
                    raise self.parser.error("Output file '%s' exists, but you have not selected the --overwrite option" % self.options.output)
 
102
        else:
 
103
            raise self.parser.error("No output was specified")
 
104
 
 
105
        try:
 
106
            self.options.precision = int(self.options.precision)
 
107
            if not self.options.precision:
 
108
                raise self.parser.error("Precision cannot be 0")
 
109
        except:
 
110
            raise self.parser.error("Precision was not an number")
 
111
            
 
112
        self.minx = None
 
113
        self.miny = None
 
114
        self.minz = None
 
115
        self.maxx = None
 
116
        self.maxy = None
 
117
        self.maxz = None
 
118
        self.count = 0
 
119
        self.first_point = True
 
120
        self.cloud_column = True
 
121
        self.header = None
 
122
        self.points = []
 
123
        
 
124
        if self.options.srs:
 
125
            self.srs = srs.SRS()
 
126
            self.srs.set_userinput(self.options.srs)
 
127
            print 'setting srs to %s' %self.srs.proj4
 
128
        else:
 
129
            self.srs = None
 
130
            
 
131
    def print_options(self):
 
132
        print self.options
 
133
        
 
134
    def connect(self):
 
135
        self.con = oci.Connection(self.options.connection)
 
136
 
 
137
    def is_block_table(self, cursor_description):
 
138
        output = True
 
139
        names = [   'OBJ_ID','BLK_ID','BLK_EXTENT','BLK_DOMAIN',
 
140
                    'PCBLK_MIN_RES','PCBLK_MAX_RES','NUM_POINTS',
 
141
                    'NUM_UNSORTED_POINTS','PT_SORT_DIM','POINTS']
 
142
        for name in cursor_description:
 
143
            if name.upper() not in names:
 
144
                return False
 
145
 
 
146
            
 
147
    def write_points(self, num_points, blob):
 
148
#       print 'writing block...', num_points
 
149
 
 
150
        if not self.points:
 
151
            for i in xrange(num_points):
 
152
                p = point.Point()
 
153
                p.header = self.header
 
154
                self.points.append(p)
 
155
        if (num_points > len(self.points)):
 
156
            for i in xrange(num_points-len(self.points)):
 
157
                p = point.Point()
 
158
                p.header = self.header
 
159
                self.points.append(p)
 
160
                    
 
161
        for i in xrange(num_points):
 
162
            rng = ptsize*i,ptsize*(i+1)
 
163
            d = struct.unpack(format,blob[ptsize*i:ptsize*(i+1)])
 
164
            x, y, z, time, classification, blk_id, pt_id = d
 
165
            p = self.points[i]
 
166
            p.x = x; p.y = y; p.z = z
 
167
            p.classification = int(classification)
 
168
            p.raw_time = time
 
169
 
 
170
            if self.first_point:
 
171
                self.minx = p.x
 
172
                self.miny = p.y
 
173
                self.maxx = p.x
 
174
                self.maxy = p.y
 
175
                self.minz = p.z
 
176
                self.maxz = p.z
 
177
                self.first_point = False
 
178
 
 
179
            # cumulate min/max for the header
 
180
            self.minx = min(self.minx, p.x)
 
181
            self.maxx = max(self.maxx, p.x)
 
182
        
 
183
            self.miny = min(self.miny, p.y)
 
184
            self.maxy = max(self.maxy, p.y)
 
185
        
 
186
            self.minz = min(self.minz, p.z)
 
187
            self.maxz = max(self.maxz, p.z)
 
188
        
 
189
            self.count += 1
 
190
            
 
191
            self.output.write(p)
 
192
    
 
193
    def summarize_files(self):
 
194
        pass
 
195
    
 
196
    def open_output(self):
 
197
        self.header = header.Header()
 
198
        
 
199
        prec = 10**-(self.options.precision-1)
 
200
        self.header.scale = [prec, prec, prec]
 
201
        
 
202
        if self.options.offset:
 
203
            h.offset = [self.minx, self.miny, self.minz]
 
204
            if self.options.verbose:
 
205
                print 'using minimum offsets', h.offset
 
206
 
 
207
        self.header.compressed = self.options.compressed
 
208
 
 
209
        if self.srs:
 
210
            self.header.srs = self.srs
 
211
        
 
212
        self.header.data_format_id = 1
 
213
        output = lasfile.File(self.options.output,mode='w',header=self.header)
 
214
        return output
 
215
    
 
216
    
 
217
    def rewrite_header(self):
 
218
        self.output.close()
 
219
        self.output = lasfile.File(self.options.output)
 
220
        h = self.output.header
 
221
        self.output.close()
 
222
        h.min = [self.minx, self.miny, self.minz]
 
223
        h.max = [self.maxx, self.maxy, self.maxz]
 
224
 
 
225
        rc = h.point_return_count
 
226
        rc[0] = self.count
 
227
        h.point_return_count = rc
 
228
        
 
229
        self.output = lasfile.File(self.options.output, mode='w+', header=h)
 
230
        self.output.close()
 
231
    
 
232
    def get_srid(self, srid):
 
233
        cur = self.con.cursor()
 
234
        if not srid: return ''
 
235
        cur.execute('SELECT WKTEXT,WKTEXT3D from MDSYS.CS_SRS where srid=%d'%(int(srid)))
 
236
        res = cur.fetchall()
 
237
        for wkt in res:
 
238
            text = wkt[0]
 
239
            text3d = wkt[1]
 
240
            s = srs.SRS()
 
241
            if text3d:
 
242
                s.wkt = text3d
 
243
            else:
 
244
                s.wkt = text
 
245
            return s
 
246
        
 
247
    def process(self):
 
248
        self.print_options()
 
249
        self.connect()
 
250
 
 
251
        self.cur = self.con.cursor()
 
252
#        self.cur.execute(self.options.sql)
 
253
#        clouds = []
 
254
#
 
255
#        res = self.cur.fetchall()
 
256
 
 
257
#        for row in res:
 
258
#            for column in row:
 
259
#                try:
 
260
#                    column.BASE_TABLE_COL
 
261
#                    clouds.append(column)
 
262
#                except AttributeError:
 
263
#                    # This column isn't a cloud
 
264
#                    pass
 
265
 
 
266
#        points = []
 
267
        
 
268
        # write an actual cloud column
 
269
#        for cloud in clouds:
 
270
#            cur2 = self.con.cursor()
 
271
#
 
272
#            cur2.execute('SELECT NUM_POINTS, POINTS, BLK_EXTENT FROM %s'% cloud.BLK_TABLE)
 
273
            
 
274
            
 
275
#            for num_points, blob, extent in cur2:
 
276
#                # set the SRS from the first geometry
 
277
#                if not self.srs:
 
278
#                    self.srs = self.get_srid(extent.SDO_SRID)
 
279
                    
 
280
#                b = blob.read()
 
281
#                points.append(self.get_points(num_points,b))
 
282
        
 
283
#        num_pts_index, blob_index = self.get_block_indexes(self.cur)
 
284
        
 
285
        # if we don't have a cloud object, we'll assume that NUM_POINTS and 
 
286
        # the POINTS blob exist in our already queried cursor
 
287
        clouds = None
 
288
        points = []
 
289
        print 'have srs?: %s' % bool(self.srs)
 
290
 
 
291
        self.output = self.open_output()
 
292
 
 
293
        if not clouds:
 
294
            cur = self.cur.execute(self.options.sql)
 
295
            num_pts_index, blob_index = self.get_block_indexes(cur)
 
296
            for row in cur:
 
297
                num_points = row[num_pts_index]
 
298
                blob = row[blob_index].read()
 
299
                self.write_points(num_points, blob)
 
300
                # try to set the SRS
 
301
                if not self.srs:
 
302
                    for col in row:
 
303
                        try:
 
304
                            col.SDO_SRID
 
305
                            self.srs = self.get_srid(col.SDO_SRID)
 
306
                            break
 
307
                        except AttributeError:
 
308
                            continue
 
309
                    
 
310
                    # if we still haven't been able to set an SRS, don't try 
 
311
                    # to anymore
 
312
                    if not self.srs:
 
313
                        self.srs = srs.SRS()
 
314
 
 
315
        
 
316
        self.rewrite_header()
 
317
 
 
318
    def get_block_indexes(self, cursor):
 
319
        
 
320
        num_pts_index = None
 
321
        blob_index = None
 
322
        i = 0
 
323
        for name in cursor.description:
 
324
            name = name[0]
 
325
            if name.upper() == 'POINTS':
 
326
                blob_index = i
 
327
            if name.upper() == 'NUM_POINTS':
 
328
                num_pts_index = i
 
329
            i+=1
 
330
        return (num_pts_index, blob_index)
 
331
 
 
332
def main():
 
333
    import optparse
 
334
 
 
335
    options = []
 
336
#     o = optparse.make_option("-r", "--remainder", dest="remainder",
 
337
#                          type="choice",default='end', 
 
338
#                           help="""what to do with the remainder -- place it at the beginning, 
 
339
# place it at the end, or evenly distribute it across the segment""",
 
340
#                           choices=['end','begin','uniform'])
 
341
#     options.append(o)
 
342
    
 
343
    d = Translator(sys.argv[1:], options=options)
 
344
    d.process()
 
345
 
 
346
if __name__=='__main__':
 
347
    main()