Tracing Geodesic Paths
The function traceGeodesic allows one to compute straightest paths along a surface (i.e. geodesic paths).
Note that straightest paths depend only on the intrinsic geometry of a surface (via the IntrinsicGeometryInterface). Therefore, these routines can be run on abstract geometric domains as well as traditional surfaces in 3D. However, these routines do assume that the domain is a ManifoldSurfaceMesh.
#include "geometrycentral/surface/trace_geodesic.h"
TraceGeodesicResult traceGeodesic(IntrinsicGeometryInterface& geom, SurfacePoint startP, Vector2 traceVec, const TraceOptions& traceOptions = defaultTraceOptions);
Trace a geodesic path along a surface mesh.
inputGeom: the input geometry (as always, aVertexPositionGeometryis valid input)startP: the point on the surface where the path should starttraceVec: the direction the path should proceed in, and the distance that it should traveltraceOptions: options to specify the behavior oftraceGeodesicin various situations
The function traceGeodesic traces out a geodesic path starting at startP which proceeds in the direction of traceVec and has length equal to traceVec.norm(), unless the path intersects a boundary edge in which case it stops there.
This is also known as the exponential map. (As an aside, geometry-central also provides procedures for computing the inverse of the exponential map, known as the logarithmic map.)
Example
#include "geometrycentral/surface/meshio.h"
#include "geometrycentral/surface/surface_point.h"
#include "geometrycentral/surface/trace_geodesic.h"
// Load a mesh
std::unique_ptr<ManifoldSurfaceMesh> mesh;
std::unique_ptr<VertexPositionGeometry> geometry;
std::tie(mesh, geometry) = readManifoldSurfaceMesh(filename);
Vertex v = mesh->vertex(0);
Vector2 traceVec = 3 * Vector2::fromAngle(M_PI/6);
SurfacePoint pathEndpoint = traceGeodesic(*geometry, SurfacePoint(v), traceVec).endPoint;
Helper Types
Options
Options are passed in to traceGeodesic via a TraceOptions object.
| Field | Default value | Meaning |
|---|---|---|
bool includePath |
false |
whether to return the entire path trajectory (as opposed to merely returning the path’s endpoint) |
bool errorOnProblem |
false |
whether to throw exceptions if the procedure encounters degenerate geometry |
EdgeData<bool>* barrierEdges |
nullptr |
if set, paths will stop when they hit barrier edges |
size_t maxIters |
INVALID_IND |
if set, paths will stop after traversing through maxIters faces |
Result
The result is returned as a TraceGeodesicResult, which has 5 fields:
| Field | Meaning |
|---|---|
SurfacePoint endPoint |
the point the path ended at |
std::vector<SurfacePoint> pathPoints |
all points along the path, including start and end |
Vector2 endingDir |
the incoming direction to the final point, in its tangent space |
bool hitBoundary |
did the path stop early because we hit a boundary? |
bool hasPath |
is pathPoints populated? |
double length |
length of the traced path (generally equals norm of traceVec unless tracing stopped early due to hitting a boundary/barrier edge or due to the iteration limit maxIters) |
Tangent Spaces
The input traceVec is specified as a vector in the tangent space of the starting point. The meaning of this vector depends on whether the starting point is located on a vertex, edge, or face of the mesh. Tangent space in geometry central are discussed in more detail on the Quantities page, but we give a brief overview here.
Given any mesh element (i.e. vertex, edge, or face) p, the x-axis of the tangent space at p points in the direction of p.halfedge(). The y-axis then points 90 degrees counterclockwise from the x-axis. (This is slightly more complicated at vertices, where one must use rescaled corner angles to define these directions. See the discussion of vertex tangent spaces) for more details.