34 std::vector<VECTOR2D> samples;
36 if( aMinDist <= 0.0 || aMinDist > 0.5 )
44 const int gridN = std::max( 3, (
int) std::ceil( std::sqrt( 2.0 ) / aMinDist ) );
45 const double cellSize = 1.0 / gridN;
47 std::vector<int>
grid( (
size_t) gridN * gridN, -1 );
48 std::vector<int> active;
51 [&](
const VECTOR2D& p ) -> std::pair<int, int>
53 int gx = (int) std::floor( p.x / cellSize );
54 int gy = (int) std::floor( p.y / cellSize );
55 gx = ( ( gx % gridN ) + gridN ) % gridN;
56 gy = ( ( gy % gridN ) + gridN ) % gridN;
61 [](
double dx,
double dy ) ->
double
63 if( dx > 0.5 ) dx -= 1.0;
64 if( dx < -0.5 ) dx += 1.0;
65 if( dy > 0.5 ) dy -= 1.0;
66 if( dy < -0.5 ) dy += 1.0;
67 return dx * dx + dy * dy;
70 boost::random::mt19937
rng( aSeed );
71 boost::random::uniform_real_distribution<double> uniform( 0.0, 1.0 );
75 auto [gx, gy] = cellOf( p );
76 samples.push_back( p );
77 grid[(size_t) gy * gridN + gx] = 0;
78 active.push_back( 0 );
82 while( !active.empty() )
84 boost::random::uniform_int_distribution<size_t> pickIdx( 0, active.size() - 1 );
85 size_t idx = pickIdx(
rng );
86 VECTOR2D base = samples[active[idx]];
87 bool accepted =
false;
89 for(
int k = 0; k < K; ++k )
91 double theta = uniform(
rng ) * 2.0 *
M_PI;
92 double rho = aMinDist + uniform(
rng ) * aMinDist;
93 VECTOR2D cand( base.
x + rho * std::cos( theta ),
94 base.
y + rho * std::sin( theta ) );
97 cand.
x -= std::floor( cand.
x );
98 cand.
y -= std::floor( cand.
y );
100 auto [cx, cy] = cellOf( cand );
101 bool tooClose =
false;
105 for(
int dy = -2; dy <= 2 && !tooClose; ++dy )
107 int ny = ( ( cy + dy ) % gridN + gridN ) % gridN;
109 for(
int dx = -2; dx <= 2 && !tooClose; ++dx )
111 int nx = ( ( cx + dx ) % gridN + gridN ) % gridN;
112 int idxN =
grid[(size_t) ny * gridN + nx];
117 if(
torDistSq( samples[idxN].x - cand.
x, samples[idxN].y - cand.
y )
118 < aMinDist * aMinDist )
128 samples.push_back( cand );
129 grid[(size_t) cy * gridN + cx] = (
int) samples.size() - 1;
130 active.push_back( (
int) samples.size() - 1 );
137 active[idx] = active.back();