feat(phase4a+4b): Newton solver + CGAL mesh I/O
Phase 4a — newton_solver.hpp:
- newton_euclidean(): SimplicialLDLT on H (PSD); solves H·Δx = −G
- newton_spherical(): SimplicialLDLT on −H (NSD→PSD); solves (−H)·Δx = G
- Backtracking line search (halving α up to 20×) for global convergence
- NewtonResult struct: x, iterations, grad_inf_norm, converged
- 7 tests: 4 spherical (convergence, few iters, large perturbation,
field consistency) + 3 Euclidean (triangle pinned, quad pinned,
mixed pinned — all with natural-theta equilibrium at x=0)
Phase 4b — mesh_io.hpp:
- read_mesh() / write_mesh(): CGAL::IO::read/write_polygon_mesh wrappers
- load_mesh() / save_mesh(): throwing convenience versions
- Supports OFF, OBJ, PLY (format detected by file extension)
- 6 tests: OFF round-trip (tet + quad), OBJ round-trip, missing-file throw,
vertex-position preservation, save/load convenience wrappers
All 75 cgal tests pass (3 skipped as before).
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
65
code/include/mesh_io.hpp
Normal file
65
code/include/mesh_io.hpp
Normal file
@@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
// mesh_io.hpp
|
||||
//
|
||||
// Phase 4b — CGAL::IO wrappers for ConformalMesh.
|
||||
//
|
||||
// Reads and writes ConformalMesh (CGAL::Surface_mesh) in standard polygon-mesh
|
||||
// formats using the CGAL Polygon Mesh I/O utilities (CGAL 5.4+).
|
||||
//
|
||||
// Supported formats (detected by file extension):
|
||||
// .off — Object File Format (read + write)
|
||||
// .obj — Wavefront OBJ (read + write)
|
||||
// .ply — Polygon File Format (read + write)
|
||||
//
|
||||
// Usage:
|
||||
// ConformalMesh mesh;
|
||||
// if (!read_mesh("input.off", mesh)) throw std::runtime_error("read failed");
|
||||
// // ... process mesh ...
|
||||
// write_mesh("output.off", mesh);
|
||||
//
|
||||
// Note: property maps (lambda0, v_idx, etc.) are NOT serialised — they must
|
||||
// be re-initialised with setup_*_maps() + compute_lambda0_from_mesh() after
|
||||
// reading a file.
|
||||
|
||||
#include "conformal_mesh.hpp"
|
||||
#include <CGAL/IO/polygon_mesh_io.h>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace conformallab {
|
||||
|
||||
// ── Read ──────────────────────────────────────────────────────────────────────
|
||||
//
|
||||
// Reads a polygon mesh from file into `mesh` (clears any existing content).
|
||||
// Returns true on success, false on failure.
|
||||
inline bool read_mesh(const std::string& filename, ConformalMesh& mesh)
|
||||
{
|
||||
mesh.clear();
|
||||
return CGAL::IO::read_polygon_mesh(filename, mesh);
|
||||
}
|
||||
|
||||
// ── Write ─────────────────────────────────────────────────────────────────────
|
||||
//
|
||||
// Writes `mesh` to `filename`. Returns true on success.
|
||||
inline bool write_mesh(const std::string& filename, const ConformalMesh& mesh)
|
||||
{
|
||||
return CGAL::IO::write_polygon_mesh(filename, mesh);
|
||||
}
|
||||
|
||||
// ── Convenience: throwing wrappers ────────────────────────────────────────────
|
||||
|
||||
inline ConformalMesh load_mesh(const std::string& filename)
|
||||
{
|
||||
ConformalMesh mesh;
|
||||
if (!read_mesh(filename, mesh))
|
||||
throw std::runtime_error("conformallab: failed to read mesh from " + filename);
|
||||
return mesh;
|
||||
}
|
||||
|
||||
inline void save_mesh(const std::string& filename, const ConformalMesh& mesh)
|
||||
{
|
||||
if (!write_mesh(filename, mesh))
|
||||
throw std::runtime_error("conformallab: failed to write mesh to " + filename);
|
||||
}
|
||||
|
||||
} // namespace conformallab
|
||||
Reference in New Issue
Block a user