ign-pdal-tools 1.7.9__py3-none-any.whl → 1.7.11__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.
- {ign_pdal_tools-1.7.9.dist-info → ign_pdal_tools-1.7.11.dist-info}/METADATA +3 -2
- {ign_pdal_tools-1.7.9.dist-info → ign_pdal_tools-1.7.11.dist-info}/RECORD +7 -7
- {ign_pdal_tools-1.7.9.dist-info → ign_pdal_tools-1.7.11.dist-info}/WHEEL +1 -1
- pdaltools/_version.py +1 -1
- pdaltools/add_points_in_pointcloud.py +210 -40
- {ign_pdal_tools-1.7.9.dist-info → ign_pdal_tools-1.7.11.dist-info/licenses}/LICENSE.md +0 -0
- {ign_pdal_tools-1.7.9.dist-info → ign_pdal_tools-1.7.11.dist-info}/top_level.txt +0 -0
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: ign-pdal-tools
|
|
3
|
-
Version: 1.7.
|
|
3
|
+
Version: 1.7.11
|
|
4
4
|
Summary: Library for common LAS files manipulation with PDAL
|
|
5
5
|
Author-email: Guillaume Liegard <guillaume.liegard@ign.fr>
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
7
7
|
License-File: LICENSE.md
|
|
8
|
+
Dynamic: license-file
|
|
8
9
|
|
|
9
10
|
# ign-pdal-tools
|
|
10
11
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
ign_pdal_tools-1.7.11.dist-info/licenses/LICENSE.md,sha256=iVzCFZTUXeiqP8bP474iuWZiWO_kDCD4SPh1Wiw125Y,1120
|
|
2
|
+
pdaltools/_version.py,sha256=lXuB5yCoqB_XdA0YVaGjTGc2J_sFF0RE_IJePTMnyjI,75
|
|
2
3
|
pdaltools/add_points_in_las.py,sha256=TGbt5JUkszjmbQiA2LCUntsjz6A8DHb7QPIXGDuEgWA,3643
|
|
3
|
-
pdaltools/add_points_in_pointcloud.py,sha256=
|
|
4
|
+
pdaltools/add_points_in_pointcloud.py,sha256=UHdC8tFagsehGggkLJCcmBCi8gknJOL4s99f_2TJjsA,12538
|
|
4
5
|
pdaltools/color.py,sha256=-a0ramyLMkZX4-M3siPq1zIio5u-a0p8UzvgcfoU6zU,8313
|
|
5
6
|
pdaltools/las_add_buffer.py,sha256=sBpTywlfsHHS8KuCUa-eydB2hylshEvjrMQt5TrqXb8,11275
|
|
6
7
|
pdaltools/las_clip.py,sha256=GvEOYu8RXV68e35kU8i42GwSkbo4P9TvmS6rkrdPmFM,1034
|
|
@@ -11,8 +12,7 @@ pdaltools/pcd_info.py,sha256=NIAH5KGikVDQLlbCcw9FuaPqe20UZvRfkHsDZd5kmZA,3210
|
|
|
11
12
|
pdaltools/replace_attribute_in_las.py,sha256=po1F-fi8s7iilqKWaryW4JRbsmdMOUe0yGvG3AEKxtk,4771
|
|
12
13
|
pdaltools/standardize_format.py,sha256=gqm2GJbtDkT4k4oC_NX2LIPh9R2BLh4sMHLKYgfKrMc,3973
|
|
13
14
|
pdaltools/unlock_file.py,sha256=pIThdWMNkTph0xgJVVRaM1o9aUMQhM6804PscScB3JI,1963
|
|
14
|
-
ign_pdal_tools-1.7.
|
|
15
|
-
ign_pdal_tools-1.7.
|
|
16
|
-
ign_pdal_tools-1.7.
|
|
17
|
-
ign_pdal_tools-1.7.
|
|
18
|
-
ign_pdal_tools-1.7.9.dist-info/RECORD,,
|
|
15
|
+
ign_pdal_tools-1.7.11.dist-info/METADATA,sha256=Bh4cFjnGLLt4DpiPw8GQuknhDTrLQqx3H5EjkFzV1n4,5745
|
|
16
|
+
ign_pdal_tools-1.7.11.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
|
17
|
+
ign_pdal_tools-1.7.11.dist-info/top_level.txt,sha256=KvGW0ZzqQbhCKzB5_Tp_buWMZyIgiO2M2krWF_ecOZc,10
|
|
18
|
+
ign_pdal_tools-1.7.11.dist-info/RECORD,,
|
pdaltools/_version.py
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import argparse
|
|
2
|
-
import
|
|
2
|
+
from shutil import copy2
|
|
3
3
|
|
|
4
4
|
import geopandas as gpd
|
|
5
5
|
import laspy
|
|
6
6
|
import numpy as np
|
|
7
7
|
from pyproj import CRS
|
|
8
8
|
from pyproj.exceptions import CRSError
|
|
9
|
-
from shapely.geometry import box
|
|
9
|
+
from shapely.geometry import MultiPoint, Point, box
|
|
10
10
|
|
|
11
11
|
from pdaltools.las_info import get_epsg_from_las, get_tile_bbox
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
def parse_args(argv=None):
|
|
15
15
|
parser = argparse.ArgumentParser("Add points from GeoJSON in LIDAR tile")
|
|
16
|
-
parser.add_argument(
|
|
16
|
+
parser.add_argument(
|
|
17
|
+
"--input_geometry", "-ig", type=str, required=True, help="Input Geometry file (GeoJSON or Shapefile)"
|
|
18
|
+
)
|
|
17
19
|
parser.add_argument("--input_las", "-i", type=str, required=True, help="Input las file")
|
|
18
20
|
parser.add_argument("--output_las", "-o", type=str, required=True, default="", help="Output las file")
|
|
19
21
|
parser.add_argument(
|
|
@@ -35,72 +37,112 @@ def parse_args(argv=None):
|
|
|
35
37
|
default=1000,
|
|
36
38
|
help="width of tiles in meters",
|
|
37
39
|
)
|
|
40
|
+
parser.add_argument(
|
|
41
|
+
"--spacing",
|
|
42
|
+
type=float,
|
|
43
|
+
default=0.25,
|
|
44
|
+
help="spacing between generated points in meters (default. 25 cm)",
|
|
45
|
+
)
|
|
46
|
+
parser.add_argument(
|
|
47
|
+
"--altitude_column",
|
|
48
|
+
"-z",
|
|
49
|
+
type=str,
|
|
50
|
+
required=False,
|
|
51
|
+
default=None,
|
|
52
|
+
help="altitude column name from input geometry (use point.z if altitude_column is not set)",
|
|
53
|
+
)
|
|
38
54
|
|
|
39
55
|
return parser.parse_args(argv)
|
|
40
56
|
|
|
41
57
|
|
|
42
|
-
def
|
|
58
|
+
def clip_3d_lines_to_tile(
|
|
59
|
+
input_lines: gpd.GeoDataFrame, input_las: str, crs: str, tile_width: int = 1000
|
|
60
|
+
) -> gpd.GeoDataFrame:
|
|
43
61
|
"""
|
|
44
|
-
|
|
62
|
+
Select lines from a GeoDataFrame that intersect the the LIDAR tile.
|
|
45
63
|
|
|
46
64
|
Args:
|
|
47
|
-
|
|
65
|
+
input_lines (gpd.GeoDataFrame): GeoDataFrame with lines.
|
|
48
66
|
input_las (str): Path to the LIDAR `.las/.laz` file.
|
|
49
67
|
crs (str): CRS of the data.
|
|
50
68
|
tile_width (int): Width of the tile in meters (default: 1000).
|
|
51
69
|
|
|
52
|
-
|
|
53
|
-
gpd.GeoDataFrame:
|
|
70
|
+
Returns:
|
|
71
|
+
gpd.GeoDataFrame: Lines that intersect with the tile.
|
|
54
72
|
"""
|
|
55
73
|
# Compute the bounding box of the LIDAR tile
|
|
56
74
|
tile_bbox = get_tile_bbox(input_las, tile_width)
|
|
57
75
|
|
|
58
|
-
|
|
59
|
-
|
|
76
|
+
if crs:
|
|
77
|
+
input_lines = input_lines.to_crs(crs)
|
|
78
|
+
|
|
79
|
+
# Create a polygon from the bounding box
|
|
80
|
+
bbox_polygon = box(*tile_bbox)
|
|
81
|
+
|
|
82
|
+
# Clip the lines to the bounding box
|
|
83
|
+
clipped_lines = input_lines[input_lines.intersects(bbox_polygon)]
|
|
84
|
+
|
|
85
|
+
return clipped_lines
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def clip_3d_points_to_tile(
|
|
89
|
+
input_points: gpd.GeoDataFrame, input_las: str, crs: str, tile_width: int = 1000
|
|
90
|
+
) -> gpd.GeoDataFrame:
|
|
91
|
+
"""
|
|
92
|
+
Select points from a GeoDataFrame that intersect the LIDAR tile
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
input_points (gpd.GeoDataFrame): GeoDataFrame with 3D points.
|
|
96
|
+
input_las (str): Path to the LIDAR `.las/.laz` file.
|
|
97
|
+
crs (str): CRS of the data.
|
|
98
|
+
tile_width (int): Width of the tile in meters (default: 1000).
|
|
99
|
+
|
|
100
|
+
Return:
|
|
101
|
+
gpd.GeoDataFrame: Points 2D with "Z" value
|
|
102
|
+
"""
|
|
103
|
+
# Compute the bounding box of the LIDAR tile
|
|
104
|
+
tile_bbox = get_tile_bbox(input_las, tile_width)
|
|
60
105
|
|
|
61
106
|
if crs:
|
|
62
|
-
|
|
107
|
+
input_points = input_points.to_crs(crs)
|
|
63
108
|
|
|
64
109
|
# Create a polygon from the bounding box
|
|
65
110
|
bbox_polygon = box(*tile_bbox)
|
|
66
111
|
|
|
67
112
|
# Clip the points to the bounding box
|
|
68
|
-
clipped_points =
|
|
113
|
+
clipped_points = input_points[input_points.intersects(bbox_polygon)]
|
|
69
114
|
|
|
70
115
|
return clipped_points
|
|
71
116
|
|
|
72
117
|
|
|
73
118
|
def add_points_to_las(
|
|
74
|
-
input_points_with_z: gpd.GeoDataFrame, input_las: str, output_las: str, crs: str, virtual_points_classes=66
|
|
119
|
+
input_points_with_z: gpd.GeoDataFrame, input_las: str, output_las: str, crs: str, virtual_points_classes: int = 66
|
|
75
120
|
):
|
|
76
121
|
"""Add points (3D points in LAZ format) by LIDAR tiles (tiling file)
|
|
77
122
|
|
|
78
123
|
Args:
|
|
79
|
-
input_points_with_z(gpd.GeoDataFrame): geometry columns (
|
|
124
|
+
input_points_with_z (gpd.GeoDataFrame): geometry columns (3D points) as encoded to WKT.
|
|
80
125
|
input_las (str): Path to the LIDAR tiles (LAZ).
|
|
81
126
|
output_las (str): Path to save the updated LIDAR file (LAS/LAZ format).
|
|
82
127
|
crs (str): CRS of the data.
|
|
83
128
|
virtual_points_classes (int): The classification value to assign to those virtual points (default: 66).
|
|
84
129
|
"""
|
|
85
|
-
|
|
86
130
|
if input_points_with_z.empty:
|
|
87
131
|
print(
|
|
88
132
|
"No points to add. All points of the geojson file are outside the tile. Copying the input file to output"
|
|
89
133
|
)
|
|
90
|
-
shutil.copy(input_las, output_las)
|
|
91
|
-
|
|
92
134
|
return
|
|
93
135
|
|
|
94
136
|
# Extract XYZ coordinates and additional attribute (classification)
|
|
137
|
+
nb_points = len(input_points_with_z.geometry.x)
|
|
95
138
|
x_coords = input_points_with_z.geometry.x
|
|
96
139
|
y_coords = input_points_with_z.geometry.y
|
|
97
|
-
z_coords = input_points_with_z.
|
|
98
|
-
classes = virtual_points_classes * np.ones(
|
|
140
|
+
z_coords = input_points_with_z.geometry.z
|
|
141
|
+
classes = virtual_points_classes * np.ones(nb_points)
|
|
99
142
|
|
|
100
|
-
|
|
101
|
-
|
|
143
|
+
# Open the input LAS file to check and possibly update the header of the output
|
|
144
|
+
with laspy.open(input_las) as las:
|
|
102
145
|
header = las.header
|
|
103
|
-
|
|
104
146
|
if not header:
|
|
105
147
|
header = laspy.LasHeader(point_format=8, version="1.4")
|
|
106
148
|
if crs:
|
|
@@ -110,45 +152,173 @@ def add_points_to_las(
|
|
|
110
152
|
raise ValueError(f"Invalid CRS: {crs}")
|
|
111
153
|
header.add_crs(crs_obj)
|
|
112
154
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
155
|
+
# Copy data pointcloud
|
|
156
|
+
copy2(input_las, output_las)
|
|
157
|
+
|
|
158
|
+
# Add the new points with 3D points
|
|
159
|
+
nb_points = len(x_coords)
|
|
160
|
+
with laspy.open(output_las, mode="a", header=header) as output_las: # mode `a` for adding points
|
|
161
|
+
# create nb_points points with "0" everywhere
|
|
162
|
+
new_points = laspy.ScaleAwarePointRecord.zeros(nb_points, header=header) # use header for input_las
|
|
163
|
+
# then fill in the gaps (X, Y, Z an classification)
|
|
164
|
+
new_points.x = x_coords.astype(new_points.x.dtype)
|
|
165
|
+
new_points.y = y_coords.astype(new_points.y.dtype)
|
|
166
|
+
new_points.z = z_coords.astype(new_points.z.dtype)
|
|
167
|
+
new_points.classification = classes.astype(new_points.classification.dtype)
|
|
118
168
|
|
|
119
|
-
|
|
120
|
-
updated_las.x = new_x
|
|
121
|
-
updated_las.y = new_y
|
|
122
|
-
updated_las.z = new_z
|
|
123
|
-
updated_las.classification = new_classes
|
|
169
|
+
output_las.append_points(new_points)
|
|
124
170
|
|
|
125
|
-
with laspy.open(output_las, mode="w", header=header, do_compress=True) as writer:
|
|
126
|
-
writer.write_points(updated_las.points)
|
|
127
171
|
|
|
172
|
+
def line_to_multipoint(line, spacing: float, z_value: float = None):
|
|
173
|
+
"""
|
|
174
|
+
Convert a LineString to a MultiPoint with equally spaced points and a given Z value.
|
|
175
|
+
|
|
176
|
+
Args:
|
|
177
|
+
line (shapely.geometry.LineString): The input LineString.
|
|
178
|
+
spacing (float): Spacing between generated points in meters.
|
|
179
|
+
z_value (float): The Z value to assign to each point.
|
|
180
|
+
|
|
181
|
+
Returns:
|
|
182
|
+
shapely.geometry.MultiPoint: A MultiPoint geometry with the generated points.
|
|
183
|
+
"""
|
|
184
|
+
# Create points along the line with spacing
|
|
185
|
+
length = line.length
|
|
186
|
+
distances = np.arange(0, length + spacing, spacing)
|
|
187
|
+
points_nd = [line.interpolate(distance) for distance in distances]
|
|
188
|
+
|
|
189
|
+
if line.has_z:
|
|
190
|
+
multipoint = MultiPoint([Point(point.x, point.y, point.z) for point in points_nd])
|
|
191
|
+
else:
|
|
192
|
+
if z_value is None:
|
|
193
|
+
raise ValueError("z_value must be provided for 2D lines.")
|
|
194
|
+
multipoint = MultiPoint([Point(point.x, point.y, z_value) for point in points_nd])
|
|
128
195
|
|
|
129
|
-
|
|
130
|
-
|
|
196
|
+
return multipoint
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def generate_3d_points_from_lines(
|
|
200
|
+
lines_gdf: gpd.GeoDataFrame, spacing: float, altitude_column: str = None
|
|
201
|
+
) -> gpd.GeoDataFrame:
|
|
202
|
+
"""
|
|
203
|
+
Generate regularly spaced 3D points from 2.5D lines in a GeoJSON file.
|
|
204
|
+
|
|
205
|
+
Args:
|
|
206
|
+
lines_gdf (gpd.GeoDataFrame): GeoDataFrame with 2.5D lines.
|
|
207
|
+
spacing (float): Spacing between generated points in meters.
|
|
208
|
+
altitude_column (str, optional): Altitude column name from input geometry.
|
|
209
|
+
If not provided, use Z from geometry.
|
|
210
|
+
|
|
211
|
+
Returns:
|
|
212
|
+
gpd.GeoDataFrame: GeoDataFrame with generated 3D points.
|
|
213
|
+
|
|
214
|
+
Raises:
|
|
215
|
+
ValueError: If altitude_column is not provided or not found in the GeoDataFrame
|
|
216
|
+
and Z coordinates are not available in the geometry.
|
|
217
|
+
"""
|
|
218
|
+
# Check if altitude_column is provided and exists in the GeoDataFrame
|
|
219
|
+
if altitude_column and (altitude_column not in lines_gdf.columns):
|
|
220
|
+
raise ValueError("altitude_column must exist in the GeoDataFrame if provided.")
|
|
221
|
+
|
|
222
|
+
if altitude_column:
|
|
223
|
+
lines_gdf["geometry"] = lines_gdf.apply(
|
|
224
|
+
lambda row: line_to_multipoint(row.geometry, spacing, row[altitude_column]), axis=1
|
|
225
|
+
)
|
|
226
|
+
else:
|
|
227
|
+
# Check if geometries have Z values
|
|
228
|
+
if lines_gdf.geometry.has_z.any():
|
|
229
|
+
lines_gdf["geometry"] = lines_gdf.apply(
|
|
230
|
+
lambda row: line_to_multipoint(row.geometry, spacing, None), axis=1
|
|
231
|
+
)
|
|
232
|
+
else:
|
|
233
|
+
raise ValueError("Geometries do not have Z values and altitude_column is not provided.")
|
|
234
|
+
|
|
235
|
+
# Explode the MultiPoint geometries into individual points
|
|
236
|
+
points_gdf = lines_gdf.dissolve().explode(index_parts=False).reset_index(drop=True)
|
|
237
|
+
|
|
238
|
+
return points_gdf
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def add_points_from_geometry_to_las(
|
|
242
|
+
input_geometry: str,
|
|
243
|
+
input_las: str,
|
|
244
|
+
output_las: str,
|
|
245
|
+
virtual_points_classes: int,
|
|
246
|
+
spatial_ref: str,
|
|
247
|
+
tile_width: int,
|
|
248
|
+
spacing: float,
|
|
249
|
+
altitude_column: str,
|
|
131
250
|
):
|
|
132
|
-
"""Add points with Z value
|
|
251
|
+
"""Add points with Z value by LIDAR tiles (tiling file)
|
|
133
252
|
|
|
134
253
|
Args:
|
|
135
|
-
|
|
254
|
+
input_geometry (str): Path to the input geometry file (GeoJSON or Shapefile) with 3D points.
|
|
136
255
|
input_las (str): Path to the LIDAR `.las/.laz` file.
|
|
137
256
|
output_las (str): Path to save the updated LIDAR file (LAS/LAZ format).
|
|
138
257
|
virtual_points_classes (int): The classification value to assign to those virtual points (default: 66).
|
|
139
258
|
spatial_ref (str): CRS of the data.
|
|
140
259
|
tile_width (int): Width of the tile in meters (default: 1000).
|
|
260
|
+
spacing (float): Spacing between generated points in meters.
|
|
261
|
+
altitude_column (str): Altitude column name from input geometry
|
|
141
262
|
|
|
142
263
|
Raises:
|
|
143
264
|
RuntimeError: If the input LAS file has no valid EPSG code.
|
|
265
|
+
ValueError: Unsupported geometry type in the input Geometry file OR
|
|
266
|
+
The parameters "spacing" <= 0.
|
|
144
267
|
"""
|
|
145
268
|
if not spatial_ref:
|
|
146
269
|
spatial_ref = get_epsg_from_las(input_las)
|
|
147
270
|
if spatial_ref is None:
|
|
148
271
|
raise RuntimeError(f"LAS file {input_las} does not have a valid EPSG code.")
|
|
149
272
|
|
|
273
|
+
# Read the input GeoJSON
|
|
274
|
+
gdf = gpd.read_file(input_geometry)
|
|
275
|
+
|
|
276
|
+
if gdf.crs is None:
|
|
277
|
+
gdf.set_crs(epsg=spatial_ref, inplace=True)
|
|
278
|
+
|
|
279
|
+
# Check if both Z in geometries and altitude_column are provided
|
|
280
|
+
if gdf.geometry.has_z.any() and altitude_column:
|
|
281
|
+
raise ValueError("Both Z in geometries and altitude_column are provided. Please provide only one.")
|
|
282
|
+
|
|
283
|
+
# Store the unique geometry type in a variable
|
|
284
|
+
unique_geom_type = gdf.geometry.geom_type.unique()
|
|
285
|
+
|
|
286
|
+
# Check the geometry type
|
|
287
|
+
if len(unique_geom_type) != 1:
|
|
288
|
+
raise ValueError("Several geometry types found in geometry file. This case is not handled.")
|
|
289
|
+
|
|
290
|
+
if unique_geom_type in ["Point", "MultiPoint"]:
|
|
291
|
+
gdf = gdf.explode(index_parts=False).reset_index(drop=True)
|
|
292
|
+
if altitude_column:
|
|
293
|
+
# Add the Z dimension from the 'RecupZ' property
|
|
294
|
+
gdf["geometry"] = gdf.apply(
|
|
295
|
+
lambda row: Point(row["geometry"].x, row["geometry"].y, row[altitude_column]), axis=1
|
|
296
|
+
)
|
|
297
|
+
# If the geometry type is Point, use the points directly
|
|
298
|
+
points_gdf = gdf[["geometry"]]
|
|
299
|
+
else:
|
|
300
|
+
# Add the Z dimension from the Geometry Z
|
|
301
|
+
gdf["geometry"] = gdf.apply(
|
|
302
|
+
lambda row: Point(row["geometry"].x, row["geometry"].y, row["geometry"].z), axis=1
|
|
303
|
+
)
|
|
304
|
+
# If the geometry type is Point, use the points directly
|
|
305
|
+
points_gdf = gdf[["geometry"]]
|
|
306
|
+
elif unique_geom_type in ["LineString", "MultiLineString"]:
|
|
307
|
+
gdf = gdf.explode(index_parts=False).reset_index(drop=True)
|
|
308
|
+
gdf = clip_3d_lines_to_tile(gdf, input_las, spatial_ref, tile_width)
|
|
309
|
+
# If the geometry type is LineString, generate 3D points
|
|
310
|
+
if spacing <= 0:
|
|
311
|
+
raise NotImplementedError(
|
|
312
|
+
f"add_points_from_geometry_to_las requires spacing > 0 to run on (Multi)LineString geometries, \
|
|
313
|
+
but the values provided are geometry type: {unique_geom_type} and spacing = {spacing} "
|
|
314
|
+
)
|
|
315
|
+
else:
|
|
316
|
+
points_gdf = generate_3d_points_from_lines(gdf, spacing, altitude_column)
|
|
317
|
+
else:
|
|
318
|
+
raise ValueError("Unsupported geometry type in the input Geometry file.")
|
|
319
|
+
|
|
150
320
|
# Clip points from GeoJSON by LIDAR tile
|
|
151
|
-
points_clipped = clip_3d_points_to_tile(
|
|
321
|
+
points_clipped = clip_3d_points_to_tile(points_gdf, input_las, spatial_ref, tile_width)
|
|
152
322
|
|
|
153
323
|
# Add points by LIDAR tile and save the result
|
|
154
324
|
add_points_to_las(points_clipped, input_las, output_las, spatial_ref, virtual_points_classes)
|
|
@@ -156,4 +326,4 @@ def add_points_from_geojson_to_las(
|
|
|
156
326
|
|
|
157
327
|
if __name__ == "__main__":
|
|
158
328
|
args = parse_args()
|
|
159
|
-
|
|
329
|
+
add_points_from_geometry_to_las(**vars(args))
|
|
File without changes
|
|
File without changes
|