23#ifndef VCL_ALGORITHMS_MESH_DISTANCE_H
24#define VCL_ALGORITHMS_MESH_DISTANCE_H
26#include <vclib/algorithms/mesh/point_sampling.h>
28#include <vclib/mesh.h>
29#include <vclib/space/complex.h>
35 double minDist = std::numeric_limits<double>::max();
36 double maxDist = std::numeric_limits<double>::lowest();
42enum HausdorffSamplingMethod {
43 HAUSDORFF_VERTEX_UNIFORM = 0,
44 HAUSDORFF_EDGE_UNIFORM,
52 SamplerConcept SamplerType,
54 LoggerConcept LogType>
55HausdorffDistResult hausdorffDist(
61 using PointSampleType = SamplerType::PointType;
62 using ScalarType = PointSampleType::ScalarType;
64 HausdorffDistResult res;
65 res.histogram = Histogramd(0, m.boundingBox().diagonal() / 100, 100);
69 "Computing distances for " + std::to_string(s.size()) +
" samples...");
71 log.startProgress(
"", s.size());
77 parallelFor(s, [&](
const PointSampleType& sample) {
79 ScalarType dist = std::numeric_limits<ScalarType>::max();
80 const auto iter = g.closestValue(sample, dist);
82 if (iter != g.end()) {
85 if (dist > res.maxDist)
87 if (dist < res.minDist)
90 res.RMSDist += dist * dist;
91 res.histogram.addValue(dist);
100 log.log(100,
"Computed " + std::to_string(ns) +
" distances.");
101 if (ns != s.size()) {
104 std::to_string(s.size() - ns) +
105 " samples were not counted because no closest vertex/face "
107 LogType::WARNING_LOG);
111 res.RMSDist = std::sqrt(res.RMSDist / ns);
117 MeshConcept MeshType,
118 SamplerConcept SamplerType,
119 LoggerConcept LogType>
120HausdorffDistResult samplerMeshHausdorff(
122 const SamplerType& s,
123 LogType& log)
requires (!HasFaces<MeshType>)
125 using VertexType = MeshType::VertexType;
127 std::string meshName =
"first mesh";
128 if constexpr (HasName<MeshType>) {
132 log.log(0,
"Building Grid on " + meshName +
" vertices...");
134 StaticGrid3<const VertexType*> grid(m.vertices() |
views::addrOf);
137 log.log(5,
"Grid built.");
139 return hausdorffDist(m, s, grid, log);
143 FaceMeshConcept MeshType,
144 SamplerConcept SamplerType,
145 LoggerConcept LogType>
146HausdorffDistResult samplerMeshHausdorff(
148 const SamplerType& s,
151 using VertexType = MeshType::VertexType;
152 using FaceType = MeshType::FaceType;
153 using ScalarType = VertexType::PositionType::ScalarType;
155 std::string meshName =
"first mesh";
156 if constexpr (HasName<MeshType>) {
159 if (m.faceNumber() == 0) {
160 log.log(0,
"Building Grid on " + meshName +
" vertices...");
162 StaticGrid3<const VertexType*, ScalarType> grid(
166 log.log(5,
"Grid built.");
168 return hausdorffDist(m, s, grid, log);
171 log.log(0,
"Building Grid on " + meshName +
" faces...");
173 StaticGrid3<const FaceType*, ScalarType> grid(
177 log.log(5,
"Grid built.");
179 return hausdorffDist(m, s, grid, log);
185 MeshConcept MeshType1,
186 MeshConcept MeshType2,
187 SamplerConcept SamplerType,
188 LoggerConcept LogType>
189HausdorffDistResult hausdorffDistance(
193 std::optional<uint> seed,
194 SamplerType& sampler,
195 std::vector<uint>& birth,
198 std::string meshName1 =
"first mesh";
199 std::string meshName2 =
"second mesh";
200 if constexpr (HasName<MeshType1>) {
201 meshName1 = m1.name();
203 if constexpr (HasName<MeshType2>) {
204 meshName2 = m2.name();
209 "Sampling " + meshName2 +
" with " + std::to_string(nSamples) +
212 if constexpr (METHOD == HAUSDORFF_VERTEX_UNIFORM) {
213 sampler = vertexUniformPointSampling<SamplerType>(
214 m2, nSamples, birth,
false, seed);
216 else if constexpr (METHOD == HAUSDORFF_EDGE_UNIFORM) {
220 sampler = montecarloPointSampling<SamplerType>(
221 m2, nSamples, birth, seed);
224 log.log(5, meshName2 +
" sampled.");
226 5, 100,
"Computing distance between samples and " + meshName1 +
"...");
228 auto res = samplerMeshHausdorff(m1, sampler, log);
230 log.endTask(
"Distance between samples and " + meshName1 +
" computed.");
238 MeshConcept MeshType1,
239 MeshConcept MeshType2,
240 LoggerConcept LogType = NullLogger>
241HausdorffDistResult hausdorffDistance(
245 HausdorffSamplingMethod sampMethod = HAUSDORFF_VERTEX_UNIFORM,
247 std::optional<uint> seed = std::nullopt)
250 nSamples = m2.vertexNumber();
252 std::vector<uint> birth;
254 switch (sampMethod) {
255 case HAUSDORFF_VERTEX_UNIFORM: {
256 ConstVertexSampler<typename MeshType2::VertexType> sampler;
258 return detail::hausdorffDistance<HAUSDORFF_VERTEX_UNIFORM>(
259 m1, m2, nSamples, seed, sampler, birth, log);
262 case HAUSDORFF_EDGE_UNIFORM: {
264 return HausdorffDistResult();
266 case HAUSDORFF_MONTECARLO: {
267 PointSampler<typename MeshType2::VertexType::PositionType> sampler;
269 return detail::hausdorffDistance<HAUSDORFF_MONTECARLO>(
270 m1, m2, nSamples, seed, sampler, birth, log);
272 default: assert(0);
return HausdorffDistResult();
A class representing a box in N-dimensional space.
Definition box.h:46
NullLogger nullLogger
The nullLogger object is an object of type NullLogger that is used as default argument in the functio...
Definition null_logger.h:123
constexpr detail::AddressOfView addrOf
The addrOf view applies the address-of operator & on the input view.
Definition pointers.h:120