feat(sprint1): motor NURBS, modelos de casco, visor 3D PyVista
Geometría:
- BSplineCurve: interpolación scipy, arc_length, tangente, chord-length
- LoftedSurface: lofting de secciones → RectBivariateSpline bivariate
Core (casco Wigley como caso de prueba):
- Section: área, centroide_z, max_half_breadth, curva B-spline
- OffsetsTable: from_wigley(), to_sections(), interpolación xy
- Hull: volumen, Awp, LCB, VCB, Cb, Cm, Cp, desplazamiento, to_mesh()
UI:
- Viewer3DWidget (pyvistaqt.QtInteractor): casco Wigley por defecto
al arrancar, fondo navy, waterplane semi-transparente, fallback
graceful si PyVista no disponible
- MainWindow: Viewer3DWidget inyectado en viewport Perspectiva 3D
Tests: 39 nuevos tests, fórmulas analíticas Wigley verificadas (±1%)
V = 4BLT/9, Cb = 4/9, Awp = 2BL/3 (derivación correcta)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -822,6 +822,16 @@ class MainWindow(QMainWindow):
|
||||
self._module_area = ModuleArea()
|
||||
self.setCentralWidget(self._module_area)
|
||||
|
||||
# Inyectar visor 3D en el viewport Perspectiva (diferido)
|
||||
from arshipdesign.ui.widgets.viewer_3d import Viewer3DWidget, _PYVISTA_OK
|
||||
if _PYVISTA_OK:
|
||||
self._viewer_3d = Viewer3DWidget()
|
||||
vp = self._module_area.four_viewport.viewport("perspective")
|
||||
if vp is not None:
|
||||
vp.set_canvas(self._viewer_3d)
|
||||
else:
|
||||
self._viewer_3d = None
|
||||
|
||||
# Dock izquierdo — capas
|
||||
self._layers_panel = LayersPanel(self._strings)
|
||||
self._dock_layers = QDockWidget("Capas", self)
|
||||
|
||||
Reference in New Issue
Block a user