2ULiDARWrapper - ctypes wrapper for LiDAR plugin
4Provides low-level ctypes interface to LiDAR C++ plugin for point cloud processing,
5synthetic scanning, triangulation, and leaf area calculations.
9from typing
import List, Tuple, Optional
10from .UContextWrapper
import UContext
11from ..plugins
import helios_lib
12from ..exceptions
import check_helios_error
17 """Opaque structure for LiDARcloud C++ class"""
23 """Automatic error checking for all LiDAR functions"""
24 check_helios_error(helios_lib.getLastErrorCode, helios_lib.getLastErrorMessage)
31 helios_lib.createLiDARcloud.argtypes = []
32 helios_lib.createLiDARcloud.restype = ctypes.POINTER(ULiDARcloud)
33 helios_lib.createLiDARcloud.errcheck = _check_error
35 helios_lib.destroyLiDARcloud.argtypes = [ctypes.POINTER(ULiDARcloud)]
36 helios_lib.destroyLiDARcloud.restype =
None
39 helios_lib.addLiDARScan.argtypes = [
40 ctypes.POINTER(ULiDARcloud),
41 ctypes.POINTER(ctypes.c_float),
51 helios_lib.addLiDARScan.restype = ctypes.c_uint
52 helios_lib.addLiDARScan.errcheck = _check_error
54 helios_lib.getLiDARScanCount.argtypes = [ctypes.POINTER(ULiDARcloud)]
55 helios_lib.getLiDARScanCount.restype = ctypes.c_uint
56 helios_lib.getLiDARScanCount.errcheck = _check_error
58 helios_lib.getLiDARScanOrigin.argtypes = [
59 ctypes.POINTER(ULiDARcloud),
61 ctypes.POINTER(ctypes.c_float)
63 helios_lib.getLiDARScanOrigin.restype =
None
64 helios_lib.getLiDARScanOrigin.errcheck = _check_error
66 helios_lib.getLiDARScanSizeTheta.argtypes = [ctypes.POINTER(ULiDARcloud), ctypes.c_uint]
67 helios_lib.getLiDARScanSizeTheta.restype = ctypes.c_uint
68 helios_lib.getLiDARScanSizeTheta.errcheck = _check_error
70 helios_lib.getLiDARScanSizePhi.argtypes = [ctypes.POINTER(ULiDARcloud), ctypes.c_uint]
71 helios_lib.getLiDARScanSizePhi.restype = ctypes.c_uint
72 helios_lib.getLiDARScanSizePhi.errcheck = _check_error
75 helios_lib.addLiDARHitPoint.argtypes = [
76 ctypes.POINTER(ULiDARcloud),
78 ctypes.POINTER(ctypes.c_float),
79 ctypes.POINTER(ctypes.c_float)
81 helios_lib.addLiDARHitPoint.restype =
None
82 helios_lib.addLiDARHitPoint.errcheck = _check_error
84 helios_lib.addLiDARHitPointRGB.argtypes = [
85 ctypes.POINTER(ULiDARcloud),
87 ctypes.POINTER(ctypes.c_float),
88 ctypes.POINTER(ctypes.c_float),
89 ctypes.POINTER(ctypes.c_float)
91 helios_lib.addLiDARHitPointRGB.restype =
None
92 helios_lib.addLiDARHitPointRGB.errcheck = _check_error
94 helios_lib.getLiDARHitCount.argtypes = [ctypes.POINTER(ULiDARcloud)]
95 helios_lib.getLiDARHitCount.restype = ctypes.c_uint
96 helios_lib.getLiDARHitCount.errcheck = _check_error
98 helios_lib.getLiDARHitXYZ.argtypes = [
99 ctypes.POINTER(ULiDARcloud),
101 ctypes.POINTER(ctypes.c_float)
103 helios_lib.getLiDARHitXYZ.restype =
None
104 helios_lib.getLiDARHitXYZ.errcheck = _check_error
106 helios_lib.getLiDARHitRaydir.argtypes = [
107 ctypes.POINTER(ULiDARcloud),
109 ctypes.POINTER(ctypes.c_float)
111 helios_lib.getLiDARHitRaydir.restype =
None
112 helios_lib.getLiDARHitRaydir.errcheck = _check_error
114 helios_lib.getLiDARHitColor.argtypes = [
115 ctypes.POINTER(ULiDARcloud),
117 ctypes.POINTER(ctypes.c_float)
119 helios_lib.getLiDARHitColor.restype =
None
120 helios_lib.getLiDARHitColor.errcheck = _check_error
122 helios_lib.deleteLiDARHitPoint.argtypes = [ctypes.POINTER(ULiDARcloud), ctypes.c_uint]
123 helios_lib.deleteLiDARHitPoint.restype =
None
124 helios_lib.deleteLiDARHitPoint.errcheck = _check_error
127 helios_lib.lidarCoordinateShift.argtypes = [
128 ctypes.POINTER(ULiDARcloud),
129 ctypes.POINTER(ctypes.c_float)
131 helios_lib.lidarCoordinateShift.restype =
None
132 helios_lib.lidarCoordinateShift.errcheck = _check_error
134 helios_lib.lidarCoordinateRotation.argtypes = [
135 ctypes.POINTER(ULiDARcloud),
136 ctypes.POINTER(ctypes.c_float)
138 helios_lib.lidarCoordinateRotation.restype =
None
139 helios_lib.lidarCoordinateRotation.errcheck = _check_error
142 helios_lib.lidarTriangulateHitPoints.argtypes = [
143 ctypes.POINTER(ULiDARcloud),
147 helios_lib.lidarTriangulateHitPoints.restype =
None
148 helios_lib.lidarTriangulateHitPoints.errcheck = _check_error
150 helios_lib.getLiDARTriangleCount.argtypes = [ctypes.POINTER(ULiDARcloud)]
151 helios_lib.getLiDARTriangleCount.restype = ctypes.c_uint
152 helios_lib.getLiDARTriangleCount.errcheck = _check_error
155 helios_lib.lidarDistanceFilter.argtypes = [ctypes.POINTER(ULiDARcloud), ctypes.c_float]
156 helios_lib.lidarDistanceFilter.restype =
None
157 helios_lib.lidarDistanceFilter.errcheck = _check_error
159 helios_lib.lidarReflectanceFilter.argtypes = [ctypes.POINTER(ULiDARcloud), ctypes.c_float]
160 helios_lib.lidarReflectanceFilter.restype =
None
161 helios_lib.lidarReflectanceFilter.errcheck = _check_error
163 helios_lib.lidarFirstHitFilter.argtypes = [ctypes.POINTER(ULiDARcloud)]
164 helios_lib.lidarFirstHitFilter.restype =
None
165 helios_lib.lidarFirstHitFilter.errcheck = _check_error
167 helios_lib.lidarLastHitFilter.argtypes = [ctypes.POINTER(ULiDARcloud)]
168 helios_lib.lidarLastHitFilter.restype =
None
169 helios_lib.lidarLastHitFilter.errcheck = _check_error
172 helios_lib.exportLiDARPointCloud.argtypes = [ctypes.POINTER(ULiDARcloud), ctypes.c_char_p]
173 helios_lib.exportLiDARPointCloud.restype =
None
174 helios_lib.exportLiDARPointCloud.errcheck = _check_error
176 helios_lib.loadLiDARXML.argtypes = [ctypes.POINTER(ULiDARcloud), ctypes.c_char_p]
177 helios_lib.loadLiDARXML.restype =
None
178 helios_lib.loadLiDARXML.errcheck = _check_error
181 helios_lib.lidarDisableMessages.argtypes = [ctypes.POINTER(ULiDARcloud)]
182 helios_lib.lidarDisableMessages.restype =
None
183 helios_lib.lidarDisableMessages.errcheck = _check_error
185 helios_lib.lidarEnableMessages.argtypes = [ctypes.POINTER(ULiDARcloud)]
186 helios_lib.lidarEnableMessages.restype =
None
187 helios_lib.lidarEnableMessages.errcheck = _check_error
190 helios_lib.addLiDARGrid.argtypes = [
191 ctypes.POINTER(ULiDARcloud),
192 ctypes.POINTER(ctypes.c_float),
193 ctypes.POINTER(ctypes.c_float),
194 ctypes.POINTER(ctypes.c_int),
197 helios_lib.addLiDARGrid.restype =
None
198 helios_lib.addLiDARGrid.errcheck = _check_error
200 helios_lib.addLiDARGridCell.argtypes = [
201 ctypes.POINTER(ULiDARcloud),
202 ctypes.POINTER(ctypes.c_float),
203 ctypes.POINTER(ctypes.c_float),
206 helios_lib.addLiDARGridCell.restype =
None
207 helios_lib.addLiDARGridCell.errcheck = _check_error
209 helios_lib.getLiDARGridCellCount.argtypes = [ctypes.POINTER(ULiDARcloud)]
210 helios_lib.getLiDARGridCellCount.restype = ctypes.c_uint
211 helios_lib.getLiDARGridCellCount.errcheck = _check_error
213 helios_lib.getLiDARCellCenter.argtypes = [
214 ctypes.POINTER(ULiDARcloud),
216 ctypes.POINTER(ctypes.c_float)
218 helios_lib.getLiDARCellCenter.restype =
None
219 helios_lib.getLiDARCellCenter.errcheck = _check_error
221 helios_lib.getLiDARCellSize.argtypes = [
222 ctypes.POINTER(ULiDARcloud),
224 ctypes.POINTER(ctypes.c_float)
226 helios_lib.getLiDARCellSize.restype =
None
227 helios_lib.getLiDARCellSize.errcheck = _check_error
229 helios_lib.getLiDARCellLeafArea.argtypes = [ctypes.POINTER(ULiDARcloud), ctypes.c_uint]
230 helios_lib.getLiDARCellLeafArea.restype = ctypes.c_float
231 helios_lib.getLiDARCellLeafArea.errcheck = _check_error
233 helios_lib.getLiDARCellLeafAreaDensity.argtypes = [ctypes.POINTER(ULiDARcloud), ctypes.c_uint]
234 helios_lib.getLiDARCellLeafAreaDensity.restype = ctypes.c_float
235 helios_lib.getLiDARCellLeafAreaDensity.errcheck = _check_error
237 helios_lib.calculateLiDARHitGridCell.argtypes = [ctypes.POINTER(ULiDARcloud)]
238 helios_lib.calculateLiDARHitGridCell.restype =
None
239 helios_lib.calculateLiDARHitGridCell.errcheck = _check_error
242 helios_lib.syntheticLiDARScan.argtypes = [
243 ctypes.POINTER(ULiDARcloud),
244 ctypes.POINTER(UContext)
246 helios_lib.syntheticLiDARScan.restype =
None
247 helios_lib.syntheticLiDARScan.errcheck = _check_error
249 helios_lib.syntheticLiDARScanAppend.argtypes = [
250 ctypes.POINTER(ULiDARcloud),
251 ctypes.POINTER(UContext),
254 helios_lib.syntheticLiDARScanAppend.restype =
None
255 helios_lib.syntheticLiDARScanAppend.errcheck = _check_error
257 helios_lib.syntheticLiDARScanWaveform.argtypes = [
258 ctypes.POINTER(ULiDARcloud),
259 ctypes.POINTER(UContext),
263 helios_lib.syntheticLiDARScanWaveform.restype =
None
264 helios_lib.syntheticLiDARScanWaveform.errcheck = _check_error
266 helios_lib.syntheticLiDARScanFull.argtypes = [
267 ctypes.POINTER(ULiDARcloud),
268 ctypes.POINTER(UContext),
275 helios_lib.syntheticLiDARScanFull.restype =
None
276 helios_lib.syntheticLiDARScanFull.errcheck = _check_error
279 helios_lib.calculateLiDARLeafArea.argtypes = [
280 ctypes.POINTER(ULiDARcloud),
281 ctypes.POINTER(UContext)
283 helios_lib.calculateLiDARLeafArea.restype =
None
284 helios_lib.calculateLiDARLeafArea.errcheck = _check_error
286 helios_lib.calculateLiDARLeafAreaMinHits.argtypes = [
287 ctypes.POINTER(ULiDARcloud),
288 ctypes.POINTER(UContext),
291 helios_lib.calculateLiDARLeafAreaMinHits.restype =
None
292 helios_lib.calculateLiDARLeafAreaMinHits.errcheck = _check_error
294 helios_lib.calculateSyntheticLiDARLeafArea.argtypes = [
295 ctypes.POINTER(ULiDARcloud),
296 ctypes.POINTER(UContext)
298 helios_lib.calculateSyntheticLiDARLeafArea.restype =
None
299 helios_lib.calculateSyntheticLiDARLeafArea.errcheck = _check_error
301 helios_lib.calculateSyntheticLiDARGtheta.argtypes = [
302 ctypes.POINTER(ULiDARcloud),
303 ctypes.POINTER(UContext)
305 helios_lib.calculateSyntheticLiDARGtheta.restype =
None
306 helios_lib.calculateSyntheticLiDARGtheta.errcheck = _check_error
308 helios_lib.getLiDARCellGtheta.argtypes = [ctypes.POINTER(ULiDARcloud), ctypes.c_uint]
309 helios_lib.getLiDARCellGtheta.restype = ctypes.c_float
310 helios_lib.getLiDARCellGtheta.errcheck = _check_error
312 helios_lib.setLiDARCellGtheta.argtypes = [ctypes.POINTER(ULiDARcloud), ctypes.c_float, ctypes.c_uint]
313 helios_lib.setLiDARCellGtheta.restype =
None
314 helios_lib.setLiDARCellGtheta.errcheck = _check_error
316 helios_lib.gapfillLiDARMisses.argtypes = [ctypes.POINTER(ULiDARcloud)]
317 helios_lib.gapfillLiDARMisses.restype =
None
318 helios_lib.gapfillLiDARMisses.errcheck = _check_error
320 helios_lib.exportLiDARGtheta.argtypes = [ctypes.POINTER(ULiDARcloud), ctypes.c_char_p]
321 helios_lib.exportLiDARGtheta.restype =
None
322 helios_lib.exportLiDARGtheta.errcheck = _check_error
325 helios_lib.exportLiDARTriangleNormals.argtypes = [ctypes.POINTER(ULiDARcloud), ctypes.c_char_p]
326 helios_lib.exportLiDARTriangleNormals.restype =
None
327 helios_lib.exportLiDARTriangleNormals.errcheck = _check_error
329 helios_lib.exportLiDARTriangleAreas.argtypes = [ctypes.POINTER(ULiDARcloud), ctypes.c_char_p]
330 helios_lib.exportLiDARTriangleAreas.restype =
None
331 helios_lib.exportLiDARTriangleAreas.errcheck = _check_error
333 helios_lib.exportLiDARLeafAreas.argtypes = [ctypes.POINTER(ULiDARcloud), ctypes.c_char_p]
334 helios_lib.exportLiDARLeafAreas.restype =
None
335 helios_lib.exportLiDARLeafAreas.errcheck = _check_error
337 helios_lib.exportLiDARLeafAreaDensities.argtypes = [ctypes.POINTER(ULiDARcloud), ctypes.c_char_p]
338 helios_lib.exportLiDARLeafAreaDensities.restype =
None
339 helios_lib.exportLiDARLeafAreaDensities.errcheck = _check_error
341 helios_lib.exportLiDARGtheta.argtypes = [ctypes.POINTER(ULiDARcloud), ctypes.c_char_p]
342 helios_lib.exportLiDARGtheta.restype =
None
343 helios_lib.exportLiDARGtheta.errcheck = _check_error
346 helios_lib.addLiDARTrianglesToContext.argtypes = [
347 ctypes.POINTER(ULiDARcloud),
348 ctypes.POINTER(UContext)
350 helios_lib.addLiDARTrianglesToContext.restype =
None
351 helios_lib.addLiDARTrianglesToContext.errcheck = _check_error
353 helios_lib.initializeLiDARCollisionDetection.argtypes = [
354 ctypes.POINTER(ULiDARcloud),
355 ctypes.POINTER(UContext)
357 helios_lib.initializeLiDARCollisionDetection.restype =
None
358 helios_lib.initializeLiDARCollisionDetection.errcheck = _check_error
360 helios_lib.enableLiDARCDGPUAcceleration.argtypes = [ctypes.POINTER(ULiDARcloud)]
361 helios_lib.enableLiDARCDGPUAcceleration.restype =
None
362 helios_lib.enableLiDARCDGPUAcceleration.errcheck = _check_error
364 helios_lib.disableLiDARCDGPUAcceleration.argtypes = [ctypes.POINTER(ULiDARcloud)]
365 helios_lib.disableLiDARCDGPUAcceleration.restype =
None
366 helios_lib.disableLiDARCDGPUAcceleration.errcheck = _check_error
368 _LIDAR_FUNCTIONS_AVAILABLE =
True
370except AttributeError:
371 _LIDAR_FUNCTIONS_AVAILABLE =
False
376 """Create LiDARcloud instance"""
377 if not _LIDAR_FUNCTIONS_AVAILABLE:
378 raise NotImplementedError(
379 "LiDAR functions not available. Rebuild PyHelios with lidar plugin:\n"
380 " build_scripts/build_helios --plugins lidar"
382 return helios_lib.createLiDARcloud()
386 """Destroy LiDARcloud instance"""
387 if cloud_ptr
and _LIDAR_FUNCTIONS_AVAILABLE:
388 helios_lib.destroyLiDARcloud(cloud_ptr)
392 origin: List[float], Ntheta: int, theta_range: Tuple[float, float],
393 Nphi: int, phi_range: Tuple[float, float],
394 exit_diameter: float, beam_divergence: float) -> int:
395 """Add a LiDAR scan to the point cloud"""
396 if not _LIDAR_FUNCTIONS_AVAILABLE:
397 raise NotImplementedError(
"LiDAR functions not available")
400 raise ValueError(
"Origin must be a 3-element array [x, y, z]")
402 origin_array = (ctypes.c_float * 3)(*origin)
403 return helios_lib.addLiDARScan(
404 cloud_ptr, origin_array, Ntheta, theta_range[0], theta_range[1],
405 Nphi, phi_range[0], phi_range[1], exit_diameter, beam_divergence
410 """Get number of scans in the cloud"""
411 if not _LIDAR_FUNCTIONS_AVAILABLE:
412 raise NotImplementedError(
"LiDAR functions not available")
413 return helios_lib.getLiDARScanCount(cloud_ptr)
416def getLiDARScanOrigin(cloud_ptr: ctypes.POINTER(ULiDARcloud), scanID: int) -> List[float]:
417 """Get origin of a specific scan"""
418 if not _LIDAR_FUNCTIONS_AVAILABLE:
419 raise NotImplementedError(
"LiDAR functions not available")
421 origin = (ctypes.c_float * 3)()
422 helios_lib.getLiDARScanOrigin(cloud_ptr, scanID, origin)
427 """Get number of zenith scan points"""
428 if not _LIDAR_FUNCTIONS_AVAILABLE:
429 raise NotImplementedError(
"LiDAR functions not available")
430 return helios_lib.getLiDARScanSizeTheta(cloud_ptr, scanID)
434 """Get number of azimuthal scan points"""
435 if not _LIDAR_FUNCTIONS_AVAILABLE:
436 raise NotImplementedError(
"LiDAR functions not available")
437 return helios_lib.getLiDARScanSizePhi(cloud_ptr, scanID)
441 xyz: List[float], direction: List[float]) ->
None:
442 """Add a hit point to the cloud"""
443 if not _LIDAR_FUNCTIONS_AVAILABLE:
444 raise NotImplementedError(
"LiDAR functions not available")
447 raise ValueError(
"XYZ must be a 3-element array")
448 if len(direction) < 2:
449 raise ValueError(
"Direction must have at least 2 elements [radius, elevation]")
451 xyz_array = (ctypes.c_float * 3)(*xyz)
452 direction_array = (ctypes.c_float * 3)(direction[0], direction[1], direction[2]
if len(direction) > 2
else 0)
453 helios_lib.addLiDARHitPoint(cloud_ptr, scanID, xyz_array, direction_array)
457 xyz: List[float], direction: List[float], color: List[float]) ->
None:
458 """Add a hit point with color to the cloud"""
459 if not _LIDAR_FUNCTIONS_AVAILABLE:
460 raise NotImplementedError(
"LiDAR functions not available")
463 raise ValueError(
"XYZ must be a 3-element array")
464 if len(direction) < 2:
465 raise ValueError(
"Direction must have at least 2 elements")
467 raise ValueError(
"Color must be a 3-element array [r, g, b]")
469 xyz_array = (ctypes.c_float * 3)(*xyz)
470 direction_array = (ctypes.c_float * 3)(direction[0], direction[1], direction[2]
if len(direction) > 2
else 0)
471 color_array = (ctypes.c_float * 3)(*color)
472 helios_lib.addLiDARHitPointRGB(cloud_ptr, scanID, xyz_array, direction_array, color_array)
476 """Get total number of hit points"""
477 if not _LIDAR_FUNCTIONS_AVAILABLE:
478 raise NotImplementedError(
"LiDAR functions not available")
479 return helios_lib.getLiDARHitCount(cloud_ptr)
482def getLiDARHitXYZ(cloud_ptr: ctypes.POINTER(ULiDARcloud), index: int) -> List[float]:
483 """Get coordinates of a hit point"""
484 if not _LIDAR_FUNCTIONS_AVAILABLE:
485 raise NotImplementedError(
"LiDAR functions not available")
487 xyz = (ctypes.c_float * 3)()
488 helios_lib.getLiDARHitXYZ(cloud_ptr, index, xyz)
492def getLiDARHitRaydir(cloud_ptr: ctypes.POINTER(ULiDARcloud), index: int) -> List[float]:
493 """Get ray direction of a hit point"""
494 if not _LIDAR_FUNCTIONS_AVAILABLE:
495 raise NotImplementedError(
"LiDAR functions not available")
497 direction = (ctypes.c_float * 3)()
498 helios_lib.getLiDARHitRaydir(cloud_ptr, index, direction)
499 return list(direction)
502def getLiDARHitColor(cloud_ptr: ctypes.POINTER(ULiDARcloud), index: int) -> List[float]:
503 """Get color of a hit point"""
504 if not _LIDAR_FUNCTIONS_AVAILABLE:
505 raise NotImplementedError(
"LiDAR functions not available")
507 color = (ctypes.c_float * 3)()
508 helios_lib.getLiDARHitColor(cloud_ptr, index, color)
513 """Delete a hit point from the cloud"""
514 if not _LIDAR_FUNCTIONS_AVAILABLE:
515 raise NotImplementedError(
"LiDAR functions not available")
516 helios_lib.deleteLiDARHitPoint(cloud_ptr, index)
520 """Translate all hit points by a shift vector"""
521 if not _LIDAR_FUNCTIONS_AVAILABLE:
522 raise NotImplementedError("LiDAR functions not available")
525 raise ValueError("Shift must be a 3-element array [x, y, z]")
527 shift_array = (ctypes.c_float * 3)(*shift)
528 helios_lib.lidarCoordinateShift(cloud_ptr, shift_array)
531def lidarCoordinateRotation(cloud_ptr: ctypes.POINTER(ULiDARcloud), rotation: List[float]) -> None:
532 """Rotate all hit points by spherical rotation angles"""
533 if not _LIDAR_FUNCTIONS_AVAILABLE:
534 raise NotImplementedError("LiDAR functions not available")
536 if len(rotation) < 2:
537 raise ValueError("Rotation must have at least 2 elements [radius, elevation]")
539 rotation_array = (ctypes.c_float * 3)(rotation[0], rotation[1], rotation[2] if len(rotation) > 2 else 0)
540 helios_lib.lidarCoordinateRotation(cloud_ptr, rotation_array)
543def lidarTriangulateHitPoints(cloud_ptr: ctypes.POINTER(ULiDARcloud),
544 Lmax: float, max_aspect_ratio: float) -> None:
545 """Generate triangle mesh from hit points"""
546 if not _LIDAR_FUNCTIONS_AVAILABLE:
547 raise NotImplementedError("LiDAR functions not available")
548 helios_lib.lidarTriangulateHitPoints(cloud_ptr, Lmax, max_aspect_ratio)
551def getLiDARTriangleCount(cloud_ptr: ctypes.POINTER(ULiDARcloud)) -> int:
552 """Get number of triangles in the mesh"""
553 if not _LIDAR_FUNCTIONS_AVAILABLE:
554 raise NotImplementedError("LiDAR functions not available")
555 return helios_lib.getLiDARTriangleCount(cloud_ptr)
558def lidarDistanceFilter(cloud_ptr: ctypes.POINTER(ULiDARcloud), maxdistance: float) -> None:
559 """Filter hit points by maximum distance"""
560 if not _LIDAR_FUNCTIONS_AVAILABLE:
561 raise NotImplementedError("LiDAR functions not available")
562 helios_lib.lidarDistanceFilter(cloud_ptr, maxdistance)
565def lidarReflectanceFilter(cloud_ptr: ctypes.POINTER(ULiDARcloud), minreflectance: float) -> None:
566 """Filter hit points by minimum reflectance"""
567 if not _LIDAR_FUNCTIONS_AVAILABLE:
568 raise NotImplementedError("LiDAR functions not available")
569 helios_lib.lidarReflectanceFilter(cloud_ptr, minreflectance)
572def lidarFirstHitFilter(cloud_ptr: ctypes.POINTER(ULiDARcloud)) -> None:
573 """Keep only first return hit points"""
574 if not _LIDAR_FUNCTIONS_AVAILABLE:
575 raise NotImplementedError("LiDAR functions not available")
576 helios_lib.lidarFirstHitFilter(cloud_ptr)
579def lidarLastHitFilter(cloud_ptr: ctypes.POINTER(ULiDARcloud)) -> None:
580 """Keep only last return hit points"""
581 if not _LIDAR_FUNCTIONS_AVAILABLE:
582 raise NotImplementedError("LiDAR functions not available")
583 helios_lib.lidarLastHitFilter(cloud_ptr)
586def exportLiDARPointCloud(cloud_ptr: ctypes.POINTER(ULiDARcloud), filename: str) -> None:
587 """Export point cloud to ASCII file"""
588 if not _LIDAR_FUNCTIONS_AVAILABLE:
589 raise NotImplementedError("LiDAR functions not available")
590 helios_lib.exportLiDARPointCloud(cloud_ptr, filename.encode('utf-8'))
593def loadLiDARXML(cloud_ptr: ctypes.POINTER(ULiDARcloud), filename: str) -> None:
594 """Load scan metadata from XML file"""
595 if not _LIDAR_FUNCTIONS_AVAILABLE:
596 raise NotImplementedError("LiDAR functions not available")
597 helios_lib.loadLiDARXML(cloud_ptr, filename.encode('utf-8'))
600def lidarDisableMessages(cloud_ptr: ctypes.POINTER(ULiDARcloud)) -> None:
601 """Disable console output messages"""
602 if not _LIDAR_FUNCTIONS_AVAILABLE:
603 raise NotImplementedError("LiDAR functions not available")
604 helios_lib.lidarDisableMessages(cloud_ptr)
607def lidarEnableMessages(cloud_ptr: ctypes.POINTER(ULiDARcloud)) -> None:
608 """Enable console output messages"""
609 if not _LIDAR_FUNCTIONS_AVAILABLE:
610 raise NotImplementedError("LiDAR functions not available")
611 helios_lib.lidarEnableMessages(cloud_ptr)
614def addLiDARGrid(cloud_ptr: ctypes.POINTER(ULiDARcloud), center: List[float],
615 size: List[float], ndiv: List[int], rotation: float) -> None:
616 """Add a rectangular grid of voxel cells"""
617 if not _LIDAR_FUNCTIONS_AVAILABLE:
618 raise NotImplementedError("LiDAR functions not available")
621 raise ValueError("Center must be a 3-element array [x, y, z]")
623 raise ValueError("Size must be a 3-element array [x, y, z]")
625 raise ValueError("Ndiv must be a 3-element array [nx, ny, nz]")
627 center_array = (ctypes.c_float * 3)(*center)
628 size_array = (ctypes.c_float * 3)(*size)
629 ndiv_array = (ctypes.c_int * 3)(*ndiv)
630 helios_lib.addLiDARGrid(cloud_ptr, center_array, size_array, ndiv_array, rotation)
633def addLiDARGridCell(cloud_ptr: ctypes.POINTER(ULiDARcloud), center: List[float],
634 size: List[float], rotation: float) -> None:
635 """Add a single grid cell"""
636 if not _LIDAR_FUNCTIONS_AVAILABLE:
637 raise NotImplementedError("LiDAR functions not available")
640 raise ValueError("Center must be a 3-element array [x, y, z]")
642 raise ValueError("Size must be a 3-element array [x, y, z]")
644 center_array = (ctypes.c_float * 3)(*center)
645 size_array = (ctypes.c_float * 3)(*size)
646 helios_lib.addLiDARGridCell(cloud_ptr, center_array, size_array, rotation)
649def getLiDARGridCellCount(cloud_ptr: ctypes.POINTER(ULiDARcloud)) -> int:
650 """Get number of grid cells"""
651 if not _LIDAR_FUNCTIONS_AVAILABLE:
652 raise NotImplementedError("LiDAR functions not available")
653 return helios_lib.getLiDARGridCellCount(cloud_ptr)
656def getLiDARCellCenter(cloud_ptr: ctypes.POINTER(ULiDARcloud), index: int) -> List[float]:
657 """Get center position of a grid cell"""
658 if not _LIDAR_FUNCTIONS_AVAILABLE:
659 raise NotImplementedError("LiDAR functions not available")
661 center = (ctypes.c_float * 3)()
662 helios_lib.getLiDARCellCenter(cloud_ptr, index, center)
666def getLiDARCellSize(cloud_ptr: ctypes.POINTER(ULiDARcloud), index: int) -> List[float]:
667 """Get size of a grid cell"""
668 if not _LIDAR_FUNCTIONS_AVAILABLE:
669 raise NotImplementedError("LiDAR functions not available")
671 size = (ctypes.c_float * 3)()
672 helios_lib.getLiDARCellSize(cloud_ptr, index, size)
676def getLiDARCellLeafArea(cloud_ptr: ctypes.POINTER(ULiDARcloud), index: int) -> float:
677 """Get leaf area of a grid cell"""
678 if not _LIDAR_FUNCTIONS_AVAILABLE:
679 raise NotImplementedError("LiDAR functions not available")
680 return helios_lib.getLiDARCellLeafArea(cloud_ptr, index)
683def getLiDARCellLeafAreaDensity(cloud_ptr: ctypes.POINTER(ULiDARcloud), index: int) -> float:
684 """Get leaf area density of a grid cell"""
685 if not _LIDAR_FUNCTIONS_AVAILABLE:
686 raise NotImplementedError("LiDAR functions not available")
687 return helios_lib.getLiDARCellLeafAreaDensity(cloud_ptr, index)
690def calculateLiDARHitGridCell(cloud_ptr: ctypes.POINTER(ULiDARcloud)) -> None:
691 """Calculate hit point grid cell assignments"""
692 if not _LIDAR_FUNCTIONS_AVAILABLE:
693 raise NotImplementedError("LiDAR functions not available")
694 helios_lib.calculateLiDARHitGridCell(cloud_ptr)
697def syntheticLiDARScan(cloud_ptr: ctypes.POINTER(ULiDARcloud),
698 context_ptr: ctypes.POINTER(UContext)) -> None:
699 """Perform synthetic discrete-return LiDAR scan"""
700 if not _LIDAR_FUNCTIONS_AVAILABLE:
701 raise NotImplementedError("LiDAR functions not available")
702 helios_lib.syntheticLiDARScan(cloud_ptr, context_ptr)
705def syntheticLiDARScanAppend(cloud_ptr: ctypes.POINTER(ULiDARcloud),
706 context_ptr: ctypes.POINTER(UContext),
707 append: bool) -> None:
708 """Perform synthetic scan with append control"""
709 if not _LIDAR_FUNCTIONS_AVAILABLE:
710 raise NotImplementedError("LiDAR functions not available")
711 helios_lib.syntheticLiDARScanAppend(cloud_ptr, context_ptr, append)
714def syntheticLiDARScanWaveform(cloud_ptr: ctypes.POINTER(ULiDARcloud),
715 context_ptr: ctypes.POINTER(UContext),
717 pulse_distance_threshold: float) -> None:
718 """Perform synthetic full-waveform LiDAR scan"""
719 if not _LIDAR_FUNCTIONS_AVAILABLE:
720 raise NotImplementedError("LiDAR functions not available")
721 helios_lib.syntheticLiDARScanWaveform(cloud_ptr, context_ptr, rays_per_pulse, pulse_distance_threshold)
724def syntheticLiDARScanFull(cloud_ptr: ctypes.POINTER(ULiDARcloud),
725 context_ptr: ctypes.POINTER(UContext),
727 pulse_distance_threshold: float,
728 scan_grid_only: bool,
730 append: bool) -> None:
731 """Perform synthetic scan with full control"""
732 if not _LIDAR_FUNCTIONS_AVAILABLE:
733 raise NotImplementedError("LiDAR functions not available")
734 helios_lib.syntheticLiDARScanFull(cloud_ptr, context_ptr, rays_per_pulse,
735 pulse_distance_threshold, scan_grid_only,
736 record_misses, append)
739def calculateLiDARLeafArea(cloud_ptr: ctypes.POINTER(ULiDARcloud),
740 context_ptr: ctypes.POINTER(UContext)) -> None:
741 """Calculate leaf area for each grid cell"""
742 if not _LIDAR_FUNCTIONS_AVAILABLE:
743 raise NotImplementedError("LiDAR functions not available")
744 helios_lib.calculateLiDARLeafArea(cloud_ptr, context_ptr)
747def calculateLiDARLeafAreaMinHits(cloud_ptr: ctypes.POINTER(ULiDARcloud),
748 context_ptr: ctypes.POINTER(UContext),
749 min_voxel_hits: int) -> None:
750 """Calculate leaf area with minimum voxel hits threshold"""
751 if not _LIDAR_FUNCTIONS_AVAILABLE:
752 raise NotImplementedError("LiDAR functions not available")
753 helios_lib.calculateLiDARLeafAreaMinHits(cloud_ptr, context_ptr, min_voxel_hits)
756def exportLiDARTriangleNormals(cloud_ptr: ctypes.POINTER(ULiDARcloud), filename: str) -> None:
757 """Export triangle normal vectors"""
758 if not _LIDAR_FUNCTIONS_AVAILABLE:
759 raise NotImplementedError("LiDAR functions not available")
760 helios_lib.exportLiDARTriangleNormals(cloud_ptr, filename.encode('utf-8'))
763def exportLiDARTriangleAreas(cloud_ptr: ctypes.POINTER(ULiDARcloud), filename: str) -> None:
764 """Export triangle areas"""
765 if not _LIDAR_FUNCTIONS_AVAILABLE:
766 raise NotImplementedError("LiDAR functions not available")
767 helios_lib.exportLiDARTriangleAreas(cloud_ptr, filename.encode('utf-8'))
770def exportLiDARLeafAreas(cloud_ptr: ctypes.POINTER(ULiDARcloud), filename: str) -> None:
771 """Export leaf areas for each grid cell"""
772 if not _LIDAR_FUNCTIONS_AVAILABLE:
773 raise NotImplementedError("LiDAR functions not available")
774 helios_lib.exportLiDARLeafAreas(cloud_ptr, filename.encode('utf-8'))
777def exportLiDARLeafAreaDensities(cloud_ptr: ctypes.POINTER(ULiDARcloud), filename: str) -> None:
778 """Export leaf area densities for each grid cell"""
779 if not _LIDAR_FUNCTIONS_AVAILABLE:
780 raise NotImplementedError("LiDAR functions not available")
781 helios_lib.exportLiDARLeafAreaDensities(cloud_ptr, filename.encode('utf-8'))
784def exportLiDARGtheta(cloud_ptr: ctypes.POINTER(ULiDARcloud), filename: str) -> None:
785 """Export G(theta) values for each grid cell"""
786 if not _LIDAR_FUNCTIONS_AVAILABLE:
787 raise NotImplementedError("LiDAR functions not available")
788 helios_lib.exportLiDARGtheta(cloud_ptr, filename.encode('utf-8'))
791def getLiDARCellGtheta(cloud_ptr: ctypes.POINTER(ULiDARcloud), index: int) -> float:
792 """Get G(theta) value for a grid cell"""
793 if not _LIDAR_FUNCTIONS_AVAILABLE:
794 raise NotImplementedError("LiDAR functions not available")
795 return helios_lib.getLiDARCellGtheta(cloud_ptr, index)
798def setLiDARCellGtheta(cloud_ptr: ctypes.POINTER(ULiDARcloud), Gtheta: float, index: int) -> None:
799 """Set G(theta) value for a grid cell"""
800 if not _LIDAR_FUNCTIONS_AVAILABLE:
801 raise NotImplementedError("LiDAR functions not available")
802 helios_lib.setLiDARCellGtheta(cloud_ptr, Gtheta, index)
805def gapfillLiDARMisses(cloud_ptr: ctypes.POINTER(ULiDARcloud)) -> None:
806 """Gapfill sky/miss points"""
807 if not _LIDAR_FUNCTIONS_AVAILABLE:
808 raise NotImplementedError("LiDAR functions not available")
809 helios_lib.gapfillLiDARMisses(cloud_ptr)
812def calculateSyntheticLiDARLeafArea(cloud_ptr: ctypes.POINTER(ULiDARcloud),
813 context_ptr: ctypes.POINTER(UContext)) -> None:
814 """Calculate synthetic leaf area for validation"""
815 if not _LIDAR_FUNCTIONS_AVAILABLE:
816 raise NotImplementedError("LiDAR functions not available")
817 helios_lib.calculateSyntheticLiDARLeafArea(cloud_ptr, context_ptr)
820def calculateSyntheticLiDARGtheta(cloud_ptr: ctypes.POINTER(ULiDARcloud),
821 context_ptr: ctypes.POINTER(UContext)) -> None:
822 """Calculate synthetic G(theta) for validation"""
823 if not _LIDAR_FUNCTIONS_AVAILABLE:
824 raise NotImplementedError("LiDAR functions not available")
825 helios_lib.calculateSyntheticLiDARGtheta(cloud_ptr, context_ptr)
828def addLiDARTrianglesToContext(cloud_ptr: ctypes.POINTER(ULiDARcloud),
829 context_ptr: ctypes.POINTER(UContext)) -> None:
830 """Add triangulated mesh to Context as primitives"""
831 if not _LIDAR_FUNCTIONS_AVAILABLE:
832 raise NotImplementedError("LiDAR functions not available")
833 helios_lib.addLiDARTrianglesToContext(cloud_ptr, context_ptr)
836def initializeLiDARCollisionDetection(cloud_ptr: ctypes.POINTER(ULiDARcloud),
837 context_ptr: ctypes.POINTER(UContext)) -> None:
838 """Initialize CollisionDetection for ray tracing"""
839 if not _LIDAR_FUNCTIONS_AVAILABLE:
840 raise NotImplementedError("LiDAR functions not available")
841 helios_lib.initializeLiDARCollisionDetection(cloud_ptr, context_ptr)
844def enableLiDARCDGPUAcceleration(cloud_ptr: ctypes.POINTER(ULiDARcloud)) -> None:
845 """Enable GPU acceleration for collision detection"""
846 if not _LIDAR_FUNCTIONS_AVAILABLE:
847 raise NotImplementedError("LiDAR functions not available")
848 helios_lib.enableLiDARCDGPUAcceleration(cloud_ptr)
851def disableLiDARCDGPUAcceleration(cloud_ptr: ctypes.POINTER(ULiDARcloud)) -> None:
852 """Disable GPU acceleration for collision detection"""
853 if not _LIDAR_FUNCTIONS_AVAILABLE:
854 raise NotImplementedError("LiDAR functions not available")
855 helios_lib.disableLiDARCDGPUAcceleration(cloud_ptr)
858# Mock mode for development
859if not _LIDAR_FUNCTIONS_AVAILABLE:
860 def mock_createLiDARcloud(*args, **kwargs):
862 "Mock mode: LiDAR not available. "
863 "This would create a LiDAR cloud instance with native library."
866 def mock_lidar_operation(*args, **kwargs):
868 "Mock mode: LiDAR operation not available. "
869 "This would execute LiDAR operations with native library."
872 # Replace functions with mocks for development
873 createLiDARcloud = mock_createLiDARcloud
874 addLiDARScan = mock_lidar_operation
875 addLiDARHitPoint = mock_lidar_operation
Opaque structure for LiDARcloud C++ class.
_check_error(result, func, args)
Automatic error checking for all LiDAR functions.
None addLiDARHitPointRGB(ctypes.POINTER(ULiDARcloud) cloud_ptr, int scanID, List[float] xyz, List[float] direction, List[float] color)
Add a hit point with color to the cloud.
List[float] getLiDARScanOrigin(ctypes.POINTER(ULiDARcloud) cloud_ptr, int scanID)
Get origin of a specific scan.
None lidarCoordinateShift(ctypes.POINTER(ULiDARcloud) cloud_ptr, List[float] shift)
Translate all hit points by a shift vecto.
int getLiDARScanSizeTheta(ctypes.POINTER(ULiDARcloud) cloud_ptr, int scanID)
Get number of zenith scan points.
int getLiDARScanSizePhi(ctypes.POINTER(ULiDARcloud) cloud_ptr, int scanID)
Get number of azimuthal scan points.
List[float] getLiDARHitXYZ(ctypes.POINTER(ULiDARcloud) cloud_ptr, int index)
Get coordinates of a hit point.
None deleteLiDARHitPoint(ctypes.POINTER(ULiDARcloud) cloud_ptr, int index)
Delete a hit point from the cloud.
List[float] getLiDARHitColor(ctypes.POINTER(ULiDARcloud) cloud_ptr, int index)
Get color of a hit point.
List[float] getLiDARHitRaydir(ctypes.POINTER(ULiDARcloud) cloud_ptr, int index)
Get ray direction of a hit point.
None destroyLiDARcloud(ctypes.POINTER(ULiDARcloud) cloud_ptr)
Destroy LiDARcloud instance.
createLiDARcloud
Create LiDARcloud instance.
int getLiDARHitCount(ctypes.POINTER(ULiDARcloud) cloud_ptr)
Get total number of hit points.
int getLiDARScanCount(ctypes.POINTER(ULiDARcloud) cloud_ptr)
Get number of scans in the cloud.