|
@@ -1,9 +1,9 @@
|
|
|
// This file is part of libigl, a simple c++ geometry processing library.
|
|
// This file is part of libigl, a simple c++ geometry processing library.
|
|
|
-//
|
|
|
|
|
|
|
+//
|
|
|
// Copyright (C) 2020 Alec Jacobson <[email protected]>
|
|
// Copyright (C) 2020 Alec Jacobson <[email protected]>
|
|
|
-//
|
|
|
|
|
-// This Source Code Form is subject to the terms of the Mozilla Public License
|
|
|
|
|
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
|
|
|
|
|
|
+//
|
|
|
|
|
+// This Source Code Form is subject to the terms of the Mozilla Public License
|
|
|
|
|
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
|
|
// obtain one at http://mozilla.org/MPL/2.0/.
|
|
// obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
#include "blue_noise.h"
|
|
#include "blue_noise.h"
|
|
|
#include "doublearea.h"
|
|
#include "doublearea.h"
|
|
@@ -126,6 +126,7 @@ namespace igl
|
|
|
std::unordered_map<BlueNoiseKeyType,int> & S,
|
|
std::unordered_map<BlueNoiseKeyType,int> & S,
|
|
|
std::vector<int> & active)
|
|
std::vector<int> & active)
|
|
|
{
|
|
{
|
|
|
|
|
+ assert(M.count(nk));
|
|
|
auto & Mvec = M.find(nk)->second;
|
|
auto & Mvec = M.find(nk)->second;
|
|
|
auto miter = Mvec.begin();
|
|
auto miter = Mvec.begin();
|
|
|
while(miter != Mvec.end())
|
|
while(miter != Mvec.end())
|
|
@@ -149,7 +150,14 @@ namespace igl
|
|
|
// back)
|
|
// back)
|
|
|
//std::swap(*miter,Mvec.back());
|
|
//std::swap(*miter,Mvec.back());
|
|
|
*miter = Mvec.back();
|
|
*miter = Mvec.back();
|
|
|
|
|
+ bool was_last = (std::next(miter) == Mvec.end());
|
|
|
Mvec.pop_back();
|
|
Mvec.pop_back();
|
|
|
|
|
+ if (was_last) {
|
|
|
|
|
+ // popping from the vector can invalidate the iterator, if it was
|
|
|
|
|
+ // pointing to the last element that was popped. Alternatively,
|
|
|
|
|
+ // one could use indices directly...
|
|
|
|
|
+ miter = Mvec.end();
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
return false;
|
|
return false;
|
|
@@ -259,20 +267,22 @@ IGL_INLINE void igl::blue_noise(
|
|
|
// function of r and s; and removing the `if S=-1 checks`)
|
|
// function of r and s; and removing the `if S=-1 checks`)
|
|
|
const Scalar s = r/sqrt(3.0);
|
|
const Scalar s = r/sqrt(3.0);
|
|
|
|
|
|
|
|
- const double area =
|
|
|
|
|
|
|
+ const double area =
|
|
|
[&](){Eigen::VectorXd A;igl::doublearea(V,F,A);return A.array().sum()/2;}();
|
|
[&](){Eigen::VectorXd A;igl::doublearea(V,F,A);return A.array().sum()/2;}();
|
|
|
// Circle packing in the plane has igl::PI*sqrt(3)/6 efficiency
|
|
// Circle packing in the plane has igl::PI*sqrt(3)/6 efficiency
|
|
|
- const double expected_number_of_points =
|
|
|
|
|
|
|
+ const double expected_number_of_points =
|
|
|
area * (igl::PI * sqrt(3.0) / 6.0) / (igl::PI * min_r * min_r / 4.0);
|
|
area * (igl::PI * sqrt(3.0) / 6.0) / (igl::PI * min_r * min_r / 4.0);
|
|
|
|
|
|
|
|
// Make a uniform random sampling with 30*expected_number_of_points.
|
|
// Make a uniform random sampling with 30*expected_number_of_points.
|
|
|
const int nx = 30.0*expected_number_of_points;
|
|
const int nx = 30.0*expected_number_of_points;
|
|
|
MatrixX3S X,XB;
|
|
MatrixX3S X,XB;
|
|
|
Eigen::VectorXi XFI;
|
|
Eigen::VectorXi XFI;
|
|
|
|
|
+ std::cout << V.rows() << " " << V.cols() << std::endl;
|
|
|
|
|
+ std::cout << F.rows() << " " << F.cols() << std::endl;
|
|
|
igl::random_points_on_mesh(nx,V,F,XB,XFI,X);
|
|
igl::random_points_on_mesh(nx,V,F,XB,XFI,X);
|
|
|
|
|
|
|
|
// Rescale so that s = 1
|
|
// Rescale so that s = 1
|
|
|
- Eigen::Matrix<int,Eigen::Dynamic,3,Eigen::RowMajor> Xs =
|
|
|
|
|
|
|
+ Eigen::Matrix<int,Eigen::Dynamic,3,Eigen::RowMajor> Xs =
|
|
|
((X.rowwise()-X.colwise().minCoeff())/s).template cast<int>();
|
|
((X.rowwise()-X.colwise().minCoeff())/s).template cast<int>();
|
|
|
const int w = Xs.maxCoeff()+1;
|
|
const int w = Xs.maxCoeff()+1;
|
|
|
{
|
|
{
|
|
@@ -294,7 +304,7 @@ IGL_INLINE void igl::blue_noise(
|
|
|
S.reserve(Xs.rows());
|
|
S.reserve(Xs.rows());
|
|
|
for(int i = 0;i<Xs.rows();i++)
|
|
for(int i = 0;i<Xs.rows();i++)
|
|
|
{
|
|
{
|
|
|
- BlueNoiseKeyType k = blue_noise_key(w,Xs(i,0),Xs(i,1),Xs(i,2));
|
|
|
|
|
|
|
+ BlueNoiseKeyType k = blue_noise_key(w,Xs(i,0),Xs(i,1),Xs(i,2));
|
|
|
const auto Miter = M.find(k);
|
|
const auto Miter = M.find(k);
|
|
|
if(Miter == M.end())
|
|
if(Miter == M.end())
|
|
|
{
|
|
{
|
|
@@ -309,7 +319,7 @@ IGL_INLINE void igl::blue_noise(
|
|
|
|
|
|
|
|
std::vector<int> active;
|
|
std::vector<int> active;
|
|
|
// precompute r²
|
|
// precompute r²
|
|
|
- // Q: is this necessary?
|
|
|
|
|
|
|
+ // Q: is this necessary?
|
|
|
const double rr = r*r;
|
|
const double rr = r*r;
|
|
|
std::vector<int> collected;
|
|
std::vector<int> collected;
|
|
|
collected.reserve(2.0*expected_number_of_points);
|
|
collected.reserve(2.0*expected_number_of_points);
|