Testing version (commented out autogenerator parameters)

Edit configuration svg to change values to 160 percent of the density
This commit is contained in:
Filip Sykala - NTB T15p 2025-01-02 16:05:05 +01:00 committed by Lukas Matena
parent 2dbc2f938a
commit 11e20327e4
6 changed files with 214 additions and 67 deletions

View File

@ -26,13 +26,13 @@
showgrid="false"
showborder="true"
borderlayer="true"
inkscape:zoom="19.02887"
inkscape:cx="14.845863"
inkscape:cy="132.29897"
inkscape:window-width="2400"
inkscape:window-height="1261"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:zoom="3.3638608"
inkscape:cx="115.78957"
inkscape:cy="88.588685"
inkscape:window-width="1920"
inkscape:window-height="1129"
inkscape:window-x="1912"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
@ -130,19 +130,19 @@
id="path12735" />
<path
style="fill:none;stroke:#b50000;stroke-width:0.4;stroke-linejoin:round;stroke-dasharray:none;stop-color:#000000"
d="M 4,0 6,3.8987591 8,15 10,40"
d="M 3.5,0 4.0915916,3.8987591 5,15 6,40"
id="path3587"
sodipodi:nodetypes="cccc" />
<text
xml:space="preserve"
style="font-size:1.05833px;line-height:0;font-family:'Cascadia Code';-inkscape-font-specification:'Cascadia Code';text-align:center;text-decoration-color:#000000;text-anchor:middle;fill:#364e59;stroke:none;stroke-width:0.4;stroke-linejoin:round;stroke-dasharray:none;stop-color:#000000"
x="16.386877"
x="9.5439215"
y="-7.5019774"
id="text4929"><tspan
sodipodi:role="line"
id="tspan4927"
style="font-size:1.05833px;fill:#364e59;stroke:none;stroke-width:0.4"
x="16.386877"
x="9.5439215"
y="-7.5019774">island supports</tspan></text>
<text
xml:space="preserve"
@ -211,7 +211,7 @@
id="tspan7390">interface</tspan></text>
<path
style="fill:#ba00ff;stroke:#364e59;stroke-width:0.1;stroke-linejoin:round;stroke-dasharray:none;marker-end:url(#Arrow2);stop-color:#000000"
d="M 13.379759,-7.2418186 10.65352,-0.96342022"
d="m 6.5368033,-7.2418186 -2.726239,6.27839838"
id="path7457"
sodipodi:nodetypes="cc" />
<text
@ -252,7 +252,7 @@
id="path9401-5" />
<path
style="fill:#364e59;stroke:#364e59;stroke-width:0.1;stroke-linejoin:round;stroke-dasharray:none;stop-color:#000000"
d="m 10.778332,39.821948 48.064712,0"
d="M 3.9353759,39.821947 H 58.843042"
id="path9670"
sodipodi:nodetypes="cc" />
<text

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -9,13 +9,15 @@
#include "libslic3r/Execution/Execution.hpp"
#include "libslic3r/KDTreeIndirect.hpp"
#include "libslic3r/ClipperUtils.hpp"
#include "libslic3r/AABBTreeLines.hpp" // closest point to layer part
// SupportIslands
#include "libslic3r/SLA/SupportIslands/UniformSupportIsland.hpp"
using namespace Slic3r;
using namespace Slic3r::sla;
//#define PERMANENT_SUPPORTS
namespace {
/// <summary>
/// Struct to store support points in KD tree to fast search for nearest ones.
@ -799,6 +801,105 @@ std::vector<Vec2f> load_curve_from_file() {
return {};
}
#ifdef PERMANENT_SUPPORTS
// Processing permanent support points
// Permanent are manualy edited points by user
namespace {
struct LayerSupport
{
SupportPoint point;
Point layer_position;
size_t part_index;
};
using LayerSupports = std::vector<LayerSupport>;
size_t get_index_of_closest_part(const Point &coor, const LayerParts &parts) {
size_t count_lines = 0;
std::vector<size_t> part_lines_ends;
part_lines_ends.reserve(parts.size());
for (const LayerPart &part : parts) {
count_lines += count_points(*part.shape);
part_lines_ends.push_back(count_lines);
}
Linesf lines;
lines.reserve(count_lines);
for (const LayerPart &part : parts)
append(lines, to_linesf({*part.shape}));
AABBTreeIndirect::Tree<2, double> tree =
AABBTreeLines::build_aabb_tree_over_indexed_lines(lines);
size_t line_idx = std::numeric_limits<size_t>::max();
Vec2d coor_d = coor.cast<double>();
Vec2d hit_point;
[[maybe_unused]] double distance_sq =
AABBTreeLines::squared_distance_to_indexed_lines(lines, tree, coor_d, line_idx, hit_point);
// Find part index of closest line
for (size_t part_index = 0; part_index < part_lines_ends.size(); ++part_index)
if (line_idx < part_lines_ends[part_index]) {
// check point lais inside prev or next part shape
// When assert appear check that part index is really the correct one
assert(union_ex(
get_polygons(parts[part_index].prev_parts),
get_polygons(parts[part_index].next_parts)).contains(coor));
return part_index;
}
assert(false); // not found
return 0;
}
LayerSupports supports_for_layer(const SupportPoints &points, size_t index,
float print_z, const LayerParts &parts) {
if (index >= points.size())
return {};
LayerSupports result;
for (const SupportPoint &point = points[index]; point.pos.z() < print_z; ++index) {
// find layer part for support
size_t part_index = parts.size();
Point coor(static_cast<coord_t>(scale_(point.pos.x())),
static_cast<coord_t>(scale_(point.pos.y())));
// find part for support point
for (const LayerPart &part : parts) {
if (part.shape_extent.contains(coor) &&
part.shape->contains(coor)) {
// parts do not overlap each other
assert(part_index >= parts.size());
part_index = &part - &parts.front();
}
}
if (part_index >= parts.size()) // support point is not in any part
part_index = get_index_of_closest_part(coor, parts);
result.push_back(LayerSupport{point, coor, part_index});
}
return {};
}
/// <summary>
/// Guess range of layers by its centers
/// NOTE: not valid range for variable layer height but divide space
/// </summary>
/// <param name="layers"></param>
/// <param name="layer_id"></param>
/// <returns>Range of layers</returns>
MinMax<float> get_layer_range(const Layers &layers, size_t layer_id) {
assert(layer_id < layers.size());
if (layer_id >= layers.size())
return MinMax<float>{0., 0.};
float print_z = layers[layer_id].print_z;
float min = (layer_id == 0) ? 0.f : (layers[layer_id - 1].print_z + print_z) / 2.f;
float max = ((layer_id + 1) < layers.size()) ?
(layers[layer_id + 1].print_z + print_z) / 2.f :
print_z + (print_z - min); // last layer guess height by prev layer center
return MinMax<float>{min, max};
}
} // namespace
#endif // PERMANENT_SUPPORTS
LayerSupportPoints Slic3r::sla::generate_support_points(
const SupportPointGeneratorData &data,
const SupportPointGeneratorConfig &config,
@ -822,17 +923,33 @@ LayerSupportPoints Slic3r::sla::generate_support_points(
// Storage for support points used by grid
LayerSupportPoints result;
// permanent supports MUST be sorted by z
assert(std::is_sorted(data.permanent_supports.begin(), data.permanent_supports.end(),
[](const SupportPoint &a, const SupportPoint &b) { return a.pos.z() < b.pos.z(); }));
// Index into data.permanent_supports
size_t permanent_index = 0;
// How to propagate permanent support position into previous layers? and how deep? requirements are chained.
// IMHO it should start togetjer from islands and permanent than propagate over surface
// grid index == part in layer index
std::vector<NearPoints> prev_grids; // same count as previous layer item size
for (size_t layer_id = 0; layer_id < layers.size(); ++layer_id) {
const Layer &layer = layers[layer_id];
prepare_supports_for_layer(result, layer.print_z, config);
// grid index == part in layer index
std::vector<NearPoints> grids;
grids.reserve(layer.parts.size());
#ifdef PERMANENT_SUPPORTS
float layer_max_z = get_layer_range(layers, layer_id).max;
if (data.permanent_supports[permanent_index].pos.z() < layer_max_z){
LayerSupports permanent =
supports_for_layer(data.permanent_supports, permanent_index, layer_max_z, layer.parts);
}
#endif // PERMANENT_SUPPORTS
for (const LayerPart &part : layer.parts) {
if (part.prev_parts.empty()) { // Island ?
// only island add new grid

View File

@ -145,6 +145,7 @@ using LayerSupportPoints = std::vector<LayerSupportPoint>;
struct Layer
{
// Absolute distance from Zero - copy value from heights<float>
// It represents center of layer(range of layer is half layer size above and belowe)
float print_z; // [in mm]
// data for one expolygon
@ -165,6 +166,9 @@ struct SupportPointGeneratorData
// and connection between layers for its part
// NOTE: contain links into slices
Layers layers;
// Manualy edited supports by user should be permanent
SupportPoints permanent_supports;
};
// call during generation of support points to check cancel event

View File

@ -702,8 +702,19 @@ void SLAPrint::Steps::support_points(SLAPrintObject &po)
ThrowOnCancel cancel = [this]() { throw_if_canceled(); };
StatusFunction status = statuscb;
LayerSupportPoints layer_support_points =
generate_support_points(po.m_support_point_generator_data, config, cancel, status);
// update permanent support points
SupportPointGeneratorData &data = po.m_support_point_generator_data;
data.permanent_supports.clear();
for (const SupportPoint &p : po.model_object()->sla_support_points)
if (p.type == SupportPointType::manual_add) {
data.permanent_supports.push_back(p);
data.permanent_supports.back().pos =
po.trafo().cast<float>() * data.permanent_supports.back().pos;
}
std::sort(data.permanent_supports.begin(), data.permanent_supports.end(),
[](const SupportPoint& p1,const SupportPoint& p2){ return p1.pos.z() < p2.pos.z(); });
LayerSupportPoints layer_support_points = generate_support_points(data, config, cancel, status);
const AABBMesh& emesh = po.m_supportdata->input.emesh;
// Maximal move of support point to mesh surface,
@ -714,6 +725,10 @@ void SLAPrint::Steps::support_points(SLAPrintObject &po)
SupportPoints support_points =
move_on_mesh_surface(layer_support_points, emesh, allowed_move, cancel);
// Naive implementation only append permanent supports to the result
support_points.insert(support_points.end(),
data.permanent_supports.begin(), data.permanent_supports.end());
throw_if_canceled();
MeshSlicingParamsEx params;

View File

@ -33,9 +33,8 @@ namespace Slic3r {
namespace GUI {
GLGizmoSlaSupports::GLGizmoSlaSupports(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
: GLGizmoSlaBase(parent, icon_filename, sprite_id, slaposDrillHoles)
{
show_sla_supports(true);
: GLGizmoSlaBase(parent, icon_filename, sprite_id, slaposDrillHoles /*slaposSupportPoints*/) {
show_sla_supports(false);
}
bool GLGizmoSlaSupports::on_init()
@ -144,8 +143,6 @@ void GLGizmoSlaSupports::on_render()
glsafe(::glEnable(GL_BLEND));
glsafe(::glEnable(GL_DEPTH_TEST));
show_sla_supports(!m_editing_mode);
render_volumes();
render_points(selection);
@ -198,10 +195,15 @@ void GLGizmoSlaSupports::render_points(const Selection& selection)
const Transform3d& view_matrix = camera.get_view_matrix();
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
const ColorRGBA selected_color = ColorRGBA::REDISH();
const ColorRGBA hovered_color = ColorRGBA::CYAN();
const ColorRGBA island_color = ColorRGBA::BLUEISH();
const ColorRGBA inactive_color = ColorRGBA::LIGHT_GRAY();
const ColorRGBA manual_color = ColorRGBA::ORANGE();
ColorRGBA render_color;
for (size_t i = 0; i < cache_size; ++i) {
const sla::SupportPoint& support_point = m_editing_mode ? m_editing_cache[i].support_point : m_normal_cache[i];
const bool point_selected = m_editing_mode ? m_editing_cache[i].selected : false;
const bool clipped = is_mesh_point_clipped(support_point.pos.cast<double>());
if (i < m_point_raycasters.size()) {
@ -211,22 +213,18 @@ void GLGizmoSlaSupports::render_points(const Selection& selection)
if (clipped)
continue;
render_color = support_point.type == sla::SupportPointType::manual_add ?
manual_color : inactive_color;
// First decide about the color of the point.
if (size_t(m_hover_id) == i && m_editing_mode) // ignore hover state unless editing mode is active
render_color = { 0.f, 1.f, 1.f, 1.f };
else { // neigher hover nor picking
bool supports_new_island = m_lock_unique_islands && support_point.type == sla::SupportPointType::island;
if (m_editing_mode) {
if (point_selected)
render_color = { 1.f, 0.3f, 0.3f, 1.f};
else
if (supports_new_island)
render_color = { 0.3f, 0.3f, 1.f, 1.f };
else
render_color = { 0.7f, 0.7f, 0.7f, 1.f };
if (m_editing_mode) {
if (size_t(m_hover_id) == i) // ignore hover state unless editing mode is active
render_color = hovered_color;
else if (m_editing_cache[i].selected)
render_color = selected_color;
else if (m_lock_unique_islands) {
render_color = support_point.type == sla::SupportPointType::island?
island_color : ColorRGBA{ 0.7f, 0.7f, 0.7f, 1.f };
}
else
render_color = { 0.5f, 0.5f, 0.5f, 1.f };
}
m_cone.model.set_color(render_color);
@ -680,10 +678,16 @@ RENDER_AGAIN:
}
else { // not in editing mode:
m_imgui->disabled_begin(!is_input_enabled());
//ImGui::AlignTextToFramePadding();
ImGuiPureWrap::text(m_desc.at("points_density"));
//ImGui::SameLine(settings_sliders_left);
ImGui::SameLine();
if (ImGui::Checkbox("##ShowSupportStructure", &m_show_support_structure)){
show_sla_supports(m_show_support_structure);
if (m_show_support_structure)
reslice_until_step(slaposPad);
} else if (ImGui::IsItemHovered())
ImGui::SetTooltip("%s", _u8L("Show/Hide supporting structure").c_str());
const char *support_points_density = "support_points_density_relative";
float density = static_cast<const ConfigOptionInt*>(get_config_options({support_points_density})[0])->value;
if (m_imgui->slider_float("##density", &density, 0.f, 200.f, "%.f %%")){
@ -711,7 +715,7 @@ RENDER_AGAIN:
wxGetApp().obj_list()->update_and_show_object_settings_item();
auto_generate();
}
const sla::SupportPoints &supports = m_normal_cache;
int count_user_edited = 0;
int count_island = 0;
@ -734,22 +738,26 @@ RENDER_AGAIN:
}
ImVec4 light_gray{0.4f, 0.4f, 0.4f, 1.0f};
ImGui::TextColored(light_gray, stats.c_str());
if (supports.empty()){
ImGui::SameLine();
if (ImGuiPureWrap::button(m_desc.at("auto_generate")))
auto_generate();
}
ImGui::Separator(); // START temporary debug
ImGui::Text("Between delimiters is temporary GUI");
sla::SampleConfig &sample_config = sla::SampleConfigFactory::get_sample_config();
if (float overhang_sample_distance = sample_config.prepare_config.discretize_overhang_step;
m_imgui->slider_float("overhang discretization", &overhang_sample_distance, 2e-5f, 10.f, "%.2f mm")){
sample_config.prepare_config.discretize_overhang_step = overhang_sample_distance;
} else if (ImGui::IsItemHovered())
ImGui::SetTooltip("Smaller will slow down. Step for discretization overhang outline for test of support need");
draw_island_config();
ImGui::Text("Distribution depends on './resources/data/sla_support.svg'\ninstruction for edit are in file");
ImGui::Separator();
if (ImGuiPureWrap::button(m_desc.at("auto_generate")))
auto_generate();
//ImGui::Separator(); // START temporary debug
//ImGui::Text("Between delimiters is temporary GUI");
//sla::SampleConfig &sample_config = sla::SampleConfigFactory::get_sample_config();
//if (float overhang_sample_distance = sample_config.prepare_config.discretize_overhang_step;
// m_imgui->slider_float("overhang discretization", &overhang_sample_distance, 2e-5f, 10.f, "%.2f mm")){
// sample_config.prepare_config.discretize_overhang_step = overhang_sample_distance;
//} else if (ImGui::IsItemHovered())
// ImGui::SetTooltip("Smaller will slow down. Step for discretization overhang outline for test of support need");
//
//draw_island_config();
//ImGui::Text("Distribution depends on './resources/data/sla_support.svg'\ninstruction for edit are in file");
//ImGui::Separator();
//if (ImGuiPureWrap::button(m_desc.at("auto_generate")))
// auto_generate();
ImGui::Separator();
if (ImGuiPureWrap::button(m_desc.at("manual_editing")))
@ -1180,7 +1188,7 @@ void GLGizmoSlaSupports::editing_mode_apply_changes()
mo->sla_support_points.clear();
mo->sla_support_points = m_normal_cache;
reslice_until_step(slaposPad);
reslice_until_step(m_show_support_structure ? slaposPad : slaposSupportPoints);
}
}
@ -1280,7 +1288,8 @@ void GLGizmoSlaSupports::get_data_from_backend()
for (const SLAPrintObject* po : m_parent.sla_print()->objects()) {
if (po->model_object()->id() == mo->id()) {
m_normal_cache.clear();
auto mat = po->trafo().inverse().cast<float>();
auto mat = po->trafo().inverse().cast<float>(); // TODO: WTF trafo????? !!!!!!
for (const sla::SupportPoint &p : po->get_support_points())
m_normal_cache.emplace_back(sla::SupportPoint{mat * p.pos, p.head_front_radius, p.type});
@ -1298,25 +1307,25 @@ void GLGizmoSlaSupports::auto_generate()
{
//wxMessageDialog dlg(GUI::wxGetApp().plater(),
MessageDialog dlg(GUI::wxGetApp().plater(),
_L("Autogeneration will erase all manually edited points.") + "\n\n" +
_L("Are you sure you want to do it?") + "\n",
_L("Autogeneration with manually edited points is inperfect but preserve wanted postion of supports.") + "\n\n" +
_L("Do you want to remove manually edited points?") + "\n",
_L("Warning"), wxICON_WARNING | wxYES | wxNO);
ModelObject* mo = m_c->selection_info()->model_object();
if (mo->sla_points_status != sla::PointsStatus::UserModified || m_normal_cache.empty() || dlg.ShowModal() == wxID_YES) {
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Autogenerate support points"));
wxGetApp().CallAfter([this]() { reslice_until_step(slaposSupportPoints); });
mo->sla_points_status = sla::PointsStatus::Generating;
if (mo->sla_points_status == sla::PointsStatus::UserModified &&
dlg.ShowModal() == wxID_YES) {
mo->sla_support_points.clear();
}
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Autogenerate support points"));
wxGetApp().CallAfter([this]() { reslice_until_step(
m_show_support_structure ? slaposPad : slaposSupportPoints); });
mo->sla_points_status = sla::PointsStatus::Generating;
}
void GLGizmoSlaSupports::switch_to_editing_mode()
{
wxGetApp().plater()->enter_gizmos_stack();
m_editing_mode = true;
show_sla_supports(false);
m_editing_cache.clear();
for (const sla::SupportPoint& sp : m_normal_cache)
m_editing_cache.emplace_back(sp);
@ -1330,6 +1339,7 @@ void GLGizmoSlaSupports::disable_editing_mode()
{
if (m_editing_mode) {
m_editing_mode = false;
show_sla_supports(m_show_support_structure);
wxGetApp().plater()->leave_gizmos_stack();
m_parent.set_as_dirty();
unregister_point_raycasters_for_picking();

View File

@ -93,6 +93,7 @@ private:
void draw_island_config();
bool m_show_support_structure = false;
bool m_lock_unique_islands = false;
bool m_editing_mode = false; // Is editing mode active?
float m_new_point_head_diameter; // Size of a new point.