tetra3 0.7.0

Rust implementation of Tetra3: Fast and robust star plate solver
Documentation
# Camera Model

The `CameraModel` encapsulates the mapping between pixel coordinates and tangent-plane (gnomonic projection) coordinates. It bundles all camera intrinsics into a single struct used throughout the solving and calibration pipeline.

## Parameters

| Parameter | Description |
|-----------|-------------|
| `focal_length_px` | Focal length in pixels (= image_width / (2 × tan(FOV/2))) |
| `image_width` | Image width in pixels |
| `image_height` | Image height in pixels |
| `crpix` | Optical center offset from image center `[x, y]` in pixels |
| `parity_flip` | Whether the image x-axis is mirrored |
| `distortion` | Optional `RadialDistortion` or `PolynomialDistortion` model |

## Pixel → Tangent Plane Pipeline

The `pixel_to_tanplane()` method applies the following steps:

1. **Subtract CRPIX** — shift to optical-center-relative coordinates
2. **Undistort** — apply the inverse distortion model (if any)
3. **Parity flip** — negate x if `parity_flip` is True
4. **Divide by focal length** — convert from pixels to radians

The result is tangent-plane coordinates `(ξ, η)` in radians, suitable for gnomonic (TAN) projection.

## Creating a Camera Model

=== "From FOV"

    ```python
    import tetra3rs

    # Simple pinhole model from field of view
    cam = tetra3rs.CameraModel.from_fov(
        fov_deg=10.0,
        image_width=2048,
        image_height=1536,
    )
    ```

=== "With explicit parameters"

    ```python
    cam = tetra3rs.CameraModel(
        focal_length_px=11718.4,
        image_width=2048,
        image_height=1536,
        crpix=[2.5, -1.3],       # optical center offset
        parity_flip=True,         # mirrored image
    )
    ```

=== "With distortion"

    ```python
    # Pure radial (Brown-Conrady with k1, k2, k3; tangential set to 0)
    distortion = tetra3rs.RadialDistortion(k1=-7e-9, k2=2e-15)

    # Or full Brown-Conrady with tangential / decentering coefficients:
    # distortion = tetra3rs.RadialDistortion(k1=-7e-9, p1=5e-7, p2=-3e-7)

    cam = tetra3rs.CameraModel(
        focal_length_px=11718.4,
        image_width=2048,
        image_height=1536,
        distortion=distortion,
    )
    ```

## Using with the Solver

Pass a `CameraModel` to `solve_from_centroids()` to apply distortion correction and parity during solving:

```python
result = db.solve_from_centroids(
    centroids,
    fov_estimate_deg=10.0,
    image_shape=image.shape,
    camera_model=cam,
)
```

The returned `SolveResult` uses the camera model's distortion and parity for its `pixel_to_world()` and `world_to_pixel()` methods.

## Calibration

Use `calibrate_camera()` to fit a camera model from one or more solved images. See [CalibrateResult](../api/calibrate-result.md) for details.

The fit selects between two distortion models via the `model` parameter:

- `model="polynomial"` (default): SIP-like polynomial of the requested
  `order`. Captures arbitrary 2D distortion, including tangential and
  decentering effects, by fitting independent per-axis coefficients
  `A_pq, B_pq`. Order-0 terms absorb the optical-center offset; higher
  orders capture lens distortion. Preferred for off-axis CCDs and astronomy
  WCS pipelines.
- `model="radial"`: full Brown-Conrady — three radial coefficients
  `(k1, k2, k3)` plus two tangential coefficients `(p1, p2)`, with the
  optical center `(cx, cy)` fit jointly. Three-to-seven free parameters
  total; well-conditioned with relatively few matches and the standard
  model in computer-vision camera calibration.

## References

### Brown-Conrady (radial + tangential)

- **Conrady, A. E.** (1919). "[Decentred Lens-Systems]https://doi.org/10.1093/mnras/79.5.384."
  *Monthly Notices of the Royal Astronomical Society*, 79(5): 384-390.
  — Original derivation of the tangential / decentering distortion form.
- **Brown, D. C.** (1966). "Decentering Distortion of Lenses."
  *Photogrammetric Engineering*, 32(3): 444-462. — Modernized the
  Conrady formulation; introduced the radial-plus-tangential form used today.
- **Brown, D. C.** (1971). "Close-Range Camera Calibration."
  *Photogrammetric Engineering*, 37(8): 855-866. — Calibration procedure;
  basis for the OpenCV / photogrammetry conventions.
- **Zhang, Z.** (2000). "[A Flexible New Technique for Camera Calibration]https://doi.org/10.1109/34.888718."
  *IEEE TPAMI*, 22(11): 1330-1334. — Multi-image planar-target calibration
  that became the standard method, and the model implemented by OpenCV's
  `calibrateCamera`.
- **OpenCV documentation** for the equivalent `(k1, k2, k3, p1, p2)`
  formulation: <https://docs.opencv.org/4.x/d9/d0c/group__calib3d.html>

### SIP polynomial

- **Shupe, D. L.; Moshir, M.; Li, J.; Makovoz, D.; Narron, R.; Hook, R. N.**
  (2005). "[The SIP Convention for Representing Distortion in FITS Image Headers]https://www.adass.org/adass/proceedings/adass04/reprints/P3-1-3.pdf."
  *Astronomical Data Analysis Software and Systems XIV*, ASP Conference
  Series, 347: 491. — The original SIP specification.
- **FITS WCS SIP convention registry entry**:
  <https://fits.gsfc.nasa.gov/registry/sip.html>