BERATools 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- beratools/__init__.py +9 -0
- beratools/core/__init__.py +0 -0
- beratools/core/algo_centerline.py +351 -0
- beratools/core/constants.py +86 -0
- beratools/core/dijkstra_algorithm.py +460 -0
- beratools/core/logger.py +85 -0
- beratools/core/tool_base.py +133 -0
- beratools/gui/__init__.py +15 -0
- beratools/gui/batch_processing_dlg.py +463 -0
- beratools/gui/beratools.json +2300 -0
- beratools/gui/bt_data.py +487 -0
- beratools/gui/bt_gui_main.py +691 -0
- beratools/gui/cli.py +18 -0
- beratools/gui/gui.json +8 -0
- beratools/gui/img/BERALogo.png +0 -0
- beratools/gui/img/closed.gif +0 -0
- beratools/gui/img/closed.png +0 -0
- beratools/gui/img/open.gif +0 -0
- beratools/gui/img/open.png +0 -0
- beratools/gui/img/tool.gif +0 -0
- beratools/gui/img/tool.png +0 -0
- beratools/gui/map_window.py +146 -0
- beratools/gui/tool_widgets.py +493 -0
- beratools/gui_tk/ASCII Banners.txt +248 -0
- beratools/gui_tk/__init__.py +20 -0
- beratools/gui_tk/beratools_main.py +515 -0
- beratools/gui_tk/bt_widgets.py +442 -0
- beratools/gui_tk/cli.py +18 -0
- beratools/gui_tk/gui.json +8 -0
- beratools/gui_tk/img/BERALogo.png +0 -0
- beratools/gui_tk/img/closed.gif +0 -0
- beratools/gui_tk/img/closed.png +0 -0
- beratools/gui_tk/img/open.gif +0 -0
- beratools/gui_tk/img/open.png +0 -0
- beratools/gui_tk/img/tool.gif +0 -0
- beratools/gui_tk/img/tool.png +0 -0
- beratools/gui_tk/main.py +14 -0
- beratools/gui_tk/map_window.py +144 -0
- beratools/gui_tk/runner.py +1481 -0
- beratools/gui_tk/tooltip.py +55 -0
- beratools/third_party/pyqtlet2/__init__.py +9 -0
- beratools/third_party/pyqtlet2/leaflet/__init__.py +26 -0
- beratools/third_party/pyqtlet2/leaflet/control/__init__.py +6 -0
- beratools/third_party/pyqtlet2/leaflet/control/control.py +59 -0
- beratools/third_party/pyqtlet2/leaflet/control/draw.py +52 -0
- beratools/third_party/pyqtlet2/leaflet/control/layers.py +20 -0
- beratools/third_party/pyqtlet2/leaflet/core/Parser.py +24 -0
- beratools/third_party/pyqtlet2/leaflet/core/__init__.py +2 -0
- beratools/third_party/pyqtlet2/leaflet/core/evented.py +180 -0
- beratools/third_party/pyqtlet2/leaflet/layer/__init__.py +5 -0
- beratools/third_party/pyqtlet2/leaflet/layer/featuregroup.py +34 -0
- beratools/third_party/pyqtlet2/leaflet/layer/icon/__init__.py +1 -0
- beratools/third_party/pyqtlet2/leaflet/layer/icon/icon.py +30 -0
- beratools/third_party/pyqtlet2/leaflet/layer/imageoverlay.py +18 -0
- beratools/third_party/pyqtlet2/leaflet/layer/layer.py +105 -0
- beratools/third_party/pyqtlet2/leaflet/layer/layergroup.py +45 -0
- beratools/third_party/pyqtlet2/leaflet/layer/marker/__init__.py +1 -0
- beratools/third_party/pyqtlet2/leaflet/layer/marker/marker.py +91 -0
- beratools/third_party/pyqtlet2/leaflet/layer/tile/__init__.py +2 -0
- beratools/third_party/pyqtlet2/leaflet/layer/tile/gridlayer.py +4 -0
- beratools/third_party/pyqtlet2/leaflet/layer/tile/tilelayer.py +16 -0
- beratools/third_party/pyqtlet2/leaflet/layer/vector/__init__.py +5 -0
- beratools/third_party/pyqtlet2/leaflet/layer/vector/circle.py +15 -0
- beratools/third_party/pyqtlet2/leaflet/layer/vector/circlemarker.py +18 -0
- beratools/third_party/pyqtlet2/leaflet/layer/vector/path.py +5 -0
- beratools/third_party/pyqtlet2/leaflet/layer/vector/polygon.py +14 -0
- beratools/third_party/pyqtlet2/leaflet/layer/vector/polyline.py +18 -0
- beratools/third_party/pyqtlet2/leaflet/layer/vector/rectangle.py +14 -0
- beratools/third_party/pyqtlet2/leaflet/map/__init__.py +1 -0
- beratools/third_party/pyqtlet2/leaflet/map/map.py +220 -0
- beratools/third_party/pyqtlet2/mapwidget.py +45 -0
- beratools/third_party/pyqtlet2/web/custom.js +43 -0
- beratools/third_party/pyqtlet2/web/map.html +23 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_193/images/layers-2x.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_193/images/layers.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_193/images/marker-icon-2x.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_193/images/marker-icon.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_193/images/marker-shadow.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_193/leaflet.css +656 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_193/leaflet.js +6 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/.codeclimate.yml +14 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/.editorconfig +4 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/.gitattributes +22 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/.travis.yml +43 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/LICENSE +20 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/images/layers-2x.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/images/layers.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/images/marker-icon-2x.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/images/marker-icon.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/images/marker-shadow.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/images/spritesheet-2x.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/images/spritesheet.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/images/spritesheet.svg +156 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/leaflet.draw.css +10 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/leaflet.draw.js +10 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_rotatedMarker_020/LICENSE +22 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_rotatedMarker_020/leaflet.rotatedMarker.js +57 -0
- beratools/tools/Beratools_r_script.r +1120 -0
- beratools/tools/Ht_metrics.py +116 -0
- beratools/tools/__init__.py +7 -0
- beratools/tools/batch_processing.py +132 -0
- beratools/tools/canopy_threshold_relative.py +670 -0
- beratools/tools/canopycostraster.py +222 -0
- beratools/tools/centerline.py +176 -0
- beratools/tools/common.py +885 -0
- beratools/tools/fl_regen_csf.py +428 -0
- beratools/tools/forest_line_attributes.py +408 -0
- beratools/tools/forest_line_ecosite.py +216 -0
- beratools/tools/lapis_all.py +103 -0
- beratools/tools/least_cost_path_from_chm.py +152 -0
- beratools/tools/line_footprint_absolute.py +363 -0
- beratools/tools/line_footprint_fixed.py +282 -0
- beratools/tools/line_footprint_functions.py +720 -0
- beratools/tools/line_footprint_relative.py +64 -0
- beratools/tools/ln_relative_metrics.py +615 -0
- beratools/tools/r_cal_lpi_elai.r +25 -0
- beratools/tools/r_generate_pd_focalraster.r +101 -0
- beratools/tools/r_interface.py +80 -0
- beratools/tools/r_point_density.r +9 -0
- beratools/tools/rpy_chm2trees.py +86 -0
- beratools/tools/rpy_dsm_chm_by.py +81 -0
- beratools/tools/rpy_dtm_by.py +63 -0
- beratools/tools/rpy_find_cellsize.py +43 -0
- beratools/tools/rpy_gnd_csf.py +74 -0
- beratools/tools/rpy_hummock_hollow.py +85 -0
- beratools/tools/rpy_hummock_hollow_raster.py +71 -0
- beratools/tools/rpy_las_info.py +51 -0
- beratools/tools/rpy_laz2las.py +40 -0
- beratools/tools/rpy_lpi_elai_lascat.py +466 -0
- beratools/tools/rpy_normalized_lidar_by.py +56 -0
- beratools/tools/rpy_percent_above_dbh.py +80 -0
- beratools/tools/rpy_points2trees.py +88 -0
- beratools/tools/rpy_vegcoverage.py +94 -0
- beratools/tools/tiler.py +206 -0
- beratools/tools/tool_template.py +54 -0
- beratools/tools/vertex_optimization.py +620 -0
- beratools/tools/zonal_threshold.py +144 -0
- beratools-0.2.0.dist-info/METADATA +63 -0
- beratools-0.2.0.dist-info/RECORD +142 -0
- beratools-0.2.0.dist-info/WHEEL +4 -0
- beratools-0.2.0.dist-info/entry_points.txt +2 -0
- beratools-0.2.0.dist-info/licenses/LICENSE +22 -0
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
import time
|
|
2
|
+
from shapely.geometry import Polygon, MultiPolygon, LineString, MultiLineString
|
|
3
|
+
from beratools.tools.common import *
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def prepare_line_args(shp_line, shp_poly, n_samples, offset):
|
|
7
|
+
"""
|
|
8
|
+
Parameters
|
|
9
|
+
----------
|
|
10
|
+
shp_line
|
|
11
|
+
shp_poly
|
|
12
|
+
n_samples
|
|
13
|
+
offset
|
|
14
|
+
|
|
15
|
+
Returns
|
|
16
|
+
-------
|
|
17
|
+
line_args : list
|
|
18
|
+
row :
|
|
19
|
+
inter_poly :
|
|
20
|
+
n_samples :
|
|
21
|
+
offset :
|
|
22
|
+
i : line ID
|
|
23
|
+
|
|
24
|
+
"""
|
|
25
|
+
line_gdf = gpd.read_file(shp_line)
|
|
26
|
+
poly_gdf = gpd.read_file(shp_poly)
|
|
27
|
+
spatial_index = poly_gdf.sindex
|
|
28
|
+
line_args = []
|
|
29
|
+
|
|
30
|
+
i = 0
|
|
31
|
+
for i, row in line_gdf.iterrows():
|
|
32
|
+
line = row.geometry
|
|
33
|
+
|
|
34
|
+
# Skip rows where geometry is None
|
|
35
|
+
if line is None:
|
|
36
|
+
print(row)
|
|
37
|
+
continue
|
|
38
|
+
|
|
39
|
+
inter_poly = poly_gdf.iloc[spatial_index.query(line)]
|
|
40
|
+
line_args.append([line_gdf.iloc[[i]], inter_poly, n_samples, offset, i])
|
|
41
|
+
|
|
42
|
+
return line_args
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
# Calculating Line Widths
|
|
46
|
+
def generate_sample_points(line, n_samples=10):
|
|
47
|
+
"""
|
|
48
|
+
Generate evenly spaced points along a line.
|
|
49
|
+
|
|
50
|
+
Parameters
|
|
51
|
+
----------
|
|
52
|
+
line : shapely LineString
|
|
53
|
+
The line along which to generate points.
|
|
54
|
+
n_samples : int, optional
|
|
55
|
+
The number of points to generate (default is 10).
|
|
56
|
+
|
|
57
|
+
Returns
|
|
58
|
+
-------
|
|
59
|
+
list
|
|
60
|
+
List of shapely Point objects.
|
|
61
|
+
"""
|
|
62
|
+
# return [line.interpolate(i / n_samples, normalized=True) for i in range(n_samples)]
|
|
63
|
+
return [Point(item) for item in list(line.coords)]
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def generate_perpendicular_line(point, line, offset=FP_PERP_LINE_OFFSET):
|
|
67
|
+
"""
|
|
68
|
+
Generate a perpendicular line to the input line at the given point.
|
|
69
|
+
|
|
70
|
+
Parameters
|
|
71
|
+
----------
|
|
72
|
+
point : shapely.geometry.Point
|
|
73
|
+
The point on the line where the perpendicular should be generated.
|
|
74
|
+
line : shapely.geometry.LineString
|
|
75
|
+
The line to which the perpendicular line will be generated.
|
|
76
|
+
offset : float, optional
|
|
77
|
+
The length of the perpendicular line.
|
|
78
|
+
|
|
79
|
+
Returns
|
|
80
|
+
-------
|
|
81
|
+
shapely.geometry.LineString
|
|
82
|
+
The generated perpendicular line.
|
|
83
|
+
"""
|
|
84
|
+
# Compute the angle of the line
|
|
85
|
+
p1, p2 = line.coords[0], line.coords[-1] # Modify this line
|
|
86
|
+
angle = np.arctan2(p2[1] - p1[1], p2[0] - p1[0])
|
|
87
|
+
|
|
88
|
+
# Compute the angle of the perpendicular line
|
|
89
|
+
angle_perp = angle + np.pi / 2.0 # Perpendicular angle
|
|
90
|
+
|
|
91
|
+
# Generate the perpendicular line
|
|
92
|
+
perp_line = LineString([(point.x - offset * np.cos(angle_perp), point.y - offset * np.sin(angle_perp)),
|
|
93
|
+
(point.x + offset * np.cos(angle_perp), point.y + offset * np.sin(angle_perp))])
|
|
94
|
+
|
|
95
|
+
return perp_line
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def process_single_line(line_arg):
|
|
99
|
+
row = line_arg[0]
|
|
100
|
+
inter_poly = line_arg[1]
|
|
101
|
+
n_samples = line_arg[2]
|
|
102
|
+
offset = line_arg[3]
|
|
103
|
+
line_id = line_arg[4]
|
|
104
|
+
|
|
105
|
+
widths, line, perp_lines = calculate_average_width(row.iloc[0].geometry, inter_poly, offset, n_samples)
|
|
106
|
+
|
|
107
|
+
# Calculate the 75th percentile width
|
|
108
|
+
# filter zeros in width array
|
|
109
|
+
arr_filter = [False if math.isclose(i, 0.0) else True for i in widths]
|
|
110
|
+
widths = widths[arr_filter]
|
|
111
|
+
|
|
112
|
+
q3_width = FP_FIXED_WIDTH_DEFAULT
|
|
113
|
+
q4_width = FP_FIXED_WIDTH_DEFAULT
|
|
114
|
+
try:
|
|
115
|
+
q3_width = np.percentile(widths, 40)
|
|
116
|
+
q4_width = np.percentile(widths, 90)
|
|
117
|
+
except Exception as e:
|
|
118
|
+
print(e)
|
|
119
|
+
|
|
120
|
+
# Store the 75th percentile width as a new attribute
|
|
121
|
+
row['avg_width'] = q3_width
|
|
122
|
+
row['max_width'] = q4_width
|
|
123
|
+
hist, bins = np.histogram(widths)
|
|
124
|
+
bins = pd.Series(bins).rolling(2).mean()[1:].to_numpy() # mid-points of bins
|
|
125
|
+
row['width_hist'] = str(hist)
|
|
126
|
+
row['width_bins'] = str(bins)
|
|
127
|
+
|
|
128
|
+
row['geometry'] = line
|
|
129
|
+
try:
|
|
130
|
+
row['perp_lines'] = perp_lines
|
|
131
|
+
except Exception as e:
|
|
132
|
+
print(e)
|
|
133
|
+
|
|
134
|
+
print('line processed: {}'.format(line_id))
|
|
135
|
+
|
|
136
|
+
return row
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def generate_fixed_width_footprint(line_gdf, shp_footprint, max_width=False):
|
|
140
|
+
"""
|
|
141
|
+
Creates a buffer around each line in the GeoDataFrame using its 'max_width' attribute and
|
|
142
|
+
saves the resulting polygons in a new shapefile.
|
|
143
|
+
|
|
144
|
+
Parameters:
|
|
145
|
+
- line_gdf: A GeoDataFrame containing LineString geometries with 'max_width' attribute.
|
|
146
|
+
- output_file_path: The path where the output shapefile will be stored.
|
|
147
|
+
"""
|
|
148
|
+
# Create a new GeoDataFrame with the buffer polygons
|
|
149
|
+
buffer_gdf = line_gdf.copy(deep=True)
|
|
150
|
+
|
|
151
|
+
mean_avg_width = line_gdf['avg_width'].mean()
|
|
152
|
+
mean_max_width = line_gdf['max_width'].mean()
|
|
153
|
+
|
|
154
|
+
line_gdf['avg_width'].fillna(mean_avg_width, inplace=True)
|
|
155
|
+
line_gdf['max_width'].fillna(mean_max_width, inplace=True)
|
|
156
|
+
|
|
157
|
+
line_gdf['avg_width'].replace(0.0, mean_avg_width, inplace=True)
|
|
158
|
+
line_gdf['max_width'].replace(0.0, mean_max_width, inplace=True)
|
|
159
|
+
|
|
160
|
+
if not max_width:
|
|
161
|
+
print('Using quantile 75% width')
|
|
162
|
+
buffer_gdf['geometry'] = line_gdf.apply(
|
|
163
|
+
lambda row: row.geometry.buffer(row.avg_width / 2) if row.geometry is not None else None, axis=1)
|
|
164
|
+
else:
|
|
165
|
+
print('Using quantile 90% + 20% width')
|
|
166
|
+
buffer_gdf['geometry'] = line_gdf.apply(
|
|
167
|
+
lambda row: row.geometry.buffer(row.max_width * 1.2 / 2) if row.geometry is not None else None, axis=1)
|
|
168
|
+
|
|
169
|
+
return buffer_gdf
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def smooth_linestring(line, tolerance=1.0):
|
|
173
|
+
"""
|
|
174
|
+
Smooths a LineString geometry using the Ramer-Douglas-Peucker algorithm.
|
|
175
|
+
|
|
176
|
+
Parameters:
|
|
177
|
+
- line: The LineString geometry to smooth.
|
|
178
|
+
- tolerance: The maximum distance from a point to a line for the point to be considered part of the line.
|
|
179
|
+
|
|
180
|
+
Returns:
|
|
181
|
+
The smoothed LineString geometry.
|
|
182
|
+
"""
|
|
183
|
+
# simplified_line = line.simplify(tolerance)
|
|
184
|
+
simplified_line = line
|
|
185
|
+
return simplified_line
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def calculate_average_width(line, polygon, offset, n_samples):
|
|
189
|
+
"""
|
|
190
|
+
Calculates the average width of a polygon perpendicular to the given line.
|
|
191
|
+
"""
|
|
192
|
+
# Smooth the line
|
|
193
|
+
line = smooth_linestring(line, tolerance=1.0)
|
|
194
|
+
|
|
195
|
+
valid_widths = 0
|
|
196
|
+
sample_points = generate_sample_points(line, n_samples=n_samples)
|
|
197
|
+
sample_points_pairs = list(zip(sample_points[:-2], sample_points[1:-1], sample_points[2:]))
|
|
198
|
+
widths = np.zeros(len(sample_points_pairs))
|
|
199
|
+
perp_lines = []
|
|
200
|
+
|
|
201
|
+
# remove polygon holes
|
|
202
|
+
poly_list = []
|
|
203
|
+
for geom in polygon.geometry:
|
|
204
|
+
if type(geom) is MultiPolygon:
|
|
205
|
+
for item in geom.geoms:
|
|
206
|
+
poly_list.append(Polygon(list(item.exterior.coords)))
|
|
207
|
+
else:
|
|
208
|
+
poly_list.append(Polygon(list(geom.exterior.coords)))
|
|
209
|
+
|
|
210
|
+
polygon_no_holes = gpd.GeoDataFrame(geometry=poly_list, crs=polygon.crs)
|
|
211
|
+
|
|
212
|
+
for i, points in enumerate(sample_points_pairs):
|
|
213
|
+
perp_line = generate_perpendicular_line_precise(points, offset=offset)
|
|
214
|
+
|
|
215
|
+
polygon_intersect = polygon_no_holes.iloc[polygon_no_holes.sindex.query(perp_line)]
|
|
216
|
+
intersections = polygon_intersect.intersection(perp_line)
|
|
217
|
+
|
|
218
|
+
line_list = []
|
|
219
|
+
try:
|
|
220
|
+
for inter in intersections:
|
|
221
|
+
if not inter.is_empty:
|
|
222
|
+
if type(inter) is MultiLineString:
|
|
223
|
+
line_list += list(inter.geoms)
|
|
224
|
+
else:
|
|
225
|
+
line_list.append(inter)
|
|
226
|
+
|
|
227
|
+
perp_lines += line_list
|
|
228
|
+
except Exception as e:
|
|
229
|
+
print(e)
|
|
230
|
+
|
|
231
|
+
try:
|
|
232
|
+
for item in line_list:
|
|
233
|
+
widths[i] = max(widths[i], item.length)
|
|
234
|
+
valid_widths += 1
|
|
235
|
+
except Exception as e:
|
|
236
|
+
print(e)
|
|
237
|
+
|
|
238
|
+
return widths, line, MultiLineString(perp_lines)
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def line_footprint_fixed(callback, in_line, in_footprint, n_samples, offset, max_width,
|
|
242
|
+
out_footprint, processes, verbose):
|
|
243
|
+
n_samples = int(n_samples)
|
|
244
|
+
offset = float(offset)
|
|
245
|
+
line_args = prepare_line_args(in_line, in_footprint, n_samples, offset)
|
|
246
|
+
|
|
247
|
+
out_lines = execute_multiprocessing(process_single_line, line_args, 'Fixed footprint',
|
|
248
|
+
processes, 1, verbose=verbose)
|
|
249
|
+
line_attr = pd.concat(out_lines)
|
|
250
|
+
|
|
251
|
+
# create fixed width footprint
|
|
252
|
+
buffer_gdf = generate_fixed_width_footprint(line_attr, in_footprint, max_width=max_width)
|
|
253
|
+
|
|
254
|
+
# Save the lines with attributes and polygons to a new shapefile
|
|
255
|
+
perp_lines_gdf = buffer_gdf.copy(deep=True)
|
|
256
|
+
buffer_gdf = buffer_gdf.drop(columns=['perp_lines'])
|
|
257
|
+
buffer_gdf.crs = perp_lines_gdf.crs
|
|
258
|
+
buffer_gdf.to_file(out_footprint)
|
|
259
|
+
|
|
260
|
+
# perpendicular lines
|
|
261
|
+
perp_lines_gdf = perp_lines_gdf.set_geometry('perp_lines')
|
|
262
|
+
perp_lines_gdf = perp_lines_gdf.drop(columns=['geometry'])
|
|
263
|
+
perp_lines_gdf.crs = buffer_gdf.crs
|
|
264
|
+
perp_lines_path = Path(out_footprint).with_stem(Path(out_footprint).stem + '_perp_lines')
|
|
265
|
+
perp_lines_gdf.to_file(perp_lines_path)
|
|
266
|
+
|
|
267
|
+
geojson_path = Path(out_footprint).with_suffix('.geojson')
|
|
268
|
+
buffer_gpd_4326 = buffer_gdf.to_crs('EPSG:4326')
|
|
269
|
+
buffer_gpd_4326.to_file(geojson_path.as_posix(), driver='GeoJSON')
|
|
270
|
+
|
|
271
|
+
gdf_simplified_path = Path(in_line).with_stem(Path(in_line).stem + "_simplified")
|
|
272
|
+
line_attr = line_attr.drop(columns='perp_lines')
|
|
273
|
+
line_attr.to_file(gdf_simplified_path)
|
|
274
|
+
|
|
275
|
+
callback('Fixed width footprint tool finished.')
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
if __name__ == '__main__':
|
|
279
|
+
in_args, in_verbose = check_arguments()
|
|
280
|
+
start_time = time.time()
|
|
281
|
+
line_footprint_fixed(print, **in_args.input, processes=int(in_args.processes), verbose=in_verbose)
|
|
282
|
+
print('Elapsed time: {}'.format(time.time() - start_time))
|