# Getting Started

## Prerequisites

| Tool | Minimum | Notes |
|---|---|---|
| C++ compiler (GCC or Clang) | C++17 | GCC 11+ or Clang 14+ recommended |
| CMake | 3.20 | |
| Boost headers | 1.70 | Only for `-DWITH_CGAL_TESTS=ON` or `-DWITH_CGAL=ON` |
| Wayland/X11 dev headers | — | Only for `-DWITH_CGAL=ON` (viewer) |

All other dependencies (Eigen 3.4, CGAL 6.1.1, libigl 2.6, GLFW 3.4, GTest 1.14)
are bundled as tarballs in `code/deps/tarballs/` and extracted automatically at CMake
configure time. No internet access is required at build time (except GTest, fetched via
`FetchContent` from GitHub).

Install Boost on your system:
```bash
# Ubuntu / Debian
apt install libboost-dev

# macOS
brew install boost
```

---

## Clone

```bash
git clone https://codeberg.org/TMoussa/ConformalLabpp
cd ConformalLabpp
```

---

## Build modes

Three modes with increasing dependencies:

### Mode 1 — Fast tests (default, no system dependencies)

Pure-math tests: Clausen functions, hyper-ideal geometry, matrix utilities.

```bash
cmake -S code -B build
cmake --build build --target conformallab_tests -j$(nproc)
ctest --test-dir build --output-on-failure
```

Expected: all pure-math tests pass (count: [`doc/api/tests.md`](api/tests.md)).

### Mode 2 — CGAL tests, headless (recommended for CI and development)

Full CGAL test suite. Requires Boost headers only — no display, no Wayland, no GLFW.

```bash
cmake -S code -B build -DWITH_CGAL_TESTS=ON
cmake --build build --target conformallab_cgal_tests -j$(nproc)
ctest --test-dir build -R "^cgal\." --output-on-failure
```

Expected: all CGAL tests pass, 0 skipped (count: [`doc/api/tests.md`](api/tests.md)).

### Mode 3 — Full local build (CLI app + interactive viewer)

Requires Wayland or X11 development packages (`wayland-scanner`, `libx11-dev`, etc.).
Automatically enables the viewer library (GLFW + libigl).

```bash
cmake -S code -B build -DWITH_CGAL=ON
cmake --build build -j$(nproc)
```

> **Note:** `-DWITH_CGAL=ON` implies `-DWITH_VIEWER=ON`. Do not use this in headless
> environments — it will fail with `Failed to find wayland-scanner`.

### Mode 4 — Low-memory build (RAM-constrained CI / Raspberry Pi ≤ 4 GB)

For machines where the CGAL build OOMs (peak ~700 MB per compilation unit at `-O3`):

```bash
cmake -S code -B build -DWITH_CGAL_TESTS=ON \
      -DCONFORMALLAB_LOW_MEMORY_BUILD=ON
cmake --build build --target conformallab_cgal_tests -j1
```

`LOW_MEMORY_BUILD` applies four measures: `-O0` (no debug info), PCH off,
unity batch size 1, `--no-keep-memory` linker flag.  Drops cc1plus peak from
~700 MB to ~150-200 MB per TU.  Tests run ~15× slower at `-O0` but all pass.
**Always use `-j1`** — parallel compilation would defeat the memory savings.

---

## Running a single test

```bash
# By GTest filter (fastest, full output)
./build/conformallab_cgal_tests --gtest_filter="NewtonSolver*"
./build/conformallab_tests       --gtest_filter="Clausen*"

# By CTest regex
ctest --test-dir build -R "cgal.NewtonSolver" --output-on-failure
```

All CGAL tests have the prefix `cgal.` in CTest (set in `tests/cgal/CMakeLists.txt`
via `TEST_PREFIX "cgal."`).

---

## First run — CLI app

After a full build (`-DWITH_CGAL=ON`):

```bash
# Euclidean conformal layout
./bin/conformallab_core -i input.off -g euclidean -o layout.off -j result.json

# Spherical layout
./bin/conformallab_core -i input.off -g spherical -o sphere.off

# Hyperbolic layout (HyperIdeal)
./bin/conformallab_core -i input.off -g hyper_ideal -o hyperbolic.off

# Show input mesh in interactive viewer
./bin/conformallab_core -i input.off -s

# All options
./bin/conformallab_core --help
```

### CLI parameter reference

| Flag | Default | Description |
|------|---------|-------------|
| `-i / --input` | *required* | Input mesh file (OFF / OBJ / PLY) |
| `-o / --output` | *(none)* | Save layout as OFF file |
| `-j / --json` | *(none)* | Serialise solver result + UV to JSON |
| `-x / --xml` | *(none)* | Serialise solver result + UV to XML |
| `-g / --geometry` | `euclidean` | Target geometry: `euclidean` · `spherical` · `hyper_ideal` |
| `-s / --show` | `false` | Open the input mesh in the interactive viewer |
| `-v / --verbose` | `false` | Print mesh topology, DOF counts, convergence details |

> **Tip:** `./bin/conformallab_core --help` always shows the canonical up-to-date
> list generated by CLI11.  The table above matches `conformallab_cli.cpp`
> as of v0.10.0.

## Example programs

```bash
# PRIMARY USE CASE: conformally flatten a mesh to the plane
./build/examples/example_flatten   code/data/obj/cathead.obj flat.off
#  → non-trivial u_v (e.g. range ≈ 2.96), real conformal deformation

# CGAL public API: one-call interface (natural theta by default)
./build/examples/example_cgal_api  [input.off]

# Full pipeline with JSON/XML serialisation and round-trip test
./build/examples/example_layout    [input.off] [layout.off] [result.json]

# Solver test (natural theta — u_v ≈ 0, used for pipeline validation)
./build/examples/example_euclidean [input.off] [output.off]

# Hyper-ideal (hyperbolic) functional
./build/examples/example_hyper_ideal [input.off] [output.off]

# Interactive viewer (requires WITH_VIEWER)
./build/examples/example_viewer    [input.off]
```

**Start here:** `example_flatten.cpp` shows the primary use case — real conformal
flattening with `Θ_v = 2π`.  `example_layout.cpp` adds JSON/XML serialisation.

> **Note on "natural theta":** `example_euclidean` and `example_layout` use the
> "natural theta" testing trick (`Θ_v = actual angle sum at x=0`), which makes
> `x* = 0` trivially the equilibrium.  The output `u_v ≈ 0` is expected and
> correct for a pipeline test, but means **no conformal deformation was applied**.
> For real UV parameterisation, use `example_flatten.cpp`.

**Expected output of `example_euclidean` on the built-in quad-strip mesh:**
```
[example_euclidean] No input file given — using make_quad_strip().
[example_euclidean] Mesh: 6 vertices, 4 faces.
[example_euclidean] DOFs: 5 (1 vertex pinned).
[example_euclidean] Solving Newton system…
[example_euclidean] Converged in 1 iterations.  ||G||_inf = 0
[example_euclidean] Per-vertex conformal factors u_i:
  v0  u = 0  (pinned)
  v1  u = -1.38778e-17       ← ≈ 0 (machine epsilon)
  ...
[example_euclidean] Mesh saved to: /tmp/conformallab_euclidean_out.off
```
Convergence in 1 iteration is expected: the "natural equilibrium" construction
sets x* = 0, so a small perturbation (-0.05) needs only one Newton step.

**Quick automated start (no interactive build needed):**
```bash
bash scripts/try_it.sh
```
This clones nothing (run from inside the repo), builds the CGAL test suite, runs
the full test suite, and prints a summary.  See `scripts/try_it.sh` for details.

---

## Known issues

### macOS Finder duplicates

macOS Finder sometimes creates duplicate files named `foo 2.hpp` when copying
the repository.  These cause confusing compile errors ("redefinition of …").

**Fix (run once from the repo root):**
```bash
find code/include -name "* 2.*" -delete
find code/include -name "*\ 2.*" -delete
```

Files without a ` 2` suffix are always canonical — the duplicates are safe to delete.

### First build is slow

The first CMake configure extracts four tarballs (Eigen 3.4, CGAL 6.1.1,
libigl 2.6, GLFW 3.4) and downloads GTest via `FetchContent`.
Allow **30–90 seconds** for the first configure.  Subsequent builds are fast
(< 10 s incremental).

---

## Rebuilding the CI Docker image

The CI runner is a self-hosted Raspberry Pi (ARM64). After changes to
`.gitea/docker/Dockerfile.ci-cpp`:

```bash
docker buildx build \
  --platform linux/arm64 \
  -f .gitea/docker/Dockerfile.ci-cpp \
  -t git.eulernest.eu/conformallab/ci-cpp:latest \
  --push \
  .gitea/docker/
```
