Skip to content

Commit 8579865

Browse files
authored
Preprocess curves for the signed heat method (#229)
* First commit for preprocessing curves * Preprocess curves by partitioning them into well-sampled components
1 parent 56152a8 commit 8579865

File tree

3 files changed

+34
-2
lines changed

3 files changed

+34
-2
lines changed

docs/docs/surface/algorithms/signed_heat_method.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ The diffusion time can also be changed using the following function.
6464
6565
Re-computes the time used for short time heat flow `tCoef * h^2`, where `h` is the mean distance between nodes of the mesh.
6666
67+
Note: On triangle meshes, each mesh edge crossed by an input curve should be explicitly represented by a SurfacePoint (otherwise the curve's geometry is not fully specified). If this is not the case, the code internally partitions input curves so that this condition is satisfied; the robustness of the heat method should fill in small gaps. Depending on how sparsely your curve is sampled, this may produce curve components with fewer than two nodes, which will be ignored; if many of your curves have fewer than two nodes, consider [FlipOut geodesics](../flip_geodesics) for shortest-path completion of curves.
68+
6769
## Helper Types
6870
6971
### Curves

include/geometrycentral/surface/signed_heat_method.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ class SignedHeatSolver {
6161
SparseMatrix<double> massMat, doubleMassMat, doubleConnectionLaplacian, doubleVectorOp;
6262

6363
// Helpers
64+
std::vector<Curve> preprocessCurves(const std::vector<Curve>& curves) const;
6465
Vector<std::complex<double>> integrateVectorHeatFlow(const std::vector<Curve>& curves,
6566
const std::vector<SurfacePoint>& points,
6667
const SignedHeatOptions& options);

src/surface/signed_heat_method.cpp

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@ VertexData<double> SignedHeatSolver::computeDistance(const std::vector<Curve>& c
3232
const std::vector<SurfacePoint>& points,
3333
const SignedHeatOptions& options) {
3434

35-
Vector<std::complex<double>> Xt = integrateVectorHeatFlow(curves, points, options);
36-
return integrateVectorField(Xt, curves, points, options);
35+
std::vector<Curve> processedCurves = preprocessCurves(curves);
36+
Vector<std::complex<double>> Xt = integrateVectorHeatFlow(processedCurves, points, options);
37+
return integrateVectorField(Xt, processedCurves, points, options);
3738
}
3839

3940
VertexData<double> SignedHeatSolver::computeDistance(const std::vector<Curve>& curves,
@@ -56,6 +57,34 @@ void SignedHeatSolver::setDiffusionTimeCoefficient(double tCoef_) {
5657
doubleVectorOp = doubleMassMat + shortTime * doubleConnectionLaplacian;
5758
}
5859

60+
std::vector<Curve> SignedHeatSolver::preprocessCurves(const std::vector<Curve>& curves) const {
61+
// If there are gaps in the curves (i.e. curves are not sampled densely along the mesh), then there is an ambiguity of
62+
// how to connect up the points into curves.
63+
// Rather than, for example, automatically connecting up curves using a geodesic path -- which would impose curves
64+
// that the user might not have meant -- we simply break up the input curves into components that do reflect how
65+
// they're sampled. (This may, however, create curves with fewer than 2 nodes, which would get ignored.)
66+
std::vector<Curve> newCurves;
67+
for (const Curve& curve : curves) {
68+
newCurves.emplace_back();
69+
newCurves.back().isSigned = curve.isSigned;
70+
size_t nNodes = curve.nodes.size();
71+
for (size_t i = 0; i < nNodes - 1; i++) {
72+
const SurfacePoint& pA = curve.nodes[i];
73+
const SurfacePoint& pB = curve.nodes[i + 1];
74+
newCurves.back().nodes.push_back(pA);
75+
Face commonFace = sharedFace(pA, pB);
76+
if (commonFace == Face()) {
77+
// Create new curve
78+
newCurves.emplace_back();
79+
newCurves.back().isSigned = curve.isSigned;
80+
}
81+
}
82+
// Don't forget the last point
83+
newCurves.back().nodes.push_back(curve.nodes[nNodes - 1]);
84+
}
85+
return newCurves;
86+
}
87+
5988
Vector<std::complex<double>> SignedHeatSolver::integrateVectorHeatFlow(const std::vector<Curve>& curves,
6089
const std::vector<SurfacePoint>& points,
6190
const SignedHeatOptions& options) {

0 commit comments

Comments
 (0)