mirror of https://gitlab.com/pamhyr/pamhyr2
Model: Profile: Add speed computation methode.
parent
fead93f0b9
commit
4c927eb7c7
|
|
@ -19,6 +19,7 @@
|
|||
import logging
|
||||
|
||||
from tools import timer
|
||||
from shapely import geometry
|
||||
|
||||
from Model.Geometry.Point import Point
|
||||
from Model.Except import NotImplementedMethodeError
|
||||
|
|
@ -341,3 +342,12 @@ class Profile(object):
|
|||
# Abstract method for width approximation
|
||||
def get_water_limits(self, z):
|
||||
raise NotImplementedMethodeError(self, self.get_water_limits)
|
||||
|
||||
def wet_points(self, z):
|
||||
raise NotImplementedMethodeError(self, self.wet_point)
|
||||
|
||||
def wet_perimeter(self, z):
|
||||
raise NotImplementedMethodeError(self, self.wet_perimeter)
|
||||
|
||||
def wet_area(self, z):
|
||||
raise NotImplementedMethodeError(self, self.wet_area)
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ from typing import List
|
|||
from functools import reduce
|
||||
|
||||
from tools import timer
|
||||
from shapely import geometry
|
||||
|
||||
from Model.Tools.PamhyrDB import SQLSubModel
|
||||
from Model.Except import ClipboardFormatError
|
||||
|
|
@ -373,99 +374,13 @@ class ProfileXYZ(Profile, SQLSubModel):
|
|||
"""
|
||||
return [x for x in lst if not np.isnan(x)]
|
||||
|
||||
def _first_point_not_nan(self):
|
||||
first_point = self.points[0]
|
||||
def speed(self, q, z):
|
||||
area = self.wet_area(z)
|
||||
|
||||
for point in self.points:
|
||||
if not point.is_nan():
|
||||
first_point = point
|
||||
break
|
||||
if area == 0:
|
||||
return 0
|
||||
|
||||
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
|
||||
|
||||
@timer
|
||||
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 None
|
||||
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 reversed(self.points):
|
||||
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)
|
||||
norm_dir_vec = vector.normalized_direction_vector()
|
||||
else:
|
||||
vector = Vector1d(first_point_not_nan, last_point_not_nan)
|
||||
norm_dir_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 = (norm_dir_vec[0] * xi +
|
||||
norm_dir_vec[1] * yi)
|
||||
station.append(station_i)
|
||||
|
||||
constant = station[index_first_named_point]
|
||||
elif first_named_point is None:
|
||||
vector = Vector1d(first_point_not_nan, last_point_not_nan)
|
||||
norm_dir_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 = (norm_dir_vec[0] * xi +
|
||||
norm_dir_vec[1] * yi)
|
||||
station.append(station_i)
|
||||
|
||||
z_min = self.z_min()
|
||||
index_profile_z_min = list(
|
||||
filter(
|
||||
lambda z: z[1] == z_min,
|
||||
enumerate(self.z())
|
||||
)
|
||||
)[0]
|
||||
constant = station[index_profile_z_min[0]]
|
||||
|
||||
return list(map(lambda s: s - constant, station))
|
||||
return q / area
|
||||
|
||||
def width_approximation(self):
|
||||
if self.has_standard_named_points():
|
||||
|
|
@ -477,6 +392,43 @@ class ProfileXYZ(Profile, SQLSubModel):
|
|||
|
||||
return abs(rg.dist(rd))
|
||||
|
||||
def wet_perimeter(self, z):
|
||||
poly = self.wet_polygon(z)
|
||||
|
||||
if poly is None:
|
||||
return 0
|
||||
|
||||
return poly.length
|
||||
|
||||
def wet_area(self, z):
|
||||
poly = self.wet_polygon(z)
|
||||
|
||||
if poly is None:
|
||||
return 0
|
||||
|
||||
return poly.area
|
||||
|
||||
def wet_polygon(self, z):
|
||||
points = self.wet_points(z)
|
||||
if len(points) < 3:
|
||||
return None
|
||||
|
||||
z = map(lambda p: p.z, points)
|
||||
station = self._get_station(points)
|
||||
|
||||
poly = geometry.Polygon(list(zip(station, z)))
|
||||
|
||||
return poly
|
||||
|
||||
def wet_points(self, z):
|
||||
left, right = self.get_water_limits(z)
|
||||
|
||||
points = list(filter(lambda p: p.z < z, self._points))
|
||||
points = [left] + points + [right]
|
||||
points = sorted(points, key=lambda p: p.x)
|
||||
|
||||
return points
|
||||
|
||||
def get_water_limits(self, z):
|
||||
"""
|
||||
Determine left and right limits of water elevation.
|
||||
|
|
@ -509,7 +461,7 @@ class ProfileXYZ(Profile, SQLSubModel):
|
|||
[self.point(i_left).z, self.point(i_left - 1).z],
|
||||
[self.point(i_left).y, self.point(i_left - 1).y]
|
||||
)
|
||||
pt_left = PointXYZ(x, y, z)
|
||||
pt_left = PointXYZ(x, y, z, name="wl_left")
|
||||
else:
|
||||
pt_left = self.point(0)
|
||||
|
||||
|
|
@ -525,8 +477,105 @@ class ProfileXYZ(Profile, SQLSubModel):
|
|||
[self.point(i_right).z, self.point(i_right + 1).z],
|
||||
[self.point(i_right).y, self.point(i_right + 1).y]
|
||||
)
|
||||
pt_right = PointXYZ(x, y, z)
|
||||
pt_right = PointXYZ(x, y, z, name="wl_right")
|
||||
else:
|
||||
pt_right = self.point(self.number_points - 1)
|
||||
|
||||
return pt_left, pt_right
|
||||
|
||||
def get_station(self):
|
||||
"""Projection of the points of the profile on a plane.
|
||||
|
||||
Args:
|
||||
self: The profile
|
||||
|
||||
Returns:
|
||||
Projection of the points of the profile on a plane.
|
||||
"""
|
||||
if self.nb_points < 3:
|
||||
return None
|
||||
else:
|
||||
return self._get_station(self.points)
|
||||
|
||||
@timer
|
||||
def _get_station(self, points):
|
||||
first_named_point = None
|
||||
index_first_named_point = None
|
||||
last_named_point = None
|
||||
|
||||
first_point_not_nan = self._first_point_not_nan(points)
|
||||
last_point_not_nan = self._last_point_not_nan(points)
|
||||
|
||||
for index, point in enumerate(points):
|
||||
if point.point_is_named():
|
||||
index_first_named_point = index
|
||||
first_named_point = point
|
||||
break
|
||||
|
||||
for point in reversed(points):
|
||||
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)
|
||||
norm_dir_vec = vector.normalized_direction_vector()
|
||||
else:
|
||||
vector = Vector1d(first_point_not_nan, last_point_not_nan)
|
||||
norm_dir_vec = vector.normalized_direction_vector()
|
||||
|
||||
for point in points:
|
||||
xi = point.x - first_named_point.x
|
||||
yi = point.y - first_named_point.y
|
||||
station_i = (norm_dir_vec[0] * xi +
|
||||
norm_dir_vec[1] * yi)
|
||||
station.append(station_i)
|
||||
|
||||
constant = station[index_first_named_point]
|
||||
elif first_named_point is None:
|
||||
vector = Vector1d(first_point_not_nan, last_point_not_nan)
|
||||
norm_dir_vec = vector.normalized_direction_vector()
|
||||
|
||||
for point in points:
|
||||
xi = point.x - first_point_not_nan.x
|
||||
yi = point.y - first_point_not_nan.y
|
||||
station_i = (norm_dir_vec[0] * xi +
|
||||
norm_dir_vec[1] * yi)
|
||||
station.append(station_i)
|
||||
|
||||
z_min = self.z_min()
|
||||
index_profile_z_min = list(
|
||||
filter(
|
||||
lambda z: z[1] == z_min,
|
||||
enumerate(self.z())
|
||||
)
|
||||
)[0]
|
||||
constant = station[index_profile_z_min[0]]
|
||||
|
||||
return list(map(lambda s: s - constant, station))
|
||||
|
||||
def _first_point_not_nan(self, points):
|
||||
first_point = None
|
||||
|
||||
for point in points:
|
||||
if not point.is_nan():
|
||||
first_point = point
|
||||
break
|
||||
|
||||
return first_point
|
||||
|
||||
def _last_point_not_nan(self, points):
|
||||
last_point = None
|
||||
|
||||
for point in reversed(points):
|
||||
if not point.is_nan():
|
||||
last_point = point
|
||||
break
|
||||
|
||||
return last_point
|
||||
|
|
|
|||
Loading…
Reference in New Issue