NEW:add step mesh parameters

jira: STUDIO-7415
Change-Id: I5e09a1eb1ad31063ad56d08d5738907a804dc112
(cherry picked from commit ccbe9630076b754ab440e98977c4164afff96250)
This commit is contained in:
Mack 2024-09-09 11:52:59 +08:00 committed by Lane.Wei
parent 4e3893a6e3
commit 84e7063c54
8 changed files with 314 additions and 13 deletions

View File

@ -34,9 +34,6 @@
#include "TopExp_Explorer.hxx"
#include "BRep_Tool.hxx"
const double STEP_TRANS_CHORD_ERROR = 0.003;
const double STEP_TRANS_ANGLE_RES = 0.5;
namespace Slic3r {
@ -220,7 +217,10 @@ static void getNamedSolids(const TopLoc_Location& location, const std::string& p
}
}
bool load_step(const char *path, Model *model, bool& is_cancel, ImportStepProgressFn stepFn, StepIsUtf8Fn isUtf8Fn)
bool load_step(const char *path, Model *model, bool& is_cancel,
double linear_defletion/*=0.003*/,
double angle_defletion/*= 0.5*/,
ImportStepProgressFn stepFn, StepIsUtf8Fn isUtf8Fn, long& mesh_face_num)
{
bool cb_cancel = false;
if (stepFn) {
@ -275,7 +275,7 @@ bool load_step(const char *path, Model *model, bool& is_cancel, ImportStepProgre
stl.resize(namedSolids.size());
tbb::parallel_for(tbb::blocked_range<size_t>(0, namedSolids.size()), [&](const tbb::blocked_range<size_t> &range) {
for (size_t i = range.begin(); i < range.end(); i++) {
BRepMesh_IncrementalMesh mesh(namedSolids[i].solid, STEP_TRANS_CHORD_ERROR, false, STEP_TRANS_ANGLE_RES, true);
BRepMesh_IncrementalMesh mesh(namedSolids[i].solid, linear_defletion, false, angle_defletion, true);
// BBS: calculate total number of the nodes and triangles
int aNbNodes = 0;
int aNbTriangles = 0;
@ -348,6 +348,14 @@ bool load_step(const char *path, Model *model, bool& is_cancel, ImportStepProgre
}
});
if (mesh_face_num != -1) {
for (size_t i = 0; i < stl.size(); i++) {
// Test for overflow
mesh_face_num += stl[i].stats.number_of_facets;
}
return true;
}
ModelObject *new_object = model->add_object();
const char * last_slash = strrchr(path, DIR_SEPARATOR);
new_object->name.assign((last_slash == nullptr) ? path : last_slash + 1);

View File

@ -17,7 +17,13 @@ typedef std::function<void(int load_stage, int current, int total, bool& cancel)
typedef std::function<void(bool isUtf8)> StepIsUtf8Fn;
//BBS: Load an step file into a provided model.
extern bool load_step(const char *path, Model *model, bool& is_cancel, ImportStepProgressFn proFn = nullptr, StepIsUtf8Fn isUtf8Fn = nullptr);
extern bool load_step(const char *path, Model *model,
bool& is_cancel,
double linear_defletion = 0.003,
double angle_defletion = 0.5,
ImportStepProgressFn proFn = nullptr,
StepIsUtf8Fn isUtf8Fn = nullptr,
long& mesh_face_num = *(new long(-1)));
//BBS: Used to detect what kind of encoded type is used in name field of step
// If is encoded in UTF8, the file don't need to be handled, then return the original path directly.

View File

@ -30,6 +30,7 @@
#include "SVG.hpp"
#include <Eigen/Dense>
#include <functional>
#include "GCodeWriter.hpp"
// BBS: for segment
@ -183,7 +184,8 @@ Model Model::read_from_file(const std::string& input_file, DynamicPrintConfig* c
StepIsUtf8Fn stepIsUtf8Fn,
BBLProject * project,
int plate_id,
ObjImportColorFn objFn)
ObjImportColorFn objFn,
std::function<int(double&, double&)> step_mesh_fn)
{
Model model;
@ -208,9 +210,19 @@ Model Model::read_from_file(const std::string& input_file, DynamicPrintConfig* c
bool is_cb_cancel = false;
std::string message;
if (boost::algorithm::iends_with(input_file, ".stp") ||
boost::algorithm::iends_with(input_file, ".step"))
result = load_step(input_file.c_str(), &model, is_cb_cancel, stepFn, stepIsUtf8Fn);
else if (boost::algorithm::iends_with(input_file, ".stl"))
boost::algorithm::iends_with(input_file, ".step")) {
double linear_defletion = 0.003;
double angle_defletion = 0.5;
if (step_mesh_fn) {
if (step_mesh_fn(linear_defletion, angle_defletion) == -1) {
result = false;
goto end;
}
}
result = load_step(input_file.c_str(), &model, is_cb_cancel, linear_defletion, angle_defletion, stepFn, stepIsUtf8Fn);
end:
BOOST_LOG_TRIVIAL(info) << "Cancel step mesh dialog";
} else if (boost::algorithm::iends_with(input_file, ".stl"))
result = load_stl(input_file.c_str(), &model, nullptr, stlFn);
else if (boost::algorithm::iends_with(input_file, ".oltp"))
result = load_stl(input_file.c_str(), &model, nullptr, stlFn,256);

View File

@ -1579,7 +1579,8 @@ public:
StepIsUtf8Fn stepIsUtf8Fn = nullptr,
BBLProject * project = nullptr,
int plate_id = 0,
ObjImportColorFn objFn = nullptr
ObjImportColorFn objFn = nullptr,
std::function<int(double&, double&)> step_mesh_fn = nullptr
);
// BBS
static bool obj_import_vertex_color_deal(const std::vector<unsigned char> &vertex_filament_ids, const unsigned char &first_extruder_id, Model *model);

View File

@ -295,6 +295,8 @@ set(SLIC3R_GUI_SOURCES
GUI/RemovableDriveManager.hpp
GUI/SendSystemInfoDialog.cpp
GUI/SendSystemInfoDialog.hpp
GUI/StepMeshDialog.cpp
GUI/StepMeshDialog.hpp
GUI/PlateSettingsDialog.cpp
GUI/PlateSettingsDialog.hpp
GUI/ImGuiWrapper.hpp

View File

@ -139,6 +139,7 @@
#include "PlateSettingsDialog.hpp"
#include "DailyTips.hpp"
#include "CreatePresetsDialog.hpp"
#include "StepMeshDialog.hpp"
using boost::optional;
namespace fs = boost::filesystem;
@ -3973,7 +3974,20 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
filament_ids.clear();
}
};
model = Slic3r::Model::read_from_file(
auto step_mesh = [this, &path, &is_user_cancel](double& linear_value, double& angle_value)-> int {
if (boost::iends_with(path.string(), ".step") ||
boost::iends_with(path.string(), ".stp")){
StepMeshDialog mesh_dlg(nullptr, path);
if (mesh_dlg.ShowModal() == wxID_OK) {
linear_value = mesh_dlg.get_linear_defletion();
angle_value = mesh_dlg.get_angle_defletion();
return 1;
}
}
is_user_cancel = false;
return -1;
};
model = Slic3r::Model:: read_from_file(
path.string(), nullptr, nullptr, strategy, &plate_data, &project_presets, &is_xxx, &file_version, nullptr,
[this, &dlg, real_filename, &progress_percent, &file_percent, INPUT_FILES_RATIO, total_files, i, &designer_model_id, &designer_country_code](int current, int total, bool &cancel, std::string &mode_id, std::string &code)
{
@ -4003,7 +4017,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
Slic3r::GUI::show_info(nullptr, _L("Name of components inside step file is not UTF8 format!") + "\n\n" + _L("The name may show garbage characters!"),
_L("Attention!"));
},
nullptr, 0, obj_color_fun);
nullptr, 0, obj_color_fun, step_mesh);
if (designer_model_id.empty() && boost::algorithm::iends_with(path.string(), ".stl")) {

View File

@ -0,0 +1,216 @@
#include "StepMeshDialog.hpp"
#include "BBLStatusBar.hpp"
#include "I18N.hpp"
#include "GUI_App.hpp"
#include "Widgets/Button.hpp"
#include "MainFrame.hpp"
#include <wx/sizer.h>
#include <wx/slider.h>
using namespace Slic3r;
using namespace Slic3r::GUI;
static int _scale(const int val) { return val * Slic3r::GUI::wxGetApp().em_unit() / 10; }
static int _ITEM_WIDTH() { return _scale(30); }
#define MIN_DIALOG_WIDTH FromDIP(400)
#define SLIDER_WIDTH FromDIP(150)
#define TEXT_CTRL_WIDTH FromDIP(40)
#define BUTTON_SIZE wxSize(FromDIP(58), FromDIP(24))
#define BUTTON_BORDER FromDIP(int(400 - 58 * 2) / 8)
#define SLIDER_SCALE(val) ((val) / 0.001)
#define SLIDER_UNSCALE(val) ((val) * 0.001)
#define SLIDER_SCALE_10(val) ((val) / 0.01)
#define SLIDER_UNSCALE_10(val) ((val) * 0.01)
#define LEFT_RIGHT_PADING FromDIP(20)
void StepMeshDialog::on_dpi_changed(const wxRect& suggested_rect) {
};
bool StepMeshDialog:: validate_number_range(const wxString& value, double min, double max) {
double num;
if (!value.ToDouble(&num)) {
return false;
}
return (num >= min && num <= max);
}
StepMeshDialog::StepMeshDialog(wxWindow* parent, fs::path file)
: DPIDialog(parent ? parent : static_cast<wxWindow *>(wxGetApp().mainframe),
wxID_ANY,
_(L("Step file import parameters")),
wxDefaultPosition,
wxDefaultSize,
wxDEFAULT_DIALOG_STYLE /* | wxRESIZE_BORDER*/), m_file(file)
{
std::string icon_path = (boost::format("%1%/images/BambuStudioTitle.ico")
% Slic3r::resources_dir()).str();
SetIcon(wxIcon(Slic3r::encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO));
SetBackgroundColour(*wxWHITE);
wxBoxSizer* bSizer = new wxBoxSizer(wxVERTICAL);
bSizer->SetMinSize(wxSize(MIN_DIALOG_WIDTH, -1));
wxBoxSizer* linear_sizer = new wxBoxSizer(wxHORIZONTAL);
//linear_sizer->SetMinSize(wxSize(MIN_DIALOG_WIDTH, -1));
wxStaticText* linear_title = new wxStaticText(this,
wxID_ANY,
_L("Linear Deflection:"));
linear_sizer->Add(linear_title, 0, wxALIGN_LEFT);
linear_sizer->AddStretchSpacer(1);
wxSlider* linear_slider = new wxSlider(this, wxID_ANY,
SLIDER_SCALE(get_linear_defletion()),
1, 100, wxDefaultPosition,
wxSize(SLIDER_WIDTH, -1),
wxSL_HORIZONTAL);
linear_sizer->Add(linear_slider, 0, wxALIGN_RIGHT | wxLEFT, FromDIP(5));
wxTextValidator valid_number(wxFILTER_NUMERIC);
wxTextCtrl* linear_textctrl = new wxTextCtrl(this, wxID_ANY,
m_linear_last,
wxDefaultPosition, wxSize(TEXT_CTRL_WIDTH, -1),
0, valid_number);
linear_sizer->Add(linear_textctrl, 0, wxALIGN_RIGHT | wxLEFT, FromDIP(5));
// textctrl loss focus
linear_textctrl->Bind(wxEVT_KILL_FOCUS, ([this, linear_textctrl](wxFocusEvent& e) {
wxString value = linear_textctrl->GetValue();
if(!validate_number_range(value, 0.001, 0.1)) {
linear_textctrl->SetValue(m_linear_last);
}
m_linear_last = value;
update_mesh_number_text();
e.Skip();
}));
// slider bind textctrl
linear_slider->Bind(wxEVT_SLIDER, ([this, linear_slider, linear_textctrl](wxCommandEvent& e) {
double slider_value = SLIDER_UNSCALE(linear_slider->GetValue());
linear_textctrl->SetValue(wxString::Format("%.3f", slider_value));
m_linear_last = wxString::Format("%.3f", slider_value);
update_mesh_number_text();
}));
// textctrl bind slider
linear_textctrl->Bind(wxEVT_TEXT, ([this, linear_textctrl, linear_slider](wxCommandEvent& e) {
double slider_value_long;
int slider_value;
wxString value = linear_textctrl->GetValue();
if (value.ToDouble(&slider_value_long)) {
slider_value = SLIDER_SCALE(slider_value_long);
if (slider_value >= linear_slider->GetMin() && slider_value <= linear_slider->GetMax()) {
linear_slider->SetValue(slider_value);
}
}
}));
bSizer->Add(linear_sizer, 1, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, LEFT_RIGHT_PADING);
wxBoxSizer* angle_sizer = new wxBoxSizer(wxHORIZONTAL);
wxStaticText* angle_title = new wxStaticText(this,
wxID_ANY,
_L("Angle Deflection:"));
angle_sizer->Add(angle_title, 0, wxALIGN_LEFT);
angle_sizer->AddStretchSpacer(1);
wxSlider* angle_slider = new wxSlider(this, wxID_ANY,
SLIDER_SCALE_10(get_angle_defletion()),
1, 100, wxDefaultPosition,
wxSize(SLIDER_WIDTH, -1),
wxSL_HORIZONTAL);
angle_sizer->Add(angle_slider, 0, wxALIGN_RIGHT | wxLEFT, FromDIP(5));
wxTextCtrl* angle_textctrl = new wxTextCtrl(this, wxID_ANY,
m_angle_last,
wxDefaultPosition, wxSize(TEXT_CTRL_WIDTH, -1),
0, valid_number);
angle_sizer->Add(angle_textctrl, 0, wxALIGN_RIGHT | wxLEFT, FromDIP(5));
// textctrl loss focus
angle_textctrl->Bind(wxEVT_KILL_FOCUS, ([this, angle_textctrl](wxFocusEvent& e) {
wxString value = angle_textctrl->GetValue();
if (!validate_number_range(value, 0.01, 1)) {
angle_textctrl->SetValue(m_angle_last);
}
m_angle_last = value;
update_mesh_number_text();
e.Skip();
}));
// slider bind textctrl
angle_slider->Bind(wxEVT_SLIDER, ([this, angle_slider, angle_textctrl](wxCommandEvent& e) {
double slider_value = SLIDER_UNSCALE_10(angle_slider->GetValue());
angle_textctrl->SetValue(wxString::Format("%.2f", slider_value));
m_angle_last = wxString::Format("%.2f", slider_value);
update_mesh_number_text();
}));
// textctrl bind slider
linear_textctrl->Bind(wxEVT_TEXT, ([this, angle_slider, angle_textctrl](wxCommandEvent& e) {
double slider_value_long;
int slider_value;
wxString value = angle_textctrl->GetValue();
if (value.ToDouble(&slider_value_long)) {
slider_value = SLIDER_SCALE_10(slider_value_long);
if (slider_value >= angle_slider->GetMin() && slider_value <= angle_slider->GetMax()) {
angle_slider->SetValue(slider_value);
}
}
}));
bSizer->Add(angle_sizer, 1, wxEXPAND | wxLEFT | wxRIGHT, LEFT_RIGHT_PADING);
mesh_face_number_text = new wxStaticText(this, wxID_ANY, _L("Number of generated surfaces: 0"));
bSizer->Add(mesh_face_number_text, 1, wxEXPAND | wxLEFT | wxRIGHT, LEFT_RIGHT_PADING);
wxBoxSizer* bSizer_button = new wxBoxSizer(wxHORIZONTAL);
bSizer_button->SetMinSize(wxSize(FromDIP(100), -1));
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed), std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
std::pair<wxColour, int>(AMS_CONTROL_BRAND_COLOUR, StateColor::Normal));
m_button_ok = new Button(this, _L("OK"));
m_button_ok->SetBackgroundColor(btn_bg_green);
m_button_ok->SetBorderColor(*wxWHITE);
m_button_ok->SetTextColor(wxColour(0xFFFFFE));
m_button_ok->SetFont(Label::Body_12);
m_button_ok->SetSize(BUTTON_SIZE);
m_button_ok->SetMinSize(BUTTON_SIZE);
m_button_ok->SetCornerRadius(FromDIP(12));
bSizer_button->Add(m_button_ok, 0, wxALIGN_RIGHT, BUTTON_BORDER);
m_button_ok->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) { EndModal(wxID_OK); });
StateColor btn_bg_white(std::pair<wxColour, int>(wxColour(206, 206, 206), StateColor::Pressed), std::pair<wxColour, int>(wxColour(238, 238, 238), StateColor::Hovered),
std::pair<wxColour, int>(*wxWHITE, StateColor::Normal));
m_button_cancel = new Button(this, _L("Cancel"));
m_button_cancel->SetBackgroundColor(btn_bg_white);
m_button_cancel->SetBorderColor(wxColour(38, 46, 48));
m_button_cancel->SetFont(Label::Body_12);
m_button_cancel->SetSize(BUTTON_SIZE);
m_button_cancel->SetMinSize(BUTTON_SIZE);
m_button_cancel->SetCornerRadius(FromDIP(12));
bSizer_button->Add(m_button_cancel, 0, wxALIGN_RIGHT | wxLEFT, BUTTON_BORDER);
m_button_cancel->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) { EndModal(wxID_CANCEL); });
bSizer->Add(bSizer_button, 0, wxALIGN_RIGHT | wxRIGHT| wxBOTTOM, LEFT_RIGHT_PADING);
this->SetSizer(bSizer);
update_mesh_number_text();
this->Layout();
bSizer->Fit(this);
this->Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent& e) { });
wxGetApp().UpdateDlgDarkUI(this);
}
long StepMeshDialog::get_mesh_number()
{
Model model;
long number = 0;
const std::string file_path = m_file.string();
bool is_cb_cancel = false;
bool result = load_step(file_path.c_str(), &model, is_cb_cancel, get_linear_defletion(), get_angle_defletion(), nullptr, nullptr, number);
return number;
}
void StepMeshDialog::update_mesh_number_text()
{
long number = get_mesh_number();
wxString newText = wxString::Format("Number of generated surfaces: %d", number);
mesh_face_number_text->SetLabel(newText);
}

View File

@ -0,0 +1,42 @@
#ifndef _STEP_MESH_DIALOG_H_
#define _STEP_MESH_DIALOG_H_
#include "GUI_Utils.hpp"
#include <boost/filesystem.hpp>
#include <wx/sizer.h>
class Button;
namespace fs = boost::filesystem;
class StepMeshDialog : public Slic3r::GUI::DPIDialog
{
public:
StepMeshDialog(wxWindow* parent, fs::path file);
void on_dpi_changed(const wxRect& suggested_rect) override;
inline double get_linear_defletion() {
double value;
if (m_linear_last.ToDouble(&value)) {
return value;
}else {
return 0.003;
}
}
inline double get_angle_defletion() {
double value;
if (m_angle_last.ToDouble(&value)) {
return value;
} else {
return 0.5;
}
}
long get_mesh_number();
private:
fs::path m_file;
Button* m_button_ok = nullptr;
Button* m_button_cancel = nullptr;
wxString m_linear_last = wxString::Format("%.3f", 0.003);
wxString m_angle_last = wxString::Format("%.2f", 0.5);
wxStaticText* mesh_face_number_text;
bool validate_number_range(const wxString& value, double min, double max);
void update_mesh_number_text();
};
#endif // _STEP_MESH_DIALOG_H_