ign-pdal-tools 1.7.7__tar.gz → 1.7.9__tar.gz

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.
Files changed (35) hide show
  1. {ign_pdal_tools-1.7.7 → ign_pdal_tools-1.7.9}/PKG-INFO +1 -1
  2. {ign_pdal_tools-1.7.7 → ign_pdal_tools-1.7.9}/ign_pdal_tools.egg-info/PKG-INFO +1 -1
  3. {ign_pdal_tools-1.7.7 → ign_pdal_tools-1.7.9}/pdaltools/_version.py +1 -1
  4. {ign_pdal_tools-1.7.7 → ign_pdal_tools-1.7.9}/pdaltools/add_points_in_pointcloud.py +9 -20
  5. {ign_pdal_tools-1.7.7 → ign_pdal_tools-1.7.9}/pdaltools/color.py +2 -9
  6. {ign_pdal_tools-1.7.7 → ign_pdal_tools-1.7.9}/pdaltools/las_info.py +26 -1
  7. ign_pdal_tools-1.7.9/test/test_add_points_in_pointcloud.py +117 -0
  8. {ign_pdal_tools-1.7.7 → ign_pdal_tools-1.7.9}/test/test_color.py +1 -1
  9. {ign_pdal_tools-1.7.7 → ign_pdal_tools-1.7.9}/test/test_las_info.py +21 -0
  10. {ign_pdal_tools-1.7.7 → ign_pdal_tools-1.7.9}/test/test_unlock.py +4 -0
  11. ign_pdal_tools-1.7.7/test/test_add_points_in_pointcloud.py +0 -172
  12. {ign_pdal_tools-1.7.7 → ign_pdal_tools-1.7.9}/LICENSE.md +0 -0
  13. {ign_pdal_tools-1.7.7 → ign_pdal_tools-1.7.9}/README.md +0 -0
  14. {ign_pdal_tools-1.7.7 → ign_pdal_tools-1.7.9}/ign_pdal_tools.egg-info/SOURCES.txt +0 -0
  15. {ign_pdal_tools-1.7.7 → ign_pdal_tools-1.7.9}/ign_pdal_tools.egg-info/dependency_links.txt +0 -0
  16. {ign_pdal_tools-1.7.7 → ign_pdal_tools-1.7.9}/ign_pdal_tools.egg-info/top_level.txt +0 -0
  17. {ign_pdal_tools-1.7.7 → ign_pdal_tools-1.7.9}/pdaltools/add_points_in_las.py +0 -0
  18. {ign_pdal_tools-1.7.7 → ign_pdal_tools-1.7.9}/pdaltools/las_add_buffer.py +0 -0
  19. {ign_pdal_tools-1.7.7 → ign_pdal_tools-1.7.9}/pdaltools/las_clip.py +0 -0
  20. {ign_pdal_tools-1.7.7 → ign_pdal_tools-1.7.9}/pdaltools/las_merge.py +0 -0
  21. {ign_pdal_tools-1.7.7 → ign_pdal_tools-1.7.9}/pdaltools/las_remove_dimensions.py +0 -0
  22. {ign_pdal_tools-1.7.7 → ign_pdal_tools-1.7.9}/pdaltools/pcd_info.py +0 -0
  23. {ign_pdal_tools-1.7.7 → ign_pdal_tools-1.7.9}/pdaltools/replace_attribute_in_las.py +0 -0
  24. {ign_pdal_tools-1.7.7 → ign_pdal_tools-1.7.9}/pdaltools/standardize_format.py +0 -0
  25. {ign_pdal_tools-1.7.7 → ign_pdal_tools-1.7.9}/pdaltools/unlock_file.py +0 -0
  26. {ign_pdal_tools-1.7.7 → ign_pdal_tools-1.7.9}/pyproject.toml +0 -0
  27. {ign_pdal_tools-1.7.7 → ign_pdal_tools-1.7.9}/setup.cfg +0 -0
  28. {ign_pdal_tools-1.7.7 → ign_pdal_tools-1.7.9}/test/test_add_points_in_las.py +0 -0
  29. {ign_pdal_tools-1.7.7 → ign_pdal_tools-1.7.9}/test/test_las_add_buffer.py +0 -0
  30. {ign_pdal_tools-1.7.7 → ign_pdal_tools-1.7.9}/test/test_las_clip.py +0 -0
  31. {ign_pdal_tools-1.7.7 → ign_pdal_tools-1.7.9}/test/test_las_merge.py +0 -0
  32. {ign_pdal_tools-1.7.7 → ign_pdal_tools-1.7.9}/test/test_las_remove_dimensions.py +0 -0
  33. {ign_pdal_tools-1.7.7 → ign_pdal_tools-1.7.9}/test/test_pcd_info.py +0 -0
  34. {ign_pdal_tools-1.7.7 → ign_pdal_tools-1.7.9}/test/test_replace_attribute_in_las.py +0 -0
  35. {ign_pdal_tools-1.7.7 → ign_pdal_tools-1.7.9}/test/test_standardize_format.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: ign-pdal-tools
3
- Version: 1.7.7
3
+ Version: 1.7.9
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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: ign-pdal-tools
3
- Version: 1.7.7
3
+ Version: 1.7.9
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
@@ -1,4 +1,4 @@
1
- __version__ = "1.7.7"
1
+ __version__ = "1.7.9"
2
2
 
3
3
 
4
4
  if __name__ == "__main__":
@@ -1,4 +1,5 @@
1
1
  import argparse
2
+ import shutil
2
3
 
3
4
  import geopandas as gpd
4
5
  import laspy
@@ -7,7 +8,7 @@ from pyproj import CRS
7
8
  from pyproj.exceptions import CRSError
8
9
  from shapely.geometry import box
9
10
 
10
- from pdaltools.las_info import get_epsg_from_las, get_tile_origin_using_header_info
11
+ from pdaltools.las_info import get_epsg_from_las, get_tile_bbox
11
12
 
12
13
 
13
14
  def parse_args(argv=None):
@@ -38,23 +39,6 @@ def parse_args(argv=None):
38
39
  return parser.parse_args(argv)
39
40
 
40
41
 
41
- def get_tile_bbox(input_las, tile_width=1000) -> tuple:
42
- """
43
- Get the theoretical bounding box (xmin, ymin, xmax, ymax) of a LIDAR tile
44
- using its origin and the predefined tile width.
45
-
46
- Args:
47
- input_las (str): Path to the LIDAR `.las/.laz` file.
48
- tile_width (int): Width of the tile in meters (default: 1000).
49
-
50
- Returns:
51
- tuple: Bounding box as (xmin, ymin, xmax, ymax).
52
- """
53
- origin_x, origin_y = get_tile_origin_using_header_info(input_las)
54
- bbox = (origin_x, origin_y - tile_width, origin_x + tile_width, origin_y)
55
- return bbox
56
-
57
-
58
42
  def clip_3d_points_to_tile(input_points: str, input_las: str, crs: str, tile_width: int) -> gpd.GeoDataFrame:
59
43
  """
60
44
  Add points from a GeoJSON file in the LIDAR's tile.
@@ -98,9 +82,14 @@ def add_points_to_las(
98
82
  crs (str): CRS of the data.
99
83
  virtual_points_classes (int): The classification value to assign to those virtual points (default: 66).
100
84
  """
101
- # Check if input points are empty
85
+
102
86
  if input_points_with_z.empty:
103
- raise ValueError("No points to add. The input GeoDataFrame is empty.")
87
+ print(
88
+ "No points to add. All points of the geojson file are outside the tile. Copying the input file to output"
89
+ )
90
+ shutil.copy(input_las, output_las)
91
+
92
+ return
104
93
 
105
94
  # Extract XYZ coordinates and additional attribute (classification)
106
95
  x_coords = input_points_with_z.geometry.x
@@ -37,15 +37,9 @@ def retry(times, delay, factor=2, debug=False):
37
37
  need_retry = False
38
38
  try:
39
39
  return func(*args, **kwargs)
40
- except requests.exceptions.ConnectionError as err:
40
+ except requests.exceptions.RequestException as err:
41
41
  print("Connection Error:", err)
42
42
  need_retry = True
43
- except requests.exceptions.HTTPError as err:
44
- if "Server Error" in str(err):
45
- print("HTTP Error:", err)
46
- need_retry = True
47
- else:
48
- raise err
49
43
  if need_retry:
50
44
  print(f"{attempt}/{times} Nouvel essai après une pause de {pretty_time_delta(new_delay)} .. ")
51
45
  if not debug:
@@ -126,8 +120,7 @@ def color(
126
120
 
127
121
  writer_extra_dims = "all"
128
122
 
129
- # apply decorator to retry 3 times, and wait 30 seconds each times
130
- download_image_from_geoplateforme_retrying = retry(7, 15, 2)(download_image_from_geoplateforme)
123
+ download_image_from_geoplateforme_retrying = retry(times=9, delay=5, factor=2)(download_image_from_geoplateforme)
131
124
 
132
125
  if veget_index_file and veget_index_file != "":
133
126
  print(f"Remplissage du champ Deviation à partir du fichier {veget_index_file}")
@@ -1,6 +1,7 @@
1
1
  import json
2
2
  import logging
3
3
  import os
4
+ from pathlib import Path
4
5
  from typing import Dict, Tuple
5
6
 
6
7
  import laspy
@@ -51,6 +52,23 @@ def get_tile_origin_using_header_info(filename: str, tile_width: int = 1000) ->
51
52
  return infer_tile_origin(minx, maxx, miny, maxy, tile_width)
52
53
 
53
54
 
55
+ def get_tile_bbox(input_las, tile_width=1000) -> tuple:
56
+ """
57
+ Get the theoretical bounding box (xmin, ymin, xmax, ymax) of a LIDAR tile
58
+ using its origin and the predefined tile width.
59
+
60
+ Args:
61
+ input_las (str): Path to the LIDAR `.las/.laz` file.
62
+ tile_width (int): Width of the tile in meters (default: 1000).
63
+
64
+ Returns:
65
+ tuple: Bounding box as (xmin, ymin, xmax, ymax).
66
+ """
67
+ origin_x, origin_y = get_tile_origin_using_header_info(input_las, tile_width)
68
+ bbox = (origin_x, origin_y - tile_width, origin_x + tile_width, origin_y)
69
+ return bbox
70
+
71
+
54
72
  def get_epsg_from_header_info(metadata):
55
73
  if "srs" not in metadata.keys():
56
74
  raise RuntimeError("EPSG could not be inferred from metadata: No 'srs' key in metadata.")
@@ -143,7 +161,14 @@ def parse_filename(file: str):
143
161
  For example Semis_2021_0000_1111_LA93_IGN69.las"""
144
162
  basename = os.path.basename(file) # Make sure that we work on the base name and not the full path
145
163
 
146
- prefix1, prefix2, coordx, coordy, suffix = basename.split("_", 4)
164
+ try:
165
+ prefix1, prefix2, coordx, coordy, suffix = basename.split("_", 4)
166
+ except ValueError:
167
+ raise ValueError(
168
+ f"Filename {Path(file).name} does not have the expected format. "
169
+ "Expected prefix1_prefix2_coordx_coordy_suffix"
170
+ )
171
+
147
172
  prefix = f"{prefix1}_{prefix2}"
148
173
 
149
174
  return prefix, int(coordx), int(coordy), suffix
@@ -0,0 +1,117 @@
1
+ import inspect
2
+ import os
3
+ from pathlib import Path
4
+
5
+ import geopandas as gpd
6
+ import pytest
7
+
8
+ from pdaltools import add_points_in_pointcloud
9
+ from pdaltools.count_occurences.count_occurences_for_attribute import (
10
+ compute_count_one_file,
11
+ )
12
+
13
+ TEST_PATH = os.path.dirname(os.path.abspath(__file__))
14
+ TMP_PATH = os.path.join(TEST_PATH, "tmp/add_points_in_pointcloud")
15
+ DATA_LIDAR_PATH = os.path.join(TEST_PATH, "data/decimated_laz")
16
+ DATA_POINTS_PATH = os.path.join(TEST_PATH, "data/points_3d")
17
+
18
+ INPUT_PCD = os.path.join(DATA_LIDAR_PATH, "test_semis_2023_0292_6833_LA93_IGN69.laz")
19
+ INPUT_POINTS = os.path.join(DATA_POINTS_PATH, "Points_virtuels_0292_6833.geojson")
20
+ OUTPUT_FILE = os.path.join(TMP_PATH, "test_semis_2023_0292_6833_LA93_IGN69.laz")
21
+
22
+ # Cropped las tile used to test adding points that belong to the theorical tile but not to the
23
+ # effective las file extent
24
+ INPUT_PCD_CROPPED = os.path.join(DATA_LIDAR_PATH, "test_semis_2021_0382_6565_LA93_IGN69_cropped.laz")
25
+ INPUT_POINTS_FOR_CROPPED_PCD = os.path.join(DATA_POINTS_PATH, "Points_virtuels_0382_6565.geojson")
26
+ OUTPUT_FILE_CROPPED_PCD = os.path.join(TMP_PATH, "test_semis_2021_0382_6565_LA93_IGN69.laz")
27
+
28
+
29
+ def setup_module(module):
30
+ os.makedirs(TMP_PATH, exist_ok=True)
31
+
32
+
33
+ @pytest.mark.parametrize(
34
+ "epsg",
35
+ [
36
+ "EPSG:2154", # should work when providing an epsg value
37
+ None, # Should also work with no epsg value (get from las file)
38
+ ],
39
+ )
40
+ def test_clip_3d_points_to_tile(epsg):
41
+ # With EPSG
42
+ points_clipped = add_points_in_pointcloud.clip_3d_points_to_tile(INPUT_POINTS, INPUT_PCD, epsg, 1000)
43
+ assert len(points_clipped) == 678 # check the entity's number of points
44
+
45
+
46
+ @pytest.mark.parametrize(
47
+ "input_file, epsg, expected_nb_points",
48
+ [
49
+ (INPUT_PCD, "EPSG:2154", 2423), # should work when providing an epsg value
50
+ (INPUT_PCD, None, 2423), # Should also work with no epsg value (get from las file)
51
+ (INPUT_PCD_CROPPED, None, 2423),
52
+ ],
53
+ )
54
+ def test_add_points_to_las(input_file, epsg, expected_nb_points):
55
+ # Ensure the output file doesn't exist before the test
56
+ if Path(OUTPUT_FILE).exists():
57
+ os.remove(OUTPUT_FILE)
58
+
59
+ points = gpd.read_file(INPUT_POINTS)
60
+ add_points_in_pointcloud.add_points_to_las(points, input_file, OUTPUT_FILE, epsg, 68)
61
+ assert Path(OUTPUT_FILE).exists() # check output exists
62
+
63
+ point_count = compute_count_one_file(OUTPUT_FILE)["68"]
64
+ assert point_count == expected_nb_points # Add all points from geojson
65
+
66
+
67
+ @pytest.mark.parametrize(
68
+ "input_file, input_points, epsg, expected_nb_points",
69
+ [
70
+ (INPUT_PCD, INPUT_POINTS, None, 678), # should add only points within tile extent
71
+ (INPUT_PCD_CROPPED, INPUT_POINTS_FOR_CROPPED_PCD, None, 186),
72
+ (
73
+ INPUT_PCD_CROPPED,
74
+ INPUT_POINTS,
75
+ None,
76
+ 0,
77
+ ), # Should add no points when there is only points outside the tile extent
78
+ (
79
+ INPUT_PCD_CROPPED,
80
+ INPUT_POINTS_FOR_CROPPED_PCD,
81
+ "EPSG:2154",
82
+ 186,
83
+ ), # Should work with or without an input epsg
84
+ ],
85
+ )
86
+ def test_add_points_from_geojson_to_las(input_file, input_points, epsg, expected_nb_points):
87
+ # Ensure the output file doesn't exist before the test
88
+ if Path(OUTPUT_FILE).exists():
89
+ os.remove(OUTPUT_FILE)
90
+
91
+ add_points_in_pointcloud.add_points_from_geojson_to_las(input_points, input_file, OUTPUT_FILE, 68, epsg, 1000)
92
+ assert Path(OUTPUT_FILE).exists() # check output exists
93
+ point_count = compute_count_one_file(OUTPUT_FILE)["68"]
94
+ assert point_count == expected_nb_points # Add all points from geojson
95
+
96
+
97
+ def test_parse_args():
98
+ # sanity check for arguments parsing
99
+ args = add_points_in_pointcloud.parse_args(
100
+ [
101
+ "--input_geojson",
102
+ "data/points_3d/Points_virtuels_0292_6833.geojson",
103
+ "--input_las",
104
+ "data/decimated_laz/test_semis_2023_0292_6833_LA93_IGN69.laz",
105
+ "--output_las",
106
+ "data/output/test_semis_2023_0292_6833_LA93_IGN69.laz",
107
+ "--virtual_points_classes",
108
+ "68",
109
+ "--spatial_ref",
110
+ "EPSG:2154",
111
+ "--tile_width",
112
+ "1000",
113
+ ]
114
+ )
115
+ parsed_args_keys = args.__dict__.keys()
116
+ main_parameters = inspect.signature(add_points_in_pointcloud.add_points_from_geojson_to_las).parameters.keys()
117
+ assert set(parsed_args_keys) == set(main_parameters)
@@ -140,7 +140,7 @@ def test_retry_on_connection_error():
140
140
 
141
141
  def test_retry_param():
142
142
  # Here you can change retry params
143
- @color.retry(7, 15, 2, True)
143
+ @color.retry(times=9, delay=5, factor=2, debug=True)
144
144
  def raise_server_error():
145
145
  raise requests.exceptions.HTTPError("Server Error")
146
146
 
@@ -45,6 +45,27 @@ def test_get_tile_origin_using_header_info():
45
45
  assert (origin_x, origin_y) == (COORD_X * TILE_COORD_SCALE, COORD_Y * TILE_COORD_SCALE)
46
46
 
47
47
 
48
+ @pytest.mark.parametrize(
49
+ "tile_filename, tile_width, expected_bbox",
50
+ [
51
+ ( # Standard 1000m tile width
52
+ os.path.join(DATA_PATH, "decimated_laz", "test_semis_2023_0292_6833_LA93_IGN69.laz"),
53
+ 1000,
54
+ (292000.0, 6832000.0, 293000.0, 6833000.0),
55
+ ),
56
+ (
57
+ # Test 50m tile
58
+ INPUT_FILE,
59
+ 50,
60
+ (INPUT_MINS[0], INPUT_MINS[1], INPUT_MAXS[0], INPUT_MAXS[1]),
61
+ ),
62
+ ],
63
+ )
64
+ def test_get_tile_bbox(tile_filename, tile_width, expected_bbox):
65
+ bbox = las_info.get_tile_bbox(tile_filename, tile_width)
66
+ assert bbox == expected_bbox # check the bbox from LIDAR tile
67
+
68
+
48
69
  def test_get_epsg_from_quickinfo_metadata_ok():
49
70
  metadata = las_info.las_info_metadata(INPUT_FILE)
50
71
  assert las_info.get_epsg_from_header_info(metadata) == "2154"
@@ -52,6 +52,10 @@ def test_copy_and_hack_decorator_color():
52
52
  assert os.path.isfile(LAS_FILE)
53
53
 
54
54
 
55
+ @pytest.mark.xfail(
56
+ reason="Unlock is deprecated as versions of pdal >= 2.7.2 don't raise an error anymore when GlobalEncoding "
57
+ "is not set correctly for WKT see https://github.com/PDAL/PDAL/releases/tag/2.7.2"
58
+ )
55
59
  def test_unlock_file():
56
60
  TMP_FILE = os.path.join(TMPDIR, "unlock_file.laz")
57
61
  shutil.copy(LAZ_FILE, TMP_FILE)
@@ -1,172 +0,0 @@
1
- import inspect
2
- import os
3
- from pathlib import Path
4
-
5
- import pdal
6
- import pytest
7
-
8
- from pdaltools import add_points_in_pointcloud
9
-
10
- TEST_PATH = os.path.dirname(os.path.abspath(__file__))
11
- TMP_PATH = os.path.join(TEST_PATH, "data/output")
12
- DATA_LIDAR_PATH = os.path.join(TEST_PATH, "data/decimated_laz")
13
- DATA_POINTS_PATH = os.path.join(TEST_PATH, "data/points_3d")
14
-
15
- INPUT_FILE = os.path.join(DATA_LIDAR_PATH, "test_semis_2023_0292_6833_LA93_IGN69.laz")
16
- INPUT_POINTS = os.path.join(DATA_POINTS_PATH, "Points_virtuels_0292_6833.geojson")
17
- OUTPUT_FILE = os.path.join(TMP_PATH, "test_semis_2023_0292_6833_LA93_IGN69.laz")
18
-
19
- INPUT_FILE_SMALL = os.path.join(DATA_LIDAR_PATH, "test_semis_2021_0382_6565_LA93_IGN69.laz")
20
- INPUT_POINTS_SMALL = os.path.join(DATA_POINTS_PATH, "Points_virtuels_0382_6565.geojson")
21
- OUTPUT_FILE_SMALL = os.path.join(TMP_PATH, "test_semis_2021_0382_6565_LA93_IGN69.laz")
22
-
23
-
24
- def setup_module(module):
25
- os.makedirs("test/data/output", exist_ok=True)
26
-
27
-
28
- def test_get_tile_bbox():
29
- bbox = add_points_in_pointcloud.get_tile_bbox(INPUT_FILE, 1000)
30
- assert bbox == (292000.0, 6832000.0, 293000.0, 6833000.0) # check the bbox from LIDAR tile
31
-
32
-
33
- def test_clip_3d_points_to_tile():
34
- # With EPSG
35
- points_clipped = add_points_in_pointcloud.clip_3d_points_to_tile(INPUT_POINTS, INPUT_FILE, "EPSG:2154", 1000)
36
- assert len(points_clipped) == 678 # chech the entity's number of points
37
-
38
-
39
- def test_clip_3d_points_to_tile_from_epsg_none():
40
- points_clipped = add_points_in_pointcloud.clip_3d_points_to_tile(INPUT_POINTS, INPUT_FILE, None, 1000)
41
- assert len(points_clipped) == 678 # chech the entity's number of points
42
-
43
-
44
- def test_add_line_to_lidar():
45
- # Ensure the output file doesn't exist before the test
46
- if Path(OUTPUT_FILE).exists():
47
- os.remove(OUTPUT_FILE)
48
-
49
- points_clipped = add_points_in_pointcloud.clip_3d_points_to_tile(INPUT_POINTS, INPUT_FILE, "EPSG:2154", 1000)
50
-
51
- add_points_in_pointcloud.add_points_to_las(points_clipped, INPUT_FILE, OUTPUT_FILE, "EPSG:2154", 68)
52
- assert Path(OUTPUT_FILE).exists() # check output exists
53
-
54
- # Filter pointcloud by classes
55
- pipeline = (
56
- pdal.Reader.las(filename=OUTPUT_FILE, nosrs=True)
57
- | pdal.Filter.range(
58
- limits="Classification[68:68]",
59
- )
60
- | pdal.Filter.stats()
61
- )
62
- pipeline.execute()
63
- metadata = pipeline.metadata
64
- # Count the pointcloud's number from classe "68"
65
- point_count = metadata["metadata"]["filters.stats"]["statistic"][0]["count"]
66
- assert point_count == 678
67
-
68
-
69
- def test_add_line_to_lidar_from_epsg_none():
70
- # Ensure the output file doesn't exist before the test
71
- if Path(OUTPUT_FILE).exists():
72
- os.remove(OUTPUT_FILE)
73
-
74
- points_clipped = add_points_in_pointcloud.clip_3d_points_to_tile(INPUT_POINTS, INPUT_FILE, None, 1000)
75
-
76
- add_points_in_pointcloud.add_points_to_las(points_clipped, INPUT_FILE, OUTPUT_FILE, None, 68)
77
- assert Path(OUTPUT_FILE).exists() # check output exists
78
-
79
- # Filter pointcloud by classes
80
- pipeline = (
81
- pdal.Reader.las(filename=OUTPUT_FILE, nosrs=True)
82
- | pdal.Filter.range(
83
- limits="Classification[68:68]",
84
- )
85
- | pdal.Filter.stats()
86
- )
87
- pipeline.execute()
88
- metadata = pipeline.metadata
89
- # Count the pointcloud's number from classe "68"
90
- point_count = metadata["metadata"]["filters.stats"]["statistic"][0]["count"]
91
- assert point_count == 678
92
-
93
-
94
- def test_get_tile_bbox_small():
95
- # Tile is not complete (NOT 1km * 1km)
96
- bbox = add_points_in_pointcloud.get_tile_bbox(INPUT_FILE_SMALL, 1000)
97
- assert bbox == (382000.0, 6564000.0, 383000.0, 6565000.0) # return BBOX 1km * 1km
98
-
99
-
100
- def test_add_line_to_lidar_small():
101
- # Ensure the output file doesn't exist before the test
102
- if Path(OUTPUT_FILE_SMALL).exists():
103
- os.remove(OUTPUT_FILE_SMALL)
104
-
105
- # Tile is not complete (NOT 1km * 1km)
106
- points_clipped = add_points_in_pointcloud.clip_3d_points_to_tile(
107
- INPUT_POINTS_SMALL, INPUT_FILE_SMALL, "EPSG:2154", 1000
108
- )
109
-
110
- add_points_in_pointcloud.add_points_to_las(points_clipped, INPUT_FILE_SMALL, OUTPUT_FILE_SMALL, "EPSG:2154", 68)
111
- assert Path(OUTPUT_FILE).exists() # check output exists
112
-
113
- # Filter pointcloud by classes
114
- pipeline = (
115
- pdal.Reader.las(filename=OUTPUT_FILE_SMALL, nosrs=True)
116
- | pdal.Filter.range(
117
- limits="Classification[68:68]",
118
- )
119
- | pdal.Filter.stats()
120
- )
121
- pipeline.execute()
122
- metadata = pipeline.metadata
123
- # Count the pointcloud's number from classe "68"
124
- point_count = metadata["metadata"]["filters.stats"]["statistic"][0]["count"]
125
- assert point_count == 186
126
-
127
-
128
- def test_add_points_from_geojson_to_las():
129
- # Ensure the output file doesn't exist before the test
130
- if Path(OUTPUT_FILE).exists():
131
- os.remove(OUTPUT_FILE)
132
-
133
- add_points_in_pointcloud.add_points_from_geojson_to_las(
134
- INPUT_POINTS, INPUT_FILE, OUTPUT_FILE, 68, "EPSG:2154", 1000
135
- )
136
- assert Path(OUTPUT_FILE).exists() # check output exists
137
-
138
-
139
- def test_add_points_from_geojson_to_las_no_epsg():
140
- # Ensure the output file doesn't exist before the test
141
- if Path(OUTPUT_FILE).exists():
142
- os.remove(OUTPUT_FILE)
143
-
144
- INPUT_FILE_WITHOUT_EPSG = os.path.join(TEST_PATH, "data/test_noepsg_043500_629205_IGN69.laz")
145
-
146
- with pytest.raises(RuntimeError, match="does not have a valid EPSG code"):
147
- add_points_in_pointcloud.add_points_from_geojson_to_las(
148
- INPUT_POINTS, INPUT_FILE_WITHOUT_EPSG, OUTPUT_FILE, 68, None, 1000
149
- )
150
-
151
-
152
- def test_parse_args():
153
- # sanity check for arguments parsing
154
- args = add_points_in_pointcloud.parse_args(
155
- [
156
- "--input_geojson",
157
- "data/points_3d/Points_virtuels_0292_6833.geojson",
158
- "--input_las",
159
- "data/decimated_laz/test_semis_2023_0292_6833_LA93_IGN69.laz",
160
- "--output_las",
161
- "data/output/test_semis_2023_0292_6833_LA93_IGN69.laz",
162
- "--virtual_points_classes",
163
- "68",
164
- "--spatial_ref",
165
- "EPSG:2154",
166
- "--tile_width",
167
- "1000",
168
- ]
169
- )
170
- parsed_args_keys = args.__dict__.keys()
171
- main_parameters = inspect.signature(add_points_in_pointcloud.add_points_from_geojson_to_las).parameters.keys()
172
- assert set(parsed_args_keys) == set(main_parameters)
File without changes
File without changes