1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
#pragma once
#include "config/types.h"
#include "triangle.h"
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
#include <source_location>
#include <thirdparty/openmesh/glmcompat.h>
#include <thirdparty/openmesh/helpers.h>
struct GeoDataTraits : public OpenMesh::DefaultTraits {
FaceAttributes(OpenMesh::Attributes::Status);
EdgeAttributes(OpenMesh::Attributes::Status);
VertexAttributes(OpenMesh::Attributes::Normal | OpenMesh::Attributes::Status);
HalfedgeAttributes(OpenMesh::Attributes::Status);
using Point = GlobalPosition3D;
using Normal = Normal3D;
};
class GeoDataMesh : public OpenMesh::TriMesh_ArrayKernelT<GeoDataTraits> {
public:
struct PointFace {
// NOLINTNEXTLINE(hicpp-explicit-conversions)
PointFace(GlobalPosition2D coord) : point {coord} { }
PointFace(GlobalPosition2D coord, FaceHandle face) : point {coord}, faceCache {face} { }
PointFace(GlobalPosition2D coord, const GeoDataMesh *);
PointFace(GlobalPosition2D coord, GeoDataMesh const *, FaceHandle start);
const GlobalPosition2D point;
[[nodiscard]] FaceHandle face(const GeoDataMesh *) const;
[[nodiscard]] FaceHandle face(const GeoDataMesh *, FaceHandle start) const;
[[nodiscard]] bool
isLocated() const
{
return faceCache.is_valid();
}
private:
mutable FaceHandle faceCache;
};
template<glm::length_t Dim> using Triangle = ::Triangle<Dim, GlobalDistance>;
[[nodiscard]] FaceHandle findPoint(GlobalPosition2D) const;
[[nodiscard]] FaceHandle findPoint(GlobalPosition2D, FaceHandle) const;
[[nodiscard]] GlobalPosition3D positionAt(const PointFace &) const;
protected:
#ifndef NDEBUG
void sanityCheck(const std::source_location & = std::source_location::current()) const;
#endif
[[nodiscard]] bool faceContainsPoint(GlobalPosition2D, FaceHandle) const;
[[nodiscard]] HalfedgeHandle findBoundaryStart() const;
[[nodiscard]] RelativePosition3D difference(HalfedgeHandle) const;
using HalfEdgeVertices = std::pair<VertexHandle, VertexHandle>;
[[nodiscard]] HalfEdgeVertices toVertexHandles(HalfedgeHandle) const;
using HalfEdgePoints = std::pair<GlobalPosition3D, GlobalPosition3D>;
[[nodiscard]] HalfEdgePoints points(HalfEdgeVertices) const;
template<glm::length_t D>
[[nodiscard]] auto
vertexDistanceFunction(GlobalPosition<D> point) const
{
struct DistanceCalculator {
[[nodiscard]] std::pair<VertexHandle, float>
operator()(VertexHandle compVertex) const
{
return std::make_pair(
compVertex, ::distance<D, GlobalDistance, glm::defaultp>(point, mesh->point(compVertex)));
}
[[nodiscard]]
std::pair<HalfedgeHandle, float>
operator()(const HalfedgeHandle compHalfedge) const
{
const auto edgePoints = mesh->points(mesh->toVertexHandles(compHalfedge));
return std::make_pair(compHalfedge, Triangle<2> {edgePoints.second, edgePoints.first, point}.height());
};
const GeoDataMesh * mesh;
GlobalPosition<D> point;
};
return DistanceCalculator {this, point};
}
[[nodiscard]] bool canFlip(HalfedgeHandle edge) const;
[[nodiscard]] std::optional<EdgeHandle> shouldFlip(HalfedgeHandle next, GlobalPosition2D startPoint) const;
template<glm::length_t D>
[[nodiscard]] RelativeDistance
length(HalfedgeHandle heh) const
{
return ::distance<D, GlobalDistance, glm::defaultp>(
point(to_vertex_handle(heh)), point(from_vertex_handle(heh)));
}
[[nodiscard]] GlobalPosition3D centre(HalfedgeHandle) const;
template<glm::length_t Dim>
[[nodiscard]] Triangle<Dim>
triangle(FaceHandle face) const
{
Triangle<Dim> triangle;
std::ranges::transform(fv_range(face), triangle.begin(), [this](auto vertex) {
return point(vertex);
});
return triangle;
}
};
|