ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
PoissonReconLib.cpp
Go to the documentation of this file.
1 // ##########################################################################
2 // # #
3 // # ACloudViewer WRAPPER: PoissonReconLib #
4 // # #
5 // # This program is free software; you can redistribute it and/or modify #
6 // # it under the terms of the GNU General Public License as published by #
7 // # the Free Software Foundation; version 2 or later of the License. #
8 // # #
9 // # This program is distributed in the hope that it will be useful, #
10 // # but WITHOUT ANY WARRANTY; without even the implied warranty of #
11 // # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
12 // # GNU General Public License for more details. #
13 // # #
14 // # COPYRIGHT: Daniel Girardeau-Montaut #
15 // # #
16 // ##########################################################################
17 
18 #include "PoissonReconLib.h"
19 
20 // PoissonRecon
21 #include <cassert>
22 
23 #include "../Src/FEMTree.h"
24 #include "PointData.h"
25 
26 namespace {
27 // The order of the B-Spline used to splat in data for color interpolation
28 constexpr int DATA_DEGREE = 0;
29 // The order of the B-Spline used to splat in the weights for density estimation
30 constexpr int WEIGHT_DEGREE = 2;
31 // The order of the B-Spline used to splat in the normals for constructing the
32 // Laplacian constraints
33 constexpr int NORMAL_DEGREE = 2;
34 // The default finite-element degree
35 constexpr int DEFAULT_FEM_DEGREE = 1;
36 // The dimension of the system
37 constexpr int DIMENSION = 3;
38 
39 inline float ComputeNorm(const float vec[3]) {
40  return sqrt(vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2]);
41 }
42 
43 inline double ComputeNorm(const double vec[3]) {
44  return sqrt(vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2]);
45 }
46 } // namespace
47 
49 #ifdef WITH_OPENMP
51 #endif
52 }
53 
54 template <typename _Real>
55 class Vertex : public PointData<_Real> {
56 public:
57  typedef _Real Real;
58 
59  Vertex(const Point<Real, 3>& point)
60  : PointData<Real>(), point(point), w(0) {}
61 
62  Vertex(const Point<Real, 3>& point,
63  const PointData<Real>& data,
64  double _w = 0.0)
65  : PointData<Real>(data.normal, data.color), point(point), w(_w) {}
66 
67  Vertex() : Vertex(Point<Real, 3>(0, 0, 0)) {}
68 
71  point *= s;
72  w *= s;
73 
74  return *this;
75  }
76 
79  point /= s;
80  w /= s;
81  return *this;
82  }
83 
84  Vertex& operator+=(const Vertex& p) {
86  point += p.point;
87  w += p.w;
88 
89  return *this;
90  }
91 
92 public:
93  Point<Real, 3> point;
94  double w;
95 };
96 
97 template <typename Real>
99  : public InputPointStreamWithData<Real, DIMENSION, PointData<Real>> {
100 public:
102  : cloud(_cloud), xform(nullptr), currentIndex(0) {}
103 
104  void reset(void) override { currentIndex = 0; }
105 
106  bool nextPoint(Point<Real, 3>& p, PointData<Real>& d) override {
107  if (currentIndex >= cloud.size()) {
108  return false;
109  }
110  cloud.getPoint(currentIndex, p.coords);
111 
112  if (xform != nullptr) {
113  p = (*xform) * p;
114  }
115 
116  if (cloud.hasNormals()) {
117  cloud.getNormal(currentIndex, d.normal);
118  } else {
119  d.normal[0] = d.normal[1] = d.normal[2];
120  }
121 
122  if (cloud.hasColors()) {
123  cloud.getColor(currentIndex, d.color);
124  } else {
125  d.color[0] = d.color[1] = d.color[2];
126  }
127 
128  currentIndex++;
129  return true;
130  }
131 
132 public:
134  XForm<Real, 4>* xform;
135  size_t currentIndex;
136 };
137 
138 template <unsigned int Dim, class Real>
140  FEMTree<Dim, Real>& tree;
141  double t;
142 
143  FEMTreeProfiler(FEMTree<Dim, Real>& t) : tree(t) {}
144  void start(void) {
145  t = Time(), FEMTree<Dim, Real>::ResetLocalMemoryUsage();
146  }
147  void dumpOutput(const char* header) const {
148  FEMTree<Dim, Real>::MemoryUsage();
149  // if (header) {
150  // utility::LogDebug("{} {} (s), {} (MB) / {} (MB) / {} (MB)",
151  // header, Time() - t, FEMTree<Dim,
152  // Real>::LocalMemoryUsage(), FEMTree<Dim,
153  // Real>::MaxMemoryUsage(),
154  // MemoryInfo::PeakMemoryUsageMB());
155  // }
156  // else {
157  // utility::LogDebug("{} (s), {} (MB) / {} (MB) / {} (MB)", Time()
158  //- t, FEMTree<Dim, Real>::LocalMemoryUsage(),
159  // FEMTree<Dim, Real>::MaxMemoryUsage(),
160  // MemoryInfo::PeakMemoryUsageMB());
161  // }
162  }
163 };
164 
165 template <class Real, unsigned int Dim>
166 XForm<Real, Dim + 1> GetBoundingBoxXForm(Point<Real, Dim> min,
167  Point<Real, Dim> max,
168  Real scaleFactor) {
169  Point<Real, Dim> center = (max + min) / 2;
170  Real scale = max[0] - min[0];
171  for (unsigned int d = 1; d < Dim; d++) {
172  scale = std::max<Real>(scale, max[d] - min[d]);
173  }
174  scale *= scaleFactor;
175  for (unsigned int i = 0; i < Dim; i++) {
176  center[i] -= scale / 2;
177  }
178  XForm<Real, Dim + 1> tXForm = XForm<Real, Dim + 1>::Identity(),
179  sXForm = XForm<Real, Dim + 1>::Identity();
180  for (unsigned int i = 0; i < Dim; i++) {
181  sXForm(i, i) = static_cast<Real>(1. / scale),
182  tXForm(Dim, i) = -center[i];
183  }
184  return sXForm * tXForm;
185 }
186 
187 template <class Real, unsigned int Dim>
188 XForm<Real, Dim + 1> GetBoundingBoxXForm(Point<Real, Dim> min,
189  Point<Real, Dim> max,
190  Real width,
191  Real scaleFactor,
192  int& depth) {
193  // Get the target resolution (along the largest dimension)
194  Real resolution = (max[0] - min[0]) / width;
195  for (unsigned int d = 1; d < Dim; d++) {
196  resolution = std::max<Real>(resolution, (max[d] - min[d]) / width);
197  }
198  resolution *= scaleFactor;
199  depth = 0;
200  while ((1 << depth) < resolution) {
201  depth++;
202  }
203 
204  Point<Real, Dim> center = (max + min) / 2;
205  Real scale = (1 << depth) * width;
206 
207  for (unsigned int i = 0; i < Dim; i++) {
208  center[i] -= scale / 2;
209  }
210  XForm<Real, Dim + 1> tXForm = XForm<Real, Dim + 1>::Identity();
211  XForm<Real, Dim + 1> sXForm = XForm<Real, Dim + 1>::Identity();
212  for (unsigned int i = 0; i < Dim; i++) {
213  sXForm(i, i) = static_cast<Real>(1.0 / scale);
214  tXForm(Dim, i) = -center[i];
215  }
216  return sXForm * tXForm;
217 }
218 
219 template <class Real, unsigned int Dim>
220 XForm<Real, Dim + 1> GetPointXForm(InputPointStream<Real, Dim>& stream,
221  Real width,
222  Real scaleFactor,
223  int& depth) {
224  Point<Real, Dim> min, max;
225  stream.boundingBox(min, max);
226  return GetBoundingBoxXForm(min, max, width, scaleFactor, depth);
227 }
228 
229 template <class Real, unsigned int Dim>
230 XForm<Real, Dim + 1> GetPointXForm(InputPointStream<Real, Dim>& stream,
231  Real scaleFactor) {
232  Point<Real, Dim> min, max;
233  stream.boundingBox(min, max);
234  return GetBoundingBoxXForm(min, max, scaleFactor);
235 }
236 
237 template <unsigned int Dim, typename Real>
239  Real target, weight;
240  ConstraintDual(Real t, Real w) : target(t), weight(w) {}
241  CumulativeDerivativeValues<Real, Dim, 0> operator()(
242  const Point<Real, Dim>& p) const {
243  return CumulativeDerivativeValues<Real, Dim, 0>(target * weight);
244  };
245 };
246 
247 template <unsigned int Dim, typename Real>
248 struct SystemDual {
249  SystemDual(Real w) : weight(w) {}
250  CumulativeDerivativeValues<Real, Dim, 0> operator()(
251  const Point<Real, Dim>& p,
252  const CumulativeDerivativeValues<Real, Dim, 0>& dValues) const {
253  return dValues * weight;
254  };
255 
256  CumulativeDerivativeValues<double, Dim, 0> operator()(
257  const Point<Real, Dim>& p,
258  const CumulativeDerivativeValues<double, Dim, 0>& dValues) const {
259  return dValues * weight;
260  };
261 
262  Real weight;
263 };
264 
265 template <unsigned int Dim>
266 struct SystemDual<Dim, double> {
267  typedef double Real;
268 
269  SystemDual(Real w) : weight(w) {}
270  CumulativeDerivativeValues<Real, Dim, 0> operator()(
271  const Point<Real, Dim>& p,
272  const CumulativeDerivativeValues<Real, Dim, 0>& dValues) const {
273  return dValues * weight;
274  };
275 
277 };
278 
279 template <typename Vertex,
280  typename Real,
281  typename SetVertexFunction,
282  unsigned int... FEMSigs,
283  typename... SampleData>
286  UIntPack<FEMSigs...>,
287  std::tuple<SampleData...>,
288  FEMTree<sizeof...(FEMSigs), Real>& tree,
289  const DenseNodeData<Real, UIntPack<FEMSigs...>>& solution,
290  Real isoValue,
291  const std::vector<typename FEMTree<sizeof...(FEMSigs),
292  Real>::PointSample>* samples,
293  std::vector<PointData<Real>>* sampleData,
294  const typename FEMTree<sizeof...(FEMSigs),
295  Real>::template DensityEstimator<WEIGHT_DEGREE>*
296  density,
297  const SetVertexFunction& SetVertex,
298  XForm<Real, sizeof...(FEMSigs) + 1> iXForm,
299  PoissonReconLib::IMesh<Real>& out_mesh) {
300  static const int Dim = sizeof...(FEMSigs);
301  typedef UIntPack<FEMSigs...> Sigs;
302  static const unsigned int DataSig =
303  FEMDegreeAndBType<DATA_DEGREE, BOUNDARY_FREE>::Signature;
304 
305  const bool non_manifold = true;
306  const bool polygon_mesh = false;
307 
309 
310  if (samples && sampleData) {
311  typedef typename FEMTree<Dim,
312  Real>::template DensityEstimator<WEIGHT_DEGREE>
313  DensityEstimator;
314 
316  IsotropicUIntPack<Dim, DataSig>>
317  _sampleData =
318  tree.template setMultiDepthDataField<DataSig, false>(
319  *samples, *sampleData,
320  (DensityEstimator*)nullptr);
321 
322  for (const RegularTreeNode<Dim, FEMTreeNodeData, depth_and_offset_type>*
323  n = tree.tree().nextNode();
324  n; n = tree.tree().nextNode(n)) {
325  ProjectiveData<PointData<Real>, Real>* color = _sampleData(n);
326  if (color)
327  (*color) *= static_cast<Real>(
328  pow(params.colorPullFactor, tree.depth(n)));
329  }
330 
331  IsoSurfaceExtractor<Dim, Real, Vertex>::template Extract<
333  Sigs(), UIntPack<WEIGHT_DEGREE>(), UIntPack<DataSig>(), tree,
334  density, &_sampleData, solution, isoValue, mesh, SetVertex,
335  !params.linearFit, !non_manifold, polygon_mesh, false);
336  } else {
337  IsoSurfaceExtractor<Dim, Real, Vertex>::template Extract<
339  Sigs(), UIntPack<WEIGHT_DEGREE>(), UIntPack<DataSig>(), tree,
340  density, nullptr, solution, isoValue, mesh, SetVertex,
341  !params.linearFit, !non_manifold, polygon_mesh, false);
342  }
343 
344  mesh.resetIterator();
345 
346  for (size_t vidx = 0; vidx < mesh.outOfCorePointCount(); ++vidx) {
347  Vertex v;
348  mesh.nextOutOfCorePoint(v);
349  v.point = iXForm * v.point;
350 
351  out_mesh.addVertex(v.point.coords);
352  if (sampleData) {
353  // out_mesh.addNormal(v.normal);
354  out_mesh.addColor(v.color);
355  }
356  if (params.density) {
357  out_mesh.addDensity(v.w);
358  }
359  }
360 
361  for (size_t tidx = 0; tidx < mesh.polygonCount(); ++tidx) {
362  std::vector<CoredVertexIndex<node_index_type>> triangle;
363  mesh.nextPolygon(triangle);
364  if (triangle.size() == 3) {
365  out_mesh.addTriangle(triangle[0].idx, triangle[1].idx,
366  triangle[2].idx);
367  } else {
368  assert(false);
369  }
370  }
371 }
372 
373 template <class Real, typename... SampleData, unsigned int... FEMSigs>
374 static bool Execute(PointStream<Real>& pointStream,
377  UIntPack<FEMSigs...>) {
378  static const int Dim = sizeof...(FEMSigs);
379  typedef UIntPack<FEMSigs...> Sigs;
380  typedef UIntPack<FEMSignature<FEMSigs>::Degree...> Degrees;
381  typedef UIntPack<FEMDegreeAndBType<
382  NORMAL_DEGREE, DerivativeBoundary<FEMSignature<FEMSigs>::BType,
383  1>::BType>::Signature...>
384  NormalSigs;
385  typedef typename FEMTree<Dim,
386  Real>::template DensityEstimator<WEIGHT_DEGREE>
387  DensityEstimator;
388  typedef typename FEMTree<Dim, Real>::template InterpolationInfo<Real, 0>
389  InterpolationInfo;
390 
391  // Compute scaling transformation (and optionally the depth)
392  int depth = params.depth;
393  XForm<Real, Dim + 1> xForm = XForm<Real, Dim + 1>::Identity();
394  {
395  if (params.finestCellWidth > 0) {
396  Real scaleFactor =
397  static_cast<Real>(params.scale > 0 ? params.scale : 1.0);
398  xForm = GetPointXForm<Real, Dim>(pointStream,
399  params.finestCellWidth,
400  scaleFactor, depth) *
401  xForm; // warning: depth may change!
402  } else if (params.scale > 0) {
403  xForm = GetPointXForm<Real, Dim>(pointStream,
404  static_cast<Real>(params.scale)) *
405  xForm;
406  }
407  pointStream.xform = &xForm;
408  }
409 
410  if (depth < 2) {
411  // depth should be greater than 2
412  assert(false);
413  return false;
414  }
415 
416  // default parameters
417  const int solve_depth = depth;
418  const int full_depth = 5;
419  const bool exact_interpolation = false;
420  const Real target_value = static_cast<Real>(0.5);
421 
422  // Read in the samples (and color data)
423  FEMTree<Dim, Real> tree(MEMORY_ALLOCATOR_BLOCK_SIZE);
424  typedef std::vector<typename FEMTree<Dim, Real>::PointSample> SampleSet;
425  typedef std::vector<PointData<Real>> SampleDataSet;
426  std::unique_ptr<SampleSet> samples;
427  std::unique_ptr<SampleDataSet> sampleData;
428  try {
429  samples.reset(new SampleSet);
430  sampleData.reset(new SampleDataSet);
431 
432  if (params.normalConfidence > 0) {
433  auto ProcessDataWithConfidence = [&](const Point<Real, Dim>& p,
434  PointData<Real>& d) {
435  Real l = ComputeNorm(d.normal);
436  if (std::isnan(l) || l == 0) return static_cast<Real>(-1.0);
437 
438  return static_cast<Real>(pow(l, params.normalConfidence));
439  };
440 
441  FEMTreeInitializer<Dim, Real>::template Initialize<PointData<Real>>(
442  tree.spaceRoot(), pointStream, depth, *samples, *sampleData,
443  true, tree.nodeAllocators[0], tree.initializer(),
444  ProcessDataWithConfidence);
445  } else {
446  auto ProcessData = [](const Point<Real, Dim>& p,
447  PointData<Real>& d) {
448  Real l = ComputeNorm(d.normal);
449  if (std::isnan(l) || l == 0) return static_cast<Real>(-1.0);
450 
451  d.normal[0] /= l;
452  d.normal[1] /= l;
453  d.normal[2] /= l;
454  return static_cast<Real>(1.0);
455  };
456 
457  FEMTreeInitializer<Dim, Real>::template Initialize<PointData<Real>>(
458  tree.spaceRoot(), pointStream, solve_depth, *samples,
459  *sampleData, true, tree.nodeAllocators[0],
460  tree.initializer(), ProcessData);
461  }
462  } catch (std::exception e) {
463  return false;
464  }
465 
466  DenseNodeData<Real, Sigs> solution;
467  std::unique_ptr<DensityEstimator> density;
468  SparseNodeData<Point<Real, Dim>, NormalSigs>* normalInfo = nullptr;
469  Real pointWeightSum = 0;
470  {
471  tree.resetNodeIndices();
472 
473  // Get the kernel density estimator
474  {
475  int kernelDepth = solve_depth - 2;
476  assert(kernelDepth >= 0);
477 
478  density.reset(tree.template setDensityEstimator<WEIGHT_DEGREE>(
479  *samples, kernelDepth, params.samplesPerNode, 1));
480  }
481 
482  // Transform the Hermite samples into a vector field
483  {
484  normalInfo = new SparseNodeData<Point<Real, Dim>, NormalSigs>();
485 
486  if (params.normalConfidenceBias > 0) {
487  std::function<bool(PointData<Real>, Point<Real, Dim>&, Real&)>
488  ConversionAndBiasFunction = [&](PointData<Real> in,
489  Point<Real, Dim>& out,
490  Real& bias) {
491  // Point<Real, Dim> n = in.template data<0>();
492  Point<Real, Dim> n(in.normal[0], in.normal[1],
493  in.normal[2]);
494  Real l = static_cast<Real>(Length(n));
495  // It is possible that the samples have non-zero
496  // normals but there are two co-located samples with
497  // negative normals...
498  if (l == 0) return false;
499 
500  out = n / l;
501  bias = static_cast<Real>(
502  log(l) * params.normalConfidenceBias /
503  log(1 << (Dim - 1)));
504 
505  return true;
506  };
507 
508  *normalInfo = tree.setDataField(
509  NormalSigs(), *samples, *sampleData, density.get(),
510  pointWeightSum, ConversionAndBiasFunction);
511  } else {
512  std::function<bool(PointData<Real>, Point<Real, Dim>&)>
513  ConversionFunction = [](PointData<Real> in,
514  Point<Real, Dim>& out) {
515  Point<Real, Dim> n(in.normal[0], in.normal[1],
516  in.normal[2]);
517  Real l = static_cast<Real>(Length(n));
518  // It is possible that the samples have non-zero
519  // normals but there are two co-located samples with
520  // negative normals...
521  if (l == 0) return false;
522 
523  out = n / l;
524  return true;
525  };
526 
527  *normalInfo = tree.setDataField(
528  NormalSigs(), *samples, *sampleData, density.get(),
529  pointWeightSum, ConversionFunction);
530  }
531 
532  auto InvertNormal = [&](unsigned int, size_t i) {
533  (*normalInfo)[i] *= static_cast<Real>(-1.0);
534  };
535 
536  ThreadPool::Parallel_for(0, normalInfo->size(), InvertNormal);
537  }
538 
539  if (!params.density) {
540  density.reset();
541  }
542  if (!params.withColors || params.colorPullFactor == 0) {
543  sampleData.reset();
544  }
545 
546  // Trim the tree and prepare for multigrid
547  {
548  constexpr int MAX_DEGREE = NORMAL_DEGREE > Degrees::Max()
549  ? NORMAL_DEGREE
550  : Degrees::Max();
551 
552  tree.template finalizeForMultigrid<MAX_DEGREE>(
553  full_depth,
554  typename FEMTree<Dim, Real>::template HasNormalDataFunctor<
555  NormalSigs>(*normalInfo),
556  normalInfo, density.get());
557  }
558 
559  // Add the FEM constraints
560  DenseNodeData<Real, Sigs> constraints;
561  {
562  constraints = tree.initDenseNodeData(Sigs());
563  typename FEMIntegrator::template Constraint<
564  Sigs, IsotropicUIntPack<Dim, 1>, NormalSigs,
565  IsotropicUIntPack<Dim, 0>, Dim>
566  F;
567  unsigned int derivatives2[Dim];
568 
569  for (unsigned int d = 0; d < Dim; d++) derivatives2[d] = 0;
570 
571  typedef IsotropicUIntPack<Dim, 1> Derivatives1;
572  typedef IsotropicUIntPack<Dim, 0> Derivatives2;
573  for (unsigned int d = 0; d < Dim; d++) {
574  unsigned int derivatives1[Dim];
575  for (unsigned int dd = 0; dd < Dim; dd++)
576  derivatives1[dd] = (dd == d ? 1 : 0);
577 
578  F.weights[d]
581  derivatives2)] = 1;
582  }
583 
584  tree.addFEMConstraints(F, *normalInfo, constraints, solve_depth);
585  }
586 
587  // Free up the normal info
588  if (normalInfo) {
589  delete normalInfo;
590  normalInfo = nullptr;
591  }
592 
593  // Add the interpolation constraints
594  InterpolationInfo* iInfo = nullptr;
595  if (params.pointWeight > 0) {
596  if (exact_interpolation) {
597  iInfo = FEMTree<Dim, Real>::
598  template InitializeExactPointInterpolationInfo<Real, 0>(
599  tree, *samples,
601  target_value,
602  static_cast<Real>(params.pointWeight) *
603  pointWeightSum),
605  static_cast<Real>(params.pointWeight) *
606  pointWeightSum),
607  true, 0);
608  } else {
609  iInfo = FEMTree<Dim, Real>::
610  template InitializeApproximatePointInterpolationInfo<
611  Real, 0>(
612  tree, *samples,
614  target_value,
615  static_cast<Real>(params.pointWeight) *
616  pointWeightSum),
618  static_cast<Real>(params.pointWeight) *
619  pointWeightSum),
620  true, 1);
621  }
622  tree.addInterpolationConstraints(constraints, solve_depth, *iInfo);
623  }
624 
625  // Solve the linear system
626  {
627  typename FEMTree<Dim, Real>::SolverInfo sInfo;
628  {
629  sInfo.cgDepth = 0;
630  sInfo.cascadic = true;
631  sInfo.vCycles = 1;
632  sInfo.iters = params.iters;
633  sInfo.cgAccuracy = params.cgAccuracy;
634  sInfo.verbose = false;
635  sInfo.showResidual = false;
636  sInfo.showGlobalResidual = SHOW_GLOBAL_RESIDUAL_NONE;
637  sInfo.sliceBlockSize = 1;
638  sInfo.baseDepth = params.baseDepth;
639  sInfo.baseVCycles = params.baseVCycles;
640  }
641  typename FEMIntegrator::template System<Sigs,
642  IsotropicUIntPack<Dim, 1>>
643  F({0.0, 1.0});
644 
645  solution = tree.solveSystem(Sigs(), F, constraints, solve_depth,
646  sInfo, iInfo);
647  }
648 
649  // Free up the interpolation info
650  if (iInfo) {
651  delete iInfo;
652  iInfo = nullptr;
653  }
654  }
655 
656  Real isoValue = 0;
657  {
658  double valueSum = 0, weightSum = 0;
659  typename FEMTree<Dim, Real>::template MultiThreadedEvaluator<Sigs, 0>
660  evaluator(&tree, solution);
661 
662  std::vector<double> valueSums(ThreadPool::NumThreads(), 0);
663  std::vector<double> weightSums(ThreadPool::NumThreads(), 0);
664 
665  auto func = [&](unsigned int thread, size_t j) {
666  const ProjectiveData<Point<Real, Dim>, Real>& sample =
667  (*samples)[j].sample;
668  if (sample.weight > 0) {
669  weightSums[thread] += sample.weight;
670  valueSums[thread] +=
671  evaluator.values(sample.data / sample.weight, thread,
672  (*samples)[j].node)[0] *
673  sample.weight;
674  }
675  };
676 
677  ThreadPool::Parallel_for(0, samples->size(), func);
678 
679  for (size_t t = 0; t < valueSums.size(); t++) {
680  valueSum += valueSums[t];
681  weightSum += weightSums[t];
682  }
683 
684  isoValue = static_cast<Real>(valueSum / weightSum);
685 
686  if (!params.withColors || params.colorPullFactor == 0) {
687  samples.reset();
688  }
689  }
690 
691  auto SetVertex = [](Vertex<Real>& v, Point<Real, Dim> p, double w,
692  PointData<Real> d) { v = Vertex<Real>(p, d, w); };
693 
694  ExtractMesh<Vertex<Real>, Real>(
695  params, UIntPack<FEMSigs...>(), std::tuple<SampleData...>(), tree,
696  solution, isoValue, samples.get(), sampleData.get(), density.get(),
697  SetVertex, xForm.inverse(), out_mesh);
698 
699  return true;
700 }
701 
703  const ICloud<float>& inCloud,
704  IMesh<float>& outMesh) {
705  if (!inCloud.hasNormals()) {
706  // we need normals
707  return false;
708  }
709 
710 #ifdef WITH_OPENMP
711  ThreadPool::Init((ThreadPool::ParallelType)(int)ThreadPool::OPEN_MP,
712  std::thread::hardware_concurrency());
713 #else
714  ThreadPool::Init((ThreadPool::ParallelType)(int)ThreadPool::THREAD_POOL,
715  std::thread::hardware_concurrency());
716 #endif
717 
718  PointStream<float> pointStream(inCloud);
719 
720  bool success = false;
721 
722  switch (params.boundary) {
723  case Parameters::FREE:
724  typedef IsotropicUIntPack<
725  DIMENSION, FEMDegreeAndBType<DEFAULT_FEM_DEGREE,
726  BOUNDARY_FREE>::Signature>
727  FEMSigsFree;
728  success =
729  Execute<float>(pointStream, outMesh, params, FEMSigsFree());
730  break;
732  typedef IsotropicUIntPack<
733  DIMENSION, FEMDegreeAndBType<DEFAULT_FEM_DEGREE,
734  BOUNDARY_DIRICHLET>::Signature>
735  FEMSigsDirichlet;
736  success = Execute<float>(pointStream, outMesh, params,
737  FEMSigsDirichlet());
738  break;
739  case Parameters::NEUMANN:
740  typedef IsotropicUIntPack<
741  DIMENSION, FEMDegreeAndBType<DEFAULT_FEM_DEGREE,
742  BOUNDARY_NEUMANN>::Signature>
743  FEMSigsNeumann;
744  success = Execute<float>(pointStream, outMesh, params,
745  FEMSigsNeumann());
746  break;
747  default:
748  assert(false);
749  break;
750  }
751 
752  ThreadPool::Terminate();
753 
754  return success;
755 }
756 
758  const ICloud<double>& inCloud,
759  IMesh<double>& outMesh) {
760  if (!inCloud.hasNormals()) {
761  // we need normals
762  return false;
763  }
764 
765 #ifdef WITH_OPENMP
766  ThreadPool::Init((ThreadPool::ParallelType)(int)ThreadPool::OPEN_MP,
767  std::thread::hardware_concurrency());
768 #else
769  ThreadPool::Init((ThreadPool::ParallelType)(int)ThreadPool::THREAD_POOL,
770  std::thread::hardware_concurrency());
771 #endif
772 
773  PointStream<double> pointStream(inCloud);
774 
775  bool success = false;
776 
777  switch (params.boundary) {
778  case Parameters::FREE:
779  typedef IsotropicUIntPack<
780  DIMENSION, FEMDegreeAndBType<DEFAULT_FEM_DEGREE,
781  BOUNDARY_FREE>::Signature>
782  FEMSigsFree;
783  success = Execute<double>(pointStream, outMesh, params,
784  FEMSigsFree());
785  break;
787  typedef IsotropicUIntPack<
788  DIMENSION, FEMDegreeAndBType<DEFAULT_FEM_DEGREE,
789  BOUNDARY_DIRICHLET>::Signature>
790  FEMSigsDirichlet;
791  success = Execute<double>(pointStream, outMesh, params,
792  FEMSigsDirichlet());
793  break;
794  case Parameters::NEUMANN:
795  typedef IsotropicUIntPack<
796  DIMENSION, FEMDegreeAndBType<DEFAULT_FEM_DEGREE,
797  BOUNDARY_NEUMANN>::Signature>
798  FEMSigsNeumann;
799  success = Execute<double>(pointStream, outMesh, params,
800  FEMSigsNeumann());
801  break;
802  default:
803  assert(false);
804  break;
805  }
806 
807  ThreadPool::Terminate();
808 
809  return success;
810 }
double normal[3]
int width
math::float4 color
#define NORMAL_DEGREE
#define DATA_DEGREE
int omp_get_num_procs(void)
#define WEIGHT_DEGREE
double Time(void)
Definition: MyTime.h:38
static bool Execute(PointStream< Real > &pointStream, PoissonReconLib::IMesh< Real > &out_mesh, const PoissonReconLib::Parameters &params, UIntPack< FEMSigs... >)
void ExtractMesh(const PoissonReconLib::Parameters &params, UIntPack< FEMSigs... >, std::tuple< SampleData... >, FEMTree< sizeof...(FEMSigs), Real > &tree, const DenseNodeData< Real, UIntPack< FEMSigs... >> &solution, Real isoValue, const std::vector< typename FEMTree< sizeof...(FEMSigs), Real >::PointSample > *samples, std::vector< PointData< Real >> *sampleData, const typename FEMTree< sizeof...(FEMSigs), Real >::template DensityEstimator< WEIGHT_DEGREE > *density, const SetVertexFunction &SetVertex, XForm< Real, sizeof...(FEMSigs)+1 > iXForm, PoissonReconLib::IMesh< Real > &out_mesh)
XForm< Real, Dim+1 > GetPointXForm(InputPointStream< Real, Dim > &stream, Real width, Real scaleFactor, int &depth)
XForm< Real, Dim+1 > GetBoundingBoxXForm(Point< Real, Dim > min, Point< Real, Dim > max, Real scaleFactor)
double Length(const Point3D< Real > &p)
#define DIMENSION
Definition: Octree.h:38
cmdLineReadable * params[]
int polygonCount(void)
void resetIterator(void)
int nextPolygon(std::vector< CoredVertexIndex > &vertices)
int nextOutOfCorePoint(Vertex &p)
int outOfCorePointCount(void)
void reset(void) override
PointStream(const PoissonReconLib::ICloud< Real > &_cloud)
XForm< Real, 4 > * xform
bool nextPoint(Point< Real, 3 > &p, PointData< Real > &d) override
const PoissonReconLib::ICloud< Real > & cloud
Input cloud interface.
virtual bool hasNormals() const =0
Output mesh interface.
virtual void addDensity(double d)=0
virtual void addColor(const Real *rgb)=0
virtual void addVertex(const Real *coords)=0
virtual void addTriangle(size_t i1, size_t i2, size_t i3)=0
static bool Reconstruct(const Parameters &params, const PoissonReconLib::ICloud< float > &inCloud, PoissonReconLib::IMesh< float > &ouMesh)
Reconstruct a mesh from a point cloud (float version)
Vertex & operator*=(Real s)
Vertex(const Point< Real, 3 > &point, const PointData< Real > &data, double _w=0.0)
Point< Real, 3 > point
Vertex & operator/=(Real s)
Vertex(const Point< Real, 3 > &point)
Vertex & operator+=(const Vertex &p)
int min(int a, int b)
Definition: cutil_math.h:53
int max(int a, int b)
Definition: cutil_math.h:48
void Extract(const std::string &file_path, const std::string &extract_dir)
Function to extract compressed files.
Definition: Extract.cpp:33
struct Index Index
Definition: sqlite3.c:14646
ConstraintDual(Real t, Real w)
CumulativeDerivativeValues< Real, Dim, 0 > operator()(const Point< Real, Dim > &p) const
void dumpOutput(const char *header) const
FEMTree< Dim, Real > & tree
FEMTreeProfiler(FEMTree< Dim, Real > &t)
Real normal[3]
Definition: PointData.h:60
PointData & operator+=(const PointData &d)
Definition: PointData.h:40
Real color[3]
Definition: PointData.h:61
PointData & operator*=(Real s)
Definition: PointData.h:49
Algorithm parameters.
Parameters()
Default initializer.
CumulativeDerivativeValues< Real, Dim, 0 > operator()(const Point< Real, Dim > &p, const CumulativeDerivativeValues< Real, Dim, 0 > &dValues) const
CumulativeDerivativeValues< double, Dim, 0 > operator()(const Point< Real, Dim > &p, const CumulativeDerivativeValues< double, Dim, 0 > &dValues) const
SystemDual(Real w)
CumulativeDerivativeValues< Real, Dim, 0 > operator()(const Point< Real, Dim > &p, const CumulativeDerivativeValues< Real, Dim, 0 > &dValues) const
Definition: lsd.c:149