Merge branch 'et_sequential' of https://github.com/Prusa-Development/PrusaSlicerPrivate into et_sequential
This commit is contained in:
commit
295dd0dfda
@ -871,7 +871,7 @@ template<class P> auto rcend(const P& p) -> decltype(_backward(cbegin(p)))
|
||||
|
||||
template<class P> TPoint<P> front(const P& p) { return *shapelike::cbegin(p); }
|
||||
template<class P> TPoint<P> back (const P& p) {
|
||||
return *backward(shapelike::cend(p));
|
||||
return *std::prev(shapelike::cend(p));
|
||||
}
|
||||
|
||||
// Optional, does nothing by default
|
||||
|
@ -157,26 +157,34 @@ template<class RawShape> class EdgeCache {
|
||||
|
||||
void createCache(const RawShape& sh) {
|
||||
{ // For the contour
|
||||
auto first = shapelike::cbegin(sh);
|
||||
auto next = std::next(first);
|
||||
auto endit = shapelike::cend(sh);
|
||||
auto first = sl::cbegin(sh);
|
||||
auto endit = sl::cend(sh);
|
||||
auto next = first == endit ? endit : std::next(first);
|
||||
|
||||
contour_.distances.reserve(shapelike::contourVertexCount(sh));
|
||||
contour_.distances.reserve(sl::contourVertexCount(sh));
|
||||
|
||||
while(next != endit) {
|
||||
contour_.emap.emplace_back(*(first++), *(next++));
|
||||
contour_.full_distance += length(contour_.emap.back());
|
||||
contour_.distances.emplace_back(contour_.full_distance);
|
||||
}
|
||||
|
||||
if constexpr (ClosureTypeV<RawShape> == Closure::OPEN) {
|
||||
if (sl::contourVertexCount(sh) > 0) {
|
||||
contour_.emap.emplace_back(sl::back(sh), sl::front(sh));
|
||||
contour_.full_distance += length(contour_.emap.back());
|
||||
contour_.distances.emplace_back(contour_.full_distance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(auto& h : shapelike::holes(sh)) { // For the holes
|
||||
auto first = h.begin();
|
||||
auto next = std::next(first);
|
||||
auto endit = h.end();
|
||||
auto first = sl::cbegin(h);
|
||||
auto endit = sl::cend(h);
|
||||
auto next = first == endit ? endit :std::next(first);
|
||||
|
||||
ContourCache hc;
|
||||
hc.distances.reserve(endit - first);
|
||||
hc.distances.reserve(sl::contourVertexCount(h));
|
||||
|
||||
while(next != endit) {
|
||||
hc.emap.emplace_back(*(first++), *(next++));
|
||||
@ -184,6 +192,14 @@ template<class RawShape> class EdgeCache {
|
||||
hc.distances.emplace_back(hc.full_distance);
|
||||
}
|
||||
|
||||
if constexpr (ClosureTypeV<RawShape> == Closure::OPEN) {
|
||||
if (sl::contourVertexCount(h) > 0) {
|
||||
hc.emap.emplace_back(sl::back(sh), sl::front(sh));
|
||||
hc.full_distance += length(hc.emap.back());
|
||||
hc.distances.emplace_back(hc.full_distance);
|
||||
}
|
||||
}
|
||||
|
||||
holes_.emplace_back(std::move(hc));
|
||||
}
|
||||
}
|
||||
@ -206,7 +222,6 @@ template<class RawShape> class EdgeCache {
|
||||
contour_.corners.reserve(N / S + 1);
|
||||
contour_.corners.emplace_back(0.0);
|
||||
auto N_1 = N-1;
|
||||
contour_.corners.emplace_back(0.0);
|
||||
for(size_t i = 0; i < N_1; i += S) {
|
||||
contour_.corners.emplace_back(
|
||||
contour_.distances.at(i) / contour_.full_distance);
|
||||
|
@ -234,6 +234,7 @@ namespace client
|
||||
delete m_data.s;
|
||||
m_type = TYPE_EMPTY;
|
||||
}
|
||||
~expr() { reset(); }
|
||||
|
||||
enum Type {
|
||||
TYPE_EMPTY = 0,
|
||||
|
@ -466,13 +466,13 @@ std::string Print::validate(std::string* warning) const
|
||||
return L("The supplied settings will cause an empty print.");
|
||||
|
||||
if (m_config.complete_objects) {
|
||||
if (!sequential_print_horizontal_clearance_valid(*this, const_cast<Polygons*>(&m_sequential_print_clearance_polygons)))
|
||||
if (!sequential_print_horizontal_clearance_valid(*this, const_cast<Polygons*>(&m_sequential_print_clearance_contours)))
|
||||
return L("Some objects are too close; your extruder will collide with them.");
|
||||
if (!sequential_print_vertical_clearance_valid(*this))
|
||||
return L("Some objects are too tall and cannot be printed without extruder collisions.");
|
||||
}
|
||||
else
|
||||
const_cast<Polygons*>(&m_sequential_print_clearance_polygons)->clear();
|
||||
const_cast<Polygons*>(&m_sequential_print_clearance_contours)->clear();
|
||||
|
||||
if (m_config.avoid_crossing_perimeters && m_config.avoid_crossing_curled_overhangs) {
|
||||
return L("Avoid crossing perimeters option and avoid crossing curled overhangs option cannot be both enabled together.");
|
||||
|
@ -597,7 +597,7 @@ public:
|
||||
const PrintRegion& get_print_region(size_t idx) const { return *m_print_regions[idx]; }
|
||||
const ToolOrdering& get_tool_ordering() const { return m_wipe_tower_data.tool_ordering; }
|
||||
|
||||
const Polygons& get_sequential_print_clearance_polygons() const { return m_sequential_print_clearance_polygons; }
|
||||
const Polygons& get_sequential_print_clearance_contours() const { return m_sequential_print_clearance_contours; }
|
||||
static bool sequential_print_horizontal_clearance_valid(const Print& print, Polygons* polygons = nullptr);
|
||||
|
||||
protected:
|
||||
@ -647,8 +647,8 @@ private:
|
||||
// Estimated print time, filament consumed.
|
||||
PrintStatistics m_print_statistics;
|
||||
|
||||
// Cache to store sequential print clearance polygons
|
||||
Polygons m_sequential_print_clearance_polygons;
|
||||
// Cache to store sequential print clearance contours
|
||||
Polygons m_sequential_print_clearance_contours;
|
||||
|
||||
// To allow GCode to set the Print's GCodeExport step status.
|
||||
friend class GCode;
|
||||
|
@ -206,7 +206,7 @@ FileArchiveDialog::FileArchiveDialog(wxWindow* parent_window, mz_zip_archive* ar
|
||||
reduce_stack(stack, struct_size);
|
||||
}
|
||||
if (!file.has_extension() && stack.size() == struct_size)
|
||||
stack.push_back(avc->get_model()->AddFile((stack.empty() ? std::shared_ptr<ArchiveViewNode>(nullptr) : stack.back()), GUI::format_wxstr(file.filename().string()), true)); // filename string to wstring?
|
||||
stack.push_back(avc->get_model()->AddFile((stack.empty() ? std::shared_ptr<ArchiveViewNode>(nullptr) : stack.back()), boost::nowide::widen(file.filename().string()), true)); // filename string to wstring?
|
||||
return struct_size + 1;
|
||||
};
|
||||
|
||||
@ -223,7 +223,7 @@ FileArchiveDialog::FileArchiveDialog(wxWindow* parent_window, mz_zip_archive* ar
|
||||
path = boost::filesystem::path(extra.substr(0, extra_size));
|
||||
} else {
|
||||
wxString wname = boost::nowide::widen(stat.m_filename);
|
||||
std::string name = GUI::format(wname);
|
||||
std::string name = boost::nowide::narrow(wname);
|
||||
path = boost::filesystem::path(name);
|
||||
}
|
||||
assert(!path.empty());
|
||||
@ -247,7 +247,7 @@ FileArchiveDialog::FileArchiveDialog(wxWindow* parent_window, mz_zip_archive* ar
|
||||
if (!stack.empty())
|
||||
parent = stack.back();
|
||||
if (std::regex_match(path.extension().string(), pattern_drop)) { // this leaves out non-compatible files
|
||||
m_avc->get_model()->AddFile(parent, GUI::format_wxstr(path.filename().string()), false)->set_fullpath(/*std::move(path)*/path); // filename string to wstring?
|
||||
m_avc->get_model()->AddFile(parent, boost::nowide::widen(path.filename().string()), false)->set_fullpath(/*std::move(path)*/path); // filename string to wstring?
|
||||
entry_count++;
|
||||
}
|
||||
}
|
||||
|
@ -880,20 +880,22 @@ void GLCanvas3D::Tooltip::render(const Vec2d& mouse_position, GLCanvas3D& canvas
|
||||
ImGui::PopStyleVar(2);
|
||||
}
|
||||
|
||||
void GLCanvas3D::SequentialPrintClearance::set_polygons(const Polygons& polygons)
|
||||
void GLCanvas3D::SequentialPrintClearance::set_contours(const ContoursList& contours)
|
||||
{
|
||||
m_perimeter.reset();
|
||||
m_contours.clear();
|
||||
m_instances.clear();
|
||||
m_fill.reset();
|
||||
if (polygons.empty())
|
||||
|
||||
if (contours.empty())
|
||||
return;
|
||||
|
||||
if (m_render_fill) {
|
||||
GLModel::Geometry fill_data;
|
||||
fill_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3 };
|
||||
fill_data.color = { 0.3333f, 0.0f, 0.0f, 0.5f };
|
||||
fill_data.color = { 0.3333f, 0.0f, 0.0f, 0.5f };
|
||||
|
||||
// vertices + indices
|
||||
const ExPolygons polygons_union = union_ex(polygons);
|
||||
const ExPolygons polygons_union = union_ex(contours.contours);
|
||||
unsigned int vertices_counter = 0;
|
||||
for (const ExPolygon& poly : polygons_union) {
|
||||
const std::vector<Vec3d> triangulation = triangulate_expolygon_3d(poly);
|
||||
@ -906,17 +908,42 @@ void GLCanvas3D::SequentialPrintClearance::set_polygons(const Polygons& polygons
|
||||
fill_data.add_triangle(vertices_counter - 3, vertices_counter - 2, vertices_counter - 1);
|
||||
}
|
||||
}
|
||||
|
||||
m_fill.init_from(std::move(fill_data));
|
||||
}
|
||||
|
||||
m_perimeter.init_from(polygons, 0.025f); // add a small positive z to avoid z-fighting
|
||||
for (size_t i = 0; i < contours.contours.size(); ++i) {
|
||||
GLModel& model = m_contours.emplace_back(GLModel());
|
||||
model.init_from(contours.contours[i], 0.025f); // add a small positive z to avoid z-fighting
|
||||
}
|
||||
|
||||
if (contours.trafos.has_value()) {
|
||||
// create the requested instances
|
||||
for (const auto& instance : contours.trafos.value()) {
|
||||
m_instances.emplace_back(instance.first, instance.second);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// no instances have been specified
|
||||
// create one instance for every polygon
|
||||
for (size_t i = 0; i < contours.contours.size(); ++i) {
|
||||
m_instances.emplace_back(i, Transform3f::Identity());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GLCanvas3D::SequentialPrintClearance::update_instances_trafos(const std::vector<Transform3d>& trafos)
|
||||
{
|
||||
assert(trafos.size() == m_instances.size());
|
||||
for (size_t i = 0; i < trafos.size(); ++i) {
|
||||
m_instances[i].second = trafos[i];
|
||||
}
|
||||
}
|
||||
|
||||
void GLCanvas3D::SequentialPrintClearance::render()
|
||||
{
|
||||
const ColorRGBA FILL_COLOR = { 1.0f, 0.0f, 0.0f, 0.5f };
|
||||
const ColorRGBA NO_FILL_COLOR = { 1.0f, 1.0f, 1.0f, 0.75f };
|
||||
const ColorRGBA FILL_COLOR = { 1.0f, 0.0f, 0.0f, 0.5f };
|
||||
const ColorRGBA NO_FILL_COLOR = { 1.0f, 1.0f, 1.0f, 0.75f };
|
||||
const ColorRGBA NO_FILL_EVALUATING_COLOR = { 1.0f, 1.0f, 0.0f, 1.0f };
|
||||
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("flat");
|
||||
if (shader == nullptr)
|
||||
@ -933,9 +960,34 @@ void GLCanvas3D::SequentialPrintClearance::render()
|
||||
glsafe(::glEnable(GL_BLEND));
|
||||
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
|
||||
|
||||
m_perimeter.set_color(m_render_fill ? FILL_COLOR : NO_FILL_COLOR);
|
||||
m_perimeter.render();
|
||||
m_fill.render();
|
||||
if (m_render_fill)
|
||||
m_fill.render();
|
||||
|
||||
#if ENABLE_GL_CORE_PROFILE
|
||||
if (OpenGLManager::get_gl_info().is_core_profile()) {
|
||||
shader->stop_using();
|
||||
|
||||
shader = wxGetApp().get_shader("dashed_thick_lines");
|
||||
if (shader == nullptr)
|
||||
return;
|
||||
|
||||
shader->start_using();
|
||||
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||
const std::array<int, 4>& viewport = camera.get_viewport();
|
||||
shader->set_uniform("viewport_size", Vec2d(double(viewport[2]), double(viewport[3])));
|
||||
shader->set_uniform("width", 1.0f);
|
||||
shader->set_uniform("gap_size", 0.0f);
|
||||
}
|
||||
else
|
||||
#endif // ENABLE_GL_CORE_PROFILE
|
||||
glsafe(::glLineWidth(2.0f));
|
||||
|
||||
for (const auto& [id, trafo] : m_instances) {
|
||||
shader->set_uniform("view_model_matrix", camera.get_view_matrix() * trafo);
|
||||
assert(id < m_contours.size());
|
||||
m_contours[id].set_color(m_render_fill ? FILL_COLOR : m_evaluating ? NO_FILL_EVALUATING_COLOR : NO_FILL_COLOR);
|
||||
m_contours[id].render();
|
||||
}
|
||||
|
||||
glsafe(::glDisable(GL_BLEND));
|
||||
glsafe(::glEnable(GL_CULL_FACE));
|
||||
@ -3531,7 +3583,11 @@ void GLCanvas3D::do_move(const std::string& snapshot_type)
|
||||
if (wipe_tower_origin != Vec3d::Zero())
|
||||
post_event(Vec3dEvent(EVT_GLCANVAS_WIPETOWER_MOVED, std::move(wipe_tower_origin)));
|
||||
|
||||
reset_sequential_print_clearance();
|
||||
if (current_printer_technology() == ptFFF && fff_print()->config().complete_objects) {
|
||||
m_sequential_print_clearance_first_displacement = true;
|
||||
update_sequential_clearance();
|
||||
m_sequential_print_clearance.set_evaluating(true);
|
||||
}
|
||||
|
||||
m_dirty = true;
|
||||
}
|
||||
@ -3609,6 +3665,12 @@ void GLCanvas3D::do_rotate(const std::string& snapshot_type)
|
||||
if (!done.empty())
|
||||
post_event(SimpleEvent(EVT_GLCANVAS_INSTANCE_ROTATED));
|
||||
|
||||
if (current_printer_technology() == ptFFF && fff_print()->config().complete_objects) {
|
||||
m_sequential_print_clearance_first_displacement = true;
|
||||
update_sequential_clearance();
|
||||
m_sequential_print_clearance.set_evaluating(true);
|
||||
}
|
||||
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
@ -3674,6 +3736,12 @@ void GLCanvas3D::do_scale(const std::string& snapshot_type)
|
||||
if (!done.empty())
|
||||
post_event(SimpleEvent(EVT_GLCANVAS_INSTANCE_SCALED));
|
||||
|
||||
if (current_printer_technology() == ptFFF && fff_print()->config().complete_objects) {
|
||||
m_sequential_print_clearance_first_displacement = true;
|
||||
update_sequential_clearance();
|
||||
m_sequential_print_clearance.set_evaluating(true);
|
||||
}
|
||||
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
@ -3942,7 +4010,7 @@ void GLCanvas3D::update_sequential_clearance()
|
||||
return;
|
||||
|
||||
// collects instance transformations from volumes
|
||||
// first define temporary cache
|
||||
// first: define temporary cache
|
||||
unsigned int instances_count = 0;
|
||||
std::vector<std::vector<std::optional<Geometry::Transformation>>> instance_transforms;
|
||||
for (size_t obj = 0; obj < m_model->objects.size(); ++obj) {
|
||||
@ -3957,7 +4025,7 @@ void GLCanvas3D::update_sequential_clearance()
|
||||
if (instances_count == 1)
|
||||
return;
|
||||
|
||||
// second fill temporary cache with data from volumes
|
||||
// second: fill temporary cache with data from volumes
|
||||
for (const GLVolume* v : m_volumes.volumes) {
|
||||
if (v->is_modifier || v->is_wipe_tower)
|
||||
continue;
|
||||
@ -3967,14 +4035,24 @@ void GLCanvas3D::update_sequential_clearance()
|
||||
transform = v->get_instance_transformation();
|
||||
}
|
||||
|
||||
// helper function to calculate the transformation to be applied to the sequential print clearance contours
|
||||
auto instance_trafo = [](const Transform3d& hull_trafo, const Geometry::Transformation& inst_trafo) {
|
||||
Vec3d offset = inst_trafo.get_offset() - hull_trafo.translation();
|
||||
offset.z() = 0.0;
|
||||
return Geometry::translation_transform(offset) *
|
||||
Geometry::rotation_transform(Geometry::rotation_diff_z(hull_trafo, inst_trafo.get_matrix()) * Vec3d::UnitZ());
|
||||
};
|
||||
|
||||
set_sequential_print_clearance_render_fill(false);
|
||||
|
||||
// calculates objects 2d hulls (see also: Print::sequential_print_horizontal_clearance_valid())
|
||||
// this is done only the first time this method is called while moving the mouse,
|
||||
// the results are then cached for following displacements
|
||||
if (m_sequential_print_clearance_first_displacement) {
|
||||
m_sequential_print_clearance.m_hull_2d_cache.clear();
|
||||
m_sequential_print_clearance.m_hulls_2d_cache.clear();
|
||||
const float shrink_factor = static_cast<float>(scale_(0.5 * fff_print()->config().extruder_clearance_radius.value - EPSILON));
|
||||
const double mitter_limit = scale_(0.1);
|
||||
m_sequential_print_clearance.m_hull_2d_cache.reserve(m_model->objects.size());
|
||||
m_sequential_print_clearance.m_hulls_2d_cache.reserve(m_model->objects.size());
|
||||
for (size_t i = 0; i < m_model->objects.size(); ++i) {
|
||||
ModelObject* model_object = m_model->objects[i];
|
||||
ModelInstance* model_instance0 = model_object->instances.front();
|
||||
@ -3986,38 +4064,51 @@ void GLCanvas3D::update_sequential_clearance()
|
||||
shrink_factor,
|
||||
jtRound, mitter_limit).front();
|
||||
|
||||
Pointf3s& cache_hull_2d = m_sequential_print_clearance.m_hull_2d_cache.emplace_back(Pointf3s());
|
||||
cache_hull_2d.reserve(hull_2d.points.size());
|
||||
Pointf3s& new_hull_2d = m_sequential_print_clearance.m_hulls_2d_cache.emplace_back(std::make_pair(Pointf3s(), trafo.get_matrix())).first;
|
||||
new_hull_2d.reserve(hull_2d.points.size());
|
||||
const Transform3d inv_trafo = trafo.get_matrix().inverse();
|
||||
for (const Point& p : hull_2d.points) {
|
||||
cache_hull_2d.emplace_back(inv_trafo * Vec3d(unscale<double>(p.x()), unscale<double>(p.y()), 0.0));
|
||||
new_hull_2d.emplace_back(Vec3d(unscale<double>(p.x()), unscale<double>(p.y()), 0.0));
|
||||
}
|
||||
}
|
||||
|
||||
ContoursList contours;
|
||||
contours.contours.reserve(instance_transforms.size());
|
||||
contours.trafos = std::vector<std::pair<size_t, Transform3d>>();
|
||||
contours.trafos.value().reserve(instances_count);
|
||||
for (size_t i = 0; i < instance_transforms.size(); ++i) {
|
||||
const auto& [hull, hull_trafo] = m_sequential_print_clearance.m_hulls_2d_cache[i];
|
||||
Points hull_pts;
|
||||
hull_pts.reserve(hull.size());
|
||||
for (size_t j = 0; j < hull.size(); ++j) {
|
||||
hull_pts.emplace_back(scaled<double>(hull[j].x()), scaled<double>(hull[j].y()));
|
||||
}
|
||||
contours.contours.emplace_back(Geometry::convex_hull(std::move(hull_pts)));
|
||||
|
||||
const auto& instances = instance_transforms[i];
|
||||
for (const auto& instance : instances) {
|
||||
contours.trafos.value().emplace_back(i, instance_trafo(hull_trafo, instance.value()));
|
||||
}
|
||||
}
|
||||
|
||||
set_sequential_print_clearance_contours(contours);
|
||||
m_sequential_print_clearance_first_displacement = false;
|
||||
}
|
||||
|
||||
// calculates instances 2d hulls (see also: Print::sequential_print_horizontal_clearance_valid())
|
||||
Polygons polygons;
|
||||
polygons.reserve(instances_count);
|
||||
for (size_t i = 0; i < instance_transforms.size(); ++i) {
|
||||
const auto& instances = instance_transforms[i];
|
||||
for (const auto& instance : instances) {
|
||||
const Transform3d& trafo = instance->get_matrix();
|
||||
const Pointf3s& hull_2d = m_sequential_print_clearance.m_hull_2d_cache[i];
|
||||
Points inst_pts;
|
||||
inst_pts.reserve(hull_2d.size());
|
||||
for (size_t j = 0; j < hull_2d.size(); ++j) {
|
||||
const Vec3d p = trafo * hull_2d[j];
|
||||
inst_pts.emplace_back(scaled<double>(p.x()), scaled<double>(p.y()));
|
||||
else {
|
||||
std::vector<Transform3d> trafos;
|
||||
trafos.reserve(instances_count);
|
||||
for (size_t i = 0; i < instance_transforms.size(); ++i) {
|
||||
const auto& [hull, hull_trafo] = m_sequential_print_clearance.m_hulls_2d_cache[i];
|
||||
const auto& instances = instance_transforms[i];
|
||||
for (const auto& instance : instances) {
|
||||
trafos.emplace_back(instance_trafo(hull_trafo, instance.value()));
|
||||
}
|
||||
polygons.emplace_back(Geometry::convex_hull(std::move(inst_pts)));
|
||||
}
|
||||
m_sequential_print_clearance.update_instances_trafos(trafos);
|
||||
}
|
||||
|
||||
// sends instances 2d hulls to be rendered
|
||||
set_sequential_print_clearance_visible(true);
|
||||
set_sequential_print_clearance_render_fill(false);
|
||||
set_sequential_print_clearance_polygons(polygons);
|
||||
}
|
||||
|
||||
bool GLCanvas3D::is_object_sinking(int object_idx) const
|
||||
|
@ -587,22 +587,38 @@ public:
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct ContoursList
|
||||
{
|
||||
// list of unique contours
|
||||
std::vector<Polygon> contours;
|
||||
// if defined: list of transforms to apply to contours
|
||||
std::optional<std::vector<std::pair<size_t, Transform3d>>> trafos;
|
||||
|
||||
bool empty() const { return contours.empty(); }
|
||||
};
|
||||
|
||||
private:
|
||||
void load_arrange_settings();
|
||||
|
||||
class SequentialPrintClearance
|
||||
{
|
||||
GLModel m_fill;
|
||||
GLModel m_perimeter;
|
||||
// list of unique contours
|
||||
std::vector<GLModel> m_contours;
|
||||
// list of transforms used to render the contours
|
||||
std::vector<std::pair<size_t, Transform3d>> m_instances;
|
||||
bool m_render_fill{ true };
|
||||
bool m_visible{ false };
|
||||
bool m_evaluating{ false };
|
||||
|
||||
std::vector<Pointf3s> m_hull_2d_cache;
|
||||
std::vector<std::pair<Pointf3s, Transform3d>> m_hulls_2d_cache;
|
||||
|
||||
public:
|
||||
void set_polygons(const Polygons& polygons);
|
||||
void set_contours(const ContoursList& contours);
|
||||
void update_instances_trafos(const std::vector<Transform3d>& trafos);
|
||||
void set_render_fill(bool render_fill) { m_render_fill = render_fill; }
|
||||
void set_visible(bool visible) { m_visible = visible; }
|
||||
void set_evaluating(bool evaluating) { m_evaluating = evaluating; }
|
||||
void render();
|
||||
|
||||
friend class GLCanvas3D;
|
||||
@ -927,7 +943,7 @@ public:
|
||||
void reset_sequential_print_clearance() {
|
||||
m_sequential_print_clearance.set_visible(false);
|
||||
m_sequential_print_clearance.set_render_fill(false);
|
||||
m_sequential_print_clearance.set_polygons(Polygons());
|
||||
m_sequential_print_clearance.set_contours(ContoursList());
|
||||
}
|
||||
|
||||
void set_sequential_print_clearance_visible(bool visible) {
|
||||
@ -938,8 +954,12 @@ public:
|
||||
m_sequential_print_clearance.set_render_fill(render_fill);
|
||||
}
|
||||
|
||||
void set_sequential_print_clearance_polygons(const Polygons& polygons) {
|
||||
m_sequential_print_clearance.set_polygons(polygons);
|
||||
void set_sequential_print_clearance_contours(const ContoursList& contours) {
|
||||
m_sequential_print_clearance.set_contours(contours);
|
||||
}
|
||||
|
||||
void set_sequential_print_clearance_evaluating(bool evaluating) {
|
||||
m_sequential_print_clearance.set_evaluating(evaluating);
|
||||
}
|
||||
|
||||
void update_sequential_clearance();
|
||||
|
@ -596,6 +596,38 @@ void GLModel::init_from(const indexed_triangle_set& its)
|
||||
}
|
||||
}
|
||||
|
||||
void GLModel::init_from(const Polygon& polygon, float z)
|
||||
{
|
||||
if (is_initialized()) {
|
||||
// call reset() if you want to reuse this model
|
||||
assert(false);
|
||||
return;
|
||||
}
|
||||
|
||||
Geometry& data = m_render_data.geometry;
|
||||
data.format = { Geometry::EPrimitiveType::Lines, Geometry::EVertexLayout::P3 };
|
||||
|
||||
const size_t segments_count = polygon.points.size();
|
||||
data.reserve_vertices(2 * segments_count);
|
||||
data.reserve_indices(2 * segments_count);
|
||||
|
||||
// vertices + indices
|
||||
unsigned int vertices_counter = 0;
|
||||
for (size_t i = 0; i < segments_count; ++i) {
|
||||
const Point& p0 = polygon.points[i];
|
||||
const Point& p1 = (i == segments_count - 1) ? polygon.points.front() : polygon.points[i + 1];
|
||||
data.add_vertex(Vec3f(unscale<float>(p0.x()), unscale<float>(p0.y()), z));
|
||||
data.add_vertex(Vec3f(unscale<float>(p1.x()), unscale<float>(p1.y()), z));
|
||||
vertices_counter += 2;
|
||||
data.add_line(vertices_counter - 2, vertices_counter - 1);
|
||||
}
|
||||
|
||||
// update bounding box
|
||||
for (size_t i = 0; i < vertices_count(); ++i) {
|
||||
m_bounding_box.merge(data.extract_position_3(i).cast<double>());
|
||||
}
|
||||
}
|
||||
|
||||
void GLModel::init_from(const Polygons& polygons, float z)
|
||||
{
|
||||
if (is_initialized()) {
|
||||
|
@ -227,6 +227,7 @@ namespace GUI {
|
||||
void init_from(const TriangleMesh& mesh);
|
||||
#endif // ENABLE_SMOOTH_NORMALS
|
||||
void init_from(const indexed_triangle_set& its);
|
||||
void init_from(const Polygon& polygon, float z);
|
||||
void init_from(const Polygons& polygons, float z);
|
||||
bool init_from_file(const std::string& filename);
|
||||
|
||||
|
@ -2305,18 +2305,6 @@ bool GUI_App::load_language(wxString language, bool initial)
|
||||
// Override language at the active wxTranslations class (which is stored in the active m_wxLocale)
|
||||
// to load possibly different dictionary, for example, load Czech dictionary for Slovak language.
|
||||
wxTranslations::Get()->SetLanguage(language_dict);
|
||||
{
|
||||
// ysFIXME after fix for wxWidgets issue (https://github.com/wxWidgets/wxWidgets/issues/23210)
|
||||
// UKR Localization specific workaround till the wxWidgets doesn't fixed:
|
||||
// From wxWidgets 3.1.6 calls setlocation(0, wxInfoLanguage->LocaleTag), see (https://github.com/prusa3d/wxWidgets/commit/deef116a09748796711d1e3509965ee208dcdf0b#diff-7de25e9a71c4dce61bbf76492c589623d5b93fd1bb105ceaf0662075d15f4472),
|
||||
// where LocaleTag is a Tag of locale in BCP 47 - like notation.
|
||||
// For Ukrainian Language LocaleTag is "uk".
|
||||
// But setlocale(0, "uk") returns "English_United Kingdom.1252" instead of "uk",
|
||||
// and, as a result, locales are set to English_United Kingdom
|
||||
|
||||
if (language_info->CanonicalName == "uk")
|
||||
setlocale(0, language_info->GetCanonicalWithRegion().data());
|
||||
}
|
||||
m_wxLocale->AddCatalog(SLIC3R_APP_KEY);
|
||||
m_imgui->set_language(into_u8(language_info->CanonicalName));
|
||||
//FIXME This is a temporary workaround, the correct solution is to switch to "C" locale during file import / export only.
|
||||
|
@ -596,6 +596,12 @@ void ObjectManipulation::update_ui_from_settings()
|
||||
|
||||
void ObjectManipulation::update_settings_value(const Selection& selection)
|
||||
{
|
||||
if (selection.is_empty()) {
|
||||
// No selection, reset the cache.
|
||||
reset_settings_value();
|
||||
return;
|
||||
}
|
||||
|
||||
m_new_move_label_string = L("Position");
|
||||
m_new_rotate_label_string = L("Rotation");
|
||||
m_new_scale_label_string = L("Scale factors");
|
||||
@ -674,11 +680,6 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
|
||||
m_new_size = selection.get_bounding_box_in_current_reference_system().first.size();
|
||||
m_new_enabled = true;
|
||||
}
|
||||
else {
|
||||
// No selection, reset the cache.
|
||||
// assert(selection.is_empty());
|
||||
reset_settings_value();
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectManipulation::update_if_dirty()
|
||||
@ -1066,8 +1067,9 @@ void ObjectManipulation::on_change(const std::string& opt_key, int axis, double
|
||||
if (new_value > 0.0)
|
||||
change_size_value(axis, new_value);
|
||||
else {
|
||||
new_value = m_cache.size(axis);
|
||||
m_cache.size(axis) = 0.0;
|
||||
Vec3d& size = m_imperial_units ? m_cache.size_inches : m_cache.size;
|
||||
new_value = size(axis);
|
||||
size(axis) = 0.0;
|
||||
m_cache.size_rounded(axis) = DBL_MAX;
|
||||
change_size_value(axis, new_value);
|
||||
}
|
||||
|
@ -971,6 +971,8 @@ bool GLGizmosManager::activate_gizmo(EType type)
|
||||
|
||||
new_gizmo.register_raycasters_for_picking();
|
||||
|
||||
m_parent.reset_sequential_print_clearance();
|
||||
|
||||
// sucessful activation of gizmo
|
||||
return true;
|
||||
}
|
||||
|
@ -3293,10 +3293,12 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
|
||||
return_state |= UPDATE_BACKGROUND_PROCESS_INVALID;
|
||||
if (printer_technology == ptFFF) {
|
||||
const Print* print = background_process.fff_print();
|
||||
const Polygons polygons = print->get_sequential_print_clearance_polygons();
|
||||
view3D->get_canvas3d()->set_sequential_print_clearance_visible(!polygons.empty());
|
||||
view3D->get_canvas3d()->set_sequential_print_clearance_render_fill(!polygons.empty());
|
||||
view3D->get_canvas3d()->set_sequential_print_clearance_polygons(polygons);
|
||||
GLCanvas3D::ContoursList contours;
|
||||
contours.contours = print->get_sequential_print_clearance_contours();
|
||||
view3D->get_canvas3d()->set_sequential_print_clearance_visible(!contours.empty());
|
||||
view3D->get_canvas3d()->set_sequential_print_clearance_render_fill(!contours.empty());
|
||||
view3D->get_canvas3d()->set_sequential_print_clearance_contours(contours);
|
||||
view3D->get_canvas3d()->set_sequential_print_clearance_evaluating(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5549,7 +5551,7 @@ bool Plater::preview_zip_archive(const boost::filesystem::path& archive_path)
|
||||
for (mz_uint i = 0; i < num_entries; ++i) {
|
||||
if (mz_zip_reader_file_stat(&archive, i, &stat)) {
|
||||
wxString wname = boost::nowide::widen(stat.m_filename);
|
||||
std::string name = GUI::format(wname);
|
||||
std::string name = boost::nowide::narrow(wname);
|
||||
fs::path archive_path(name);
|
||||
|
||||
std::string extra(1024, 0);
|
||||
@ -6476,9 +6478,9 @@ void Plater::export_stl_obj(bool extended, bool selection_only)
|
||||
}
|
||||
}
|
||||
|
||||
if (path.EndsWith(".stl"))
|
||||
if (path.Lower().EndsWith(".stl"))
|
||||
Slic3r::store_stl(path_u8.c_str(), &mesh, true);
|
||||
else if (path.EndsWith(".obj"))
|
||||
else if (path.Lower().EndsWith(".obj"))
|
||||
Slic3r::store_obj(path_u8.c_str(), &mesh);
|
||||
// p->statusbar()->set_status_text(format_wxstr(_L("STL file exported to %s"), path));
|
||||
}
|
||||
|
@ -1024,9 +1024,15 @@ TEST_CASE("pointOnPolygonContour", "[Geometry]") {
|
||||
REQUIRE(getX(first) == getX(ecache.coords(0)));
|
||||
REQUIRE(getY(first) == getY(ecache.coords(0)));
|
||||
|
||||
auto last = *std::prev(input.end());
|
||||
REQUIRE(getX(last) == getX(ecache.coords(1.0)));
|
||||
REQUIRE(getY(last) == getY(ecache.coords(1.0)));
|
||||
if constexpr (ClosureTypeV<PolygonImpl> == Closure::CLOSED) {
|
||||
auto last = *std::prev(input.end());
|
||||
REQUIRE(getX(last) == getX(ecache.coords(1.0)));
|
||||
REQUIRE(getY(last) == getY(ecache.coords(1.0)));
|
||||
} else {
|
||||
auto last = *input.begin();
|
||||
REQUIRE(getX(last) == getX(ecache.coords(1.0)));
|
||||
REQUIRE(getY(last) == getY(ecache.coords(1.0)));
|
||||
}
|
||||
|
||||
for(int i = 0; i <= 100; i++) {
|
||||
auto v = ecache.coords(i*(0.01));
|
||||
|
Loading…
Reference in New Issue
Block a user