mirror of
https://gitlab.com/pamhyr/pamhyr2.git
synced 2026-10-30 03:20:41 +01:00
optimization + debug
This commit is contained in:
1 parent
e4224e6358
commit
6f7a891a6d
10 files changed
+155
-99
No files matched your search
@@ -20,6 +20,7 @@ import logging
|
||||
import numpy as np
|
||||
from typing import List
|
||||
from functools import reduce
|
||||
from dataclasses import dataclass
|
||||
|
||||
from tools import timer
|
||||
from shapely import geometry
|
||||
@@ -33,6 +34,13 @@ from Model.Geometry.Vector_1d import Vector1d
|
||||
logger = logging.getLogger()
|
||||
|
||||
|
||||
@dataclass
|
||||
class Tabulation:
|
||||
z: np.array([])
|
||||
A: np.array([])
|
||||
L: np.array([])
|
||||
|
||||
|
||||
class ProfileXYZ(Profile, SQLSubModel):
|
||||
_sub_classes = [
|
||||
PointXYZ,
|
||||
@@ -70,6 +78,14 @@ class ProfileXYZ(Profile, SQLSubModel):
|
||||
status=status,
|
||||
)
|
||||
|
||||
self.tab = Tabulation([], [], [])
|
||||
self.tab_up_to_date = False
|
||||
self.time_z = 0.0
|
||||
self.time_A = 0.0
|
||||
self.time_l = 0.0
|
||||
self._station = []
|
||||
self.station_up_to_date = False
|
||||
|
||||
@classmethod
|
||||
def _db_create(cls, execute):
|
||||
execute("""
|
||||
@@ -305,6 +321,8 @@ class ProfileXYZ(Profile, SQLSubModel):
|
||||
pt = PointXYZ(*point, profile=self, status=self._status)
|
||||
self.points.append(pt)
|
||||
self._status.modified()
|
||||
self.tab_up_to_date = False
|
||||
self.station_up_to_date = False
|
||||
|
||||
def get_point_i(self, index: int) -> PointXYZ:
|
||||
"""Get point at index.
|
||||
@@ -366,6 +384,8 @@ class ProfileXYZ(Profile, SQLSubModel):
|
||||
point_xyz = PointXYZ(0., 0., 0., profile=self, status=self._status)
|
||||
self.points.append(point_xyz)
|
||||
self._status.modified()
|
||||
self.tab_up_to_date = False
|
||||
self.station_up_to_date = False
|
||||
|
||||
def insert(self, index: int):
|
||||
"""Insert a new point at index.
|
||||
@@ -379,6 +399,8 @@ class ProfileXYZ(Profile, SQLSubModel):
|
||||
point = PointXYZ(0., 0., 0., profile=self, status=self._status)
|
||||
self.points.insert(index, point)
|
||||
self._status.modified()
|
||||
self.tab_up_to_date = False
|
||||
self.station_up_to_date = False
|
||||
return point
|
||||
|
||||
def filter_isnan(self, lst):
|
||||
@@ -410,7 +432,7 @@ class ProfileXYZ(Profile, SQLSubModel):
|
||||
|
||||
return abs(rg.dist(rd))
|
||||
|
||||
def wet_width(self, z):
|
||||
def compute_wet_width(self, z):
|
||||
start, end = self.get_all_water_limits_ac(z)
|
||||
|
||||
if len(start) == 0:
|
||||
@@ -421,6 +443,17 @@ class ProfileXYZ(Profile, SQLSubModel):
|
||||
length += abs(s - e)
|
||||
return length
|
||||
|
||||
def wet_width(self, z):
|
||||
if self.tab_up_to_date:
|
||||
if z > self.tab.z[-1]:
|
||||
return self.tab.L[-1]
|
||||
elif z < self.tab.z[0]:
|
||||
return 0.0
|
||||
else:
|
||||
return np.interp(z, self.tab.z, self.tab.L)
|
||||
else:
|
||||
return self.compute_wet_width(z)
|
||||
|
||||
def wet_perimeter(self, z):
|
||||
lines = self.wet_lines(z)
|
||||
|
||||
@@ -432,17 +465,46 @@ class ProfileXYZ(Profile, SQLSubModel):
|
||||
length += line.length
|
||||
return length
|
||||
|
||||
def wet_area(self, z):
|
||||
lines = self.wet_lines(z)
|
||||
|
||||
if lines is None:
|
||||
return 0
|
||||
|
||||
def compute_wet_area(self, z):
|
||||
area = 0.0
|
||||
for line in lines:
|
||||
if len(line.coords) > 2:
|
||||
poly = geometry.Polygon(line)
|
||||
area += poly.area
|
||||
if len(self.tab.L) > 0:
|
||||
if z < self.tab.z[0]:
|
||||
return 0.0
|
||||
i = np.searchsorted([z], self.tab.z, side='right')[0]
|
||||
for j in range(i-1):
|
||||
area += (self.tab.L[j] + self.tab.L[j+1]) * (
|
||||
self.tab.z[j+1] - self.tab.z[j]) / 2.0
|
||||
area += (self.tab.L[i-1] + self.wet_width(z))
|
||||
else:
|
||||
lines = self.wet_lines(z)
|
||||
|
||||
if lines is None:
|
||||
return 0.0
|
||||
for line in lines:
|
||||
if len(line.coords) > 2:
|
||||
poly = geometry.Polygon(line)
|
||||
area += poly.area
|
||||
return area
|
||||
|
||||
def wet_area(self, z):
|
||||
if self.tab_up_to_date:
|
||||
if z > self.tab.z[-1]:
|
||||
return self.tab.A[-1] + self.tab.L[-1] * (z - self.tab.z[-1])
|
||||
elif z < self.tab.z[0]:
|
||||
return 0.0
|
||||
else:
|
||||
return np.interp(z, self.tab.z, self.tab.A)
|
||||
else:
|
||||
lines = self.wet_lines(z)
|
||||
|
||||
if lines is None:
|
||||
return 0.0
|
||||
|
||||
area = 0.0
|
||||
for line in lines:
|
||||
if len(line.coords) > 2:
|
||||
poly = geometry.Polygon(line)
|
||||
area += poly.area
|
||||
return area
|
||||
|
||||
def wet_radius(self, z):
|
||||
@@ -563,7 +625,7 @@ class ProfileXYZ(Profile, SQLSubModel):
|
||||
return None
|
||||
|
||||
zz = list(map(lambda p: p.z, points))
|
||||
station = self._get_station(points)
|
||||
station = self.get_station()
|
||||
|
||||
start = []
|
||||
if points[0].z <= z:
|
||||
@@ -651,6 +713,19 @@ class ProfileXYZ(Profile, SQLSubModel):
|
||||
|
||||
return pt_left, pt_right
|
||||
|
||||
def compute_tabulation(self):
|
||||
sorted_points = sorted(self._points, key=lambda p: p.z)
|
||||
self.tab.z = np.array([p.z for p in sorted_points], np.float64)
|
||||
self.tab.L = np.zeros(len(self.tab.z), np.float64)
|
||||
self.tab.A = np.zeros(len(self.tab.z), np.float64)
|
||||
for i in range(1, len(self.tab.z)):
|
||||
self.tab.L[i] = self.compute_wet_width(self.tab.z[i])
|
||||
dx = (self.tab.L[i] + self.tab.L[i-1])/2
|
||||
dz = self.tab.z[i] - self.tab.z[i-1]
|
||||
self.tab.A[i] = self.tab.A[i-1] + dz * dx
|
||||
|
||||
self.tab_up_to_date = True
|
||||
|
||||
def get_station(self):
|
||||
"""Projection of the points of the profile on a plane.
|
||||
|
||||
@@ -663,7 +738,12 @@ class ProfileXYZ(Profile, SQLSubModel):
|
||||
if self.nb_points < 2:
|
||||
return [0.0]
|
||||
else:
|
||||
return self._get_station(self.points)
|
||||
if self.station_up_to_date:
|
||||
return self._station
|
||||
else:
|
||||
self._station = self._get_station(self.points)
|
||||
self.station_up_to_date = True
|
||||
return self._station
|
||||
|
||||
@timer
|
||||
def _get_station(self, points):
|
||||
|
||||
Reference in new issue
Block a user