Merge remote-tracking branch 'origin/master' into ys_unsaved_changes
This commit is contained in:
commit
8f15efbf9a
@ -126,9 +126,9 @@ uqptr<sla::RasterBase> SL1Archive::create_raster() const
|
||||
return sla::create_raster_grayscale_aa(res, pxdim, gamma, tr);
|
||||
}
|
||||
|
||||
sla::EncodedRaster SL1Archive::encode_raster(const sla::RasterBase &rst) const
|
||||
sla::RasterEncoder SL1Archive::get_encoder() const
|
||||
{
|
||||
return rst.encode(sla::PNGRasterEncoder());
|
||||
return sla::PNGRasterEncoder{};
|
||||
}
|
||||
|
||||
void SL1Archive::export_print(Zipper& zipper,
|
||||
|
@ -13,7 +13,7 @@ class SL1Archive: public SLAPrinter {
|
||||
|
||||
protected:
|
||||
uqptr<sla::RasterBase> create_raster() const override;
|
||||
sla::EncodedRaster encode_raster(const sla::RasterBase &rst) const override;
|
||||
sla::RasterEncoder get_encoder() const override;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -114,15 +114,6 @@ template<class T> struct remove_cvref
|
||||
|
||||
template<class T> using remove_cvref_t = typename remove_cvref<T>::type;
|
||||
|
||||
template<class T, class I, class... Args> // Arbitrary allocator can be used
|
||||
inline IntegerOnly<I, std::vector<T, Args...>> reserve_vector(I capacity)
|
||||
{
|
||||
std::vector<T, Args...> ret;
|
||||
if (capacity > I(0)) ret.reserve(size_t(capacity));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// Exactly like Matlab https://www.mathworks.com/help/matlab/ref/linspace.html
|
||||
template<class T, class I, class = IntegerOnly<I>>
|
||||
inline std::vector<T> linspace_vector(const ArithmeticOnly<T> &start,
|
||||
|
@ -4,6 +4,8 @@
|
||||
#include <tbb/spin_mutex.h>
|
||||
#include <tbb/mutex.h>
|
||||
#include <tbb/parallel_for.h>
|
||||
#include <algorithm>
|
||||
#include <libslic3r/libslic3r.h>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace sla {
|
||||
@ -17,16 +19,29 @@ template<bool> struct _ccr {};
|
||||
template<> struct _ccr<true>
|
||||
{
|
||||
using SpinningMutex = tbb::spin_mutex;
|
||||
using BlockingMutex = tbb::mutex;
|
||||
|
||||
using BlockingMutex = tbb::mutex;
|
||||
|
||||
template<class It, class Fn>
|
||||
static inline void enumerate(It from, It to, Fn fn)
|
||||
static IteratorOnly<It, void> for_each(It from,
|
||||
It to,
|
||||
Fn && fn,
|
||||
size_t granularity = 1)
|
||||
{
|
||||
auto iN = to - from;
|
||||
size_t N = iN < 0 ? 0 : size_t(iN);
|
||||
|
||||
tbb::parallel_for(size_t(0), N, [from, fn](size_t n) {
|
||||
fn(*(from + decltype(iN)(n)), n);
|
||||
tbb::parallel_for(tbb::blocked_range{from, to, granularity},
|
||||
[&fn, from](const auto &range) {
|
||||
for (auto &el : range) fn(el);
|
||||
});
|
||||
}
|
||||
|
||||
template<class I, class Fn>
|
||||
static IntegerOnly<I, void> for_each(I from,
|
||||
I to,
|
||||
Fn && fn,
|
||||
size_t granularity = 1)
|
||||
{
|
||||
tbb::parallel_for(tbb::blocked_range{from, to, granularity},
|
||||
[&fn](const auto &range) {
|
||||
for (I i = range.begin(); i < range.end(); ++i) fn(i);
|
||||
});
|
||||
}
|
||||
};
|
||||
@ -39,11 +54,23 @@ private:
|
||||
public:
|
||||
using SpinningMutex = _Mtx;
|
||||
using BlockingMutex = _Mtx;
|
||||
|
||||
|
||||
template<class It, class Fn>
|
||||
static inline void enumerate(It from, It to, Fn fn)
|
||||
static IteratorOnly<It, void> for_each(It from,
|
||||
It to,
|
||||
Fn &&fn,
|
||||
size_t /* ignore granularity */ = 1)
|
||||
{
|
||||
for (auto it = from; it != to; ++it) fn(*it, size_t(it - from));
|
||||
for (auto it = from; it != to; ++it) fn(*it);
|
||||
}
|
||||
|
||||
template<class I, class Fn>
|
||||
static IntegerOnly<I, void> for_each(I from,
|
||||
I to,
|
||||
Fn &&fn,
|
||||
size_t /* ignore granularity */ = 1)
|
||||
{
|
||||
for (I i = from; i < to; ++i) fn(i);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -320,10 +320,10 @@ PointSet normals(const PointSet& points,
|
||||
PointSet ret(range.size(), 3);
|
||||
|
||||
// for (size_t ridx = 0; ridx < range.size(); ++ridx)
|
||||
ccr::enumerate(
|
||||
range.begin(), range.end(),
|
||||
[&ret, &mesh, &points, thr, eps](unsigned el, size_t ridx) {
|
||||
ccr::for_each(size_t(0), range.size(),
|
||||
[&ret, &mesh, &points, thr, eps, &range](size_t ridx) {
|
||||
thr();
|
||||
unsigned el = range[ridx];
|
||||
auto eidx = Eigen::Index(el);
|
||||
int faceid = 0;
|
||||
Vec3d p;
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <tbb/parallel_for.h>
|
||||
|
||||
#include "SupportPointGenerator.hpp"
|
||||
#include "Concurrency.hpp"
|
||||
#include "Model.hpp"
|
||||
#include "ExPolygon.hpp"
|
||||
#include "SVG.hpp"
|
||||
@ -87,27 +88,28 @@ void SupportPointGenerator::project_onto_mesh(std::vector<sla::SupportPoint>& po
|
||||
// The function makes sure that all the points are really exactly placed on the mesh.
|
||||
|
||||
// Use a reasonable granularity to account for the worker thread synchronization cost.
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, points.size(), 64),
|
||||
[this, &points](const tbb::blocked_range<size_t>& range) {
|
||||
for (size_t point_id = range.begin(); point_id < range.end(); ++ point_id) {
|
||||
if ((point_id % 16) == 0)
|
||||
// Don't call the following function too often as it flushes CPU write caches due to synchronization primitves.
|
||||
m_throw_on_cancel();
|
||||
Vec3f& p = points[point_id].pos;
|
||||
// Project the point upward and downward and choose the closer intersection with the mesh.
|
||||
sla::IndexedMesh::hit_result hit_up = m_emesh.query_ray_hit(p.cast<double>(), Vec3d(0., 0., 1.));
|
||||
sla::IndexedMesh::hit_result hit_down = m_emesh.query_ray_hit(p.cast<double>(), Vec3d(0., 0., -1.));
|
||||
static constexpr size_t gransize = 64;
|
||||
|
||||
bool up = hit_up.is_hit();
|
||||
bool down = hit_down.is_hit();
|
||||
ccr_par::for_each(size_t(0), points.size(), [this, &points](size_t idx)
|
||||
{
|
||||
if ((idx % 16) == 0)
|
||||
// Don't call the following function too often as it flushes CPU write caches due to synchronization primitves.
|
||||
m_throw_on_cancel();
|
||||
|
||||
if (!up && !down)
|
||||
continue;
|
||||
Vec3f& p = points[idx].pos;
|
||||
// Project the point upward and downward and choose the closer intersection with the mesh.
|
||||
sla::IndexedMesh::hit_result hit_up = m_emesh.query_ray_hit(p.cast<double>(), Vec3d(0., 0., 1.));
|
||||
sla::IndexedMesh::hit_result hit_down = m_emesh.query_ray_hit(p.cast<double>(), Vec3d(0., 0., -1.));
|
||||
|
||||
sla::IndexedMesh::hit_result& hit = (!down || (hit_up.distance() < hit_down.distance())) ? hit_up : hit_down;
|
||||
p = p + (hit.distance() * hit.direction()).cast<float>();
|
||||
}
|
||||
});
|
||||
bool up = hit_up.is_hit();
|
||||
bool down = hit_down.is_hit();
|
||||
|
||||
if (!up && !down)
|
||||
return;
|
||||
|
||||
sla::IndexedMesh::hit_result& hit = (!down || (hit_up.distance() < hit_down.distance())) ? hit_up : hit_down;
|
||||
p = p + (hit.distance() * hit.direction()).cast<float>();
|
||||
}, gransize);
|
||||
}
|
||||
|
||||
static std::vector<SupportPointGenerator::MyLayer> make_layers(
|
||||
@ -126,78 +128,80 @@ static std::vector<SupportPointGenerator::MyLayer> make_layers(
|
||||
//const float pixel_area = pow(wxGetApp().preset_bundle->project_config.option<ConfigOptionFloat>("display_width") / wxGetApp().preset_bundle->project_config.option<ConfigOptionInt>("display_pixels_x"), 2.f); //
|
||||
const float pixel_area = pow(0.047f, 2.f);
|
||||
|
||||
// Use a reasonable granularity to account for the worker thread synchronization cost.
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, layers.size(), 32),
|
||||
[&layers, &slices, &heights, pixel_area, throw_on_cancel](const tbb::blocked_range<size_t>& range) {
|
||||
for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) {
|
||||
if ((layer_id % 8) == 0)
|
||||
// Don't call the following function too often as it flushes CPU write caches due to synchronization primitves.
|
||||
throw_on_cancel();
|
||||
SupportPointGenerator::MyLayer &layer = layers[layer_id];
|
||||
const ExPolygons &islands = slices[layer_id];
|
||||
//FIXME WTF?
|
||||
const float height = (layer_id>2 ? heights[layer_id-3] : heights[0]-(heights[1]-heights[0]));
|
||||
layer.islands.reserve(islands.size());
|
||||
for (const ExPolygon &island : islands) {
|
||||
float area = float(island.area() * SCALING_FACTOR * SCALING_FACTOR);
|
||||
if (area >= pixel_area)
|
||||
//FIXME this is not a correct centroid of a polygon with holes.
|
||||
layer.islands.emplace_back(layer, island, get_extents(island.contour), Slic3r::unscale(island.contour.centroid()).cast<float>(), area, height);
|
||||
}
|
||||
}
|
||||
});
|
||||
ccr_par::for_each(size_t(0), layers.size(),
|
||||
[&layers, &slices, &heights, pixel_area, throw_on_cancel](size_t layer_id)
|
||||
{
|
||||
if ((layer_id % 8) == 0)
|
||||
// Don't call the following function too often as it flushes
|
||||
// CPU write caches due to synchronization primitves.
|
||||
throw_on_cancel();
|
||||
|
||||
SupportPointGenerator::MyLayer &layer = layers[layer_id];
|
||||
const ExPolygons & islands = slices[layer_id];
|
||||
// FIXME WTF?
|
||||
const float height = (layer_id > 2 ?
|
||||
heights[layer_id - 3] :
|
||||
heights[0] - (heights[1] - heights[0]));
|
||||
layer.islands.reserve(islands.size());
|
||||
for (const ExPolygon &island : islands) {
|
||||
float area = float(island.area() * SCALING_FACTOR * SCALING_FACTOR);
|
||||
if (area >= pixel_area)
|
||||
// FIXME this is not a correct centroid of a polygon with holes.
|
||||
layer.islands.emplace_back(layer, island, get_extents(island.contour),
|
||||
unscaled<float>(island.contour.centroid()), area, height);
|
||||
}
|
||||
}, 32 /*gransize*/);
|
||||
|
||||
// Calculate overlap of successive layers. Link overlapping islands.
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(1, layers.size(), 8),
|
||||
[&layers, &heights, throw_on_cancel](const tbb::blocked_range<size_t>& range) {
|
||||
for (size_t layer_id = range.begin(); layer_id < range.end(); ++layer_id) {
|
||||
if ((layer_id % 2) == 0)
|
||||
// Don't call the following function too often as it flushes CPU write caches due to synchronization primitves.
|
||||
throw_on_cancel();
|
||||
SupportPointGenerator::MyLayer &layer_above = layers[layer_id];
|
||||
SupportPointGenerator::MyLayer &layer_below = layers[layer_id - 1];
|
||||
//FIXME WTF?
|
||||
const float layer_height = (layer_id!=0 ? heights[layer_id]-heights[layer_id-1] : heights[0]);
|
||||
const float safe_angle = 5.f * (float(M_PI)/180.f); // smaller number - less supports
|
||||
const float between_layers_offset = float(scale_(layer_height / std::tan(safe_angle)));
|
||||
const float slope_angle = 75.f * (float(M_PI)/180.f); // smaller number - less supports
|
||||
const float slope_offset = float(scale_(layer_height / std::tan(slope_angle)));
|
||||
//FIXME This has a quadratic time complexity, it will be excessively slow for many tiny islands.
|
||||
for (SupportPointGenerator::Structure &top : layer_above.islands) {
|
||||
for (SupportPointGenerator::Structure &bottom : layer_below.islands) {
|
||||
float overlap_area = top.overlap_area(bottom);
|
||||
if (overlap_area > 0) {
|
||||
top.islands_below.emplace_back(&bottom, overlap_area);
|
||||
bottom.islands_above.emplace_back(&top, overlap_area);
|
||||
}
|
||||
}
|
||||
if (! top.islands_below.empty()) {
|
||||
Polygons top_polygons = to_polygons(*top.polygon);
|
||||
Polygons bottom_polygons = top.polygons_below();
|
||||
top.overhangs = diff_ex(top_polygons, bottom_polygons);
|
||||
if (! top.overhangs.empty()) {
|
||||
top.overhangs_area = 0.f;
|
||||
std::vector<std::pair<ExPolygon*, float>> expolys_with_areas;
|
||||
for (ExPolygon &ex : top.overhangs) {
|
||||
float area = float(ex.area());
|
||||
expolys_with_areas.emplace_back(&ex, area);
|
||||
top.overhangs_area += area;
|
||||
}
|
||||
std::sort(expolys_with_areas.begin(), expolys_with_areas.end(),
|
||||
ccr_par::for_each(size_t(1), layers.size(),
|
||||
[&layers, &heights, throw_on_cancel] (size_t layer_id)
|
||||
{
|
||||
if ((layer_id % 2) == 0)
|
||||
// Don't call the following function too often as it flushes CPU write caches due to synchronization primitves.
|
||||
throw_on_cancel();
|
||||
SupportPointGenerator::MyLayer &layer_above = layers[layer_id];
|
||||
SupportPointGenerator::MyLayer &layer_below = layers[layer_id - 1];
|
||||
//FIXME WTF?
|
||||
const float layer_height = (layer_id!=0 ? heights[layer_id]-heights[layer_id-1] : heights[0]);
|
||||
const float safe_angle = 5.f * (float(M_PI)/180.f); // smaller number - less supports
|
||||
const float between_layers_offset = float(scale_(layer_height / std::tan(safe_angle)));
|
||||
const float slope_angle = 75.f * (float(M_PI)/180.f); // smaller number - less supports
|
||||
const float slope_offset = float(scale_(layer_height / std::tan(slope_angle)));
|
||||
//FIXME This has a quadratic time complexity, it will be excessively slow for many tiny islands.
|
||||
for (SupportPointGenerator::Structure &top : layer_above.islands) {
|
||||
for (SupportPointGenerator::Structure &bottom : layer_below.islands) {
|
||||
float overlap_area = top.overlap_area(bottom);
|
||||
if (overlap_area > 0) {
|
||||
top.islands_below.emplace_back(&bottom, overlap_area);
|
||||
bottom.islands_above.emplace_back(&top, overlap_area);
|
||||
}
|
||||
}
|
||||
if (! top.islands_below.empty()) {
|
||||
Polygons top_polygons = to_polygons(*top.polygon);
|
||||
Polygons bottom_polygons = top.polygons_below();
|
||||
top.overhangs = diff_ex(top_polygons, bottom_polygons);
|
||||
if (! top.overhangs.empty()) {
|
||||
top.overhangs_area = 0.f;
|
||||
std::vector<std::pair<ExPolygon*, float>> expolys_with_areas;
|
||||
for (ExPolygon &ex : top.overhangs) {
|
||||
float area = float(ex.area());
|
||||
expolys_with_areas.emplace_back(&ex, area);
|
||||
top.overhangs_area += area;
|
||||
}
|
||||
std::sort(expolys_with_areas.begin(), expolys_with_areas.end(),
|
||||
[](const std::pair<ExPolygon*, float> &p1, const std::pair<ExPolygon*, float> &p2)
|
||||
{ return p1.second > p2.second; });
|
||||
ExPolygons overhangs_sorted;
|
||||
for (auto &p : expolys_with_areas)
|
||||
overhangs_sorted.emplace_back(std::move(*p.first));
|
||||
top.overhangs = std::move(overhangs_sorted);
|
||||
top.overhangs_area *= float(SCALING_FACTOR * SCALING_FACTOR);
|
||||
top.overhangs_slopes = diff_ex(top_polygons, offset(bottom_polygons, slope_offset));
|
||||
top.dangling_areas = diff_ex(top_polygons, offset(bottom_polygons, between_layers_offset));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
{ return p1.second > p2.second; });
|
||||
ExPolygons overhangs_sorted;
|
||||
for (auto &p : expolys_with_areas)
|
||||
overhangs_sorted.emplace_back(std::move(*p.first));
|
||||
top.overhangs = std::move(overhangs_sorted);
|
||||
top.overhangs_area *= float(SCALING_FACTOR * SCALING_FACTOR);
|
||||
top.overhangs_slopes = diff_ex(top_polygons, offset(bottom_polygons, slope_offset));
|
||||
top.dangling_areas = diff_ex(top_polygons, offset(bottom_polygons, between_layers_offset));
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 8 /* gransize */);
|
||||
|
||||
return layers;
|
||||
}
|
||||
|
@ -209,14 +209,16 @@ IndexedMesh::hit_result SupportTreeBuildsteps::pinhead_mesh_intersect(
|
||||
// of the pinhead robe (side) surface. The result will be the smallest
|
||||
// hit distance.
|
||||
|
||||
ccr::enumerate(hits.begin(), hits.end(),
|
||||
[&m, &rings, sd](HitResult &hit, size_t i) {
|
||||
ccr::for_each(size_t(0), hits.size(),
|
||||
[&m, &rings, sd, &hits](size_t i) {
|
||||
|
||||
// Point on the circle on the pin sphere
|
||||
Vec3d ps = rings.pinring(i);
|
||||
// This is the point on the circle on the back sphere
|
||||
Vec3d p = rings.backring(i);
|
||||
|
||||
auto &hit = hits[i];
|
||||
|
||||
// Point ps is not on mesh but can be inside or
|
||||
// outside as well. This would cause many problems
|
||||
// with ray-casting. To detect the position we will
|
||||
@ -265,8 +267,10 @@ IndexedMesh::hit_result SupportTreeBuildsteps::bridge_mesh_intersect(
|
||||
// Hit results
|
||||
std::array<Hit, SAMPLES> hits;
|
||||
|
||||
ccr::enumerate(hits.begin(), hits.end(),
|
||||
[this, r, src, /*ins_check,*/ &ring, dir, sd] (Hit &hit, size_t i) {
|
||||
ccr::for_each(size_t(0), hits.size(),
|
||||
[this, r, src, /*ins_check,*/ &ring, dir, sd, &hits] (size_t i)
|
||||
{
|
||||
Hit &hit = hits[i];
|
||||
|
||||
// Point on the circle on the pin sphere
|
||||
Vec3d p = ring.get(i, src, r + sd);
|
||||
@ -744,10 +748,10 @@ void SupportTreeBuildsteps::filter()
|
||||
}
|
||||
};
|
||||
|
||||
ccr::enumerate(filtered_indices.begin(), filtered_indices.end(),
|
||||
[this, &filterfn](unsigned fidx, size_t i) {
|
||||
filterfn(fidx, i, m_cfg.head_back_radius_mm);
|
||||
});
|
||||
ccr::for_each(size_t(0), filtered_indices.size(),
|
||||
[this, &filterfn, &filtered_indices] (size_t i) {
|
||||
filterfn(filtered_indices[i], i, m_cfg.head_back_radius_mm);
|
||||
});
|
||||
|
||||
for (size_t i = 0; i < heads.size(); ++i)
|
||||
if (heads[i].is_valid()) {
|
||||
@ -1033,8 +1037,8 @@ void SupportTreeBuildsteps::routing_to_model()
|
||||
// If it can be routed there with a bridge shorter than
|
||||
// min_bridge_distance.
|
||||
|
||||
ccr::enumerate(m_iheads_onmodel.begin(), m_iheads_onmodel.end(),
|
||||
[this] (const unsigned idx, size_t) {
|
||||
ccr::for_each(m_iheads_onmodel.begin(), m_iheads_onmodel.end(),
|
||||
[this] (const unsigned idx) {
|
||||
m_thr();
|
||||
|
||||
auto& head = m_builder.head(idx);
|
||||
|
@ -374,7 +374,7 @@ protected:
|
||||
std::vector<sla::EncodedRaster> m_layers;
|
||||
|
||||
virtual uqptr<sla::RasterBase> create_raster() const = 0;
|
||||
virtual sla::EncodedRaster encode_raster(const sla::RasterBase &rst) const = 0;
|
||||
virtual sla::RasterEncoder get_encoder() const = 0;
|
||||
|
||||
public:
|
||||
virtual ~SLAPrinter() = default;
|
||||
@ -385,12 +385,13 @@ public:
|
||||
template<class Fn> void draw_layers(size_t layer_num, Fn &&drawfn)
|
||||
{
|
||||
m_layers.resize(layer_num);
|
||||
sla::ccr::enumerate(m_layers.begin(), m_layers.end(),
|
||||
[this, &drawfn](sla::EncodedRaster& enc, size_t idx) {
|
||||
auto rst = create_raster();
|
||||
drawfn(*rst, idx);
|
||||
enc = encode_raster(*rst);
|
||||
});
|
||||
sla::ccr::for_each(size_t(0), m_layers.size(),
|
||||
[this, &drawfn] (size_t idx) {
|
||||
sla::EncodedRaster& enc = m_layers[idx];
|
||||
auto rst = create_raster();
|
||||
drawfn(*rst, idx);
|
||||
enc = rst->encode(get_encoder());
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -264,11 +264,12 @@ void SLAPrint::Steps::slice_model(SLAPrintObject &po)
|
||||
std::vector<ExPolygons> interior_slices;
|
||||
interior_slicer.slice(slice_grid, SlicingMode::Regular, closing_r, &interior_slices, thr);
|
||||
|
||||
sla::ccr::enumerate(interior_slices.begin(), interior_slices.end(),
|
||||
[&po](const ExPolygons &slice, size_t i) {
|
||||
po.m_model_slices[i] =
|
||||
diff_ex(po.m_model_slices[i], slice);
|
||||
});
|
||||
sla::ccr::for_each(size_t(0), interior_slices.size(),
|
||||
[&po, &interior_slices] (size_t i) {
|
||||
const ExPolygons &slice = interior_slices[i];
|
||||
po.m_model_slices[i] =
|
||||
diff_ex(po.m_model_slices[i], slice);
|
||||
});
|
||||
}
|
||||
|
||||
auto mit = slindex_it;
|
||||
@ -679,14 +680,16 @@ void SLAPrint::Steps::merge_slices_and_eval_stats() {
|
||||
using Lock = std::lock_guard<sla::ccr::SpinningMutex>;
|
||||
|
||||
// Going to parallel:
|
||||
auto printlayerfn = [
|
||||
auto printlayerfn = [this,
|
||||
// functions and read only vars
|
||||
areafn, area_fill, display_area, exp_time, init_exp_time, fast_tilt, slow_tilt, delta_fade_time,
|
||||
|
||||
// write vars
|
||||
&mutex, &models_volume, &supports_volume, &estim_time, &slow_layers,
|
||||
&fast_layers, &fade_layer_time](PrintLayer& layer, size_t sliced_layer_cnt)
|
||||
&fast_layers, &fade_layer_time](size_t sliced_layer_cnt)
|
||||
{
|
||||
PrintLayer &layer = m_print->m_printer_input[sliced_layer_cnt];
|
||||
|
||||
// vector of slice record references
|
||||
auto& slicerecord_references = layer.slices();
|
||||
|
||||
@ -789,7 +792,7 @@ void SLAPrint::Steps::merge_slices_and_eval_stats() {
|
||||
|
||||
// sequential version for debugging:
|
||||
// for(size_t i = 0; i < m_printer_input.size(); ++i) printlayerfn(i);
|
||||
sla::ccr::enumerate(printer_input.begin(), printer_input.end(), printlayerfn);
|
||||
sla::ccr::for_each(size_t(0), printer_input.size(), printlayerfn);
|
||||
|
||||
auto SCALING2 = SCALING_FACTOR * SCALING_FACTOR;
|
||||
print_statistics.support_used_material = supports_volume * SCALING2;
|
||||
|
@ -261,6 +261,20 @@ using IntegerOnly = std::enable_if_t<std::is_integral<T>::value, O>;
|
||||
template<class T, class O = T>
|
||||
using ArithmeticOnly = std::enable_if_t<std::is_arithmetic<T>::value, O>;
|
||||
|
||||
template<class T, class O = T>
|
||||
using IteratorOnly = std::enable_if_t<
|
||||
!std::is_same_v<typename std::iterator_traits<T>::value_type, void>, O
|
||||
>;
|
||||
|
||||
template<class T, class I, class... Args> // Arbitrary allocator can be used
|
||||
IntegerOnly<I, std::vector<T, Args...>> reserve_vector(I capacity)
|
||||
{
|
||||
std::vector<T, Args...> ret;
|
||||
if (capacity > I(0)) ret.reserve(size_t(capacity));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif
|
||||
|
@ -715,7 +715,7 @@ void PlaterPresetComboBox::update()
|
||||
|
||||
std::map<wxString, wxBitmap*> nonsys_presets;
|
||||
|
||||
wxString selected = "";
|
||||
wxString selected_user_preset = "";
|
||||
wxString tooltip = "";
|
||||
const std::deque<Preset>& presets = m_collection->get_presets();
|
||||
|
||||
@ -742,7 +742,7 @@ void PlaterPresetComboBox::update()
|
||||
{
|
||||
// Assign an extruder color to the selected item if the extruder color is defined.
|
||||
filament_rgb = preset.config.opt_string("filament_colour", 0);
|
||||
extruder_rgb = (selected && !extruder_color.empty()) ? extruder_color : filament_rgb;
|
||||
extruder_rgb = (is_selected && !extruder_color.empty()) ? extruder_color : filament_rgb;
|
||||
single_bar = filament_rgb == extruder_rgb;
|
||||
|
||||
bitmap_key += single_bar ? filament_rgb : filament_rgb + extruder_rgb;
|
||||
@ -764,7 +764,7 @@ void PlaterPresetComboBox::update()
|
||||
{
|
||||
nonsys_presets.emplace(wxString::FromUTF8((name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()), bmp);
|
||||
if (is_selected) {
|
||||
selected = wxString::FromUTF8((name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str());
|
||||
selected_user_preset = wxString::FromUTF8((name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str());
|
||||
tooltip = wxString::FromUTF8(preset.name.c_str());
|
||||
}
|
||||
}
|
||||
@ -776,7 +776,7 @@ void PlaterPresetComboBox::update()
|
||||
set_label_marker(Append(separator(L("User presets")), wxNullBitmap));
|
||||
for (std::map<wxString, wxBitmap*>::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) {
|
||||
Append(it->first, *it->second);
|
||||
validate_selection(it->first == selected);
|
||||
validate_selection(it->first == selected_user_preset);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1173,7 +1173,13 @@ void SavePresetDialog::Item::accept()
|
||||
SavePresetDialog::SavePresetDialog(Preset::Type type, const std::string& suffix)
|
||||
: DPIDialog(nullptr, wxID_ANY, _L("Save preset"), wxDefaultPosition, wxSize(45 * wxGetApp().em_unit(), 5 * wxGetApp().em_unit()), wxDEFAULT_DIALOG_STYLE | wxICON_WARNING | wxRESIZE_BORDER)
|
||||
{
|
||||
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
||||
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
||||
#if ENABLE_WX_3_1_3_DPI_CHANGED_EVENT
|
||||
// ys_FIXME! temporary workaround for correct font scaling
|
||||
// Because of from wxWidgets 3.1.3 auto rescaling is implemented for the Fonts,
|
||||
// From the very beginning set dialog font to the wxSYS_DEFAULT_GUI_FONT
|
||||
this->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
|
||||
#endif // ENABLE_WX_3_1_3_DPI_CHANGED_EVENT
|
||||
|
||||
wxBoxSizer* topSizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
|
@ -3995,9 +3995,16 @@ void TabSLAPrint::build()
|
||||
optgroup->append_single_option_line("support_base_safety_distance");
|
||||
|
||||
// Mirrored parameter from Pad page for toggling elevation on the same page
|
||||
optgroup->append_single_option_line("pad_around_object");
|
||||
// optgroup->append_single_option_line("pad_around_object");
|
||||
optgroup->append_single_option_line("support_object_elevation");
|
||||
|
||||
Line line{ "", "" };
|
||||
line.full_width = 1;
|
||||
line.widget = [this](wxWindow* parent) {
|
||||
return description_line_widget(parent, &m_support_object_elevation_description_line);
|
||||
};
|
||||
optgroup->append_line(line);
|
||||
|
||||
optgroup = page->new_optgroup(L("Connection of the support sticks and junctions"));
|
||||
optgroup->append_single_option_line("support_critical_angle");
|
||||
optgroup->append_single_option_line("support_max_bridge_length");
|
||||
@ -4071,6 +4078,14 @@ void TabSLAPrint::update()
|
||||
m_update_cnt++;
|
||||
|
||||
m_config_manipulation.update_print_sla_config(m_config, true);
|
||||
|
||||
bool elev = !m_config->opt_bool("pad_enable") || !m_config->opt_bool("pad_around_object");
|
||||
m_support_object_elevation_description_line->SetText(elev ? "" :
|
||||
from_u8((boost::format(_u8L("\"%1%\" is disabled because \"%2%\" is on in \"%3%\" category.\n"
|
||||
"To enable \"%1%\", please switch off \"%2%\""))
|
||||
% _L("Object elevation") % _L("Pad around object") % _L("Pad")).str()));
|
||||
Layout();
|
||||
|
||||
m_update_cnt--;
|
||||
|
||||
if (m_update_cnt == 0) {
|
||||
|
@ -461,6 +461,9 @@ public:
|
||||
// Tab(parent, _(L("Print Settings")), L("sla_print")) {}
|
||||
Tab(parent, _(L("Print Settings")), Slic3r::Preset::TYPE_SLA_PRINT) {}
|
||||
~TabSLAPrint() {}
|
||||
|
||||
ogStaticText* m_support_object_elevation_description_line = nullptr;
|
||||
|
||||
void build() override;
|
||||
void reload_config() override;
|
||||
void update() override;
|
||||
|
Loading…
Reference in New Issue
Block a user