219{
223
224
225 m_cell = std::max(MinCellSize, std::cbrt(extent.prod() / MaxNodes));
227 while (double(nodes(extent.x())) * nodes(extent.y()) * nodes(extent.z()) > MaxNodes)
229 m_size =
Vec3i32(nodes(extent.x()), nodes(extent.y()), nodes(extent.z()));
231
232 const size_t sy = size_t(
m_size.x());
233 const size_t sz = sy *
m_size.y();
235 tbb::parallel_for(tbb::blocked_range<int>(0,
m_size.z()), [&](
const tbb::blocked_range<int> &
range) {
236 for (int k = range.begin(); k < range.end(); ++k) {
237 const double z = m_origin.z() + k * m_cell;
238 auto it = std::lower_bound(slices.begin(), slices.end(), z, [](const Slice &s, double z) { return s.top_z < z; });
239 if (it != slices.end() && z > it->bottom_z)
240 rasterize(*it->expolygons, m_origin.head<2>(), m_cell, m_size.x(), m_size.y(), depth.data() + k * sz);
241 }
242 throw_if_canceled();
243 });
247
248 auto position = [this, sy, sz](size_t i) {
250 };
251 const std::array<std::ptrdiff_t, 6> steps{1, -1, std::ptrdiff_t(sy), -std::ptrdiff_t(sy), std::ptrdiff_t(sz), -std::ptrdiff_t(sz)};
252
253 auto node_of = [
this, sy, sz](
const Vec3d &pt) -> std::ptrdiff_t {
255 const long x = std::lround(
f.x()), y = std::lround(
f.y()), z = std::lround(
f.z());
257 return -1;
258 return std::ptrdiff_t(size_t(z) * sz + size_t(y) * sy + size_t(x));
259 };
260
261 auto in_section = [
this](
size_t step) {
return int(step / 2) !=
m_axis; };
262 std::vector<std::ptrdiff_t> neighbours;
263 for (int dz = -1; dz <= 1; ++dz)
264 for (int dy = -1; dy <= 1; ++dy)
265 for (int dx = -1; dx <= 1; ++dx)
267 neighbours.push_back(std::ptrdiff_t(dz) * std::ptrdiff_t(sz) + std::ptrdiff_t(dy) * std::ptrdiff_t(sy) + dx);
268
269
270
271
274 std::vector<size_t> body_nodes;
275 for (
size_t seed = 0; seed <
depth.size(); ++seed) {
277 continue;
278 const int id = int(
m_bodies.size());
279 body_nodes.assign(1, seed);
281 float max_depth = 0.f;
282 for (size_t k = 0; k < body_nodes.size(); ++k) {
283 max_depth = std::max(max_depth,
depth[body_nodes[k]]);
284 for (size_t s = 0; s < steps.size(); ++s)
285 if (
const size_t j = body_nodes[k] + steps[s]; in_section(s) &&
depth[j] > 0.f &&
m_body[j] < 0) {
287 body_nodes.push_back(j);
288 }
289 }
291 if (!lobes)
292 continue;
293
294 std::vector<size_t> peaks;
295 for (size_t i : body_nodes)
296 if (
depth[i] >=
sqr(MinLobeRatio) * max_depth &&
297 std::all_of(neighbours.begin(), neighbours.end(), [&](std::ptrdiff_t n) { return depth[i + n] <= depth[i]; }))
298 peaks.push_back(i);
299 std::sort(peaks.begin(), peaks.end(), [&
depth](
size_t a,
size_t b) { return depth[a] > depth[b] || (depth[a] == depth[b] && a < b); });
300 auto necked = [&](size_t a, size_t b) {
301 const Vec3d pa = position(a), pb = position(b);
302 const double limit =
sqr(NeckRatio) * std::min(
depth[a],
depth[b]);
303 const int samples = int(std::ceil((pb - pa).norm() / (0.5 *
m_cell)));
304 for (int s = 1; s < samples; ++s)
305 if (
depth[node_of(pa + (pb - pa) * (
double(s) / samples))] < limit)
306 return true;
307 return false;
308 };
309
310
311 std::vector<std::vector<size_t>> ties;
312 while (!peaks.empty()) {
313 const size_t front = peaks.front();
314 std::vector<char> joins(peaks.size(), 0);
315 tbb::parallel_for(tbb::blocked_range<size_t>(1, peaks.size()), [&](
const tbb::blocked_range<size_t> &
range) {
316 for (size_t k = range.begin(); k < range.end(); ++k)
317 if (!necked(front, peaks[k]))
318 joins[k] = std::sqrt(depth[peaks[k]]) >= std::sqrt(depth[front]) - 1.f ? 1 : 2;
319 });
320 std::vector<size_t> &tied = ties.emplace_back(1, front);
321 std::vector<size_t> remaining;
322 for (size_t k = 1; k < peaks.size(); ++k)
323 if (joins[k] == 0)
324 remaining.push_back(peaks[k]);
325 else if (joins[k] == 1)
326 tied.push_back(peaks[k]);
327 peaks = std::move(remaining);
328 }
329 m_bodies.back().lobes = ties.size();
330 for (const std::vector<size_t> &tied : ties) {
331 Vec3d middle(0., 0., 0.);
332 for (size_t i : tied)
333 middle += position(i);
334 middle /= double(tied.size());
336 for (size_t i : tied)
337 if ((position(i) - middle).squaredNorm() < (
center - middle).squaredNorm())
340 }
341 }
342 throw_if_canceled();
343
346 for (
size_t i = 0; i <
depth.size(); ++i)
349 }
350
351
352
353 std::vector<int> lobe_body(
m_lobes.size());
354 for (
size_t id = 0;
id <
m_bodies.size(); ++id)
355 std::fill_n(lobe_body.begin() +
m_bodies[
id].first_lobe,
m_bodies[
id].lobes,
int(
id));
357 auto direction = [this](int i, int j) {
358 const double azimuth = j * 2. *
PI /
Azimuth;
359 Vec3d dir = Vec3d::Zero();
361 const double polar = (i + 0.5) *
PI /
Polar;
362 dir =
Vec3d(std::sin(polar) * std::cos(azimuth), std::sin(polar) * std::sin(azimuth), std::cos(polar));
363 } else {
364 dir[(
m_axis + 1) % 3] = std::cos(azimuth);
365 dir[(
m_axis + 2) % 3] = std::sin(azimuth);
366 }
367 return dir;
368 };
369
370 auto smooth = [
rows](std::vector<double> &values,
size_t count) {
371 for (int pass = 0; pass < 2; ++pass) {
372 std::vector<double> smoothed(values.size(), 0.);
373 for (
int i = 0; i <
rows; ++i)
374 for (
int j = 0; j <
Azimuth; ++j)
375 for (
size_t k = 0; k <
count; ++k) {
376 double &sum = smoothed[size_t(i *
Azimuth + j) *
count + k];
377 for (int di = -1; di <= 1; ++di)
378 for (int dj = -1; dj <= 1; ++dj)
380 sum /= 9.;
381 }
382 values = std::move(smoothed);
383 }
384 };
385 tbb::parallel_for(tbb::blocked_range<size_t>(0,
m_lobes.size()), [&](
const tbb::blocked_range<size_t> &
range) {
386 for (size_t l = range.begin(); l < range.end(); ++l) {
387 const int id = lobe_body[l];
388 const Body &body = m_bodies[id];
389 Lobe &lobe = m_lobes[l];
390
391 std::vector<std::pair<double, size_t>> others;
392 for (size_t k = body.first_lobe; k < body.first_lobe + body.lobes; ++k)
393 if (k != l)
394 others.emplace_back((m_lobes[k].center - lobe.center).norm() / (1. + m_lobes[k].depth / lobe.depth), k);
395 std::sort(others.begin(), others.end());
396 auto nearer_lobe = [&](const Vec3d &pt, double r) {
397 for (auto it = others.begin(); it != others.end() && it->first < r; ++it)
398 if ((pt - m_lobes[it->second].center).norm() / m_lobes[it->second].depth < r / lobe.depth)
399 return true;
400 return false;
401 };
402 const double step = 0.5 * m_cell;
403 std::vector<double> log_reach(this->directions());
404 for (int i = 0; i < rows; ++i)
405 for (int j = 0; j < Azimuth; ++j) {
406 const Vec3d dir = direction(i, j);
407 double r = 0.;
408 double limit = InfD;
409 for (;;) {
410 const Vec3d pt = lobe.center + (r + step) * dir;
411 const std::ptrdiff_t n = node_of(pt);
412 if (n < 0 || depth[n] == 0.f || m_body[n] != id || r + step >= limit)
413 break;
414 if (limit == InfD && nearer_lobe(pt, r + step))
415 limit = LobeReach * (r + step);
416 r += step;
417 }
418 log_reach[i * Azimuth + j] = std::log(std::min(r + 0.5 * step, limit));
419 }
420 smooth(log_reach, 1);
421 lobe.reach.resize(log_reach.size());
422 std::transform(log_reach.begin(), log_reach.end(), lobe.reach.begin(), [](double v) { return float(std::exp(v)); });
423
424 if (m_mode == AdaptiveInfillMode::DistanceWarp) {
425 std::vector<double> mean(log_reach.size() * (Samples + 1));
426 for (size_t d = 0; d < log_reach.size(); ++d) {
427 const Vec3d dir = direction(int(d) / Azimuth, int(d) % Azimuth);
428 double integral = 0.;
429 double previous = this->depth(lobe.center);
430 mean[d * (Samples + 1)] = previous;
431 for (int k = 1; k <= Samples; ++k) {
432
433 const double t0 = double(k - 1) / Samples;
434 const double t1 = double(k) / Samples;
435 const double d1 = this->depth(lobe.center + t1 * lobe.reach[d] * dir);
436 const double b = (d1 - previous) * Samples;
437 const double a = previous - b * t0;
438 integral += a * (std::pow(t1, 3) - std::pow(t0, 3)) / 3. + b * (std::pow(t1, 4) - std::pow(t0, 4)) / 4.;
439 previous = d1;
440 mean[d * (Samples + 1) + k] = 3. * integral / std::pow(t1, 3);
441 }
442 }
443
444 smooth(mean, Samples + 1);
445 lobe.mean_depth.assign(mean.begin(), mean.end());
446 }
447 }
448 throw_if_canceled();
449 });
450
451
454 for (
size_t i = 0; i <
m_body.size(); ++i)
460 if (k - d >= 0 && has_body[k - d])
464 }
465
466 if (!lobes) {
468 return;
469 }
472 return;
473 }
474 std::deque<size_t> queue;
475 for (
size_t i = 0; i <
m_body.size(); ++i)
477 queue.push_back(i);
478 while (!queue.empty()) {
479 const size_t i = queue.front();
480 queue.pop_front();
481 const size_t x = i % sy, y = i / sy %
m_size.y(), z = i / sz;
482 const std::array<bool, 6> valid{x + 1 < sy, x > 0, y + 1 < size_t(
m_size.y()), y > 0, z + 1 < size_t(
m_size.z()), z > 0};
483 for (size_t k = 0; k < steps.size(); ++k)
484 if (valid[k] && in_section(k) &&
m_body[i + steps[k]] < 0) {
486 queue.push_back(i + steps[k]);
487 }
488 }
489}
static unsigned int count
Definition AuxiliaryDataViewModel.cpp:246
static constexpr int Azimuth
Definition AdaptiveInfillField.hpp:92
std::vector< int > m_section
Definition AdaptiveInfillField.hpp:104
Vec3d m_origin
Definition AdaptiveInfillField.hpp:96
double m_cell
Definition AdaptiveInfillField.hpp:97
std::vector< Body > m_bodies
Definition AdaptiveInfillField.hpp:101
double depth(const Vec3d &pt) const
Definition AdaptiveInfillField.cpp:491
int axis() const
Definition AdaptiveInfillField.hpp:58
AdaptiveInfillMode m_mode
Definition AdaptiveInfillField.hpp:94
Vec3i32 m_size
Definition AdaptiveInfillField.hpp:98
int directions() const
Definition AdaptiveInfillField.hpp:88
std::vector< Lobe > m_lobes
Definition AdaptiveInfillField.hpp:102
std::vector< int > m_body
Definition AdaptiveInfillField.hpp:100
int m_axis
Definition AdaptiveInfillField.hpp:95
std::vector< float > m_depth
Definition AdaptiveInfillField.hpp:106
AdaptiveInfillMode mode() const
Definition AdaptiveInfillField.hpp:59
static constexpr int Polar
Definition AdaptiveInfillField.hpp:91
static constexpr double PI
Definition libslic3r.h:81
void distance_transform_axis(std::vector< float > &grid, const Vec3i32 &size, int axis, const std::function< void()> &throw_if_canceled)
Definition AdaptiveInfillField.cpp:86
double length(const Points &pts)
Definition MultiPoint.hpp:181
Eigen::Matrix< double, 3, 1, Eigen::DontAlign > Vec3d
Definition Point.hpp:68
void center(ExPolygonsWithIds &e)
Definition Emboss.cpp:1382
@ SmoothBlend
Definition PrintConfig.hpp:293
@ NormalX
Definition PrintConfig.hpp:298
@ SteppedShells
Definition PrintConfig.hpp:294
@ NormalZ
Definition PrintConfig.hpp:296
@ DistanceWarp
Definition PrintConfig.hpp:292
@ Disabled
Definition PrintConfig.hpp:291
@ NormalY
Definition PrintConfig.hpp:297
auto range(Cont &&cont)
Definition libslic3r.h:405
static double f(double x, double z_sin, double z_cos, bool vertical, bool flip)
Definition FillGyroid.cpp:124
constexpr Eigen::Matrix< Tout, 2, EigenArgs... > unscaled(const Slic3r::Point &v) noexcept
Definition Arrange.cpp:81
constexpr T sqr(T x)
Definition libslic3r.h:301
Eigen::Matrix< int32_t, 3, 1, Eigen::DontAlign > Vec3i32
Definition Point.hpp:59
void step(Coord &crd, const Dir d, const long n=1)
Definition MarchingSquares.hpp:213
size_t rows(const T &raster)
Definition MarchingSquares.hpp:171