Migrating from potpourri3d
potpourri3d (the Python binding for geometry-central) is the reference for the heat-method
family — vector heat, parallel transport, log maps, and signed heat — and triwarp's
triwarp.heat module mirrors that scope. The main structural difference:
potpourri3d builds a stateful *Solver object per mesh and reuses it across calls; triwarp
separates that into an explicit, cacheable operator bundle
(heat.heat_operators /
heat.vector_heat_operators) you pass back into each
solve.
import potpourri3d as pp3d # before
import triwarp as tw # after
Distance and vector heat
| potpourri3d | triwarp |
|---|---|
pp3d.MeshHeatMethodDistanceSolver(V, F) then .compute_distance(source) |
heat.heat_operators(vertices, faces) then heat.heat_geodesic(vertices, faces, sources, operators=...) |
pp3d.MeshVectorHeatSolver(V, F) then .extend_scalar(sources, values) |
heat.vector_heat_operators then heat.extend_scalar |
.transport_tangent_vector(source, vector) |
heat.transport_tangent_vectors |
.compute_log_map(source) |
heat.log_map |
pp3d.SignedHeatSolver(V, F) then .compute_distance(curve) |
heat.heat_signed_distance |
pp3d.edges(V, F) |
edges.faces_to_edges / edges.edges_unique |
| Tangent frames used internally by the solvers | tangent_space.vertex_tangent_frames / face_tangent_frames (public and directly inspectable in triwarp) |
What's different, not just renamed
- Operators are explicit, not hidden inside a solver object. potpourri3d's
use_robustanduse_intrinsic_delaunaymollification flags are constructor arguments to a solver you keep around; triwarp exposes the equivalent behindheat.heat_operators's own keyword, and the operators it returns are a plain value you can cache yourself (see Geodesic distance fields in the cookbook) — nothing solver-shaped to construct once and mutate. - Tangent-space quantities are gauge-dependent in both libraries. A tangent frame from
tangent_space.vertex_tangent_framesagrees with potpourri3d's own frames only up to a rotation about the normal — compare transport results through a gauge-invariant combination (e.g. the angle between two transported vectors), never their raw 2D tangent components, exactly as you would with potpourri3d's own output. log_map's barycentric output is decoded directly as a triwarp array, not as potpourri3d's geometry-central element-index pairs — seeheat.log_map's own docstring for the returned convention.