1
1
import os
2
2
import pyproj
3
3
import numpy as np
4
+ from shapely .geometry import Polygon , Point
4
5
from easyric .external import shapefile
5
6
from easyric .io .geotiff import point_query , mean_values , min_values , get_header
6
7
@@ -120,16 +121,69 @@ def read_shp2d(shp_path, shp_proj=None, geotiff_proj=None, name_field=None, titl
120
121
return shp_dict
121
122
122
123
123
- def read_shp3d (shp_path , dsm_path , get_z_by = 'mean' , shp_proj = None , geotiff_proj = None , geo_head = None , name_field = None , title_include = False , encoding = 'utf-8' ):
124
- '''
125
- shp_path: full shp_file directory
126
- get_z_by:
127
- "all": using the mean value of whole DSM as the same z-value for all boundary points
128
- -> this will get a 2D plane of ROI
129
- "mean": using the mean value of boundary points closed part.
130
- "local" using the z value of where boundary points located, each point will get different z-values
124
+ def read_shp3d (shp_path , dsm_path , get_z_by = 'mean' , get_z_buffer = 0 , shp_proj = None , geotiff_proj = None , geo_head = None , name_field = None , title_include = False , encoding = 'utf-8' ):
125
+ """[summary]
126
+
127
+ Parameters
128
+ ----------
129
+ shp_path : str
130
+ full shp_file directory
131
+ dsm_path : str
132
+ full dsm_file directory where want to extract height from
133
+ get_z_by : str, optional
134
+ ["local", "mean", "min", "max", "all"], by default 'mean'
135
+ - "local" using the z value of where boundary points located, each point will get different z-values
131
136
-> this will get a 3D curved mesh of ROI
132
- '''
137
+ - "mean": using the mean value of boundary points closed part.
138
+ - "min": 5th percentile mean height (the mean value of all pixels < 5th percentile)
139
+ - "max": 95th percentile mean height (the mean value of all pixels > 95th percentile)
140
+ - "all": using the mean value of whole DSM as the same z-value for all boundary points
141
+ -> this will get a 2D plane of ROI
142
+ get_z_buffer : int, optional
143
+ the buffer of ROI, by default 0
144
+ it is suitable when the given ROI is points rather than polygons. Given this paramter will generate a round buffer
145
+ polygon first, then extract the z-value by this region, but the return will only be a single point
146
+ The unit of buffer follows the ROI coordinates, either pixel or meter.
147
+ shp_proj : str or pyproj.CRS object, optional
148
+ The projection coordinate of given shp file, by default None, it will automatic find the proj file
149
+ geotiff_proj : pyproj.CRS object, optional
150
+ The projection coordinate of given dsm file, by default None, it will automatic find it in geohead
151
+ geo_head : dict, optional
152
+ returned dict of geotiff.get_header() , by default None
153
+ specify this to save the dsm file reading time cost
154
+ name_field : int | str | list, optional
155
+ The column name of shp file to use as index of ROI, by default None
156
+ e.g. shp file with following title:
157
+ | id | plot | species |
158
+ |----|------|---------|
159
+ | 01 | aaa | xxx |
160
+ | 02 | bbb | yyy |
161
+
162
+ - "int": the colume number used as title, start from 0
163
+ e.g. name_field = 0
164
+ -> {"01": [...], "02": [...], ...}
165
+ - "str": the colume title used as title
166
+ e.g. name_field = "plot"
167
+ -> {"aaa": [...], "bbb": [...]}
168
+ - "list": combine multipule title together
169
+ e.g.: name_field = ["plot", "species"]
170
+ -> {"aaa_xxx": [...], "bbb_yyy":[...], ...}
171
+ title_include : bool, optional
172
+ where add column title into index, by default False
173
+ e.g.: name_field = ["plot", "species"]
174
+ title_include = False
175
+ -> {"aaa_xxx": [...], "bbb_yyy":[...], ...}
176
+ title_include = True
177
+ -> {"plot_aaa_species_xxx": [...], "plot_bbb_species_yyy":[...], ...}
178
+ encoding : str, optional
179
+ by default 'utf-8'
180
+
181
+ Returns
182
+ -------
183
+ [type]
184
+ [description]
185
+ """
186
+
133
187
shp_dict = {}
134
188
if geo_head is None :
135
189
tiff_header = get_header (dsm_path )
@@ -146,6 +200,16 @@ def read_shp3d(shp_path, dsm_path, get_z_by='mean', shp_proj=None, geotiff_proj=
146
200
keys = list (shp_dict_2d .keys ())
147
201
coord_list = [shp_dict_2d [k ] for k in keys ]
148
202
203
+ if get_z_buffer != 0 :
204
+ coord_list_buffer = []
205
+ for k in keys :
206
+ seed = shp_dict_2d [k ]
207
+ if seed .shape [0 ] == 1 : # single point
208
+ buffered = Point (seed [0 ,:]).buffer (get_z_buffer )
209
+ else : # polygon
210
+ buffered = Polygon (seed ).buffer (get_z_buffer )
211
+ coord_list_buffer .append (np .asarray (buffered .exterior .coords ))
212
+
149
213
print (f"[io][shp][name] Loading Z values from DSM, this may take a while" )
150
214
# then add z_values on it
151
215
if get_z_by == 'local' :
@@ -154,17 +218,28 @@ def read_shp3d(shp_path, dsm_path, get_z_by='mean', shp_proj=None, geotiff_proj=
154
218
coord_np = np .concatenate ([coord_np , coord_z [:, None ]], axis = 1 )
155
219
shp_dict [k ] = coord_np
156
220
elif get_z_by == 'mean' :
157
- z_lists = mean_values (dsm_path , polygon = coord_list , geo_head = tiff_header )
221
+ if get_z_buffer == 0 :
222
+ z_lists = mean_values (dsm_path , polygon = coord_list , geo_head = tiff_header )
223
+ else :
224
+ z_lists = mean_values (dsm_path , polygon = coord_list_buffer , geo_head = tiff_header )
225
+
158
226
for k , coord_np , coord_z in zip (keys , coord_list , z_lists ):
159
227
coord_np = np .insert (coord_np , obj = 2 , values = coord_z , axis = 1 )
160
228
shp_dict [k ] = coord_np
161
229
elif get_z_by == 'min' :
162
- z_lists = min_values (dsm_path , polygon = coord_list , geo_head = tiff_header )
230
+ if get_z_buffer == 0 :
231
+ z_lists = min_values (dsm_path , polygon = coord_list , geo_head = tiff_header )
232
+ else :
233
+ z_lists = min_values (dsm_path , polygon = coord_list_buffer , geo_head = tiff_header )
234
+
163
235
for k , coord_np , coord_z in zip (keys , coord_list , z_lists ):
164
236
coord_np = np .insert (coord_np , obj = 2 , values = coord_z , axis = 1 )
165
237
shp_dict [k ] = coord_np
166
238
elif get_z_by == 'max' :
167
- z_lists = min_values (dsm_path , polygon = coord_list , geo_head = tiff_header , pctl = 95 )
239
+ if get_z_buffer == 0 :
240
+ z_lists = min_values (dsm_path , polygon = coord_list , geo_head = tiff_header , pctl = 95 )
241
+ else :
242
+ z_lists = min_values (dsm_path , polygon = coord_list_buffer , geo_head = tiff_header , pctl = 95 )
168
243
for k , coord_np , coord_z in zip (keys , coord_list , z_lists ):
169
244
coord_np = np .insert (coord_np , obj = 2 , values = coord_z , axis = 1 )
170
245
shp_dict [k ] = coord_np
0 commit comments