23#ifndef VCL_ALGORITHMS_MESH_DISTANCE_H
24#define VCL_ALGORITHMS_MESH_DISTANCE_H
26#include <vclib/algorithms/mesh/point_sampling.h>
27#include <vclib/math/histogram.h>
28#include <vclib/mesh/requirements.h>
29#include <vclib/misc/logger.h>
30#include <vclib/misc/parallel.h>
31#include <vclib/space/complex/grid.h>
32#include <vclib/views/pointers.h>
38 double minDist = std::numeric_limits<double>::max();
39 double maxDist = std::numeric_limits<double>::lowest();
45enum HausdorffSamplingMethod {
46 HAUSDORFF_VERTEX_UNIFORM = 0,
47 HAUSDORFF_EDGE_UNIFORM,
55 SamplerConcept SamplerType,
57 LoggerConcept LogType>
58HausdorffDistResult hausdorffDist(
64 using PointSampleType = SamplerType::PointType;
65 using ScalarType = PointSampleType::ScalarType;
67 HausdorffDistResult res;
68 res.histogram = Histogramd(0, m.boundingBox().diagonal() / 100, 100);
72 "Computing distances for " + std::to_string(s.size()) +
" samples...");
74 log.startProgress(
"", s.size());
80 parallelFor(s, [&](
const PointSampleType& sample) {
82 ScalarType dist = std::numeric_limits<ScalarType>::max();
83 const auto iter = g.closestValue(sample, dist);
85 if (iter != g.end()) {
88 if (dist > res.maxDist)
90 if (dist < res.minDist)
93 res.RMSDist += dist * dist;
94 res.histogram.addValue(dist);
103 log.log(100,
"Computed " + std::to_string(ns) +
" distances.");
104 if (ns != s.size()) {
107 std::to_string(s.size() - ns) +
108 " samples were not counted because no closest vertex/face "
110 LogType::WARNING_LOG);
114 res.RMSDist = std::sqrt(res.RMSDist / ns);
120 MeshConcept MeshType,
121 SamplerConcept SamplerType,
122 LoggerConcept LogType>
123HausdorffDistResult samplerMeshHausdorff(
125 const SamplerType& s,
126 LogType& log)
requires (!HasFaces<MeshType>)
128 using VertexType = MeshType::VertexType;
130 std::string meshName =
"first mesh";
131 if constexpr (HasName<MeshType>) {
135 log.log(0,
"Building Grid on " + meshName +
" vertices...");
137 StaticGrid3<const VertexType*> grid(m.vertices() |
views::addrOf);
140 log.log(5,
"Grid built.");
142 return hausdorffDist(m, s, grid, log);
146 FaceMeshConcept MeshType,
147 SamplerConcept SamplerType,
148 LoggerConcept LogType>
149HausdorffDistResult samplerMeshHausdorff(
151 const SamplerType& s,
154 using VertexType = MeshType::VertexType;
155 using FaceType = MeshType::FaceType;
156 using ScalarType = VertexType::CoordType::ScalarType;
158 std::string meshName =
"first mesh";
159 if constexpr (HasName<MeshType>) {
162 if (m.faceNumber() == 0) {
163 log.log(0,
"Building Grid on " + meshName +
" vertices...");
165 StaticGrid3<const VertexType*, ScalarType> grid(
169 log.log(5,
"Grid built.");
171 return hausdorffDist(m, s, grid, log);
174 log.log(0,
"Building Grid on " + meshName +
" faces...");
176 StaticGrid3<const FaceType*, ScalarType> grid(
180 log.log(5,
"Grid built.");
182 return hausdorffDist(m, s, grid, log);
188 MeshConcept MeshType1,
189 MeshConcept MeshType2,
190 SamplerConcept SamplerType,
191 LoggerConcept LogType>
192HausdorffDistResult hausdorffDistance(
197 SamplerType& sampler,
198 std::vector<uint>& birth,
201 std::string meshName1 =
"first mesh";
202 std::string meshName2 =
"second mesh";
203 if constexpr (HasName<MeshType1>) {
204 meshName1 = m1.name();
206 if constexpr (HasName<MeshType2>) {
207 meshName2 = m2.name();
212 "Sampling " + meshName2 +
" with " + std::to_string(nSamples) +
215 if constexpr (METHOD == HAUSDORFF_VERTEX_UNIFORM) {
216 sampler = vertexUniformPointSampling<SamplerType>(
217 m2, nSamples, birth,
false, deterministic);
219 else if constexpr (METHOD == HAUSDORFF_EDGE_UNIFORM) {
223 sampler = montecarloPointSampling<SamplerType>(
224 m2, nSamples, birth, deterministic);
227 log.log(5, meshName2 +
" sampled.");
229 5, 100,
"Computing distance between samples and " + meshName1 +
"...");
231 auto res = samplerMeshHausdorff(m1, sampler, log);
233 log.endTask(
"Distance between samples and " + meshName1 +
" computed.");
241 MeshConcept MeshType1,
242 MeshConcept MeshType2,
243 LoggerConcept LogType = NullLogger>
244HausdorffDistResult hausdorffDistance(
248 HausdorffSamplingMethod sampMethod = HAUSDORFF_VERTEX_UNIFORM,
250 bool deterministic =
false)
253 nSamples = m2.vertexNumber();
255 std::vector<uint> birth;
257 switch (sampMethod) {
258 case HAUSDORFF_VERTEX_UNIFORM: {
259 ConstVertexSampler<typename MeshType2::VertexType> sampler;
261 return detail::hausdorffDistance<HAUSDORFF_VERTEX_UNIFORM>(
262 m1, m2, nSamples, deterministic, sampler, birth, log);
265 case HAUSDORFF_EDGE_UNIFORM: {
267 return HausdorffDistResult();
269 case HAUSDORFF_MONTECARLO: {
270 PointSampler<typename MeshType2::VertexType::CoordType> sampler;
272 return detail::hausdorffDistance<HAUSDORFF_MONTECARLO>(
273 m1, m2, nSamples, deterministic, sampler, birth, log);
275 default: assert(0);
return HausdorffDistResult();
A class representing a line segment in n-dimensional space. The class is parameterized by a PointConc...
Definition segment.h:43
NullLogger nullLogger
The nullLogger object is an object of type NullLogger that is used as default argument in the functio...
Definition null_logger.h:125
constexpr detail::AddressOfView addrOf
The addrOf view applies the address-of operator & on the input view.
Definition pointers.h:120