mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-15 14:15:53 +08:00
Add support settings into GUI
This commit is contained in:
parent
02ca74cced
commit
74db5d1ed2
@ -26,13 +26,13 @@
|
|||||||
showgrid="false"
|
showgrid="false"
|
||||||
showborder="true"
|
showborder="true"
|
||||||
borderlayer="true"
|
borderlayer="true"
|
||||||
inkscape:zoom="3.3638608"
|
inkscape:zoom="19.02887"
|
||||||
inkscape:cx="92.601929"
|
inkscape:cx="14.845863"
|
||||||
inkscape:cy="110.88449"
|
inkscape:cy="132.29897"
|
||||||
inkscape:window-width="1920"
|
inkscape:window-width="2400"
|
||||||
inkscape:window-height="1129"
|
inkscape:window-height="1261"
|
||||||
inkscape:window-x="1912"
|
inkscape:window-x="-9"
|
||||||
inkscape:window-y="-8"
|
inkscape:window-y="-9"
|
||||||
inkscape:window-maximized="1"
|
inkscape:window-maximized="1"
|
||||||
inkscape:current-layer="layer1" />
|
inkscape:current-layer="layer1" />
|
||||||
<defs
|
<defs
|
||||||
@ -130,7 +130,7 @@
|
|||||||
id="path12735" />
|
id="path12735" />
|
||||||
<path
|
<path
|
||||||
style="fill:none;stroke:#b50000;stroke-width:0.4;stroke-linejoin:round;stroke-dasharray:none;stop-color:#000000"
|
style="fill:none;stroke:#b50000;stroke-width:0.4;stroke-linejoin:round;stroke-dasharray:none;stop-color:#000000"
|
||||||
d="M 5,0 6,3.8987591 8,15 10,40"
|
d="M 4,0 6,3.8987591 8,15 10,40"
|
||||||
id="path3587"
|
id="path3587"
|
||||||
sodipodi:nodetypes="cccc" />
|
sodipodi:nodetypes="cccc" />
|
||||||
<text
|
<text
|
||||||
@ -174,7 +174,7 @@
|
|||||||
style="font-weight:normal;font-size:2.11667px;stroke-width:0.4"
|
style="font-weight:normal;font-size:2.11667px;stroke-width:0.4"
|
||||||
x="24.711193"
|
x="24.711193"
|
||||||
y="63.303635"
|
y="63.303635"
|
||||||
id="tspan9676" /></text>
|
id="tspan9676">Last virtual point of curve is [last.x, ∞]</tspan></text>
|
||||||
<text
|
<text
|
||||||
xml:space="preserve"
|
xml:space="preserve"
|
||||||
style="font-size:2.11667px;line-height:1.3;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"
|
style="font-size:2.11667px;line-height:1.3;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"
|
||||||
@ -356,6 +356,6 @@
|
|||||||
id="text17458"><tspan
|
id="text17458"><tspan
|
||||||
sodipodi:role="line"
|
sodipodi:role="line"
|
||||||
id="tspan17456"
|
id="tspan17456"
|
||||||
style="stroke-width:2.5"></tspan></text>
|
style="stroke-width:2.5" /></text>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
@ -473,6 +473,7 @@ set(SLIC3R_SOURCES
|
|||||||
SLA/SupportIslands/PostProcessNeighbors.cpp
|
SLA/SupportIslands/PostProcessNeighbors.cpp
|
||||||
SLA/SupportIslands/PostProcessNeighbors.hpp
|
SLA/SupportIslands/PostProcessNeighbors.hpp
|
||||||
SLA/SupportIslands/SampleConfig.hpp
|
SLA/SupportIslands/SampleConfig.hpp
|
||||||
|
SLA/SupportIslands/SampleConfigFactory.cpp
|
||||||
SLA/SupportIslands/SampleConfigFactory.hpp
|
SLA/SupportIslands/SampleConfigFactory.hpp
|
||||||
SLA/SupportIslands/SampleIslandUtils.cpp
|
SLA/SupportIslands/SampleIslandUtils.cpp
|
||||||
SLA/SupportIslands/SampleIslandUtils.hpp
|
SLA/SupportIslands/SampleIslandUtils.hpp
|
||||||
|
@ -13,12 +13,12 @@ struct SampleConfig
|
|||||||
{
|
{
|
||||||
// Every point on island has at least one support point in maximum distance
|
// Every point on island has at least one support point in maximum distance
|
||||||
// MUST be bigger than zero
|
// MUST be bigger than zero
|
||||||
coord_t max_distance = 2;
|
coord_t max_distance = static_cast<coord_t>(scale_(5.));
|
||||||
coord_t half_distance = 1; // has to be half od max_distance
|
coord_t half_distance = static_cast<coord_t>(scale_(2.5)); // has to be half od max_distance
|
||||||
|
|
||||||
// Support point head radius
|
// Support point head radius
|
||||||
// MUST be bigger than zero
|
// MUST be bigger than zero
|
||||||
coord_t head_radius = 1; // [nano meter]
|
coord_t head_radius = static_cast<coord_t>(scale_(.4)); // [nano meter]
|
||||||
|
|
||||||
// When it is possible, there will be this minimal distance from outline.
|
// When it is possible, there will be this minimal distance from outline.
|
||||||
// zero when head should be on outline
|
// zero when head should be on outline
|
||||||
@ -27,7 +27,7 @@ struct SampleConfig
|
|||||||
// Measured as sum of VD edge length from outline
|
// Measured as sum of VD edge length from outline
|
||||||
// Used only when there is no space for outline offset on first/last point
|
// Used only when there is no space for outline offset on first/last point
|
||||||
// Must be bigger than minimal_distance_from_outline
|
// Must be bigger than minimal_distance_from_outline
|
||||||
coord_t maximal_distance_from_outline = 1.;// [nano meter]
|
coord_t maximal_distance_from_outline = static_cast<coord_t>(scale_(1.));// [nano meter]
|
||||||
|
|
||||||
// When angle on outline is smaller than max_interesting_angle
|
// When angle on outline is smaller than max_interesting_angle
|
||||||
// than create unmovable support point.
|
// than create unmovable support point.
|
||||||
@ -44,23 +44,23 @@ struct SampleConfig
|
|||||||
|
|
||||||
// Maximal length of longest path in voronoi diagram to be island
|
// Maximal length of longest path in voronoi diagram to be island
|
||||||
// supported only by one single support point this point will be in center of path.
|
// supported only by one single support point this point will be in center of path.
|
||||||
coord_t max_length_for_one_support_point = 1.;
|
coord_t max_length_for_one_support_point = static_cast<coord_t>(scale_(1.));
|
||||||
|
|
||||||
// Maximal length of island supported by 2 points
|
// Maximal length of island supported by 2 points
|
||||||
coord_t max_length_for_two_support_points = 1.;
|
coord_t max_length_for_two_support_points = static_cast<coord_t>(scale_(1.));
|
||||||
|
|
||||||
// Maximal width of line island supported in the middle of line
|
// Maximal width of line island supported in the middle of line
|
||||||
// Must be greater or equal to min_width_for_outline_support
|
// Must be greater or equal to min_width_for_outline_support
|
||||||
coord_t max_width_for_center_support_line = 1.;
|
coord_t max_width_for_center_support_line = static_cast<coord_t>(scale_(1.));
|
||||||
|
|
||||||
// Minimal width to be supported by outline
|
// Minimal width to be supported by outline
|
||||||
// Must be smaller or equal to max_width_for_center_support_line
|
// Must be smaller or equal to max_width_for_center_support_line
|
||||||
coord_t min_width_for_outline_support = 1.;
|
coord_t min_width_for_outline_support = static_cast<coord_t>(scale_(1.));
|
||||||
|
|
||||||
|
|
||||||
// Term criteria for end of alignment
|
// Term criteria for end of alignment
|
||||||
// Minimal change in manhatn move of support position before termination
|
// Minimal change in manhatn move of support position before termination
|
||||||
coord_t minimal_move = 1000; // in nanometers, devide from print resolution to quater pixel
|
coord_t minimal_move = static_cast<coord_t>(scale_(.01)); // devide from print resolution to quater pixel
|
||||||
|
|
||||||
// Maximal count of align iteration
|
// Maximal count of align iteration
|
||||||
size_t count_iteration = 100;
|
size_t count_iteration = 100;
|
||||||
@ -75,7 +75,7 @@ struct SampleConfig
|
|||||||
// There is no need to calculate with precisse island
|
// There is no need to calculate with precisse island
|
||||||
// NOTE: Slice of Cylinder bottom has tip of trinagles on contour
|
// NOTE: Slice of Cylinder bottom has tip of trinagles on contour
|
||||||
// (neighbor coordinate - create issue in voronoi)
|
// (neighbor coordinate - create issue in voronoi)
|
||||||
double simplification_tolerance = 1e4; // [nm]
|
double simplification_tolerance = scale_(0.05 /*mm*/);
|
||||||
};
|
};
|
||||||
} // namespace Slic3r::sla
|
} // namespace Slic3r::sla
|
||||||
#endif // slic3r_SLA_SuppotstIslands_SampleConfig_hpp_
|
#endif // slic3r_SLA_SuppotstIslands_SampleConfig_hpp_
|
||||||
|
104
src/libslic3r/SLA/SupportIslands/SampleConfigFactory.cpp
Normal file
104
src/libslic3r/SLA/SupportIslands/SampleConfigFactory.cpp
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
#include "SampleConfigFactory.hpp"
|
||||||
|
|
||||||
|
using namespace Slic3r::sla;
|
||||||
|
|
||||||
|
bool SampleConfigFactory::verify(SampleConfig &cfg) {
|
||||||
|
auto verify_max = [](coord_t &c, coord_t max) {
|
||||||
|
assert(c <= max);
|
||||||
|
if (c > max) {
|
||||||
|
c = max;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
auto verify_min = [](coord_t &c, coord_t min) {
|
||||||
|
assert(c >= min);
|
||||||
|
if (c < min) {
|
||||||
|
c = min;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
auto verify_min_max = [](coord_t &min, coord_t &max) {
|
||||||
|
// min must be smaller than max
|
||||||
|
assert(min < max);
|
||||||
|
if (min > max) {
|
||||||
|
std::swap(min, max);
|
||||||
|
return false;
|
||||||
|
} else if (min == max) {
|
||||||
|
min /= 2; // cut in half
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
bool res = true;
|
||||||
|
res &= verify_min_max(cfg.max_length_for_one_support_point, cfg.max_length_for_two_support_points);
|
||||||
|
res &= verify_min_max(cfg.min_width_for_outline_support, cfg.max_width_for_center_support_line); // check histeresis
|
||||||
|
res &= verify_max(cfg.max_length_for_one_support_point,
|
||||||
|
2 * cfg.max_distance +
|
||||||
|
2 * cfg.head_radius +
|
||||||
|
2 * cfg.minimal_distance_from_outline);
|
||||||
|
res &= verify_min(cfg.max_length_for_one_support_point,
|
||||||
|
2 * cfg.head_radius + 2 * cfg.minimal_distance_from_outline);
|
||||||
|
res &= verify_max(cfg.max_length_for_two_support_points,
|
||||||
|
2 * cfg.max_distance +
|
||||||
|
2 * 2 * cfg.head_radius +
|
||||||
|
2 * cfg.minimal_distance_from_outline);
|
||||||
|
res &= verify_min(cfg.max_width_for_center_support_line,
|
||||||
|
2 * cfg.head_radius + 2 * cfg.minimal_distance_from_outline);
|
||||||
|
res &= verify_max(cfg.max_width_for_center_support_line,
|
||||||
|
2 * cfg.max_distance + 2 * cfg.head_radius);
|
||||||
|
if (!res) while (!verify(cfg));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
SampleConfig SampleConfigFactory::create(float support_head_diameter_in_mm)
|
||||||
|
{
|
||||||
|
coord_t head_diameter = static_cast<coord_t>(scale_(support_head_diameter_in_mm));
|
||||||
|
coord_t minimal_distance = head_diameter * 7;
|
||||||
|
coord_t min_distance = head_diameter / 2 + minimal_distance;
|
||||||
|
coord_t max_distance = 3 * min_distance;
|
||||||
|
|
||||||
|
// TODO: find valid params !!!!
|
||||||
|
SampleConfig result;
|
||||||
|
result.max_distance = max_distance;
|
||||||
|
result.half_distance = result.max_distance / 2;
|
||||||
|
result.head_radius = head_diameter / 2;
|
||||||
|
result.minimal_distance_from_outline = result.head_radius;
|
||||||
|
result.maximal_distance_from_outline = result.max_distance/3;
|
||||||
|
assert(result.minimal_distance_from_outline < result.maximal_distance_from_outline);
|
||||||
|
result.minimal_support_distance = result.minimal_distance_from_outline +
|
||||||
|
result.half_distance;
|
||||||
|
|
||||||
|
result.min_side_branch_length = 2 * result.minimal_distance_from_outline + result.max_distance/4;
|
||||||
|
result.max_length_for_one_support_point =
|
||||||
|
max_distance / 3 +
|
||||||
|
2 * result.minimal_distance_from_outline +
|
||||||
|
head_diameter;
|
||||||
|
result.max_length_for_two_support_points =
|
||||||
|
result.max_length_for_one_support_point + max_distance / 2;
|
||||||
|
result.max_width_for_center_support_line =
|
||||||
|
2 * head_diameter + 2 * result.minimal_distance_from_outline +
|
||||||
|
max_distance / 2;
|
||||||
|
result.min_width_for_outline_support = result.max_width_for_center_support_line - 2 * head_diameter;
|
||||||
|
result.outline_sample_distance = 3*result.max_distance/4;
|
||||||
|
|
||||||
|
// Align support points
|
||||||
|
// TODO: propagate print resolution
|
||||||
|
result.minimal_move = scale_(0.1); // 0.1 mm is enough
|
||||||
|
// [in nanometers --> 0.01mm ], devide from print resolution to quater pixel is too strict
|
||||||
|
result.count_iteration = 30; // speed VS precission
|
||||||
|
result.max_align_distance = result.max_distance / 2;
|
||||||
|
|
||||||
|
verify(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<SampleConfig> SampleConfigFactory::gui_sample_config_opt;
|
||||||
|
SampleConfig &SampleConfigFactory::get_sample_config() {
|
||||||
|
// init config
|
||||||
|
if (!gui_sample_config_opt.has_value())
|
||||||
|
// create default configuration
|
||||||
|
gui_sample_config_opt = sla::SampleConfigFactory::create(.4f);
|
||||||
|
return *gui_sample_config_opt;
|
||||||
|
}
|
@ -1,8 +1,9 @@
|
|||||||
#ifndef slic3r_SLA_SuppotstIslands_SampleConfigFactory_hpp_
|
#ifndef slic3r_SLA_SuppotstIslands_SampleConfigFactory_hpp_
|
||||||
#define slic3r_SLA_SuppotstIslands_SampleConfigFactory_hpp_
|
#define slic3r_SLA_SuppotstIslands_SampleConfigFactory_hpp_
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
#include "SampleConfig.hpp"
|
#include "SampleConfig.hpp"
|
||||||
#include "../SupportPointGenerator.hpp"
|
#include "libslic3r/PrintConfig.hpp"
|
||||||
|
|
||||||
namespace Slic3r::sla {
|
namespace Slic3r::sla {
|
||||||
|
|
||||||
@ -14,78 +15,15 @@ class SampleConfigFactory
|
|||||||
public:
|
public:
|
||||||
SampleConfigFactory() = delete;
|
SampleConfigFactory() = delete;
|
||||||
|
|
||||||
// factory method to iniciate config
|
static bool verify(SampleConfig &cfg);
|
||||||
static SampleConfig create(const SupportPointGeneratorConfig &config)
|
static SampleConfig create(float support_head_diameter_in_mm);
|
||||||
{
|
|
||||||
coord_t head_diameter = scale_((double)config.head_diameter.min);
|
|
||||||
coord_t minimal_distance = head_diameter * 7;
|
|
||||||
coord_t min_distance = head_diameter / 2 + minimal_distance;
|
|
||||||
coord_t max_distance = 3 * min_distance;
|
|
||||||
|
|
||||||
// TODO: find valid params !!!!
|
private:
|
||||||
SampleConfig result;
|
// TODO: REMOVE IT. Do not use in production
|
||||||
result.max_distance = max_distance;
|
// Global variable to temporary set configuration from GUI into SLA print steps
|
||||||
result.half_distance = result.max_distance / 2;
|
static std::optional<SampleConfig> gui_sample_config_opt;
|
||||||
result.head_radius = head_diameter / 2;
|
public:
|
||||||
result.minimal_distance_from_outline = result.head_radius;
|
static SampleConfig &get_sample_config();
|
||||||
result.maximal_distance_from_outline = result.max_distance/3;
|
|
||||||
assert(result.minimal_distance_from_outline < result.maximal_distance_from_outline);
|
|
||||||
result.minimal_support_distance = result.minimal_distance_from_outline +
|
|
||||||
result.half_distance;
|
|
||||||
|
|
||||||
result.min_side_branch_length = 2 * result.minimal_distance_from_outline;
|
|
||||||
|
|
||||||
result.max_length_for_one_support_point =
|
|
||||||
2 * result.minimal_distance_from_outline +
|
|
||||||
head_diameter;
|
|
||||||
coord_t max_length_for_one_support_point =
|
|
||||||
2 * max_distance +
|
|
||||||
head_diameter +
|
|
||||||
2 * result.minimal_distance_from_outline;
|
|
||||||
if (result.max_length_for_one_support_point > max_length_for_one_support_point)
|
|
||||||
result.max_length_for_one_support_point = max_length_for_one_support_point;
|
|
||||||
coord_t min_length_for_one_support_point =
|
|
||||||
2 * head_diameter +
|
|
||||||
2 * result.minimal_distance_from_outline;
|
|
||||||
if (result.max_length_for_one_support_point < min_length_for_one_support_point)
|
|
||||||
result.max_length_for_one_support_point = min_length_for_one_support_point;
|
|
||||||
|
|
||||||
result.max_length_for_two_support_points =
|
|
||||||
2 * max_distance + 2 * head_diameter +
|
|
||||||
2 * result.minimal_distance_from_outline;
|
|
||||||
coord_t max_length_for_two_support_points =
|
|
||||||
2 * max_distance +
|
|
||||||
2 * head_diameter +
|
|
||||||
2 * result.minimal_distance_from_outline;
|
|
||||||
if (result.max_length_for_two_support_points > max_length_for_two_support_points)
|
|
||||||
result.max_length_for_two_support_points = max_length_for_two_support_points;
|
|
||||||
assert(result.max_length_for_two_support_points > result.max_length_for_one_support_point);
|
|
||||||
|
|
||||||
result.max_width_for_center_support_line =
|
|
||||||
2 * head_diameter + 2 * result.minimal_distance_from_outline +
|
|
||||||
max_distance / 2;
|
|
||||||
coord_t min_width_for_center_support_line = head_diameter + 2 * result.minimal_distance_from_outline;
|
|
||||||
if (result.max_width_for_center_support_line < min_width_for_center_support_line)
|
|
||||||
result.max_width_for_center_support_line = min_width_for_center_support_line;
|
|
||||||
coord_t max_width_for_center_support_line = 2 * max_distance + head_diameter;
|
|
||||||
if (result.max_width_for_center_support_line > max_width_for_center_support_line)
|
|
||||||
result.max_width_for_center_support_line = max_width_for_center_support_line;
|
|
||||||
|
|
||||||
result.min_width_for_outline_support = result.max_width_for_center_support_line - 2 * head_diameter;
|
|
||||||
assert(result.min_width_for_outline_support <= result.max_width_for_center_support_line);
|
|
||||||
|
|
||||||
result.outline_sample_distance = 3*result.max_distance/4;
|
|
||||||
|
|
||||||
// Align support points
|
|
||||||
// TODO: propagate print resolution
|
|
||||||
result.minimal_move = scale_(0.1); // 0.1 mm is enough
|
|
||||||
// [in nanometers --> 0.01mm ], devide from print resolution to quater pixel is too strict
|
|
||||||
result.count_iteration = 30; // speed VS precission
|
|
||||||
result.max_align_distance = result.max_distance / 2;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Slic3r::sla
|
} // namespace Slic3r::sla
|
||||||
#endif // slic3r_SLA_SuppotstIslands_SampleConfigFactory_hpp_
|
#endif // slic3r_SLA_SuppotstIslands_SampleConfigFactory_hpp_
|
||||||
|
@ -57,26 +57,84 @@ const ExPolygon &get_expolygon_with_biggest_contour(const ExPolygons &expolygons
|
|||||||
}
|
}
|
||||||
return *biggest;
|
return *biggest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// When radius of all points is smaller than max radius set output center and return true
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="points"></param>
|
||||||
|
/// <param name="max_radius"></param>
|
||||||
|
/// <param name="output_center"></param>
|
||||||
|
/// <returns>True when Bounding box of points is smaller than max radius</returns>
|
||||||
|
bool get_center(const Points &points, coord_t max_radius, Point& output_center){
|
||||||
|
if (points.size()<=2)
|
||||||
|
return false;
|
||||||
|
auto it = points.begin();
|
||||||
|
Point min = *it;
|
||||||
|
Point max = *it;
|
||||||
|
for (++it; it != points.end(); ++it) {
|
||||||
|
if (min.x() > it->x()) {
|
||||||
|
min.x() = it->x();
|
||||||
|
if (max.x() - min.x() > max_radius)
|
||||||
|
return false;
|
||||||
|
} else if(max.x() < it->x()) {
|
||||||
|
max.x() = it->x();
|
||||||
|
if (max.x() - min.x() > max_radius)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (min.y() > it->y()) {
|
||||||
|
min.y() = it->y();
|
||||||
|
if (max.y() - min.y() > max_radius)
|
||||||
|
return false;
|
||||||
|
} else if (max.y() < it->y()) {
|
||||||
|
max.y() = it->y();
|
||||||
|
if (max.y() - min.y() > max_radius)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// prevent overflow of point range, no care about 1 size
|
||||||
|
output_center = min/2 + max/2;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Decrease level of detail
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="island">Polygon to reduce count of points</param>
|
||||||
|
/// <param name="config">Define progressivness of reduction</param>
|
||||||
|
/// <returns>Simplified island</returns>
|
||||||
|
ExPolygon get_simplified(const ExPolygon &island, const SampleConfig &config) {
|
||||||
|
//// closing similar to FDM arachne do before voronoi inspiration in make_expolygons inside TriangleMeshSlicer
|
||||||
|
//float closing_radius = scale_(0.0499f);
|
||||||
|
//float offset_out = closing_radius;
|
||||||
|
//float offset_in = -closing_radius;
|
||||||
|
//ExPolygons closed_expolygons = offset2_ex({island}, offset_out, offset_in); // mitter
|
||||||
|
//ExPolygon closed_expolygon = get_expolygon_with_biggest_contour(closed_expolygons);
|
||||||
|
//// "Close" operation still create neighbor pixel for sharp triangle tip - cause VD issues
|
||||||
|
|
||||||
|
ExPolygons simplified_expolygons = island.simplify(config.simplification_tolerance);
|
||||||
|
return simplified_expolygons.empty() ?
|
||||||
|
island : get_expolygon_with_biggest_contour(simplified_expolygons);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
SupportIslandPoints SampleIslandUtils::uniform_cover_island(
|
SupportIslandPoints SampleIslandUtils::uniform_cover_island(
|
||||||
const ExPolygon &island, const SampleConfig &config
|
const ExPolygon &island, const SampleConfig &config
|
||||||
) {
|
) {
|
||||||
// closing similar to FDM arachne do before voronoi
|
ExPolygon simplified_island = get_simplified(island, config);
|
||||||
// inspired by make_expolygons inside TriangleMeshSlicer
|
|
||||||
float closing_radius = scale_(0.0499f);
|
|
||||||
float offset_out = closing_radius;
|
|
||||||
float offset_in = -closing_radius;
|
|
||||||
ExPolygons closed_expolygons = offset2_ex({island}, offset_out, offset_in); // mitter
|
|
||||||
ExPolygon closed_expolygon = get_expolygon_with_biggest_contour(closed_expolygons);
|
|
||||||
|
|
||||||
// "Close" operation create neighbor pixel for sharp triangle tip
|
// When island is smaller than minimal-head diameter,
|
||||||
double tolerance = scale_(0.05);
|
// it will be supported whole by support poin in center
|
||||||
ExPolygons simplified_expolygons = island.simplify(tolerance);
|
if (Point center; get_center(simplified_island.contour.points, config.head_radius, center)) {
|
||||||
ExPolygon simplified_expolygon = get_expolygon_with_biggest_contour(simplified_expolygons);
|
SupportIslandPoints result;
|
||||||
|
result.push_back(std::make_unique<SupportIslandNoMovePoint>(
|
||||||
|
center, SupportIslandInnerPoint::Type::one_bb_center_point));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
Slic3r::Geometry::VoronoiDiagram vd;
|
Slic3r::Geometry::VoronoiDiagram vd;
|
||||||
Lines lines = to_lines(simplified_expolygon);
|
Lines lines = to_lines(simplified_island);
|
||||||
vd.construct_voronoi(lines.begin(), lines.end());
|
vd.construct_voronoi(lines.begin(), lines.end());
|
||||||
Slic3r::Voronoi::annotate_inside_outside(vd, lines);
|
Slic3r::Voronoi::annotate_inside_outside(vd, lines);
|
||||||
VoronoiGraph skeleton = VoronoiGraphUtils::create_skeleton(vd, lines);
|
VoronoiGraph skeleton = VoronoiGraphUtils::create_skeleton(vd, lines);
|
||||||
@ -976,7 +1034,6 @@ SupportIslandPoints SampleIslandUtils::sample_voronoi_graph(
|
|||||||
// every island has to have a point on contour
|
// every island has to have a point on contour
|
||||||
assert(start_node != nullptr);
|
assert(start_node != nullptr);
|
||||||
longest_path = VoronoiGraphUtils::create_longest_path(start_node);
|
longest_path = VoronoiGraphUtils::create_longest_path(start_node);
|
||||||
// longest_path = create_longest_path_recursive(start_node);
|
|
||||||
|
|
||||||
#ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_VORONOI_GRAPH_TO_SVG_PATH
|
#ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_VORONOI_GRAPH_TO_SVG_PATH
|
||||||
{
|
{
|
||||||
|
@ -34,6 +34,7 @@ public:
|
|||||||
outline, // keep position align with island outline
|
outline, // keep position align with island outline
|
||||||
inner, // point inside wide part, without restriction on move
|
inner, // point inside wide part, without restriction on move
|
||||||
|
|
||||||
|
one_bb_center_point, // for island smaller than head radius
|
||||||
undefined
|
undefined
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
#include "libslic3r/KDTreeIndirect.hpp"
|
#include "libslic3r/KDTreeIndirect.hpp"
|
||||||
|
|
||||||
// SupportIslands
|
// SupportIslands
|
||||||
#include "libslic3r/SLA/SupportIslands/SampleConfigFactory.hpp"
|
|
||||||
#include "libslic3r/SLA/SupportIslands/SampleIslandUtils.hpp"
|
#include "libslic3r/SLA/SupportIslands/SampleIslandUtils.hpp"
|
||||||
|
|
||||||
using namespace Slic3r;
|
using namespace Slic3r;
|
||||||
@ -232,7 +231,6 @@ void support_part_overhangs(
|
|||||||
(const LayerSupportPoint &support_point, const Point &p) -> bool {
|
(const LayerSupportPoint &support_point, const Point &p) -> bool {
|
||||||
// Debug visualization of all sampled outline
|
// Debug visualization of all sampled outline
|
||||||
//return false;
|
//return false;
|
||||||
|
|
||||||
coord_t r = support_point.current_radius;
|
coord_t r = support_point.current_radius;
|
||||||
Point dp = support_point.position_on_layer - p;
|
Point dp = support_point.position_on_layer - p;
|
||||||
if (std::abs(dp.x()) > r) return false;
|
if (std::abs(dp.x()) > r) return false;
|
||||||
@ -270,8 +268,7 @@ void support_part_overhangs(
|
|||||||
/// <param name="cfg"></param>
|
/// <param name="cfg"></param>
|
||||||
void support_island(const LayerPart &part, NearPoints& near_points, float part_z,
|
void support_island(const LayerPart &part, NearPoints& near_points, float part_z,
|
||||||
const SupportPointGeneratorConfig &cfg) {
|
const SupportPointGeneratorConfig &cfg) {
|
||||||
SampleConfig sample_cfg = SampleConfigFactory::create(cfg);
|
SupportIslandPoints samples = SampleIslandUtils::uniform_cover_island(*part.shape, cfg.island_configuration);
|
||||||
SupportIslandPoints samples = SampleIslandUtils::uniform_cover_island(*part.shape, sample_cfg);
|
|
||||||
//samples = {std::make_unique<SupportIslandPoint>(island.contour.centroid())};
|
//samples = {std::make_unique<SupportIslandPoint>(island.contour.centroid())};
|
||||||
for (const SupportIslandPointPtr &sample : samples)
|
for (const SupportIslandPointPtr &sample : samples)
|
||||||
near_points.add(LayerSupportPoint{
|
near_points.add(LayerSupportPoint{
|
||||||
@ -443,6 +440,12 @@ Points sample_overhangs(const LayerPart& part, double dist2) {
|
|||||||
|
|
||||||
void prepare_supports_for_layer(LayerSupportPoints &supports, float layer_z,
|
void prepare_supports_for_layer(LayerSupportPoints &supports, float layer_z,
|
||||||
const SupportPointGeneratorConfig &config) {
|
const SupportPointGeneratorConfig &config) {
|
||||||
|
auto set_radius = [&config](LayerSupportPoint &support, float radius) {
|
||||||
|
if (!is_approx(config.density_relative, 1.f, 1e-4f)) // exist relative density
|
||||||
|
radius /= config.density_relative;
|
||||||
|
support.current_radius = static_cast<coord_t>(scale_(radius));
|
||||||
|
};
|
||||||
|
|
||||||
const std::vector<Vec2f>& curve = config.support_curve;
|
const std::vector<Vec2f>& curve = config.support_curve;
|
||||||
// calculate support area for each support point as radius
|
// calculate support area for each support point as radius
|
||||||
// IMPROVE: use some offsets of previous supported island
|
// IMPROVE: use some offsets of previous supported island
|
||||||
@ -458,7 +461,7 @@ void prepare_supports_for_layer(LayerSupportPoints &supports, float layer_z,
|
|||||||
|
|
||||||
if ((index+1) >= curve.size()) {
|
if ((index+1) >= curve.size()) {
|
||||||
// set maximal radius
|
// set maximal radius
|
||||||
support.current_radius = static_cast<coord_t>(scale_(curve.back().x()));
|
set_radius(support, curve.back().x());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// interpolate radius on input curve
|
// interpolate radius on input curve
|
||||||
@ -467,7 +470,7 @@ void prepare_supports_for_layer(LayerSupportPoints &supports, float layer_z,
|
|||||||
assert(a.y() <= diff_z && diff_z <= b.y());
|
assert(a.y() <= diff_z && diff_z <= b.y());
|
||||||
float t = (diff_z - a.y()) / (b.y() - a.y());
|
float t = (diff_z - a.y()) / (b.y() - a.y());
|
||||||
assert(0 <= t && t <= 1);
|
assert(0 <= t && t <= 1);
|
||||||
support.current_radius = static_cast<coord_t>(scale_(a.x() + t * (b.x() - a.x())));
|
set_radius(support, a.x() + t * (b.x() - a.x()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "libslic3r/Point.hpp"
|
#include "libslic3r/Point.hpp"
|
||||||
#include "libslic3r/ExPolygon.hpp"
|
#include "libslic3r/ExPolygon.hpp"
|
||||||
#include "libslic3r/SLA/SupportPoint.hpp"
|
#include "libslic3r/SLA/SupportPoint.hpp"
|
||||||
|
#include "libslic3r/SLA/SupportIslands/SampleConfig.hpp"
|
||||||
|
|
||||||
namespace Slic3r::sla {
|
namespace Slic3r::sla {
|
||||||
|
|
||||||
@ -31,7 +32,7 @@ struct SupportPointGeneratorConfig{
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Size range for support point interface (head)
|
/// Size range for support point interface (head)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
MinMax<float> head_diameter = {0.2f, 0.6f}; // [in mm]
|
float head_diameter = 0.4f; // [in mm]
|
||||||
|
|
||||||
// FIXME: calculate actual pixel area from printer config:
|
// FIXME: calculate actual pixel area from printer config:
|
||||||
// const float pixel_area =
|
// const float pixel_area =
|
||||||
@ -46,6 +47,9 @@ struct SupportPointGeneratorConfig{
|
|||||||
// y axis .. mean difference of height(Z)
|
// y axis .. mean difference of height(Z)
|
||||||
// Points of lines [in mm]
|
// Points of lines [in mm]
|
||||||
std::vector<Vec2f> support_curve;
|
std::vector<Vec2f> support_curve;
|
||||||
|
|
||||||
|
// Configuration for sampling island
|
||||||
|
SampleConfig island_configuration;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LayerPart; // forward decl.
|
struct LayerPart; // forward decl.
|
||||||
|
@ -53,6 +53,7 @@
|
|||||||
#include "libslic3r/SLA/RasterBase.hpp"
|
#include "libslic3r/SLA/RasterBase.hpp"
|
||||||
#include "libslic3r/SLA/SupportTree.hpp"
|
#include "libslic3r/SLA/SupportTree.hpp"
|
||||||
#include "libslic3r/SLA/SupportTreeStrategies.hpp"
|
#include "libslic3r/SLA/SupportTreeStrategies.hpp"
|
||||||
|
#include "libslic3r/SLA/SupportIslands/SampleConfigFactory.hpp"
|
||||||
#include "libslic3r/SLAPrint.hpp"
|
#include "libslic3r/SLAPrint.hpp"
|
||||||
#include "libslic3r/TriangleMesh.hpp"
|
#include "libslic3r/TriangleMesh.hpp"
|
||||||
|
|
||||||
@ -627,99 +628,104 @@ void SLAPrint::Steps::support_points(SLAPrintObject &po)
|
|||||||
BOOST_LOG_TRIVIAL(debug) << "Support point count "
|
BOOST_LOG_TRIVIAL(debug) << "Support point count "
|
||||||
<< mo.sla_support_points.size();
|
<< mo.sla_support_points.size();
|
||||||
|
|
||||||
// Unless the user modified the points or we already did the calculation,
|
if (mo.sla_points_status == sla::PointsStatus::UserModified) {
|
||||||
// we will do the autoplacement. Otherwise we will just blindly copy the
|
|
||||||
// frontend data into the backend cache.
|
|
||||||
if (mo.sla_points_status != sla::PointsStatus::UserModified) {
|
|
||||||
throw_if_canceled();
|
|
||||||
sla::SupportPointGeneratorConfig config;
|
|
||||||
const SLAPrintObjectConfig& cfg = po.config();
|
|
||||||
|
|
||||||
// the density config value is in percents:
|
|
||||||
config.density_relative = float(cfg.support_points_density_relative / 100.f);
|
|
||||||
|
|
||||||
switch (cfg.support_tree_type) {
|
|
||||||
case sla::SupportTreeType::Default:
|
|
||||||
case sla::SupportTreeType::Organic:
|
|
||||||
config.head_diameter = {float(cfg.support_head_front_diameter), .0};
|
|
||||||
break;
|
|
||||||
case sla::SupportTreeType::Branching:
|
|
||||||
config.head_diameter = {float(cfg.branchingsupport_head_front_diameter), .0};
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// scaling for the sub operations
|
|
||||||
double d = objectstep_scale * OBJ_STEP_LEVELS[slaposSupportPoints] / 100.0;
|
|
||||||
double init = current_status();
|
|
||||||
|
|
||||||
auto statuscb = [this, d, init](unsigned st)
|
|
||||||
{
|
|
||||||
double current = init + st * d;
|
|
||||||
if(std::round(current_status()) < std::round(current))
|
|
||||||
report_status(current, OBJ_STEP_LABELS(slaposSupportPoints));
|
|
||||||
};
|
|
||||||
|
|
||||||
// Construction of this object does the calculation.
|
|
||||||
throw_if_canceled();
|
|
||||||
|
|
||||||
// TODO: filter small unprintable islands in slices
|
|
||||||
// (Island with area smaller than 1 pixel was skipped in support generator)
|
|
||||||
|
|
||||||
std::vector<ExPolygons> slices = po.get_model_slices(); // copy
|
|
||||||
const std::vector<float>& heights = po.m_model_height_levels;
|
|
||||||
sla::ThrowOnCancel cancel = [this]() { throw_if_canceled(); };
|
|
||||||
sla::StatusFunction status = statuscb;
|
|
||||||
sla::SupportPointGeneratorData data =
|
|
||||||
sla::prepare_generator_data(std::move(slices), heights, cancel, status);
|
|
||||||
|
|
||||||
sla::LayerSupportPoints layer_support_points =
|
|
||||||
sla::generate_support_points(data, config, cancel, status);
|
|
||||||
|
|
||||||
const AABBMesh& emesh = po.m_supportdata->input.emesh;
|
|
||||||
// Maximal move of support point to mesh surface,
|
|
||||||
// no more than height of layer
|
|
||||||
assert(po.m_model_height_levels.size() > 1);
|
|
||||||
double allowed_move = (po.m_model_height_levels[1] - po.m_model_height_levels[0]) +
|
|
||||||
std::numeric_limits<float>::epsilon();
|
|
||||||
sla::SupportPoints support_points =
|
|
||||||
sla::move_on_mesh_surface(layer_support_points, emesh, allowed_move, cancel);
|
|
||||||
|
|
||||||
throw_if_canceled();
|
|
||||||
|
|
||||||
MeshSlicingParamsEx params;
|
|
||||||
params.closing_radius = float(po.config().slice_closing_radius.value);
|
|
||||||
std::vector<ExPolygons> blockers =
|
|
||||||
slice_volumes(po.model_object()->volumes,
|
|
||||||
po.m_model_height_levels, po.trafo(), params,
|
|
||||||
[](const ModelVolume *vol) {
|
|
||||||
return vol->is_support_blocker();
|
|
||||||
});
|
|
||||||
|
|
||||||
std::vector<ExPolygons> enforcers =
|
|
||||||
slice_volumes(po.model_object()->volumes,
|
|
||||||
po.m_model_height_levels, po.trafo(), params,
|
|
||||||
[](const ModelVolume *vol) {
|
|
||||||
return vol->is_support_enforcer();
|
|
||||||
});
|
|
||||||
|
|
||||||
SuppPtMask mask{blockers, enforcers, po.config().support_enforcers_only.getBool()};
|
|
||||||
filter_support_points_by_modifiers(support_points, mask, po.m_model_height_levels);
|
|
||||||
|
|
||||||
po.m_supportdata->input.pts = support_points;
|
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug)
|
|
||||||
<< "Automatic support points: "
|
|
||||||
<< po.m_supportdata->input.pts.size();
|
|
||||||
|
|
||||||
// Using RELOAD_SLA_SUPPORT_POINTS to tell the Plater to pass
|
|
||||||
// the update status to GLGizmoSlaSupports
|
|
||||||
report_status(-1, _u8L("Generating support points"),
|
|
||||||
SlicingStatus::RELOAD_SLA_SUPPORT_POINTS);
|
|
||||||
} else {
|
|
||||||
// There are either some points on the front-end, or the user
|
// There are either some points on the front-end, or the user
|
||||||
// removed them on purpose. No calculation will be done.
|
// removed them on purpose. No calculation will be done.
|
||||||
po.m_supportdata->input.pts = po.transformed_support_points();
|
po.m_supportdata->input.pts = po.transformed_support_points();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
// Unless the user modified the points or we already did the calculation,
|
||||||
|
// we will do the autoplacement. Otherwise we will just blindly copy the
|
||||||
|
// frontend data into the backend cache.
|
||||||
|
// if (mo.sla_points_status != sla::PointsStatus::UserModified)
|
||||||
|
|
||||||
|
throw_if_canceled();
|
||||||
|
const SLAPrintObjectConfig& cfg = po.config();
|
||||||
|
|
||||||
|
// the density config value is in percents:
|
||||||
|
sla::SupportPointGeneratorConfig config;
|
||||||
|
config.density_relative = float(cfg.support_points_density_relative / 100.f);
|
||||||
|
|
||||||
|
switch (cfg.support_tree_type) {
|
||||||
|
case sla::SupportTreeType::Default:
|
||||||
|
case sla::SupportTreeType::Organic:
|
||||||
|
config.head_diameter = float(cfg.support_head_front_diameter);
|
||||||
|
break;
|
||||||
|
case sla::SupportTreeType::Branching:
|
||||||
|
config.head_diameter = float(cfg.branchingsupport_head_front_diameter);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy current configuration for sampling islands
|
||||||
|
config.island_configuration = sla::SampleConfigFactory::get_sample_config();
|
||||||
|
|
||||||
|
// scaling for the sub operations
|
||||||
|
double d = objectstep_scale * OBJ_STEP_LEVELS[slaposSupportPoints] / 100.0;
|
||||||
|
double init = current_status();
|
||||||
|
|
||||||
|
auto statuscb = [this, d, init](unsigned st)
|
||||||
|
{
|
||||||
|
double current = init + st * d;
|
||||||
|
if(std::round(current_status()) < std::round(current))
|
||||||
|
report_status(current, OBJ_STEP_LABELS(slaposSupportPoints));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Construction of this object does the calculation.
|
||||||
|
throw_if_canceled();
|
||||||
|
|
||||||
|
// TODO: filter small unprintable islands in slices
|
||||||
|
// (Island with area smaller than 1 pixel was skipped in support generator)
|
||||||
|
|
||||||
|
std::vector<ExPolygons> slices = po.get_model_slices(); // copy
|
||||||
|
const std::vector<float>& heights = po.m_model_height_levels;
|
||||||
|
sla::ThrowOnCancel cancel = [this]() { throw_if_canceled(); };
|
||||||
|
sla::StatusFunction status = statuscb;
|
||||||
|
sla::SupportPointGeneratorData data =
|
||||||
|
sla::prepare_generator_data(std::move(slices), heights, cancel, status);
|
||||||
|
|
||||||
|
sla::LayerSupportPoints layer_support_points =
|
||||||
|
sla::generate_support_points(data, config, cancel, status);
|
||||||
|
|
||||||
|
const AABBMesh& emesh = po.m_supportdata->input.emesh;
|
||||||
|
// Maximal move of support point to mesh surface,
|
||||||
|
// no more than height of layer
|
||||||
|
assert(po.m_model_height_levels.size() > 1);
|
||||||
|
double allowed_move = (po.m_model_height_levels[1] - po.m_model_height_levels[0]) +
|
||||||
|
std::numeric_limits<float>::epsilon();
|
||||||
|
sla::SupportPoints support_points =
|
||||||
|
sla::move_on_mesh_surface(layer_support_points, emesh, allowed_move, cancel);
|
||||||
|
|
||||||
|
throw_if_canceled();
|
||||||
|
|
||||||
|
MeshSlicingParamsEx params;
|
||||||
|
params.closing_radius = float(po.config().slice_closing_radius.value);
|
||||||
|
std::vector<ExPolygons> blockers =
|
||||||
|
slice_volumes(po.model_object()->volumes,
|
||||||
|
po.m_model_height_levels, po.trafo(), params,
|
||||||
|
[](const ModelVolume *vol) {
|
||||||
|
return vol->is_support_blocker();
|
||||||
|
});
|
||||||
|
|
||||||
|
std::vector<ExPolygons> enforcers =
|
||||||
|
slice_volumes(po.model_object()->volumes,
|
||||||
|
po.m_model_height_levels, po.trafo(), params,
|
||||||
|
[](const ModelVolume *vol) {
|
||||||
|
return vol->is_support_enforcer();
|
||||||
|
});
|
||||||
|
|
||||||
|
SuppPtMask mask{blockers, enforcers, po.config().support_enforcers_only.getBool()};
|
||||||
|
filter_support_points_by_modifiers(support_points, mask, po.m_model_height_levels);
|
||||||
|
|
||||||
|
po.m_supportdata->input.pts = support_points;
|
||||||
|
|
||||||
|
BOOST_LOG_TRIVIAL(debug)
|
||||||
|
<< "Automatic support points: "
|
||||||
|
<< po.m_supportdata->input.pts.size();
|
||||||
|
|
||||||
|
// Using RELOAD_SLA_SUPPORT_POINTS to tell the Plater to pass
|
||||||
|
// the update status to GLGizmoSlaSupports
|
||||||
|
report_status(-1, _u8L("Generating support points"),
|
||||||
|
SlicingStatus::RELOAD_SLA_SUPPORT_POINTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SLAPrint::Steps::support_tree(SLAPrintObject &po)
|
void SLAPrint::Steps::support_tree(SLAPrintObject &po)
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
#include "libslic3r/PresetBundle.hpp"
|
#include "libslic3r/PresetBundle.hpp"
|
||||||
#include "libslic3r/SLAPrint.hpp"
|
#include "libslic3r/SLAPrint.hpp"
|
||||||
|
|
||||||
|
#include "libslic3r/SLA/SupportIslands/SampleConfigFactory.hpp"
|
||||||
|
|
||||||
static const double CONE_RADIUS = 0.25;
|
static const double CONE_RADIUS = 0.25;
|
||||||
static const double CONE_HEIGHT = 0.75;
|
static const double CONE_HEIGHT = 0.75;
|
||||||
|
|
||||||
@ -677,6 +679,92 @@ RENDER_AGAIN:
|
|||||||
}
|
}
|
||||||
else { // not in editing mode:
|
else { // not in editing mode:
|
||||||
m_imgui->disabled_begin(!is_input_enabled());
|
m_imgui->disabled_begin(!is_input_enabled());
|
||||||
|
if (int density = static_cast<const ConfigOptionInt*>(get_config_options({"support_points_density_relative"})[0])->value;
|
||||||
|
ImGui::SliderInt("points_density", &density, 0, 200, "%d \%")) {
|
||||||
|
mo->config.set("support_points_density_relative", density);
|
||||||
|
} else if (ImGui::IsItemHovered()) {
|
||||||
|
ImGui::SetTooltip("Divider for the supported radius\nSmaller mean less point(75% -> supported radius is enlaged to 133%, for 50% it is 200% of radius)\nLarger mean more points(125% -> supported radius is reduced to 80%, for value 150% it is 66% of radius, for 200% -> 50%)");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::TreeNode("Support islands:")) {
|
||||||
|
sla::SampleConfig &sample_config = sla::SampleConfigFactory::get_sample_config();
|
||||||
|
bool exist_change = false;
|
||||||
|
if (float simplification_tolerance = unscale<float>(sample_config.simplification_tolerance); // [in mm]
|
||||||
|
ImGui::InputFloat("input simplify", &simplification_tolerance, .1f, 1.f, "%.2f mm")) {
|
||||||
|
sample_config.simplification_tolerance = scale_(simplification_tolerance);
|
||||||
|
exist_change = true;
|
||||||
|
} else if (ImGui::IsItemHovered())
|
||||||
|
ImGui::SetTooltip("There is no need to calculate with precisse island\nNOTE: Slice of Cylinder bottom has tip of trinagles on contour\n(neighbor coordinate -> create issue in boost::voronoi)");
|
||||||
|
if (float max_distance = unscale<float>(sample_config.max_distance); // [in mm]
|
||||||
|
ImGui::InputFloat("Max dist", &max_distance, .1f, 1.f, "%.2f mm")) {
|
||||||
|
sample_config.max_distance = scale_(max_distance);
|
||||||
|
sample_config.half_distance = sample_config.max_distance / 2;
|
||||||
|
exist_change = true;
|
||||||
|
} else if (ImGui::IsItemHovered())
|
||||||
|
ImGui::SetTooltip("Every support point on island has at least one support point in maximum distance\nMUST be bigger than zero");
|
||||||
|
ImGui::SameLine(); ImGui::Text("half is %.2f", unscale<float>(sample_config.half_distance));
|
||||||
|
if (float minimal_distance_from_outline = unscale<float>(sample_config.minimal_distance_from_outline); // [in mm]
|
||||||
|
ImGui::InputFloat("from outline", &minimal_distance_from_outline, .1f, 1.f, "%.2f mm")) {
|
||||||
|
sample_config.minimal_distance_from_outline = scale_(minimal_distance_from_outline);
|
||||||
|
exist_change = true;
|
||||||
|
} else if (ImGui::IsItemHovered())
|
||||||
|
ImGui::SetTooltip("When it is possible, there will be this minimal distance from outline.\nZERO when head center should be on outline\nSHOULD be positive number");
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (float maximal_distance_from_outline = unscale<float>(sample_config.maximal_distance_from_outline); // [in mm]
|
||||||
|
ImGui::InputFloat("max from outline", &maximal_distance_from_outline, .1f, 1.f, "%.2f mm")) {
|
||||||
|
sample_config.maximal_distance_from_outline = scale_(maximal_distance_from_outline);
|
||||||
|
exist_change = true;
|
||||||
|
} else if (ImGui::IsItemHovered())
|
||||||
|
ImGui::SetTooltip("Measured as sum of VD edge length from outline\nUsed only when there is no space for outline offset on first/last point\nMust be bigger than minimal_distance_from_outline");
|
||||||
|
ImGui::Text("max_interesting_angle is %.0f", float(sample_config.max_interesting_angle*180/M_PI));
|
||||||
|
if (ImGui::IsItemHovered()) ImGui::SetTooltip(" When angle on outline is smaller than max_interesting_angle\nthan create unmovable support point.\nShould be in range from 90 to 180");
|
||||||
|
if (float minimal_support_distance = unscale<float>(sample_config.minimal_support_distance); // [in mm]
|
||||||
|
ImGui::InputFloat("Thin dist", &minimal_support_distance, .1f, 1.f, "%.2f mm")) {
|
||||||
|
sample_config.minimal_support_distance = scale_(minimal_support_distance);
|
||||||
|
exist_change = true;
|
||||||
|
} else if (ImGui::IsItemHovered())
|
||||||
|
ImGui::SetTooltip("Distinguish when to add support point on Voronoi Diagram\nMUST be bigger than minimal_distance_from_outline\nSmaller -> more supports AND Larger -> less amount");
|
||||||
|
if (float min_side_branch_length = unscale<float>(sample_config.min_side_branch_length); // [in mm]
|
||||||
|
ImGui::InputFloat("min_side_branch_length", &min_side_branch_length, .1f, 1.f, "%.2f mm")) {
|
||||||
|
sample_config.min_side_branch_length = scale_(min_side_branch_length);
|
||||||
|
exist_change = true;
|
||||||
|
} else if (ImGui::IsItemHovered())
|
||||||
|
ImGui::SetTooltip("minimal length of side branch to be sampled\nit is used for sampling in center only");
|
||||||
|
if (float max_for_one = unscale<float>(sample_config.max_length_for_one_support_point); // [in mm]
|
||||||
|
ImGui::InputFloat("Max len for one", &max_for_one, .1f, 1.f, "%.2f mm")) {
|
||||||
|
sample_config.max_length_for_one_support_point = scale_(max_for_one);
|
||||||
|
exist_change = true;
|
||||||
|
} else if (ImGui::IsItemHovered())
|
||||||
|
ImGui::SetTooltip("Maximal island length (longest voronoi path) for support by point in path center");
|
||||||
|
if (float max_for_two = unscale<float>(sample_config.max_length_for_two_support_points); // [in mm]
|
||||||
|
ImGui::InputFloat("Max len for two", &max_for_two, .1f, 1.f, "%.2f mm")) {
|
||||||
|
sample_config.max_length_for_two_support_points = scale_(max_for_two);
|
||||||
|
exist_change = true;
|
||||||
|
} else if (ImGui::IsItemHovered())
|
||||||
|
ImGui::SetTooltip("Maximal island length (longest voronoi path)\n for support by 2 points on path sides");
|
||||||
|
if (float max_width_for_center_support_line = unscale<float>(sample_config.max_width_for_center_support_line); // [in mm]
|
||||||
|
ImGui::InputFloat("thin max width", &max_width_for_center_support_line, .1f, 1.f, "%.2f mm")) {
|
||||||
|
sample_config.max_width_for_center_support_line = scale_(max_width_for_center_support_line);
|
||||||
|
exist_change = true;
|
||||||
|
} else if (ImGui::IsItemHovered())
|
||||||
|
ImGui::SetTooltip("Maximal width of line island supported in the middle of line\nMust be greater or equal to thick min width(to make hysteresis)");
|
||||||
|
if (float min_width_for_outline_support = unscale<float>(sample_config.min_width_for_outline_support); // [in mm]
|
||||||
|
ImGui::InputFloat("thick min width", &min_width_for_outline_support, .1f, 1.f, "%.2f mm")) {
|
||||||
|
sample_config.min_width_for_outline_support = scale_(min_width_for_outline_support);
|
||||||
|
exist_change = true;
|
||||||
|
} else if (ImGui::IsItemHovered())
|
||||||
|
ImGui::SetTooltip("Minimal width to be supported by outline\nMust be smaller or equal to thin max width(to make hysteresis)");
|
||||||
|
|
||||||
|
ImGui::Text("head radius is set to %.2f", unscale<float>(sample_config.head_radius));
|
||||||
|
ImGui::Text("Alignment stop criteria: min_move(%.0f um), iter(%d x), max_VD_move(%.2f mm)", unscale<float>(sample_config.minimal_move)*1000, sample_config.count_iteration,
|
||||||
|
unscale<float>(sample_config.max_align_distance)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (exist_change){
|
||||||
|
sla::SampleConfigFactory::verify(sample_config);
|
||||||
|
}
|
||||||
|
ImGui::TreePop();
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::Text("Distribution depends on './resources/data/sla_support.svg'\ninstruction for edit are in file");
|
ImGui::Text("Distribution depends on './resources/data/sla_support.svg'\ninstruction for edit are in file");
|
||||||
|
|
||||||
@ -720,9 +808,7 @@ RENDER_AGAIN:
|
|||||||
// wxGetApp().obj_list()->update_and_show_object_settings_item();
|
// wxGetApp().obj_list()->update_and_show_object_settings_item();
|
||||||
//}
|
//}
|
||||||
|
|
||||||
bool generate = ImGuiPureWrap::button(m_desc.at("auto_generate"));
|
if (ImGuiPureWrap::button(m_desc.at("auto_generate")))
|
||||||
|
|
||||||
if (generate)
|
|
||||||
auto_generate();
|
auto_generate();
|
||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <libslic3r/ClipperUtils.hpp>
|
#include <libslic3r/ClipperUtils.hpp>
|
||||||
#include <libslic3r/TriangleMeshSlicer.hpp>
|
#include <libslic3r/TriangleMeshSlicer.hpp>
|
||||||
|
|
||||||
|
#include <libslic3r/SLA/SupportIslands/SampleConfigFactory.hpp>
|
||||||
#include <libslic3r/SLA/SupportIslands/SampleConfig.hpp>
|
#include <libslic3r/SLA/SupportIslands/SampleConfig.hpp>
|
||||||
#include <libslic3r/SLA/SupportIslands/VoronoiGraphUtils.hpp>
|
#include <libslic3r/SLA/SupportIslands/VoronoiGraphUtils.hpp>
|
||||||
#include <libslic3r/SLA/SupportIslands/SampleIslandUtils.hpp>
|
#include <libslic3r/SLA/SupportIslands/SampleIslandUtils.hpp>
|
||||||
@ -17,7 +18,7 @@
|
|||||||
using namespace Slic3r;
|
using namespace Slic3r;
|
||||||
using namespace Slic3r::sla;
|
using namespace Slic3r::sla;
|
||||||
|
|
||||||
#define STORE_SAMPLE_INTO_SVG_FILES
|
//#define STORE_SAMPLE_INTO_SVG_FILES
|
||||||
|
|
||||||
TEST_CASE("Overhanging point should be supported", "[SupGen]") {
|
TEST_CASE("Overhanging point should be supported", "[SupGen]") {
|
||||||
|
|
||||||
@ -304,9 +305,23 @@ ExPolygon create_mountains(double size) {
|
|||||||
{size / 7, size}});
|
{size / 7, size}});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Neighbor points create trouble for voronoi - test of neccessary offseting(closing) of contour
|
||||||
|
ExPolygon create_cylinder_bottom_slice() {
|
||||||
|
indexed_triangle_set its_cylinder = its_make_cylinder(6.6551999999999998, 11.800000000000001);
|
||||||
|
MeshSlicingParams param;
|
||||||
|
Polygons polygons = slice_mesh(its_cylinder, 0.0125000002, param);
|
||||||
|
return ExPolygon{polygons.front()};
|
||||||
|
}
|
||||||
|
|
||||||
|
ExPolygon load_frog(){
|
||||||
|
TriangleMesh mesh = load_model("frog_legs.obj");
|
||||||
|
std::vector<ExPolygons> slices = slice_mesh_ex(mesh.its, {0.1f});
|
||||||
|
return slices.front()[1];
|
||||||
|
}
|
||||||
|
|
||||||
ExPolygons createTestIslands(double size)
|
ExPolygons createTestIslands(double size)
|
||||||
{
|
{
|
||||||
bool useFrogLeg = false;
|
bool useFrogLeg = false;
|
||||||
// need post reorganization of longest path
|
// need post reorganization of longest path
|
||||||
ExPolygons result = {
|
ExPolygons result = {
|
||||||
// one support point
|
// one support point
|
||||||
@ -338,6 +353,9 @@ ExPolygons createTestIslands(double size)
|
|||||||
create_tiny_wide_test_2(3 * size, 2 / 3. * size),
|
create_tiny_wide_test_2(3 * size, 2 / 3. * size),
|
||||||
create_tiny_between_holes(3 * size, 2 / 3. * size),
|
create_tiny_between_holes(3 * size, 2 / 3. * size),
|
||||||
|
|
||||||
|
ExPolygon(PolygonUtils::create_equilateral_triangle(scale_(18.6))),
|
||||||
|
create_cylinder_bottom_slice(),
|
||||||
|
|
||||||
// still problem
|
// still problem
|
||||||
// three support points
|
// three support points
|
||||||
ExPolygon(PolygonUtils::create_equilateral_triangle(3 * size)),
|
ExPolygon(PolygonUtils::create_equilateral_triangle(3 * size)),
|
||||||
@ -348,13 +366,8 @@ ExPolygons createTestIslands(double size)
|
|||||||
create_square_with_hole(size, size / 2),
|
create_square_with_hole(size, size / 2),
|
||||||
create_square_with_hole(size, size / 3)
|
create_square_with_hole(size, size / 3)
|
||||||
};
|
};
|
||||||
|
if (useFrogLeg)
|
||||||
if (useFrogLeg) {
|
result.push_back(load_frog());
|
||||||
TriangleMesh mesh = load_model("frog_legs.obj");
|
|
||||||
std::vector<ExPolygons> slices = slice_mesh_ex(mesh.its, {0.1f});
|
|
||||||
ExPolygon frog_leg = slices.front()[1];
|
|
||||||
result.push_back(frog_leg);
|
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -403,7 +416,7 @@ Points rasterize(const ExPolygon &island, double distance) {
|
|||||||
SupportIslandPoints test_island_sampling(const ExPolygon & island,
|
SupportIslandPoints test_island_sampling(const ExPolygon & island,
|
||||||
const SampleConfig &config)
|
const SampleConfig &config)
|
||||||
{
|
{
|
||||||
auto points = SupportPointGenerator::uniform_cover_island(island, config);
|
auto points = SampleIslandUtils::uniform_cover_island(island, config);
|
||||||
|
|
||||||
Points chck_points = rasterize(island, config.head_radius); // TODO: Use resolution of printer
|
Points chck_points = rasterize(island, config.head_radius); // TODO: Use resolution of printer
|
||||||
bool is_ok = true;
|
bool is_ok = true;
|
||||||
@ -447,7 +460,7 @@ SupportIslandPoints test_island_sampling(const ExPolygon & island,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
CHECK(!points.empty());
|
CHECK(!points.empty());
|
||||||
//CHECK(is_ok);
|
CHECK(is_ok);
|
||||||
|
|
||||||
// all points must be inside of island
|
// all points must be inside of island
|
||||||
for (const auto &point : points) { CHECK(island.contains(point->point)); }
|
for (const auto &point : points) { CHECK(island.contains(point->point)); }
|
||||||
@ -539,12 +552,6 @@ TEST_CASE("speed sampling", "[hide], [SupGen]") {
|
|||||||
|
|
||||||
size_t count = 1;
|
size_t count = 1;
|
||||||
|
|
||||||
std::vector<std::vector<Vec2f>> result1;
|
|
||||||
result1.reserve(islands.size()*count);
|
|
||||||
for (size_t i = 0; i<count; ++i)
|
|
||||||
for (const auto& island: islands)
|
|
||||||
result1.emplace_back(sample_expolygon(island, samples_per_mm2, m_rng));
|
|
||||||
|
|
||||||
std::vector<std::vector<Vec2f>> result2;
|
std::vector<std::vector<Vec2f>> result2;
|
||||||
result2.reserve(islands.size()*count);
|
result2.reserve(islands.size()*count);
|
||||||
for (size_t i = 0; i < count; ++i)
|
for (size_t i = 0; i < count; ++i)
|
||||||
@ -560,7 +567,7 @@ TEST_CASE("speed sampling", "[hide], [SupGen]") {
|
|||||||
|
|
||||||
|
|
||||||
#ifdef STORE_SAMPLE_INTO_SVG_FILES
|
#ifdef STORE_SAMPLE_INTO_SVG_FILES
|
||||||
for (size_t i = 0; i < result1.size(); ++i) {
|
for (size_t i = 0; i < result2.size(); ++i) {
|
||||||
size_t island_index = i % islands.size();
|
size_t island_index = i % islands.size();
|
||||||
ExPolygon &island = islands[island_index];
|
ExPolygon &island = islands[island_index];
|
||||||
|
|
||||||
@ -568,9 +575,6 @@ TEST_CASE("speed sampling", "[hide], [SupGen]") {
|
|||||||
std::string name = "sample_" + std::to_string(i) + ".svg";
|
std::string name = "sample_" + std::to_string(i) + ".svg";
|
||||||
SVG svg(name, LineUtils::create_bounding_box(lines));
|
SVG svg(name, LineUtils::create_bounding_box(lines));
|
||||||
svg.draw(island, "lightgray");
|
svg.draw(island, "lightgray");
|
||||||
svg.draw_text({0, 0}, ("random samples " + std::to_string(result1[i].size())).c_str(), "blue");
|
|
||||||
for (Vec2f &p : result1[i])
|
|
||||||
svg.draw((p * 1e6).cast<coord_t>(), "blue", 1e6);
|
|
||||||
svg.draw_text({0., 5e6}, ("uniform samples " + std::to_string(result2[i].size())).c_str(), "green");
|
svg.draw_text({0., 5e6}, ("uniform samples " + std::to_string(result2[i].size())).c_str(), "green");
|
||||||
for (Vec2f &p : result2[i])
|
for (Vec2f &p : result2[i])
|
||||||
svg.draw((p * 1e6).cast<coord_t>(), "green", 1e6);
|
svg.draw((p * 1e6).cast<coord_t>(), "green", 1e6);
|
||||||
@ -580,16 +584,17 @@ TEST_CASE("speed sampling", "[hide], [SupGen]") {
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check for correct sampling of island
|
/// Check for correct sampling of island
|
||||||
///
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
TEST_CASE("Small islands should be supported in center", "[SupGen], [VoronoiSkeleton]")
|
TEST_CASE("Small islands should be supported in center", "[SupGen], [VoronoiSkeleton]")
|
||||||
{
|
{
|
||||||
double size = 3e7;
|
float head_diameter = .4f;
|
||||||
SampleConfig cfg = create_sample_config(size);
|
SampleConfig cfg = SampleConfigFactory::create(head_diameter);
|
||||||
ExPolygons islands = createTestIslands(size);
|
ExPolygons islands = createTestIslands(21 * scale_(head_diameter));
|
||||||
for (ExPolygon &island : islands) {
|
for (ExPolygon &island : islands) {
|
||||||
// information for debug which island cause problem
|
// information for debug which island cause problem
|
||||||
[[maybe_unused]] size_t debug_index = &island - &islands.front();
|
[[maybe_unused]] size_t debug_index = &island - &islands.front();
|
||||||
|
|
||||||
|
// TODO: index 17 - create field again
|
||||||
auto points = test_island_sampling(island, cfg);
|
auto points = test_island_sampling(island, cfg);
|
||||||
double angle = 3.14 / 3; // cca 60 degree
|
double angle = 3.14 / 3; // cca 60 degree
|
||||||
|
|
||||||
@ -601,46 +606,31 @@ TEST_CASE("Small islands should be supported in center", "[SupGen], [VoronoiSkel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Vec2f> sample_old(const ExPolygon &island)
|
//TEST_CASE("Cell polygon check", "") {
|
||||||
{
|
// coord_t max_distance = 9;
|
||||||
// Create the support point generator
|
// Points points{Point{0,0}, Point{10,0}};
|
||||||
static TriangleMesh mesh;
|
// using VD = Slic3r::Geometry::VoronoiDiagram;
|
||||||
static AABBMesh emesh(mesh);
|
// VD vd;
|
||||||
static sla::SupportPointGenerator::Config autogencfg;
|
// vd.construct_voronoi(points.begin(), points.end());
|
||||||
//autogencfg.minimal_distance = 8.f;
|
// assert(points.size() == vd.cells().size());
|
||||||
static sla::SupportPointGenerator generator{emesh, autogencfg, [] {}, [](int) {}};
|
// Polygons cells(points.size());
|
||||||
|
// for (const VD::cell_type &cell : vd.cells())
|
||||||
// tear preasure
|
// cells[cell.source_index()] = VoronoiGraphUtils::to_polygon(cell, points, max_distance);
|
||||||
float tp = autogencfg.tear_pressure();
|
//
|
||||||
size_t layer_id = 13;
|
// REQUIRE(cells[0].size() >= 3);
|
||||||
coordf_t print_z = 11.f;
|
// REQUIRE(cells[1].size() >= 3);
|
||||||
SupportPointGenerator::MyLayer layer(layer_id, print_z);
|
// Polygons cell_overlaps = intersection(cells[0], cells[1]);
|
||||||
ExPolygon poly = island;
|
// double area = 0;
|
||||||
BoundingBox bbox(island.contour.points);
|
// for (const Polygon &cell_overlap : cell_overlaps)
|
||||||
Vec2f centroid;
|
// area += cell_overlap.area();
|
||||||
float area = island.area();
|
// CHECK(area < 1);
|
||||||
float h = 17.f;
|
//}
|
||||||
sla::SupportPointGenerator::Structure s(layer, poly, bbox, centroid,area,h);
|
|
||||||
auto flag = sla::SupportPointGenerator::IslandCoverageFlags(
|
|
||||||
sla::SupportPointGenerator::icfIsNew | sla::SupportPointGenerator::icfWithBoundary);
|
|
||||||
SupportPointGenerator::PointGrid3D grid3d;
|
|
||||||
generator.uniformly_cover({island}, s, s.area * tp, grid3d, flag);
|
|
||||||
|
|
||||||
std::vector<Vec2f> result;
|
|
||||||
result.reserve(grid3d.grid.size());
|
|
||||||
for (auto g : grid3d.grid) {
|
|
||||||
const Vec3f &p = g.second.position;
|
|
||||||
Vec2f p2f(p.x(), p.y());
|
|
||||||
result.emplace_back(scale_(p2f));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <libslic3r/SLA/SupportIslands/SampleConfigFactory.hpp>
|
#include <libslic3r/SLA/SupportIslands/SampleConfigFactory.hpp>
|
||||||
std::vector<Vec2f> sample_filip(const ExPolygon &island)
|
std::vector<Vec2f> sample_filip(const ExPolygon &island)
|
||||||
{
|
{
|
||||||
static SampleConfig cfg = create_sample_config(1e6);
|
static SampleConfig cfg = create_sample_config(1e6);
|
||||||
SupportIslandPoints points = SupportPointGenerator::uniform_cover_island(island, cfg);
|
SupportIslandPoints points = SampleIslandUtils::uniform_cover_island(island, cfg);
|
||||||
|
|
||||||
std::vector<Vec2f> result;
|
std::vector<Vec2f> result;
|
||||||
result.reserve(points.size());
|
result.reserve(points.size());
|
||||||
@ -676,15 +666,7 @@ void store_sample(const std::vector<Vec2f> &samples, const ExPolygon& island)
|
|||||||
|
|
||||||
TEST_CASE("Compare sampling test", "[hide]")
|
TEST_CASE("Compare sampling test", "[hide]")
|
||||||
{
|
{
|
||||||
enum class Sampling {
|
std::function<std::vector<Vec2f>(const ExPolygon &)> sample = sample_filip;
|
||||||
old,
|
|
||||||
filip
|
|
||||||
} sample_type = Sampling::old;
|
|
||||||
|
|
||||||
std::function<std::vector<Vec2f>(const ExPolygon &)> sample =
|
|
||||||
(sample_type == Sampling::old) ? sample_old :
|
|
||||||
(sample_type == Sampling::filip) ? sample_filip :
|
|
||||||
nullptr;
|
|
||||||
ExPolygons islands = createTestIslands(1e6);
|
ExPolygons islands = createTestIslands(1e6);
|
||||||
ExPolygons islands_big = createTestIslands(3e6);
|
ExPolygons islands_big = createTestIslands(3e6);
|
||||||
islands.insert(islands.end(), islands_big.begin(), islands_big.end());
|
islands.insert(islands.end(), islands_big.begin(), islands_big.end());
|
||||||
|
@ -129,8 +129,7 @@ void test_supports(const std::string &obj_filename,
|
|||||||
|
|
||||||
// Create the support point generator
|
// Create the support point generator
|
||||||
sla::SupportPointGeneratorConfig autogencfg;
|
sla::SupportPointGeneratorConfig autogencfg;
|
||||||
float head_diam = 2 * supportcfg.head_front_radius_mm;
|
autogencfg.head_diameter = 2 * supportcfg.head_front_radius_mm;
|
||||||
autogencfg.head_diameter = {head_diam, head_diam};
|
|
||||||
sla::ThrowOnCancel cancel = []() {};
|
sla::ThrowOnCancel cancel = []() {};
|
||||||
sla::StatusFunction status = [](int) {};
|
sla::StatusFunction status = [](int) {};
|
||||||
sla::SupportPointGeneratorData gen_data = sla::prepare_generator_data(std::move(out.model_slices), out.slicegrid, cancel, status);
|
sla::SupportPointGeneratorData gen_data = sla::prepare_generator_data(std::move(out.model_slices), out.slicegrid, cancel, status);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user