Polyscope viewer for a triwild 2D result: input curves, envelope curves, output mesh.
./visualize_triwild.py runs/full/success/10433 # a sweep output directory
./visualize_triwild.py input.obj output.msh # explicit pair
./visualize_triwild.py output.msh # mesh alone
Needs polyscope, meshio and numpy; see README.md for the venv.
Three layers, each with its own visibility checkbox:
input curves the .obj segment network handed to triwild
envelope curves the SIMPLIFIED curves, read back out of the .msh
output mesh the triangulation, coloured by per-face AMIPS2D energy on request
Given a directory it finds the mesh (`output.msh`, `out.msh`, or the only `*.msh`), then
the input: an `input.obj` beside it, else the path recorded in the run's `config.json`,
which is what makes it work on a sweep `success/<id>/` directory unchanged. The input is
optional -- without it you get the other two layers.
Two things about the data that the obvious implementation gets wrong:
* **The .msh node array is not the mesh.** Gmsh entities own their nodes, so a triwild
output holds two disjoint blocks: the dim-2 entity's nodes are the mesh vertices, and
the dim-1 "EnvelopeSurface" entity's nodes are the simplified input curve. Handing the
whole array to register_surface_mesh draws the mesh plus several hundred unreferenced
stray vertices. Each entity is compacted onto the nodes it actually uses.
* **An OBJ `l` record is a polyline, not a segment** -- n indices mean n-1 segments. The
2D dataset uses both forms, so reading one segment per record silently drops most of
the network on the files that use long polylines.
What is deliberately NOT here: which output EDGES are constrained (tracked to the
curves). The .msh does not tag them, and inferring them by proximity would be a guess
presented as data.