feat: AR-Shipdesign initial commit
This commit is contained in:
@@ -47,11 +47,27 @@ class OffsetsTable:
|
||||
lpp: float = 0.0
|
||||
beam: float = 0.0
|
||||
draft: float = 0.0
|
||||
# Altura de la quilla por estación [m]. Permite quillas inclinadas
|
||||
# (rise of keel / rocker) y quillas con perfil curvo sin alterar la
|
||||
# cuadrícula de líneas de agua que permanece compartida.
|
||||
# Default: cero en todas las estaciones (quilla plana sobre baseline).
|
||||
keel_z: np.ndarray = field(default_factory=lambda: np.array([]))
|
||||
# Desviación vertical per-nodo [m]. shape (n_sta, n_wl).
|
||||
# La Z efectiva del nodo (i, j) = z_waterlines[j] + z_offsets[i, j].
|
||||
# Default: ceros → todos los nodos en los planos horizontales de referencia.
|
||||
z_offsets: np.ndarray = field(default_factory=lambda: np.zeros((0, 0)))
|
||||
# Desviación longitudinal per-nodo [m]. shape (n_sta, n_wl).
|
||||
# La X efectiva del nodo (i, j) = x_stations[i] + x_offsets[i, j].
|
||||
# x_stations es la referencia paramétrica FIJA; nunca se modifica en drag.
|
||||
x_offsets: np.ndarray = field(default_factory=lambda: np.zeros((0, 0)))
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
self.x_stations = np.asarray(self.x_stations, dtype=float)
|
||||
self.z_waterlines = np.asarray(self.z_waterlines, dtype=float)
|
||||
self.data = np.asarray(self.data, dtype=float)
|
||||
self.keel_z = np.asarray(self.keel_z, dtype=float)
|
||||
self.z_offsets = np.asarray(self.z_offsets, dtype=float)
|
||||
self.x_offsets = np.asarray(self.x_offsets, dtype=float)
|
||||
|
||||
n_sta = len(self.x_stations)
|
||||
n_wl = len(self.z_waterlines)
|
||||
@@ -61,6 +77,15 @@ class OffsetsTable:
|
||||
)
|
||||
if not self.station_labels:
|
||||
self.station_labels = [str(i) for i in range(n_sta)]
|
||||
# Inicializar keel_z si no se proporcionó o tiene dimensión incorrecta
|
||||
if self.keel_z.shape != (n_sta,):
|
||||
self.keel_z = np.zeros(n_sta)
|
||||
# Inicializar z_offsets si no se proporcionó o tiene dimensiones incorrectas
|
||||
if self.z_offsets.shape != (n_sta, n_wl):
|
||||
self.z_offsets = np.zeros((n_sta, n_wl))
|
||||
# Inicializar x_offsets si no se proporcionó o tiene dimensiones incorrectas
|
||||
if self.x_offsets.shape != (n_sta, n_wl):
|
||||
self.x_offsets = np.zeros((n_sta, n_wl))
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Fábrica: casco Wigley analítico
|
||||
@@ -127,7 +152,7 @@ class OffsetsTable:
|
||||
station=sta,
|
||||
x=float(x),
|
||||
half_breadths=self.data[i, :].copy(),
|
||||
z_positions=self.z_waterlines.copy(),
|
||||
z_positions=(self.z_waterlines + self.z_offsets[i, :]).copy(),
|
||||
label=f"x={x:.3f} m",
|
||||
)
|
||||
sections.append(sec)
|
||||
@@ -139,13 +164,14 @@ class OffsetsTable:
|
||||
|
||||
def half_breadth(self, x: float, z: float) -> float:
|
||||
"""Interpola la semi-manga en cualquier (x, z) [m]."""
|
||||
# Interpolar en x
|
||||
# Para cada estación: interpola la semi-manga a la altura z usando las
|
||||
# z efectivas per-nodo (z_waterlines[j] + z_offsets[i, j]).
|
||||
col_y = np.array([
|
||||
float(np.interp(x, self.x_stations, self.data[:, j]))
|
||||
for j in range(len(self.z_waterlines))
|
||||
float(np.interp(z, self.z_waterlines + self.z_offsets[i, :], self.data[i, :]))
|
||||
for i in range(len(self.x_stations))
|
||||
])
|
||||
# Interpolar en z
|
||||
return float(np.interp(z, self.z_waterlines, col_y))
|
||||
# Interpolar el resultado en x
|
||||
return float(np.interp(x, self.x_stations, col_y))
|
||||
|
||||
@property
|
||||
def n_stations(self) -> int:
|
||||
|
||||
Reference in New Issue
Block a user