# Implementation Plan

- [x] 1. Fix pre-existing bugs in 3D forward transform
- [x] 1.1 Fix arc-length parameterization to include z-component
  - Correct the 3D distance computation so that arc-length uses all three spatial dimensions (dx² + dy² + dz²) instead of only x and y
  - Verify existing 3D exact test still passes (it provides explicit `t` so is unaffected by the arc-length change)
  - _Requirements: 4.1, 4.2_
- [x] 1.2 Fix DC component calculation to use dt-weighted mean
  - Correct the 3D DC component (mean coordinate) computation to weight by the arc-length parameter increment, matching the 2D implementation
  - Apply the same correction to all three DC terms (x, y, z)
  - _Requirements: 4.1, 4.2_

- [x] 2. Implement 3D rotation matrix and geometric parameter extraction utilities
- [x] 2.1 (P) Implement ZXZ Euler angle rotation matrix construction
  - Build a 3×3 rotation matrix from three Euler angles using the ZXZ convention per Godefroy et al. (2012) Fig. 1
  - The rotation composes as Ω = R_γ · R_β · R_α where each is an elementary rotation about the appropriate axis
  - Verify identity matrix is returned for (0, 0, 0) and that the matrix is orthogonal with determinant +1
  - _Requirements: 1.2_
  - _Contracts: rotation_matrix_3d_euler_zxz Service_
- [x] 2.2 (P) Implement geometric parameter extraction for 3D ellipses
  - Given 6 Fourier coefficients of a single harmonic (cosine and sine for x, y, z), compute the geometric parameters: phase angle φ, semi-major axis a, semi-minor axis b, and three Euler angles (α, β, γ)
  - Implement the relations from Godefroy et al. (2012) §2, Eqs. 4–12
  - Enforce uniqueness constraints: φ ∈ ]−π/4, π/4[, a ≥ b > 0, β ∈ [0, π]
  - Handle the gimbal lock case (β ≈ 0 or π): set γ = 0 and compute α from the combined angle
  - Verify with a synthetic ellipse whose geometric parameters are known analytically
  - _Requirements: 1.1, 1.2_
  - _Contracts: _compute_ellipse_geometry_3d Service_

- [x] 3. Implement 3D normalization algorithm
- [x] 3.1 Implement the 4-step normalization method
  - Replace the current stub with the full Godefroy et al. (2012) §3.1 algorithm:
    - Step 1 (Rescaling): compute the area of the 1st harmonic ellipse A₁ = π·a₁·b₁ and divide all coefficients by √A₁
    - Step 2 (Reorientation): build the rotation matrix Ω₁ from the 1st harmonic's Euler angles and apply Ω₁⁻¹ to each harmonic's 3×2 coefficient matrix
    - Step 3 (Phase shift): apply a 2×2 rotation by the 1st harmonic's phase angle φ₁ to the (cos, sin) columns of each harmonic
    - Step 4 (Direction): if the y-sine coefficient of the 1st harmonic is negative after reorientation, negate all sine coefficient columns
  - Return the normalized coefficient arrays along with the orientation parameters (α₁, β₁, γ₁, φ₁) and scale (√A₁)
  - Handle degenerate 1st harmonic (all coefficients near zero) by raising a descriptive error
  - _Requirements: 1.1, 1.2, 1.3, 1.4, 2.2_
  - _Contracts: _normalize_3d Service_

- [x] 4. Integrate normalization into the 3D transform pipeline
- [x] 4.1 Wire normalization into the single-sample 3D transform
  - Connect the normalization method so it is called when `norm=True` for 3D data, replacing the previous `NotImplementedError`
  - When `return_orientation_scale=True`, append the 5 orientation/scale values (α, β, γ, φ, scale) to the output coefficient array
  - Ensure the public `transform` and `fit_transform` methods work correctly for 3D normalized output
  - _Requirements: 1.1, 2.1, 2.2_
- [x] 4.2 Update docstrings for 3D normalization
  - Update the class-level docstring to remove the note about 3D normalization not being supported
  - Document the `return_orientation_scale` output format for 3D: the 5 appended values and their ordering (α, β, γ, φ, scale)
  - Document the Euler angle convention (ZXZ per Godefroy et al. 2012)
  - _Requirements: 2.3_

- [x] 5. Implement invariance and validation tests
- [x] 5.1 Implement translation invariance test for 3D normalization
  - Generate a synthetic 3D closed curve, apply a random 3D translation, and verify that normalized coefficients are identical within numerical tolerance
  - _Requirements: 6.1_
- [x] 5.2 (P) Implement scale invariance test for 3D normalization
  - Apply a random uniform scaling factor to a 3D outline and verify normalized coefficients match the unscaled version
  - _Requirements: 6.2_
- [x] 5.3 (P) Implement rotation invariance test for 3D normalization
  - Apply a random 3D rotation matrix to an outline's coordinates and verify normalized coefficients match the unrotated version
  - _Requirements: 6.3_
- [x] 5.4 (P) Implement starting-point shift invariance test for 3D normalization
  - Cyclically permute the outline points (shift the starting point) and verify normalized coefficients match
  - _Requirements: 6.4_
- [x] 5.5 Implement round-trip reconstruction test
  - Forward-transform a 3D outline with normalization, then inverse-transform, and verify the reconstructed shape is geometrically consistent with the normalized input using Wasserstein distance
  - _Requirements: 6.5_
- [x] 5.6 Implement arc-length correction verification test
  - Create a 3D curve where z-axis variation is significant and verify that the arc-length parameterization correctly accounts for all three dimensions
  - _Requirements: 6.6_
- [x] 5.7 Implement orientation/scale return test
  - Verify that `return_orientation_scale=True` for 3D produces an output array with the correct shape (coefficients + 5 extra values)
  - Verify that the returned orientation and scale parameters allow reconstruction of the original outline's position and size
  - _Requirements: 2.1_
- [x] 5.8 Implement canonical first harmonic test
  - After normalization, verify that the 1st harmonic coefficients define an ellipse aligned with the XY-plane with the semi-major axis along X
  - _Requirements: 1.3_

- [x] 6. Verify backward compatibility
- [x] 6.1 Verify all existing 2D tests pass without modification
  - Run the full existing test suite and confirm no regressions in 2D normalization, transform, and inverse transform
  - _Requirements: 5.1, 5.3_
- [x] 6.2 Verify existing 3D unnormalized tests pass
  - Confirm the existing `test_transform_3d_exact` passes (uses explicit `t`, so arc-length fix does not affect it)
  - _Requirements: 5.2_
