Refactoring and commenting slice index solution.
This commit is contained in:
parent
5abf64e1d2
commit
d73d9309f1
@ -624,7 +624,7 @@ void SLAPrint::process()
|
||||
double ilhd = m_material_config.initial_layer_height.getFloat();
|
||||
auto ilh = float(ilhd);
|
||||
|
||||
auto ilhs = LevelID(ilhd / SCALING_FACTOR);
|
||||
auto ilhs = coord_t(ilhd / SCALING_FACTOR);
|
||||
const size_t objcount = m_objects.size();
|
||||
|
||||
const unsigned min_objstatus = 0; // where the per object operations start
|
||||
@ -652,24 +652,27 @@ void SLAPrint::process()
|
||||
|
||||
double lhd = m_objects.front()->m_config.layer_height.getFloat();
|
||||
float lh = float(lhd);
|
||||
auto lhs = LevelID(lhd / SCALING_FACTOR);
|
||||
auto lhs = coord_t(lhd / SCALING_FACTOR);
|
||||
|
||||
auto&& bb3d = mesh.bounding_box();
|
||||
double minZ = bb3d.min(Z) - po.get_elevation();
|
||||
double maxZ = bb3d.max(Z);
|
||||
|
||||
auto minZs = LevelID(minZ / SCALING_FACTOR);
|
||||
auto maxZs = LevelID(maxZ / SCALING_FACTOR);
|
||||
auto minZs = coord_t(minZ / SCALING_FACTOR);
|
||||
auto maxZs = coord_t(maxZ / SCALING_FACTOR);
|
||||
|
||||
po.m_slice_index.clear();
|
||||
po.m_slice_index.reserve(size_t(maxZs - (minZs + ilhs) / lhs) + 1);
|
||||
po.m_slice_index.emplace_back(minZs + ilhs, float(minZ) + ilh / 2.f, ilh);
|
||||
|
||||
for(LevelID h = minZs + ilhs + lhs; h <= maxZs; h += lhs) {
|
||||
for(coord_t h = minZs + ilhs + lhs; h <= maxZs; h += lhs) {
|
||||
po.m_slice_index.emplace_back(h, float(h*SCALING_FACTOR) - lh / 2.f, lh);
|
||||
}
|
||||
|
||||
auto slindex_it = po.search_slice_index(float(bb3d.min(Z)));
|
||||
// Just get the first record that is form the model:
|
||||
auto slindex_it = po.closest_slice_record(
|
||||
po.m_slice_index, float(bb3d.min(Z)),
|
||||
std::numeric_limits<float>::infinity());
|
||||
|
||||
if(slindex_it == po.m_slice_index.end())
|
||||
throw std::runtime_error(L("Slicing had to be stopped "
|
||||
@ -908,33 +911,46 @@ void SLAPrint::process()
|
||||
|
||||
// clear the rasterizer input
|
||||
m_printer_input.clear();
|
||||
auto eps = LevelID(EPSILON / SCALING_FACTOR);
|
||||
|
||||
size_t mx = 0;
|
||||
for(SLAPrintObject * o : m_objects) {
|
||||
if(auto m = o->get_slice_index().size() > mx) mx = m;
|
||||
}
|
||||
|
||||
m_printer_input.reserve(mx);
|
||||
|
||||
auto eps = coord_t(SCALED_EPSILON);
|
||||
|
||||
for(SLAPrintObject * o : m_objects) {
|
||||
LevelID gndlvl = o->get_slice_index().front().key() - ilhs;
|
||||
coord_t gndlvl = o->get_slice_index().front().print_level() - ilhs;
|
||||
|
||||
for(auto& slicerecord : o->get_slice_index()) {
|
||||
LevelID lvlid = slicerecord.key() - gndlvl;
|
||||
coord_t lvlid = slicerecord.print_level() - gndlvl;
|
||||
|
||||
// Neat trick to round the layer levels to the grid.
|
||||
lvlid = eps * (lvlid / eps);
|
||||
|
||||
auto& lyrs = m_printer_input[slicerecord.key() - gndlvl];
|
||||
auto it = std::lower_bound(m_printer_input.begin(),
|
||||
m_printer_input.end(),
|
||||
LayerRefs(lvlid));
|
||||
|
||||
if(it == m_printer_input.end() || it->level != lvlid)
|
||||
it = m_printer_input.insert(it, LayerRefs(lvlid));
|
||||
|
||||
auto& lyrs = *it;
|
||||
|
||||
const ExPolygons& objslices = o->get_slices_from_record(slicerecord, soModel);
|
||||
const ExPolygons& supslices = o->get_slices_from_record(slicerecord, soSupport);
|
||||
|
||||
if(!objslices.empty())
|
||||
lyrs.emplace_back(objslices, o->instances());
|
||||
lyrs.refs.emplace_back(objslices, o->instances());
|
||||
|
||||
if(!supslices.empty())
|
||||
lyrs.emplace_back(supslices, o->instances());
|
||||
lyrs.refs.emplace_back(supslices, o->instances());
|
||||
}
|
||||
}
|
||||
|
||||
// collect all the keys
|
||||
std::vector<long long> keys; keys.reserve(m_printer_input.size());
|
||||
for(auto& e : m_printer_input) keys.emplace_back(e.first);
|
||||
|
||||
// If the raster has vertical orientation, we will flip the coordinates
|
||||
bool flpXY = m_printer_config.display_orientation.getInt() ==
|
||||
@ -977,17 +993,17 @@ void SLAPrint::process()
|
||||
|
||||
// procedure to process one height level. This will run in parallel
|
||||
auto lvlfn =
|
||||
[this, &slck, &keys, &printer, slot, sd, ist, &pst, flpXY]
|
||||
[this, &slck, &printer, slot, sd, ist, &pst, flpXY]
|
||||
(unsigned level_id)
|
||||
{
|
||||
if(canceled()) return;
|
||||
|
||||
LayerRefs& lrange = m_printer_input[keys[level_id]];
|
||||
LayerRefs& lrange = m_printer_input[level_id];
|
||||
|
||||
// Switch to the appropriate layer in the printer
|
||||
printer.begin_layer(level_id);
|
||||
|
||||
for(auto& lyrref : lrange) { // for all layers in the current level
|
||||
for(auto& lyrref : lrange.refs) { // for all layers in the current level
|
||||
if(canceled()) break;
|
||||
const Layer& sl = lyrref.lref; // get the layer reference
|
||||
const LayerCopies& copies = lyrref.copies;
|
||||
@ -1235,7 +1251,7 @@ void SLAPrint::fill_statistics()
|
||||
size_t max_layers_cnt = 0;
|
||||
size_t highest_obj_idx = 0;
|
||||
for (SLAPrintObject *&po : m_objects) {
|
||||
const SLAPrintObject::SliceIndex& slice_index = po->get_slice_index();
|
||||
auto& slice_index = po->get_slice_index();
|
||||
if (! slice_index.empty()) {
|
||||
float z = (-- slice_index.end())->slice_level();
|
||||
size_t cnt = slice_index.size();
|
||||
@ -1249,7 +1265,7 @@ void SLAPrint::fill_statistics()
|
||||
}
|
||||
|
||||
const SLAPrintObject * highest_obj = m_objects[highest_obj_idx];
|
||||
const SLAPrintObject::SliceIndex& highest_obj_slice_index = highest_obj->get_slice_index();
|
||||
auto& highest_obj_slice_index = highest_obj->get_slice_index();
|
||||
|
||||
const double delta_fade_time = (init_exp_time - exp_time) / (fade_layers_cnt + 1);
|
||||
double fade_layer_time = init_exp_time;
|
||||
@ -1257,7 +1273,7 @@ void SLAPrint::fill_statistics()
|
||||
int sliced_layer_cnt = 0;
|
||||
for (const auto& layer : highest_obj_slice_index)
|
||||
{
|
||||
const double l_height = (layer.key() == highest_obj_slice_index.begin()->key()) ? init_layer_height : layer_height;
|
||||
const double l_height = (layer.print_level() == highest_obj_slice_index.begin()->print_level()) ? init_layer_height : layer_height;
|
||||
|
||||
// Calculation of the consumed material
|
||||
|
||||
@ -1266,13 +1282,12 @@ void SLAPrint::fill_statistics()
|
||||
|
||||
for (SLAPrintObject * po : m_objects)
|
||||
{
|
||||
const SLAPrintObject::_SliceRecord *record = nullptr;
|
||||
const SliceRecord *record = nullptr;
|
||||
{
|
||||
const SLAPrintObject::SliceIndex& index = po->get_slice_index();
|
||||
auto it = po->search_slice_index(layer.slice_level() - float(EPSILON));
|
||||
if (it == index.end() || it->slice_level() > layer.slice_level() + float(EPSILON))
|
||||
const SliceRecord& slr = po->closest_slice_to_slice_level(layer.slice_level(), float(EPSILON));
|
||||
if (!slr.is_valid())
|
||||
continue;
|
||||
record = &(*it);
|
||||
record = &slr;
|
||||
}
|
||||
|
||||
const ExPolygons &modelslices = po->get_slices_from_record(*record, soModel);
|
||||
@ -1486,77 +1501,13 @@ const TriangleMesh EMPTY_MESH;
|
||||
const ExPolygons EMPTY_SLICE;
|
||||
}
|
||||
|
||||
const SliceRecord SliceRecord::EMPTY(0, std::nanf(""), 0.f);
|
||||
|
||||
const std::vector<sla::SupportPoint>& SLAPrintObject::get_support_points() const
|
||||
{
|
||||
return m_supportdata->support_points;
|
||||
}
|
||||
|
||||
SLAPrintObject::SliceIndex::iterator
|
||||
SLAPrintObject::search_slice_index(float slice_level)
|
||||
{
|
||||
_SliceRecord query(0, slice_level, 0);
|
||||
auto it = std::lower_bound(m_slice_index.begin(), m_slice_index.end(),
|
||||
query,
|
||||
[](const _SliceRecord& r1, const _SliceRecord& r2)
|
||||
{
|
||||
return r1.slice_level() < r2.slice_level();
|
||||
});
|
||||
|
||||
return it;
|
||||
}
|
||||
|
||||
SLAPrintObject::SliceIndex::const_iterator
|
||||
SLAPrintObject::search_slice_index(float slice_level) const
|
||||
{
|
||||
_SliceRecord query(0, slice_level, 0);
|
||||
auto it = std::lower_bound(m_slice_index.cbegin(), m_slice_index.cend(),
|
||||
query,
|
||||
[](const _SliceRecord& r1, const _SliceRecord& r2)
|
||||
{
|
||||
return r1.slice_level() < r2.slice_level();
|
||||
});
|
||||
|
||||
return it;
|
||||
}
|
||||
|
||||
SLAPrintObject::SliceIndex::iterator
|
||||
SLAPrintObject::search_slice_index(SLAPrintObject::_SliceRecord::Key key,
|
||||
bool exact)
|
||||
{
|
||||
_SliceRecord query(key, 0.f, 0.f);
|
||||
auto it = std::lower_bound(m_slice_index.begin(), m_slice_index.end(),
|
||||
query,
|
||||
[](const _SliceRecord& r1, const _SliceRecord& r2)
|
||||
{
|
||||
return r1.key() < r2.key();
|
||||
});
|
||||
|
||||
// Return valid iterator only if the keys really match
|
||||
if(exact && it != m_slice_index.end() && it->key() != key)
|
||||
it = m_slice_index.end();
|
||||
|
||||
return it;
|
||||
}
|
||||
|
||||
SLAPrintObject::SliceIndex::const_iterator
|
||||
SLAPrintObject::search_slice_index(SLAPrintObject::_SliceRecord::Key key,
|
||||
bool exact) const
|
||||
{
|
||||
_SliceRecord query(key, 0.f, 0.f);
|
||||
auto it = std::lower_bound(m_slice_index.cbegin(), m_slice_index.cend(),
|
||||
query,
|
||||
[](const _SliceRecord& r1, const _SliceRecord& r2)
|
||||
{
|
||||
return r1.key() < r2.key();
|
||||
});
|
||||
|
||||
// Return valid iterator only if the keys really match
|
||||
if(exact && it != m_slice_index.end() && it->key() != key)
|
||||
it = m_slice_index.end();
|
||||
|
||||
return it;
|
||||
}
|
||||
|
||||
const std::vector<ExPolygons> &SLAPrintObject::get_support_slices() const
|
||||
{
|
||||
// assert(is_step_done(slaposSliceSupports));
|
||||
@ -1565,7 +1516,7 @@ const std::vector<ExPolygons> &SLAPrintObject::get_support_slices() const
|
||||
}
|
||||
|
||||
const ExPolygons &SLAPrintObject::get_slices_from_record(
|
||||
const _SliceRecord &rec,
|
||||
const SliceRecord &rec,
|
||||
SliceOrigin o) const
|
||||
{
|
||||
size_t idx = o == soModel ? rec.get_model_slice_idx() :
|
||||
@ -1579,15 +1530,7 @@ const ExPolygons &SLAPrintObject::get_slices_from_record(
|
||||
return idx >= v.size() ? EMPTY_SLICE : v[idx];
|
||||
}
|
||||
|
||||
const ExPolygons &SLAPrintObject::get_slices_from_record(
|
||||
SLAPrintObject::SliceRecordConstIterator it, SliceOrigin o) const
|
||||
{
|
||||
if(it.is_end()) return EMPTY_SLICE;
|
||||
return get_slices_from_record(*it, o);
|
||||
}
|
||||
|
||||
const std::vector<SLAPrintObject::_SliceRecord>&
|
||||
SLAPrintObject::get_slice_index() const
|
||||
const std::vector<SliceRecord> & SLAPrintObject::get_slice_index() const
|
||||
{
|
||||
// assert(is_step_done(slaposIndexSlices));
|
||||
return m_slice_index;
|
||||
|
@ -34,10 +34,68 @@ using _SLAPrintObjectBase =
|
||||
|
||||
// Layers according to quantized height levels. This will be consumed by
|
||||
// the printer (rasterizer) in the SLAPrint class.
|
||||
using LevelID = long long;
|
||||
// using coord_t = long long;
|
||||
|
||||
enum SliceOrigin { soSupport, soModel };
|
||||
|
||||
// The public Slice record structure. It corresponds to one printable layer.
|
||||
// To get the sliced polygons, use SLAPrintObject::get_slices_from_record
|
||||
class SliceRecord {
|
||||
public:
|
||||
// this will be the max limit of size_t
|
||||
static const size_t NONE = size_t(-1);
|
||||
|
||||
static const SliceRecord EMPTY;
|
||||
|
||||
private:
|
||||
coord_t m_print_z = 0; // Top of the layer
|
||||
float m_slice_z = 0.f; // Exact level of the slice
|
||||
float m_height = 0.f; // Height of the sliced layer
|
||||
|
||||
size_t m_model_slices_idx = NONE;
|
||||
size_t m_support_slices_idx = NONE;
|
||||
|
||||
public:
|
||||
|
||||
SliceRecord(coord_t key, float slicez, float height):
|
||||
m_print_z(key), m_slice_z(slicez), m_height(height) {}
|
||||
|
||||
// The key will be the integer height level of the top of the layer.
|
||||
inline coord_t print_level() const { return m_print_z; }
|
||||
|
||||
// Returns the exact floating point Z coordinate of the slice
|
||||
inline float slice_level() const { return m_slice_z; }
|
||||
|
||||
// Returns the current layer height
|
||||
inline float layer_height() const { return m_height; }
|
||||
|
||||
bool is_valid() const { return std::isnan(m_slice_z); }
|
||||
|
||||
template <class T> inline T level() const {
|
||||
static_assert(std::is_integral<T>::value ||
|
||||
std::is_floating_point<T>::value,
|
||||
"Slice record level is only valid for numeric types!");
|
||||
if (std::is_integral<T>::value) return T(print_level());
|
||||
else return T(slice_level());
|
||||
}
|
||||
|
||||
template <class T> inline static SliceRecord create(T val) {
|
||||
static_assert(std::is_integral<T>::value ||
|
||||
std::is_floating_point<T>::value,
|
||||
"Slice record level is only valid for numeric types!");
|
||||
if (std::is_integral<T>::value) return { coord_t(val), 0.f, 0.f };
|
||||
else return { 0, float(val), 0.f };
|
||||
}
|
||||
|
||||
// Methods for setting the indices into the slice vectors.
|
||||
void set_model_slice_idx(size_t id) { m_model_slices_idx = id; }
|
||||
void set_support_slice_idx(size_t id) { m_support_slices_idx = id; }
|
||||
|
||||
inline size_t get_model_slice_idx() const { return m_model_slices_idx; }
|
||||
inline size_t get_support_slice_idx() const { return m_support_slices_idx; }
|
||||
};
|
||||
|
||||
|
||||
class SLAPrintObject : public _SLAPrintObjectBase
|
||||
{
|
||||
private: // Prevents erroneous use by other classes.
|
||||
@ -93,145 +151,84 @@ public:
|
||||
// This method returns the support points of this SLAPrintObject.
|
||||
const std::vector<sla::SupportPoint>& get_support_points() const;
|
||||
|
||||
// The public Slice record structure. It corresponds to one printable layer.
|
||||
// To get the sliced polygons, use SLAPrintObject::get_slices_from_record
|
||||
class SliceRecord {
|
||||
public:
|
||||
using Key = LevelID;
|
||||
|
||||
private:
|
||||
Key m_print_z = 0; // Top of the layer
|
||||
float m_slice_z = 0.f; // Exact level of the slice
|
||||
float m_height = 0.f; // Height of the sliced layer
|
||||
|
||||
protected:
|
||||
SliceRecord(Key key, float slicez, float height):
|
||||
m_print_z(key), m_slice_z(slicez), m_height(height) {}
|
||||
|
||||
public:
|
||||
|
||||
// The key will be the integer height level of the top of the layer.
|
||||
inline Key key() const { return m_print_z; }
|
||||
|
||||
// Returns the exact floating point Z coordinate of the slice
|
||||
inline float slice_level() const { return m_slice_z; }
|
||||
|
||||
// Returns the current layer height
|
||||
inline float layer_height() const { return m_height; }
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
// An index record referencing the slices
|
||||
// (get_model_slices(), get_support_slices()) where the keys are the height
|
||||
// levels of the model in scaled-clipper coordinates. The levels correspond
|
||||
// to the z coordinate of the object coordinate system.
|
||||
class _SliceRecord: public SliceRecord {
|
||||
public:
|
||||
static const size_t NONE = size_t(-1); // this will be the max limit of size_t
|
||||
private:
|
||||
size_t m_model_slices_idx = NONE;
|
||||
size_t m_support_slices_idx = NONE;
|
||||
// This is a template method for searching the slice index either by
|
||||
// an integer key: print_level or a floating point key: slice_level.
|
||||
// The eps parameter gives the max deviation in + or - direction.
|
||||
//
|
||||
// This method can be used in const or non-const contexts as well.
|
||||
template<class Container, class T>
|
||||
static auto closest_slice_record(Container& cont, T lvl, T eps) -> decltype (cont.begin())
|
||||
{
|
||||
if(cont.empty()) return cont.end();
|
||||
if(cont.size() == 1 && std::abs(cont.front().template level<T>() - lvl) > eps)
|
||||
return cont.end();
|
||||
|
||||
public:
|
||||
_SliceRecord(Key key, float slicez, float height):
|
||||
SliceRecord(key, slicez, height) {}
|
||||
SliceRecord query = SliceRecord::create(lvl);
|
||||
|
||||
// Methods for setting the indices into the slice vectors.
|
||||
void set_model_slice_idx(size_t id) { m_model_slices_idx = id; }
|
||||
void set_support_slice_idx(size_t id) { m_support_slices_idx = id; }
|
||||
auto it = std::lower_bound(cont.begin(), cont.end(), query,
|
||||
[](const SliceRecord& r1,
|
||||
const SliceRecord& r2)
|
||||
{
|
||||
return r1.level<T>() < r2.level<T>();
|
||||
});
|
||||
|
||||
inline size_t get_model_slice_idx() const { return m_model_slices_idx; }
|
||||
inline size_t get_support_slice_idx() const { return m_support_slices_idx; }
|
||||
};
|
||||
T diff = std::abs(it->template level<T>() - lvl);
|
||||
|
||||
// Slice index will be a plain vector sorted by the integer height levels
|
||||
using SliceIndex = std::vector<_SliceRecord>;
|
||||
if(it != cont.begin()) {
|
||||
auto it_prev = std::prev(it);
|
||||
T diff_prev = std::abs(it_prev->template level<T>() - lvl);
|
||||
if(diff_prev < diff) { diff = diff_prev; it = it_prev; }
|
||||
}
|
||||
|
||||
// Retrieve the slice index which is readable only after slaposIndexSlices
|
||||
// is done.
|
||||
const SliceIndex& get_slice_index() const;
|
||||
if(diff > eps) it = cont.end();
|
||||
|
||||
// Search slice index for the closest slice to the given level
|
||||
SliceIndex::iterator search_slice_index(float slice_level);
|
||||
SliceIndex::const_iterator search_slice_index(float slice_level) const;
|
||||
|
||||
// Search the slice index for a particular level in integer coordinates.
|
||||
// If no such layer is present, it will return m_slice_index.end()
|
||||
// This behavior can be suppressed by the second parameter. If it is false
|
||||
// the method will return the closest (non-equal) record
|
||||
SliceIndex::iterator search_slice_index(_SliceRecord::Key key, bool exact = false);
|
||||
SliceIndex::const_iterator search_slice_index(_SliceRecord::Key key, bool = false) const;
|
||||
|
||||
const std::vector<ExPolygons>& get_model_slices() const;
|
||||
const std::vector<ExPolygons>& get_support_slices() const;
|
||||
return it;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// Should work as a polymorphic bidirectional iterator to the slice records
|
||||
using SliceRecordConstIterator =
|
||||
IndexBasedIterator<const SliceIndex, const _SliceRecord>;
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// These two methods should be callable on the client side (e.g. UI thread)
|
||||
// These methods should be callable on the client side (e.g. UI thread)
|
||||
// when the appropriate steps slaposObjectSlice and slaposSliceSupports
|
||||
// are ready. All the print objects are processed before slapsRasterize so
|
||||
// it is safe to call them during and/or after slapsRasterize.
|
||||
//
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Get the slice records from a range of slice levels (inclusive). Floating
|
||||
// point keys are the levels where the model was sliced with the mesh
|
||||
// slicer. Integral keys are the keys of the slice records, which
|
||||
// correspond to the top of each layer.. The end() method of the returned
|
||||
// range points *after* the last valid element. This is for being
|
||||
// consistent with std and makeing range based for loops work. use
|
||||
// std::prev(range.end()) or --range.end() to get the last element.
|
||||
template<class Key> Range<SliceRecordConstIterator>
|
||||
get_slice_records(Key from, Key to = std::numeric_limits<Key>::max()) const
|
||||
// Retrieve the slice index.
|
||||
const std::vector<SliceRecord>& get_slice_index() const;
|
||||
|
||||
const std::vector<ExPolygons>& get_model_slices() const;
|
||||
const std::vector<ExPolygons>& get_support_slices() const;
|
||||
|
||||
// Search slice index for the closest slice to given print_level.
|
||||
// max_epsilon gives the allowable deviation of the returned slice record's
|
||||
// level.
|
||||
const SliceRecord& closest_slice_to_print_level(
|
||||
coord_t print_level, coord_t max_epsilon = coord_t(SCALED_EPSILON)) const
|
||||
{
|
||||
static_assert (std::is_integral<Key>::value ||
|
||||
std::is_floating_point<Key>::value,
|
||||
"Only floating point or integral types are allowed.");
|
||||
|
||||
SliceIndex::const_iterator it_from, it_to;
|
||||
|
||||
if(std::is_integral<Key>::value) {
|
||||
it_from = search_slice_index(SliceRecord::Key(from));
|
||||
it_to = search_slice_index(SliceRecord::Key(to));
|
||||
} else if(std::is_floating_point<Key>::value) {
|
||||
it_from = search_slice_index(float(from));
|
||||
it_to = search_slice_index(float(to));
|
||||
}
|
||||
|
||||
auto start = m_slice_index.begin();
|
||||
|
||||
size_t bidx = it_from == m_slice_index.end() ? _SliceRecord::NONE :
|
||||
size_t(it_from - start);
|
||||
|
||||
size_t eidx = it_to == m_slice_index.end() ? _SliceRecord::NONE :
|
||||
size_t(it_to - start) + 1;
|
||||
|
||||
return {
|
||||
SliceRecordConstIterator(m_slice_index, bidx),
|
||||
SliceRecordConstIterator(m_slice_index, eidx),
|
||||
};
|
||||
auto it = closest_slice_record(m_slice_index, print_level, max_epsilon);
|
||||
if (it == m_slice_index.end()) return SliceRecord::EMPTY;
|
||||
return *it;
|
||||
}
|
||||
|
||||
// Get all the slice records as a range.
|
||||
inline Range<SliceRecordConstIterator> get_slice_records() const {
|
||||
return {
|
||||
SliceRecordConstIterator(m_slice_index, 0),
|
||||
SliceRecordConstIterator(m_slice_index, m_slice_index.size())
|
||||
};
|
||||
// Search slice index for the closest slice to given slice_level.
|
||||
// max_epsilon gives the allowable deviation of the returned slice record's
|
||||
// level.
|
||||
const SliceRecord& closest_slice_to_slice_level(
|
||||
float slice_level, float max_epsilon = float(EPSILON)) const
|
||||
{
|
||||
auto it = closest_slice_record(m_slice_index, slice_level, max_epsilon);
|
||||
if (it == m_slice_index.end()) return SliceRecord::EMPTY;
|
||||
return *it;
|
||||
}
|
||||
|
||||
const ExPolygons& get_slices_from_record(SliceRecordConstIterator it,
|
||||
SliceOrigin o) const;
|
||||
|
||||
const ExPolygons& get_slices_from_record(const _SliceRecord& rec,
|
||||
SliceOrigin o) const;
|
||||
// Get the actual slice polygons using a valid slice record.
|
||||
const ExPolygons& get_slices_from_record(
|
||||
const SliceRecord& rec, SliceOrigin o) const;
|
||||
protected:
|
||||
// to be called from SLAPrint only.
|
||||
friend class SLAPrint;
|
||||
@ -272,7 +269,7 @@ private:
|
||||
|
||||
// Exact (float) height levels mapped to the slices. Each record contains
|
||||
// the index to the model and the support slice vectors.
|
||||
std::vector<_SliceRecord> m_slice_index;
|
||||
std::vector<SliceRecord> m_slice_index;
|
||||
|
||||
std::vector<float> m_model_height_levels;
|
||||
|
||||
@ -395,8 +392,14 @@ private:
|
||||
|
||||
// One level may contain multiple slices from multiple objects and their
|
||||
// supports
|
||||
using LayerRefs = std::vector<LayerRef>;
|
||||
std::map<LevelID, LayerRefs> m_printer_input;
|
||||
struct LayerRefs {
|
||||
coord_t level;
|
||||
std::vector<LayerRef> refs;
|
||||
bool operator<(const LayerRefs& other) const { return level < other.level; }
|
||||
explicit LayerRefs(coord_t lvl) : level(lvl) {}
|
||||
};
|
||||
|
||||
std::vector<LayerRefs> m_printer_input;
|
||||
|
||||
// The printer itself
|
||||
SLAPrinterPtr m_printer;
|
||||
|
@ -5009,19 +5009,20 @@ void GLCanvas3D::_render_sla_slices() const
|
||||
instance_transforms.push_back({ to_3d(unscale(inst.shift), 0.), Geometry::rad2deg(inst.rotation) });
|
||||
}
|
||||
|
||||
if ((bottom_obj_triangles.empty() || bottom_sup_triangles.empty() || top_obj_triangles.empty() || top_sup_triangles.empty()) && obj->is_step_done(slaposIndexSlices))
|
||||
if ((bottom_obj_triangles.empty() || bottom_sup_triangles.empty() || top_obj_triangles.empty() || top_sup_triangles.empty()) &&
|
||||
obj->is_step_done(slaposIndexSlices) && !obj->get_slice_index().empty())
|
||||
{
|
||||
double initial_layer_height = print->material_config().initial_layer_height.value;
|
||||
LevelID key_zero = obj->get_slice_records().begin()->key();
|
||||
LevelID key_low = LevelID((clip_min_z - initial_layer_height) / SCALING_FACTOR) + key_zero;
|
||||
LevelID key_high = LevelID((clip_max_z - initial_layer_height) / SCALING_FACTOR) + key_zero;
|
||||
auto slice_range = obj->get_slice_records(key_low - LevelID(SCALED_EPSILON), key_high - LevelID(SCALED_EPSILON));
|
||||
auto it_low = slice_range.begin();
|
||||
auto it_high = std::prev(slice_range.end());
|
||||
coord_t key_zero = obj->get_slice_index().front().print_level();
|
||||
coord_t key_low = coord_t((clip_min_z - initial_layer_height) / SCALING_FACTOR) + key_zero;
|
||||
coord_t key_high = coord_t((clip_max_z - initial_layer_height) / SCALING_FACTOR) + key_zero;
|
||||
|
||||
SliceRecord slice_low = obj->closest_slice_to_print_level(key_low, coord_t(SCALED_EPSILON));
|
||||
SliceRecord slice_high = obj->closest_slice_to_print_level(key_high, coord_t(SCALED_EPSILON));
|
||||
|
||||
if (! it_low.is_end() && it_low->key() < key_low + LevelID(SCALED_EPSILON)) {
|
||||
const ExPolygons& obj_bottom = obj->get_slices_from_record(it_low, soModel);
|
||||
const ExPolygons& sup_bottom = obj->get_slices_from_record(it_low, soSupport);
|
||||
if (! slice_low.is_valid()) {
|
||||
const ExPolygons& obj_bottom = obj->get_slices_from_record(slice_low, soModel);
|
||||
const ExPolygons& sup_bottom = obj->get_slices_from_record(slice_low, soSupport);
|
||||
// calculate model bottom cap
|
||||
if (bottom_obj_triangles.empty() && !obj_bottom.empty())
|
||||
bottom_obj_triangles = triangulate_expolygons_3d(obj_bottom, clip_min_z, true);
|
||||
@ -5030,9 +5031,9 @@ void GLCanvas3D::_render_sla_slices() const
|
||||
bottom_sup_triangles = triangulate_expolygons_3d(sup_bottom, clip_min_z, true);
|
||||
}
|
||||
|
||||
if (! it_high.is_end() && it_high->key() < key_high + LevelID(SCALED_EPSILON)) {
|
||||
const ExPolygons& obj_top = obj->get_slices_from_record(it_high, soModel);
|
||||
const ExPolygons& sup_top = obj->get_slices_from_record(it_high, soSupport);
|
||||
if (! slice_high.is_valid()) {
|
||||
const ExPolygons& obj_top = obj->get_slices_from_record(slice_high, soModel);
|
||||
const ExPolygons& sup_top = obj->get_slices_from_record(slice_high, soSupport);
|
||||
// calculate model top cap
|
||||
if (top_obj_triangles.empty() && !obj_top.empty())
|
||||
top_obj_triangles = triangulate_expolygons_3d(obj_top, clip_max_z, false);
|
||||
|
@ -772,12 +772,11 @@ void Preview::load_print_as_sla()
|
||||
std::vector<double> zs;
|
||||
double initial_layer_height = print->material_config().initial_layer_height.value;
|
||||
for (const SLAPrintObject* obj : print->objects())
|
||||
if (obj->is_step_done(slaposIndexSlices))
|
||||
if (obj->is_step_done(slaposIndexSlices) && !obj->get_slice_index().empty())
|
||||
{
|
||||
auto slicerecords = obj->get_slice_records();
|
||||
auto low_coord = slicerecords.begin()->key();
|
||||
for (auto& rec : slicerecords)
|
||||
zs.emplace_back(initial_layer_height + (rec.key() - low_coord) * SCALING_FACTOR);
|
||||
auto low_coord = obj->get_slice_index().front().print_level();
|
||||
for (auto& rec : obj->get_slice_index())
|
||||
zs.emplace_back(initial_layer_height + (rec.print_level() - low_coord) * SCALING_FACTOR);
|
||||
}
|
||||
sort_remove_duplicates(zs);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user