From cb0c6d630475d0f60d44a53caf394711b523115e Mon Sep 17 00:00:00 2001 From: Alan Morris Date: Fri, 27 Feb 2026 09:57:49 -0700 Subject: [PATCH 1/2] Use geodesic walk for MeshDomain particle splitting instead of Euclidean offset The split particle was previously placed at a raw Euclidean offset (potentially off-surface or on the other side), now it walks along the mesh surface via geodesic_walk. --- Libs/Optimize/Domain/MeshDomain.cpp | 12 ++++++++++++ Libs/Optimize/Domain/MeshDomain.h | 2 ++ 2 files changed, 14 insertions(+) diff --git a/Libs/Optimize/Domain/MeshDomain.cpp b/Libs/Optimize/Domain/MeshDomain.cpp index 20ada028a9..d93f6b2a8d 100644 --- a/Libs/Optimize/Domain/MeshDomain.cpp +++ b/Libs/Optimize/Domain/MeshDomain.cpp @@ -35,6 +35,18 @@ MeshDomain::PointType MeshDomain::UpdateParticlePosition(const PointType &point, return newPoint; } +//------------------------------------------------------------------- +MeshDomain::PointType MeshDomain::GetPositionAfterSplit(const PointType &pt, + const VectorDoubleType &local_direction, + const VectorDoubleType &global_direction, + double epsilon) const { + VectorDoubleType update; + for (unsigned int k = 0; k < DIMENSION; k++) { + update[k] = epsilon * local_direction[k] / 5.0; + } + return UpdateParticlePosition(pt, -1, update); +} + //------------------------------------------------------------------- double MeshDomain::GetMaxDiameter() const { // todo should this not be the length of the bounding box diagonal? diff --git a/Libs/Optimize/Domain/MeshDomain.h b/Libs/Optimize/Domain/MeshDomain.h index 0da464aa12..aaf7d0b768 100644 --- a/Libs/Optimize/Domain/MeshDomain.h +++ b/Libs/Optimize/Domain/MeshDomain.h @@ -17,6 +17,8 @@ class MeshDomain : public ParticleDomain { bool ApplyVectorConstraints(VectorDoubleType &gradE, const PointType &pos) const; VectorDoubleType ProjectVectorToSurfaceTangent(VectorDoubleType &gradE, const PointType &pos, int idx) const override; PointType UpdateParticlePosition(const PointType &point, int idx, VectorDoubleType &update) const override; + PointType GetPositionAfterSplit(const PointType &pt, const VectorDoubleType &local_direction, + const VectorDoubleType &global_direction, double epsilon) const override; virtual void InvalidateParticlePosition(int idx) const override; From 858f891c080b4d996a3cfee54db78458b5b990c6 Mon Sep 17 00:00:00 2001 From: Alan Morris Date: Fri, 27 Feb 2026 11:46:50 -0700 Subject: [PATCH 2/2] Fix sign error in MeshDomain::GetPositionAfterSplit UpdateParticlePosition negates the update vector before calling geodesic_walk, so we need to negate it here to match the base class behavior (moving in the positive local_direction). --- Libs/Optimize/Domain/MeshDomain.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Libs/Optimize/Domain/MeshDomain.cpp b/Libs/Optimize/Domain/MeshDomain.cpp index d93f6b2a8d..a695bc90ce 100644 --- a/Libs/Optimize/Domain/MeshDomain.cpp +++ b/Libs/Optimize/Domain/MeshDomain.cpp @@ -42,7 +42,8 @@ MeshDomain::PointType MeshDomain::GetPositionAfterSplit(const PointType &pt, double epsilon) const { VectorDoubleType update; for (unsigned int k = 0; k < DIMENSION; k++) { - update[k] = epsilon * local_direction[k] / 5.0; + // Negate here because UpdateParticlePosition negates before calling geodesic_walk + update[k] = -epsilon * local_direction[k] / 5.0; } return UpdateParticlePosition(pt, -1, update); }