source: issm/trunk-jpl/src/m/shp/shpread.py@ 25455

Last change on this file since 25455 was 25455, checked in by jdquinn, 5 years ago

CHG: Saving chnages so that Basile has access to potential fix to solidearthmodel class

File size: 5.5 KB
Line 
1from collections import OrderedDict
2from os import path
3try:
4 import shapefile
5except ImportError:
6 print("could not import shapefile, PyShp has not been installed, no shapefile reading capabilities enabled")
7
8from pairoptions import pairoptions
9
10
11def shpread(filename, *args): #{{{
12 """SHPREAD - read a shapefile and build a list of shapes
13
14 This routine reads a shapefile and builds a list of OrderedDict objects
15 containing the fields x and y corresponding to the coordinates, one for the
16 filename of the shp file, for the density, for the nodes, and a field
17 closed to indicate if the domain is closed. If this initial shapefile is
18 point only, the fields closed and points are ommitted. The first argument
19 is the shapefile to be read and the second argument (optional) indicates if
20 the last point shall be read (1 to read it, 0 not to).
21
22 The current implementation of shpread depends on PyShp.
23
24 Usage:
25 list = shpread(filename)
26
27 Example:
28 From underling PyShp implementation, "The shapefile format is actually
29 a collection of three files. You specify the base filename of the
30 shapefile or the complete filename of any of the shapefile component
31 files."
32
33 list = shpread('domainoutline.shp')
34 OR
35 list = shpread('domainoutline.dbf')
36 OR
37 list = shpread('domainoutline')
38
39 "OR any of the other 5+ formats which are potentially part of a
40 shapefile. The library does not care about file extensions". We do,
41 however, check that a file with the base filename or base filename with
42 .shp extension exists.
43
44 Sources:
45 - https://github.com/GeospatialPython/pyshp
46
47 NOTE:
48 - OrderedDict objects are used instead of OrderedStruct objects (although
49 addressing in the latter case is closer to the MATLAB struct type) in order
50 to remain consistent with the pattern established by src/m/exp/expread.py.
51
52 TODO:
53 - Create class that can be used to store and pretty print shape structs
54 (ala OrderedStruct from src/m/qmu/helpers.py).
55 - Convert returned data structure from list of OrderedDict objects to list
56 of OrderedStruct objects and remove corresponding note (see also
57 src/m/exp/expread.py). Also, modify handling of returned data structure in,
58 - src/m/classes/basin.py
59 - src/m/classes/boundary.py
60 - src/m/modules/ExpToLevelSet.py
61 - src/m/mesh/bamg.py
62 May also need to modify addressing in corresponding FetchData function, or
63 create new one, in src/wrappers/ContoursToNodes/ContoursToNodes.cpp.
64 """
65
66 #recover options
67 options = pairoptions(*args)
68
69 #some checks
70 if not (path.isfile(filename) or path.isfile(filename + '.shp')):
71 raise RuntimeError('shpread error message: file {} or {}.shp not found!'.format(filename, filename))
72
73 #read shapefile
74 sf = shapefile.Reader(filename)
75
76 Structs = []
77 shapes = sf.shapes()
78 for i in range(len(shapes)):
79 Struct = OrderedDict()
80 shape = shapes[i]
81 if shape.shapeType == shapefile.POINT:
82 Struct['x'] = shape.points[0][0]
83 Struct['y'] = shape.points[0][1]
84 Struct['density'] = 1
85 Struct['Geometry'] = 'Point'
86 elif shape.shapeType == shapefile.POLYLINE:
87 num_points = len(shape.points)
88 x = []
89 y = []
90 for j in range(num_points):
91 point = shape.points[j]
92 x.append(point[0])
93 y.append(point[1])
94 Struct['x'] = x
95 Struct['y'] = y
96 Struct['nods'] = num_points
97 Struct['density'] = 1
98 Struct['closed'] = 1
99 Struct['BoundingBox'] = shape.bbox
100 Struct['Geometry'] = 'Line'
101 elif shape.shapeType == shapefile.POLYGON:
102 num_points = len(shape.points)
103 x = []
104 y = []
105 for j in range(num_points):
106 point = shape.points[j]
107 x.append(point[0])
108 y.append(point[1])
109 Struct['x'] = x
110 Struct['y'] = y
111 Struct['nods'] = num_points
112 Struct['density'] = 1
113 Struct['closed'] = 1
114 Struct['BoundingBox'] = shape.bbox
115 Struct['Geometry'] = 'Polygon'
116 else:
117 # NOTE: We could do this once before looping over shapes as all
118 # shapes in the file must be of the same type, but we would
119 # need to have a second check anyway in order to know how to
120 # parse the points. So, let's just assume the file is not
121 # malformed.
122 #
123 raise Exception('shpread error: geometry {} is not currently supported'.format(shape.shapeTypeName))
124
125 name = ''
126 fields = sf.fields
127 for j in range(1, len(fields)): # skip over first field, which is "DeletionFlag"
128 fieldname = fields[j][0]
129 # 'id' field gets special treatment
130 if fieldname == 'id':
131 name = str(sf.record(i)[j - 1]) # record index is offset by one, again, because of "DeletionFlag"
132 else:
133 setattr(Struct, str(fieldname), sf.record(i)[j - 1]) # cast to string removes "u" from "u'fieldname'"
134 Struct['name'] = name
135 Structs.append(Struct)
136
137 invert = options.getfieldvalue('invert', 0)
138 if invert:
139 for i in range(len(Structs)):
140 Structs[i]['x'] = np.flipud(Structs[i]['x'])
141 Structs[i]['y'] = np.flipud(Structs[i]['y'])
142
143 return Structs
144#}}}
Note: See TracBrowser for help on using the repository browser.