![Logo](./assets/banner.svg)

# Buffalo Wings

[![CI][ci-badge]][ci-link]
[![Docs][docs-badge]][docs-link]
[![License][license-badge]][license-link]

[![Tests][pytest-badge]][pytest-link]
[![mypy][mypy-badge]][mypy-link]
[![basedpyright][basedpyright-badge]][basedpyright-link]
[![Ruff lint][ruff-lint-badge]][ruff-link]
[![Ruff format][ruff-format-badge]][ruff-format-link]

[![coverage.py][coverage-badge]][coverage-link]
[![Built with Sphinx][sphinx-badge]][sphinx-link]
[![towncrier][towncrier-badge]][towncrier-link]
[![bumpversion][bumpversion-badge]][bumpversion-link]
[![uv][uv-badge]][uv-link]
[![setuptools][setuptools-badge]][setuptools-link]
[![Copier][copier-badge]][copier-link]

[ci-badge]: https://codeberg.org/BuffaloHerd/BuffaloWings/actions/workflows/ci.yaml/badge.svg?branch=main
[ci-link]: https://codeberg.org/BuffaloHerd/BuffaloWings/actions

[docs-badge]: https://img.shields.io/badge/docs-online-blue
[docs-link]: https://buffaloherd.codeberg.page/BuffaloWingsDocs

[license-badge]: https://img.shields.io/badge/license-GPL--3.0--only-yellow
[license-link]: https://buffaloherd.codeberg.page/BuffaloWingsDocs/LICENSE.html

[pytest-badge]: https://img.shields.io/badge/tests-pytest-0A9EDC?logo=python&logoColor=white
[pytest-link]: https://docs.pytest.org/

[mypy-badge]: https://img.shields.io/badge/type%20check-mypy-2A6DB2?logo=python&logoColor=white
[mypy-link]: https://mypy-lang.org/

[basedpyright-badge]: https://img.shields.io/badge/type%20check-basedpyright-3B82F6?logo=python&logoColor=white
[basedpyright-link]: https://docs.basedpyright.com/latest/

[ruff-lint-badge]: https://img.shields.io/badge/Ruff-lint-2ea44f?logo=ruff&logoColor=white
[ruff-format-badge]: https://img.shields.io/badge/Ruff-format-2ea44f?logo=ruff&logoColor=white

[ruff-link]: https://docs.astral.sh/ruff/
[ruff-format-link]: https://docs.astral.sh/ruff/formatter/

[coverage-badge]: https://img.shields.io/badge/coverage-coverage.py-6B7280?logo=python&logoColor=white
[coverage-link]: https://coverage.readthedocs.io/

[sphinx-badge]: https://img.shields.io/badge/built%20with-Sphinx-blue
[sphinx-link]: https://www.sphinx-doc.org/

[towncrier-badge]: https://img.shields.io/badge/changelog-towncrier-334155
[towncrier-link]: https://towncrier.readthedocs.io/

[bumpversion-badge]: https://img.shields.io/badge/release-bumpversion-8B5CF6
[bumpversion-link]: https://pypi.org/project/bumpversion/

[uv-badge]: https://img.shields.io/badge/deps-uv-111827
[uv-link]: https://docs.astral.sh/uv/

[setuptools-badge]: https://img.shields.io/badge/build-setuptools-64748B
[setuptools-link]: https://setuptools.pypa.io/

[copier-badge]: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/copier-org/copier/master/img/badge/badge-grayscale-inverted-border.json
[copier-link]: https://github.com/copier-org/copier

Buffalo Wings is a Python geometry library for building airfoil and wing models from aerodynamic definitions.
It is designed to support interactive design workflows, visualization tools, and downstream analysis or meshing pipelines.
The long-term goal is to provide a strong geometry foundation for GUI-based airfoil and wing design applications.

## Why This Project Exists

Buffalo Wings focuses on aerodynamic geometry rather than general-purpose CAD.
The library is meant to turn validated airfoil and wing definitions into queryable geometry objects that can support plotting, inspection, meshing, and higher-level design tools.
That includes future GUI-oriented applications for constructing and visualizing airfoils and wings.

## Current Focus

The current public API is centered on three modules:
`buffalo_wings.airfoil` for airfoil geometry and airfoil definitions,
`buffalo_wings.wing` for wing geometry and wing definitions,
and `buffalo_wings.type_aliases` for shared numeric typing helpers.

Today, the airfoil subsystem is the most mature part of the project.
Wing geometry support is under active development.
GUI applications are a planned direction rather than a released feature.

## Quick Start

Install Buffalo Wings from PyPI with:

```bash
pip install buffalo-wings
```

Create a NACA 4-digit airfoil from a designation:

```python
import numpy as np
import buffalo_wings.airfoil as bwa

airfoil = bwa.AirfoilFactory.naca4_from_designation("2412")
t = np.linspace(-1.0, 1.0, 11, dtype=np.float64)
x, y = airfoil.xy(t)
```

Create the same airfoil from a public schema object:

```python
import buffalo_wings.airfoil as bwa

spec = bwa.Naca4AirfoilSpec(designation="2412")
airfoil = bwa.AirfoilFactory.from_spec(spec)
```

The supported public modules are `buffalo_wings.airfoil`,
`buffalo_wings.wing`,
and `buffalo_wings.type_aliases`.
Modules under `buffalo_wings.*.internal` are implementation details and are not part of the supported external API.

## Where To Go Next

Start with `examples/airfoil/create_naca4_from_designation.py` for a minimal airfoil construction example.
See `examples/airfoil/create_naca4_from_spec.py` for the schema-driven airfoil path.
See `examples/wing/create_rectangular_wing.py` for a minimal public wing example.
See the [online documentation](https://buffaloherd.codeberg.page/BuffaloWingsDocs) for examples, API reference, and developer notes.
See the [changelog](https://codeberg.org/BuffaloHerd/BuffaloWings/src/branch/main/CHANGELOG.md) for recent changes and project evolution.

## Contributors

The main contributors to this project are:

- David D. Marshall

## Version History

See the [changelog](https://codeberg.org/BuffaloHerd/BuffaloWings/src/branch/main/CHANGELOG.md) for details.

## Code of Conduct

This project is governed by the Contributor Covenant Code of Conduct (v3.0).
By participating, you agree to uphold it.
Please see the [code of conduct](https://codeberg.org/BuffaloHerd/BuffaloWings/src/branch/main/CODE_OF_CONDUCT.md) for details and reporting instructions.

## License

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the [GNU General Public License](https://codeberg.org/BuffaloHerd/BuffaloWings/src/branch/main/LICENSE.md) for more details.
