Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
b6487e7
Block out functions and documentation; names could use some work
nzfeng Jan 31, 2024
db076b6
Add simple polygon operators, minus DEC operators
nzfeng Jan 31, 2024
26f9e44
Update variable names to something more manageable; flesh out everyth…
nzfeng Feb 1, 2024
0f9b813
Update docs; in the middle of simple polygon DEC operators, not sure …
nzfeng Feb 1, 2024
f4e0963
Add polygon DEC operators
nzfeng Feb 2, 2024
5f45918
Get rid of simple polygon DEC operators (d0 and hodge1) because they …
nzfeng Feb 2, 2024
e529be4
Add gradient and divergence operators
nzfeng Feb 2, 2024
aa0e80b
Fix some typos and required quantities
nzfeng Feb 2, 2024
bf79c2c
Fix DEC operators
nzfeng Feb 5, 2024
10b210a
In the middle of debugging hodge1 and connection Laplacian
nzfeng Feb 5, 2024
1fbdc3b
Add a bunch of temporary experimentation
nzfeng Feb 9, 2024
27a6370
Update DEC and docs
nzfeng Mar 12, 2024
db9b5ea
I forget what I added
nzfeng Apr 1, 2024
1c949b7
Finish polygon connection Laplacian
nzfeng Sep 3, 2024
a565c94
Get rid of redundant functions
nzfeng Sep 3, 2024
54f2dab
Use correct tangent basis vectors
nzfeng Sep 6, 2024
e1ddcaf
Add rest of heat solvers for polygon meshes
nzfeng Sep 6, 2024
f4a76fe
Finalize changes
nzfeng Sep 9, 2024
8ca9110
Add licensing info
nzfeng Sep 10, 2024
aa6ae5c
Finish implementation and docs
nzfeng Sep 12, 2024
5eacff4
Add tests
nzfeng Sep 17, 2024
dbb0b97
Update cornerAngles function
nzfeng Feb 22, 2025
bee9c13
Remove unused eps
nzfeng May 16, 2025
c94b23c
Split off helper functions into a separate file... but the code gets …
nzfeng May 16, 2025
ad2367c
Separate just the helper functions that don't depend on EmbeddedGeome…
nzfeng May 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added docs/docs/media/polygon_heat_solvers.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion docs/docs/pointcloud/algorithms/heat_solver.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ The `SignedHeatOptions` struct allows several options:
| Field | Default value |Meaning|
|---|---|---|
| `#!cpp bool preserveSourceNormals`| `false` | If `true`, preserve the initial curve normals at the source curve during vector diffusion. |
| `#!cpp LevelSetConstraint levelSetConstraint`| `LevelSetConstraint::ZeroSet` | Specifies how/if level sets should be preserved. Can be set to `LevelSetConstraint::ZeroSet`, `LevelSetConstraint::Multiple`, or `LevelSetConstraint::None`, corresponding to preserving the zero set, mulitple level sets (one for each curve component), or no level sets, respectively. |
| `#!cpp LevelSetConstraint levelSetConstraint`| `LevelSetConstraint::ZeroSet` | Specifies how/if level sets should be preserved. Can be set to `LevelSetConstraint::ZeroSet`, `LevelSetConstraint::Multiple`, or `LevelSetConstraint::None`, corresponding to preservation of `curves` as the zero set, as multiple level sets (one for each curve component), or no constraint, respectively. |
| `#!cpp double softLevelSetWeight`| `-1` | If greater than 0, gives the weight with which the given level set constraint is "softly" enforced. |

## Scalar extension
Expand Down
2 changes: 2 additions & 0 deletions docs/docs/surface/algorithms/geodesic_distance.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ This class also supports any (possibly-nonmanifold) triangle mesh as input, and

`#include "geometrycentral/surface/heat_method_distance.h"`

For the polygon mesh version, see the [polygon mesh heat solver](/surface/algorithms/polygon_heat_solver); for point clouds, see the [point cloud heat solver](/pointcloud/algorithms/heat_solver/).

### Single Solves

A one-off utility function is provided which computes the distance from a source vertex using the heat method. Repeated solves or more general source data should use the stateful version below.
Expand Down
115 changes: 115 additions & 0 deletions docs/docs/surface/algorithms/polygon_heat_solver.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# Heat distance and transport on general polygon meshes

Compute signed and unsigned geodesic distance, and transport tangent vectors using fast solvers based on short-time heat flow.

![polygon mesh heat solve results](/media/polygon_heat_solvers.png)

These routines implement polygon mesh versions of the algorithms from:

- [The Heat Method for Distance Computation](http://www.cs.cmu.edu/~kmcrane/Projects/HeatMethod/index.html) (distance)
- [The Vector Heat Method](https://nmwsharp.com/research/vector-heat-method) (parallel transport)
- [A Heat Method for Generalized Signed Distance](https://nzfeng.github.io/research/SignedHeatMethod/index.html) (signed distance)

All computation is encapsulated by the `PolygonMeshHeatSolver` class, which maintains prefactored linear systems for the various methods. Some setup work is performed both on construction, and after the first query. Subsequent queries, even with different source points, will be fast.

`#include "geometrycentral/surface/polygon_mesh_heat_solver.h"`

For the original algorithms on triangle meshes, see the documentation for the [Unsigned Heat Method](/surface/algorithms/geodesic_distance/#heat-method-for-distance), [Vector Heat Method](/surface/algorithms/vector_heat_method), and [Signed Heat Method](/surface/algorithms/signed_heat_method).

**Example:** Basic usage

```cpp
#include "geometrycentral/surface/polygon_mesh_heat_solver.h"

using namespace geometrycentral;
using namespace geometrycentral::surface;

// Read in a polygon mesh
std::unique_ptr<SurfaceMesh> mesh;
std::unique_ptr<VertexPositionGeometry> geom;
std::tie(mesh, geom) = readSurfaceMesh("my_mesh.obj");

// Create the solver
PolygonMeshHeatSolver solver(*geom);

// Pick a source point or two
Vertex vSource = mesh->vertex(7);
Vertex vSource2 = mesh->vertex(8);

// Pick some source curves
std::vector<std::vector<Vertex>> curves;
curves.push_back({mesh->vertex(11), mesh->vertex(12), mesh->vertex(15), mesh->vertex(14), mesh->vertex(13)});
curves.push_back({mesh->vertex(17), mesh->vertex(18), mesh->vertex(19)});

// Compute geodesic distance
VertexData<double> distance = solver.computeDistance(vSource);

// Compute signed distance to a set of curves.
VertexData<double> signedDistance = solver.computeSignedDistance(curves);

// Compute scalar extension
VertexData<double> extended = solver.extendScalars({{vSource, 3.},
{vSource2, -5.}});

// Compute parallel transport
Vector2 sourceVec{1, 2};
VertexData<Vector2> transport = solver.transportTangentVector(vSource, sourceVec);
```

### Constructor

??? func "`#!cpp PolygonMeshHeatSolver::PolygonMeshHeatSolver(EmbeddedGeometryInterface& geom, double tCoef = 1.0)`"

Create a new solver for the heat methods. Precomputation is performed at startup and lazily as needed.

- `geom` is the geometry (and hence mesh) on which to compute. Any embedded geometry object (`VertexPositionGeometry`, etc) can be passed here.

- `tCoef` is the time to use for short time heat flow, as a factor `m * h^2`, where `h` is the maximum between-point spacing. The default value of `1.0` is almost always sufficient.

Algorithm options (like `tCoef`) cannot be changed after construction; create a new solver object with the new settings.


## Geodesic distance

_Geodesic distance_ is the distance from a given source along the surface represented by the point cloud. Specifying multiple source points yields the distance to the nearest source.

??? func "`#!cpp VertexData<double> PolygonMeshHeatSolver::computeDistance(const Vertex& sourceVert)`"

Compute the geodesic distance from `sourceVert` to all other points.

??? func "`#!cpp VertexData<double> PolygonMeshHeatSolver::computeDistance(const std::vector<Vertex>& sourceVerts)`"

Like above, but for multiple source points.

## Signed geodesic distance

??? func "`#!cpp VertexData<double> PolygonMeshHeatSolver::computeSignedDistance(const std::vector<std::vector<Vertex>>& curves, const LevelSetConstraint& levelSetConstraint = LevelSetConstraint::ZeroSet)`"

Compute the signed geodesic distance from a set of curves `curves` to all other points. Each curve in `curves` is a single connected component specified as an ordered sequence of points; curve orientations are derived from this order. The argument `levelSetConstraint` can be set to `LevelSetConstraint::ZeroSet`, `LevelSetConstraint::Multiple`, or `LevelSetConstraint::None`, corresponding to preservation of `curves` as the zero set, as multiple level sets (one for each curve component), or no constraint, respectively.

## Scalar extension

Given scalar values defined at isolated vertices in the domain, extend it to a scalar field on all vertices. Each point will take the value from the nearest source point, in the sense of geodesic distance. Note that the fast diffusion algorithm means the result is a slightly smoothed-out field.

??? func "`#!cpp VertexData<double> PolygonMeshHeatSolver::extendScalars(const std::vector<std::tuple<Vertex, double>>& sources)`"

Given a collection of source vertices and scalars at those vertices, extends the scalar field to the whole mesh as a nearest-geodesic-neighbor interpolant.


## Vector extension

Given tangent vectors defined at one or more isolated source locations on a surface, extend transport the vectors across the entire domain according to parallel transport. Each point on the domain will take the value of the nearest source point. Note that the fast diffusion algorithm means the result is a slightly smoothed-out field.

??? func "`#!cpp VertexData<Vector2> PolygonMeshHeatSolver::transportTangentVector(const Vertex& sourceVert, const Vector2& sourceVector)`"

Shorthand for the general version below when there is just one vector.

Computes parallel transport of the given vector along shortest geodesics to the rest of the domain.

Polar directions are defined in each vertex's tangent space. [See `EmbeddedGeometryInterface::vertexTangentBasis`](/surface/geometry#vertex-tangent-basis).

??? func "`#!cpp VertexData<Vector2> PolygonMeshHeatSolver::transportTangentVectors(const std::vector<std::tuple<Vertex, Vector2>>& sources)`"

Given a collection of source vertices and tangent vectors at those vertices, extends the vector field to the whole domain as a nearest-geodesic-neighbor interpolant via parallel transport along shortest geodesics.

Polar directions are defined in each vertex's tangent space. [See `EmbeddedGeometryInterface::vertexTangentBasis`](/surface/geometry#vertex-tangent-basis).
5 changes: 3 additions & 2 deletions docs/docs/surface/algorithms/signed_heat_method.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ This section describes the _Signed Heat Method_ in geometry-central, which compu

Note that these quantities all depend 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.

These algorithms are described in [A Heat Method for Generalized Signed Distance](https://nzfeng.github.io/research/SignedHeatMethod/SignedDistance.pdf).
This algorithm is described in [A Heat Method for Generalized Signed Distance](https://nzfeng.github.io/research/SignedHeatMethod/SignedDistance.pdf).

`#include "geometrycentral/surface/signed_heat_method.h"`

For the polygon mesh version, see the [polygon mesh heat solver](/surface/algorithms/polygon_heat_solver); for point clouds, see the [point cloud heat solver](/pointcloud/algorithms/heat_solver/).

## Signed Heat Solver

Expand Down Expand Up @@ -78,7 +79,7 @@ Options are passed in to `computeDistance` via a `SignedHeatOptions` struct, whi
| Field | Default value |Meaning|
|---|---|---|
| `#!cpp bool preserveSourceNormals`| `false` | If `true`, preserve the initial curve normals at the source curve during vector diffusion. |
| `#!cpp LevelSetConstraint levelSetConstraint`| `LevelSetConstraint::ZeroSet` | Specifies how/if level sets should be preserved. Can be set to `LevelSetConstraint::ZeroSet`, `LevelSetConstraint::Multiple`, or `LevelSetConstraint::None`, corresponding to preserving the zero set, mulitple level sets (one for each curve component), or no level sets, respectively. |
| `#!cpp LevelSetConstraint levelSetConstraint`| `LevelSetConstraint::ZeroSet` | Specifies how/if level sets should be preserved. Can be set to `LevelSetConstraint::ZeroSet`, `LevelSetConstraint::Multiple`, or `LevelSetConstraint::None`, corresponding to preservation of the input curves as the zero set, as multiple level sets (one for each curve component), or no constraint, respectively. |
| `#!cpp double softLevelSetWeight`| `-1` | If greater than 0, gives the weight with which the given level set constraint is "softly" enforced. |

## Citation
Expand Down
1 change: 1 addition & 0 deletions docs/docs/surface/algorithms/vector_heat_method.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ These algorithms are described in [The Vector Heat Method](http://www.cs.cmu.edu

`#include "geometrycentral/surface/vector_heat_method.h"`

For the polygon mesh version, see the [polygon mesh heat solver](/surface/algorithms/polygon_heat_solver); for point clouds, see the [point cloud heat solver](/pointcloud/algorithms/heat_solver/).

## Vector Heat Solver

Expand Down
Loading