mirror of
https://github.com/orange-cpp/omath.git
synced 2026-02-13 07:03:25 +00:00
Documents pattern scanning API
Adds comprehensive documentation for the pattern scanning API. Details parsing behavior, complexity, and usage examples. Includes troubleshooting tips and minimal test sketches. Clarifies edge-case handling and implementation notes.
This commit is contained in:
118
docs/3d_primitives/box.md
Normal file
118
docs/3d_primitives/box.md
Normal file
@@ -0,0 +1,118 @@
|
||||
# `omath::primitives::create_box` — Build an oriented box as 12 triangles
|
||||
|
||||
> Header: your project’s `primitives/box.hpp` (declares `create_box`)
|
||||
> Namespace: `omath::primitives`
|
||||
> Depends on: `omath::Triangle<omath::Vector3<float>>`, `omath::Vector3<float>`
|
||||
|
||||
```cpp
|
||||
[[nodiscard]]
|
||||
std::array<Triangle<Vector3<float>>, 12>
|
||||
create_box(const Vector3<float>& top,
|
||||
const Vector3<float>& bottom,
|
||||
const Vector3<float>& dir_forward,
|
||||
const Vector3<float>& dir_right,
|
||||
float ratio = 4.f) noexcept;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## What it does
|
||||
|
||||
Constructs a **rectangular cuboid (“box”)** oriented in 3D space and returns its surface as **12 triangles** (2 per face × 6 faces). The box’s central axis runs from `bottom` → `top`. The **up** direction is inferred from that segment; the **forward** and **right** directions define the box’s orientation around that axis.
|
||||
|
||||
The lateral half-extents are derived from the axis length and `ratio`:
|
||||
|
||||
> Let `H = |top - bottom|`. Lateral half-size ≈ `H / ratio` along both `dir_forward` and `dir_right`
|
||||
> (i.e., the cross-section is a square of side `2H/ratio`).
|
||||
|
||||
> **Note:** This describes the intended behavior from the interface. If you rely on a different sizing rule, document it next to your implementation.
|
||||
|
||||
---
|
||||
|
||||
## Parameters
|
||||
|
||||
* `top`
|
||||
Center of the **top face**.
|
||||
|
||||
* `bottom`
|
||||
Center of the **bottom face**.
|
||||
|
||||
* `dir_forward`
|
||||
A direction that orients the box around its up axis. Should be **non-zero** and **not collinear** with `top - bottom`.
|
||||
|
||||
* `dir_right`
|
||||
A direction roughly orthogonal to both `dir_forward` and `top - bottom`. Used to fully fix orientation.
|
||||
|
||||
* `ratio` (default `4.0f`)
|
||||
Controls thickness relative to height. Larger values → thinner box.
|
||||
With the default rule above, half-extent = `|top-bottom|/ratio`.
|
||||
|
||||
---
|
||||
|
||||
## Return value
|
||||
|
||||
`std::array<Triangle<Vector3<float>>, 12>` — the six faces of the box, triangulated.
|
||||
Winding is intended to be **outward-facing** (right-handed coordinates). Do not rely on a specific **face ordering**; treat the array as opaque unless your implementation guarantees an order.
|
||||
|
||||
---
|
||||
|
||||
## Expected math & robustness
|
||||
|
||||
* Define `u = normalize(top - bottom)`.
|
||||
* Re-orthonormalize the basis to avoid skew:
|
||||
|
||||
```cpp
|
||||
f = normalize(dir_forward - u * u.dot(dir_forward)); // drop any up component
|
||||
r = normalize(u.cross(f)); // right-handed basis
|
||||
// (Optionally recompute f = r.cross(u) for orthogonality)
|
||||
```
|
||||
* Half-extents: `h = length(top - bottom) / ratio; hf = h * f; hr = h * r`.
|
||||
* Corners (top): `t±r±f = top ± hr ± hf`; (bottom): `b±r±f = bottom ± hr ± hf`.
|
||||
* Triangulate each face with consistent CCW winding when viewed from outside.
|
||||
|
||||
---
|
||||
|
||||
## Example
|
||||
|
||||
```cpp
|
||||
using omath::Vector3;
|
||||
using omath::Triangle;
|
||||
using omath::primitives::create_box;
|
||||
|
||||
// Axis from bottom to top (height 2)
|
||||
Vector3<float> bottom{0, 0, 0};
|
||||
Vector3<float> top {0, 2, 0};
|
||||
|
||||
// Orientation around the axis
|
||||
Vector3<float> forward{0, 0, 1};
|
||||
Vector3<float> right {1, 0, 0};
|
||||
|
||||
// Ratio 4 → lateral half-size = height/4 = 0.5
|
||||
auto tris = create_box(top, bottom, forward, right, 4.0f);
|
||||
|
||||
// Use the triangles (normals, rendering, collision, etc.)
|
||||
for (const auto& tri : tris) {
|
||||
auto n = tri.calculate_normal();
|
||||
(void)n;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Usage notes & pitfalls
|
||||
|
||||
* **Degenerate axis**: If `top == bottom`, the box is undefined (zero height). Guard against this.
|
||||
* **Directions**: Provide **non-zero**, **reasonably orthogonal** `dir_forward`/`dir_right`. A robust implementation should project/normalize internally, but callers should still pass sensible inputs.
|
||||
* **Winding**: If your renderer or collision expects a specific winding, verify with a unit test and flip vertex order per face if necessary.
|
||||
* **Thickness policy**: This doc assumes both lateral half-extents equal `|top-bottom|/ratio`. If your implementation diverges (e.g., separate forward/right ratios), document it.
|
||||
|
||||
---
|
||||
|
||||
## See also
|
||||
|
||||
* `omath::Triangle` (vertex utilities: normals, centroid, etc.)
|
||||
* `omath::Vector3` (geometry operations used by the construction)
|
||||
|
||||
---
|
||||
|
||||
*Last updated: 31 Oct 2025*
|
||||
98
docs/3d_primitives/plane.md
Normal file
98
docs/3d_primitives/plane.md
Normal file
@@ -0,0 +1,98 @@
|
||||
# `omath::primitives::create_plane` — Build an oriented quad (2 triangles)
|
||||
|
||||
> Header: your project’s `primitives/plane.hpp`
|
||||
> Namespace: `omath::primitives`
|
||||
> Depends on: `omath::Triangle<omath::Vector3<float>>`, `omath::Vector3<float>`
|
||||
|
||||
```cpp
|
||||
[[nodiscard]]
|
||||
std::array<Triangle<Vector3<float>>, 2>
|
||||
create_plane(const Vector3<float>& vertex_a,
|
||||
const Vector3<float>& vertex_b,
|
||||
const Vector3<float>& direction,
|
||||
float size) noexcept;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## What it does
|
||||
|
||||
Creates a **rectangle (quad)** in 3D oriented by the edge **A→B** and a second in-plane **direction**. The quad is returned as **two triangles** suitable for rendering or collision.
|
||||
|
||||
* Edge axis: `e = vertex_b - vertex_a`
|
||||
* Width axis: “direction”, **projected to be perpendicular to `e`** so the quad is planar and well-formed.
|
||||
* Normal (by right-hand rule): `n ∝ e × width`.
|
||||
|
||||
> **Sizing convention**
|
||||
> Typical construction uses **half-width = `size`** along the (normalized, orthogonalized) *direction*, i.e. the total width is `2*size`.
|
||||
> If your implementation interprets `size` as full width, adjust your expectations accordingly.
|
||||
|
||||
---
|
||||
|
||||
## Parameters
|
||||
|
||||
* `vertex_a`, `vertex_b` — two adjacent quad vertices defining the **long edge** of the plane.
|
||||
* `direction` — a vector indicating the **cross-edge direction** within the plane (does not need to be orthogonal or normalized).
|
||||
* `size` — **half-width** of the quad along the (processed) `direction`.
|
||||
|
||||
---
|
||||
|
||||
## Return
|
||||
|
||||
`std::array<Triangle<Vector3<float>>, 2>` — the quad triangulated (consistent CCW winding, outward normal per `e × width`).
|
||||
|
||||
---
|
||||
|
||||
## Robust construction (expected math)
|
||||
|
||||
1. `e = vertex_b - vertex_a`
|
||||
2. Make `d` perpendicular to `e`:
|
||||
|
||||
```
|
||||
d = direction - e * (e.dot(direction) / e.length_sqr());
|
||||
if (d.length_sqr() == 0) pick an arbitrary perpendicular to e
|
||||
d = d.normalized();
|
||||
```
|
||||
3. Offsets: `w = d * size`
|
||||
4. Four corners:
|
||||
|
||||
```
|
||||
A0 = vertex_a - w; A1 = vertex_a + w;
|
||||
B0 = vertex_b - w; B1 = vertex_b + w;
|
||||
```
|
||||
5. Triangles (CCW when viewed from +normal):
|
||||
|
||||
```
|
||||
T0 = Triangle{ A0, A1, B1 }
|
||||
T1 = Triangle{ A0, B1, B0 }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Example
|
||||
|
||||
```cpp
|
||||
using omath::Vector3;
|
||||
using omath::Triangle;
|
||||
using omath::primitives::create_plane;
|
||||
|
||||
Vector3<float> a{ -1, 0, -1 }; // edge start
|
||||
Vector3<float> b{ 1, 0, -1 }; // edge end
|
||||
Vector3<float> dir{ 0, 0, 1 }; // cross-edge direction within the plane (roughly +Z)
|
||||
float half_width = 2.0f;
|
||||
|
||||
auto quad = create_plane(a, b, dir, half_width);
|
||||
|
||||
// e.g., compute normals
|
||||
for (const auto& tri : quad) {
|
||||
auto n = tri.calculate_normal(); (void)n;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Notes & edge cases
|
||||
|
||||
* **Degenerate edge**: if `vertex_a == vertex_b`, the plane is undefined.
|
||||
* **Collinearity**: if `direction` is parallel to `vertex_b - vertex_a`, the function must choose an alternate perpendicular; expect a fallback.
|
||||
* **Winding**: If your renderer expects a specific face order, verify and swap the two vertices in each triangle as needed.
|
||||
Reference in New Issue
Block a user