Skip to content

Add FlipOutContext: fast repeated point-to-point FlipOut queries on one mesh - #259

Open
mfagerlund wants to merge 1 commit into
nmwsharp:masterfrom
mfagerlund:flipout-context
Open

mfagerlund wants to merge 1 commit into
nmwsharp:masterfrom
mfagerlund:flipout-context

Conversation

@mfagerlund

Copy link
Copy Markdown

Motivation

For a single vertex-to-vertex geodesic, FlipEdgeNetwork::constructFromDijkstraPath() + iterativeShorten() spends almost all of its time on setup that doesn't depend on the query. Profile of one query on a 48k-vertex mesh (horse):

step ms
Dijkstra over the whole mesh 16
SignpostIntrinsicTriangulation construction 29
FlipEdgeNetwork construction 10.6
iterativeShorten() 1.1
destruction 5.7

The shortening itself is under 2% of the query.

What this adds

FlipOutContext (flip_geodesics_context.h/.cpp) is built once per mesh and answers vertex-to-vertex queries:

  • a flat intrinsic triangulation (connectivity, edge lengths, signpost angles, angle sums) built directly from the input mesh, with the same angle values as the signpost triangulation;
  • the initial edge path by A* with a Euclidean heuristic when vertex positions are available (Dijkstra otherwise), using the same heap ordering as shortestEdgePath, so it returns the same path;
  • the same shortening loop as iterativeShorten(): same wedge-angle queue, flip test, epsilons and angle updates;
  • an undo log, so each query's flips are reverted in O(1) each and the next query starts from the original triangulation.

The existing FlipEdgeNetwork code is unchanged; this is a separate class.

Same output

The tests (flip_geodesics_context_test.cpp) check, on spot, bob_small, fox and cat_head (two of them with boundary), 40 random pairs each:

  • the same intrinsic halfedge sequence as the FlipEdgeNetwork route, and the same length within 1e-12 relative;
  • repeated queries and fresh contexts agree, so undoing a query leaves no trace;
  • the traced polyline matches getPathPolyline() point by point.

On 14 benchmark meshes (300 random pairs each, 4,200 queries) no length differs from the shipped route by more than 1e-9 relative, and the flip counts match.

Speed

Ryzen 9 3950X, MSVC Release, 300 random vertex pairs per mesh, geometric mean over 14 meshes (1.8k–112k vertices):

  • context reused across queries: 45x faster than the shipped route (e.g. horse 118 ms → 2.5 ms per query, happy-buddha 111 → 3.1, bimba 278 → 4.5);
  • context built per query: 5x faster, since building the flat triangulation is cheaper than the full signpost triangulation and network.

The docs page for flip geodesics gets a short section with usage.

Happy to adjust naming, scope or API to fit the library.

…sic triangulation per mesh

FlipEdgeNetwork::constructFromDijkstraPath builds a fresh signpost triangulation and
path network per query, which is ~98% of a point-to-point query on large meshes.
FlipOutContext keeps a flat intrinsic triangulation per mesh, finds the initial
edge path with A* (Dijkstra order, Euclidean heuristic), runs the same shortening
loop, and undoes its flips after each query. Paths are identical to the shipped
route (same halfedge sequences); tests check this on four meshes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant