mirror of https://gitlab.com/pamhyr/pamhyr2
216 lines
6.2 KiB
Python
216 lines
6.2 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
import numpy as np
|
|
from typing import List
|
|
|
|
from Model.Geometry.Profile import Profile
|
|
from Model.Geometry.PointXYZ import PointXYZ
|
|
from Model.Geometry.Vector_1d import Vector1d
|
|
|
|
class ProfileXYZ(Profile):
|
|
def __init__(self, num: int = 0,
|
|
code1: int = 0, code2: int = 0,
|
|
nb_point: int = 0,
|
|
kp: float = 0., name: str = "",
|
|
reach = None):
|
|
"""ProfileXYZ constructor
|
|
|
|
Args:
|
|
num: The number of this profile
|
|
code1: The interpolation code 1
|
|
code2: The interpolation code 2
|
|
kp: Kilometer point
|
|
name: The name of profile
|
|
|
|
Returns:
|
|
Nothing.
|
|
"""
|
|
super(ProfileXYZ, self).__init__(
|
|
num = num,
|
|
name = name,
|
|
kp = kp,
|
|
code1 = code1, code2 = code2,
|
|
_type = "XYZ",
|
|
reach = reach,
|
|
)
|
|
|
|
def x(self):
|
|
return [point.x for point in self._points]
|
|
|
|
def y(self):
|
|
return [point.y for point in self._points]
|
|
|
|
def z(self):
|
|
return [point.z for point in self._points]
|
|
|
|
def names(self):
|
|
return [point.name for point in self._points]
|
|
|
|
def x_max(self):
|
|
return max(self.filter_isnan(self.x()))
|
|
|
|
def x_min(self):
|
|
return min(self.filter_isnan(self.x()))
|
|
|
|
def y_max(self):
|
|
return max(self.filter_isnan(self.y()))
|
|
|
|
def y_min(self):
|
|
return min(self.filter_isnan(self.y()))
|
|
|
|
def z_max(self):
|
|
return max(self.filter_isnan(self.z()))
|
|
|
|
def z_min(self):
|
|
return min(self.filter_isnan(self.z()))
|
|
|
|
def import_points(self, list_points: list):
|
|
"""Import a list of points to profile
|
|
|
|
Args:
|
|
list_points: Liste of PointXYZ
|
|
|
|
Returns:
|
|
Nothing.
|
|
"""
|
|
for point in list_points:
|
|
pt = PointXYZ(*point)
|
|
self._points.append(pt)
|
|
|
|
def get_point_i(self, index: int) -> PointXYZ:
|
|
"""Get point at index.
|
|
|
|
Args:
|
|
index: Index of point.
|
|
|
|
Returns:
|
|
The point.
|
|
"""
|
|
try:
|
|
return self._points[index]
|
|
except IndexError:
|
|
raise IndexError(f"Invalid point index: {index}")
|
|
|
|
def add(self):
|
|
"""Add a new PointXYZ to profile.
|
|
|
|
Returns:
|
|
Nothing.
|
|
"""
|
|
point_xyz = PointXYZ(0., 0., 0.)
|
|
self._points.append(point_xyz)
|
|
|
|
def insert(self, index: int):
|
|
"""Insert a new point at index.
|
|
|
|
Args:
|
|
index: The index of new profile.
|
|
|
|
Returns:
|
|
Nothing.
|
|
"""
|
|
point = PointXYZ(0., 0., 0.)
|
|
self._points.insert(index, point)
|
|
|
|
def filter_isnan(self, lst):
|
|
"""Returns the input list without 'nan' element
|
|
|
|
Args:
|
|
lst: The list to filter
|
|
|
|
Returns:
|
|
The list without 'nan'
|
|
"""
|
|
return [x for x in lst if not np.isnan(x)]
|
|
|
|
def _first_point_not_nan(self):
|
|
first_point = self._points[0]
|
|
|
|
for point in self._points:
|
|
if not point.is_nan():
|
|
first_point = point
|
|
break
|
|
|
|
return first_point
|
|
|
|
def _last_point_not_nan(self):
|
|
last_point = self._points[-1]
|
|
|
|
for point in self._points[::-1]:
|
|
if not point.is_nan():
|
|
last_point = point
|
|
break
|
|
|
|
return last_point
|
|
|
|
def get_station(self) -> np.ndarray:
|
|
"""Projection of the points of the profile on a plane.
|
|
|
|
Args:
|
|
profile: The profile
|
|
|
|
Returns:
|
|
Projection of the points of the profile on a plane.
|
|
"""
|
|
if self.nb_points < 3:
|
|
return np.array(np.nan)
|
|
else:
|
|
first_named_point = None
|
|
index_first_named_point = None
|
|
last_named_point = None
|
|
|
|
first_point_not_nan = self._first_point_not_nan()
|
|
last_point_not_nan = self._last_point_not_nan()
|
|
|
|
for index, point in enumerate(self._points):
|
|
if point.point_is_named():
|
|
index_first_named_point = index
|
|
first_named_point = point
|
|
break
|
|
|
|
for point in self._points[::-1]:
|
|
if point.point_is_named():
|
|
last_named_point = point
|
|
break
|
|
|
|
station = []
|
|
constant = 0.0
|
|
|
|
if (first_named_point is not None and
|
|
last_named_point is not None):
|
|
if (first_named_point != last_named_point and
|
|
first_named_point.x != last_named_point.x):
|
|
vector = Vector1d(first_named_point, last_named_point)
|
|
normalized_direction_vec = vector.normalized_direction_vector()
|
|
else:
|
|
vector = Vector1d(first_point_not_nan,
|
|
last_point_not_nan)
|
|
normalized_direction_vec = vector.normalized_direction_vector()
|
|
|
|
for point in self._points:
|
|
xi = point.x - first_named_point.x
|
|
yi = point.y - first_named_point.y
|
|
station_i = (normalized_direction_vec[0] * xi +
|
|
normalized_direction_vec[1] * yi)
|
|
station.append(station_i)
|
|
|
|
ret = np.array(station)
|
|
constant = ret[index_first_named_point]
|
|
elif first_named_point is None:
|
|
vector = Vector1d(first_point_not_nan,
|
|
last_point_not_nan)
|
|
normalized_direction_vec = vector.normalized_direction_vector()
|
|
|
|
for point in self._points:
|
|
xi = point.x - first_point_not_nan.x
|
|
yi = point.y - first_point_not_nan.y
|
|
station_i = (normalized_direction_vec[0] * xi +
|
|
normalized_direction_vec[1] * yi)
|
|
station.append(station_i)
|
|
|
|
ret = np.array(station)
|
|
index_profile_z_min = np.where(np.array(self.z) == self.z_min)[0][0]
|
|
constant = ret[index_profile_z_min]
|
|
|
|
return (ret - constant)
|