#!/usr/bin/env python
# coding: utf8
#
# Copyright (c) 2020 Centre National d'Etudes Spatiales (CNES).
#
# This file is part of CARS
# (see https://github.com/CNES/cars).
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
"""
Contains function to convert the point cloud dataframe to laz format:
"""
import logging
import warnings
import laspy
import laspy.file
import laspy.header
import numpy as np
from pyproj import CRS
import cars.core.constants as cst
[docs]
def convert_pcl_to_laz(point_clouds, output_filename: str):
"""
Convert 3d point cloud to laz format
:param point_clouds: point_clouds dataframe
:param output_filename: output laz filename (with naming convention)
:return: the list of point cloud save in las format
"""
# get all layer : X, Y, Z and color
coordinates = ["X", "Y", "Z"]
las_color = ["red", "green", "blue"]
color_type = point_clouds.attrs["attributes"]["color_type"]
epsg = point_clouds.attrs["attributes"]["epsg"]
input_color = get_input_color(point_clouds)
laz_file_name = output_filename
arrays_pcl, arrays_color = extract_point_cloud(
point_clouds, coordinates, input_color, color_type
)
# generate laz
generate_laz(
laz_file_name, coordinates, las_color, arrays_pcl, arrays_color
)
# dump prj file
generate_prj_file(laz_file_name, epsg)
[docs]
def generate_prj_file(output_filename, epsg):
"""
Generate prj file associated to the laz file if projection is UTM or WGS84
:param output_filename: name of laz file
:param epsg: code of output epsg
"""
with warnings.catch_warnings():
# Ignore some crs warning
warnings.filterwarnings(
"ignore",
category=UserWarning,
message=".*You will likely lose important projection"
" information when converting to a PROJ string from "
"another format.*",
)
crs = CRS.from_epsg(epsg)
proj = crs.to_proj4()
if crs.is_geographic:
logging.warning(
"Coordinate system of point cloud is geographic: "
"Display of LAZ file may not work"
)
with open(output_filename + ".prj", "w", encoding="utf8") as file_prj:
file_prj.write(proj)
[docs]
def generate_laz(
output_filename, coordinates, las_color, arrays_pcl, arrays_color
):
"""
Generate laz file from location and color arrays
"""
# Create laz image
header = laspy.LasHeader(point_format=2)
scale_factor = 0.01
header.scales = [scale_factor, scale_factor, scale_factor]
laz = laspy.LasData(header)
# fill X,Y,Z into laspy structure, convert to cm
scale_multiplicator = 1 / scale_factor
for layer_index in range(arrays_pcl.shape[0]):
setattr(
laz,
[k for i, k in enumerate(coordinates) if i == layer_index][0],
scale_multiplicator * arrays_pcl[layer_index],
)
if arrays_color is not None:
for color_index in range(arrays_color.shape[0]):
setattr(
laz,
[k for i, k in enumerate(las_color) if i == color_index][0],
arrays_color[color_index],
)
laz.write(output_filename)