mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-15 00:26:12 +08:00
Add support settings into GUI
This commit is contained in:
parent
02ca74cced
commit
74db5d1ed2
@ -26,13 +26,13 @@
|
||||
showgrid="false"
|
||||
showborder="true"
|
||||
borderlayer="true"
|
||||
inkscape:zoom="3.3638608"
|
||||
inkscape:cx="92.601929"
|
||||
inkscape:cy="110.88449"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1129"
|
||||
inkscape:window-x="1912"
|
||||
inkscape:window-y="-8"
|
||||
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:window-maximized="1"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
@ -130,7 +130,7 @@
|
||||
id="path12735" />
|
||||
<path
|
||||
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"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<text
|
||||
@ -174,7 +174,7 @@
|
||||
style="font-weight:normal;font-size:2.11667px;stroke-width:0.4"
|
||||
x="24.711193"
|
||||
y="63.303635"
|
||||
id="tspan9676" /></text>
|
||||
id="tspan9676">Last virtual point of curve is [last.x, ∞]</tspan></text>
|
||||
<text
|
||||
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"
|
||||
@ -356,6 +356,6 @@
|
||||
id="text17458"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan17456"
|
||||
style="stroke-width:2.5"></tspan></text>
|
||||
style="stroke-width:2.5" /></text>
|
||||
</g>
|
||||
</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.hpp
|
||||
SLA/SupportIslands/SampleConfig.hpp
|
||||
SLA/SupportIslands/SampleConfigFactory.cpp
|
||||
SLA/SupportIslands/SampleConfigFactory.hpp
|
||||
SLA/SupportIslands/SampleIslandUtils.cpp
|
||||
SLA/SupportIslands/SampleIslandUtils.hpp
|
||||
|
@ -13,12 +13,12 @@ struct SampleConfig
|
||||
{
|
||||
// Every point on island has at least one support point in maximum distance
|
||||
// MUST be bigger than zero
|
||||
coord_t max_distance = 2;
|
||||
coord_t half_distance = 1; // has to be half od max_distance
|
||||
coord_t max_distance = static_cast<coord_t>(scale_(5.));
|
||||
coord_t half_distance = static_cast<coord_t>(scale_(2.5)); // has to be half od max_distance
|
||||
|
||||
// Support point head radius
|
||||
// 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.
|
||||
// zero when head should be on outline
|
||||
@ -27,7 +27,7 @@ struct SampleConfig
|
||||
// Measured as sum of VD edge length from outline
|
||||
// Used only when there is no space for outline offset on first/last point
|
||||
// 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
|
||||
// than create unmovable support point.
|
||||
@ -44,23 +44,23 @@ struct SampleConfig
|
||||
|
||||
// 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.
|
||||
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
|
||||
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
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
size_t count_iteration = 100;
|
||||
@ -75,7 +75,7 @@ struct SampleConfig
|
||||
// There is no need to calculate with precisse island
|
||||
// NOTE: Slice of Cylinder bottom has tip of trinagles on contour
|
||||
// (neighbor coordinate - create issue in voronoi)
|
||||
double simplification_tolerance = 1e4; // [nm]
|
||||
double simplification_tolerance = scale_(0.05 /*mm*/);
|
||||
};
|
||||
} // namespace Slic3r::sla
|
||||
#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_
|
||||
#define slic3r_SLA_SuppotstIslands_SampleConfigFactory_hpp_
|
||||
|
||||
#include <optional>
|
||||
#include "SampleConfig.hpp"
|
||||
#include "../SupportPointGenerator.hpp"
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
|
||||
namespace Slic3r::sla {
|
||||
|
||||
@ -14,78 +15,15 @@ class SampleConfigFactory
|
||||
public:
|
||||
SampleConfigFactory() = delete;
|
||||
|
||||
// factory method to iniciate config
|
||||
static SampleConfig create(const SupportPointGeneratorConfig &config)
|
||||
{
|
||||
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 !!!!
|
||||
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;
|
||||
static bool verify(SampleConfig &cfg);
|
||||
static SampleConfig create(float support_head_diameter_in_mm);
|
||||
|
||||
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;
|
||||
}
|
||||
private:
|
||||
// TODO: REMOVE IT. Do not use in production
|
||||
// Global variable to temporary set configuration from GUI into SLA print steps
|
||||
static std::optional<SampleConfig> gui_sample_config_opt;
|
||||
public:
|
||||
static SampleConfig &get_sample_config();
|
||||
};
|
||||
|
||||
} // namespace Slic3r::sla
|
||||
#endif // slic3r_SLA_SuppotstIslands_SampleConfigFactory_hpp_
|
||||
|
@ -57,26 +57,84 @@ const ExPolygon &get_expolygon_with_biggest_contour(const ExPolygons &expolygons
|
||||
}
|
||||
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
|
||||
|
||||
SupportIslandPoints SampleIslandUtils::uniform_cover_island(
|
||||
const ExPolygon &island, const SampleConfig &config
|
||||
) {
|
||||
// closing similar to FDM arachne do before voronoi
|
||||
// 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);
|
||||
ExPolygon simplified_island = get_simplified(island, config);
|
||||
|
||||
// "Close" operation create neighbor pixel for sharp triangle tip
|
||||
double tolerance = scale_(0.05);
|
||||
ExPolygons simplified_expolygons = island.simplify(tolerance);
|
||||
ExPolygon simplified_expolygon = get_expolygon_with_biggest_contour(simplified_expolygons);
|
||||
// When island is smaller than minimal-head diameter,
|
||||
// it will be supported whole by support poin in center
|
||||
if (Point center; get_center(simplified_island.contour.points, config.head_radius, center)) {
|
||||
SupportIslandPoints result;
|
||||
result.push_back(std::make_unique<SupportIslandNoMovePoint>(
|
||||
center, SupportIslandInnerPoint::Type::one_bb_center_point));
|
||||
return result;
|
||||
}
|
||||
|
||||
Slic3r::Geometry::VoronoiDiagram vd;
|
||||
Lines lines = to_lines(simplified_expolygon);
|
||||
Lines lines = to_lines(simplified_island);
|
||||
vd.construct_voronoi(lines.begin(), lines.end());
|
||||
Slic3r::Voronoi::annotate_inside_outside(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
|
||||
assert(start_node != nullptr);
|
||||
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
|
||||
{
|
||||
|
@ -34,6 +34,7 @@ public:
|
||||
outline, // keep position align with island outline
|
||||
inner, // point inside wide part, without restriction on move
|
||||
|
||||
one_bb_center_point, // for island smaller than head radius
|
||||
undefined
|
||||
};
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "libslic3r/KDTreeIndirect.hpp"
|
||||
|
||||
// SupportIslands
|
||||
#include "libslic3r/SLA/SupportIslands/SampleConfigFactory.hpp"
|
||||
#include "libslic3r/SLA/SupportIslands/SampleIslandUtils.hpp"
|
||||
|
||||
using namespace Slic3r;
|
||||
@ -232,7 +231,6 @@ void support_part_overhangs(
|
||||
(const LayerSupportPoint &support_point, const Point &p) -> bool {
|
||||
// Debug visualization of all sampled outline
|
||||
//return false;
|
||||
|
||||
coord_t r = support_point.current_radius;
|
||||
Point dp = support_point.position_on_layer - p;
|
||||
if (std::abs(dp.x()) > r) return false;
|
||||
@ -269,9 +267,8 @@ void support_part_overhangs(
|
||||
/// <param name="part_z">z coordinate of part</param>
|
||||
/// <param name="cfg"></param>
|
||||
void support_island(const LayerPart &part, NearPoints& near_points, float part_z,
|
||||
const SupportPointGeneratorConfig &cfg) {
|
||||
SampleConfig sample_cfg = SampleConfigFactory::create(cfg);
|
||||
SupportIslandPoints samples = SampleIslandUtils::uniform_cover_island(*part.shape, sample_cfg);
|
||||
const SupportPointGeneratorConfig &cfg) {
|
||||
SupportIslandPoints samples = SampleIslandUtils::uniform_cover_island(*part.shape, cfg.island_configuration);
|
||||
//samples = {std::make_unique<SupportIslandPoint>(island.contour.centroid())};
|
||||
for (const SupportIslandPointPtr &sample : samples)
|
||||
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,
|
||||
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;
|
||||
// calculate support area for each support point as radius
|
||||
// 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()) {
|
||||
// set maximal radius
|
||||
support.current_radius = static_cast<coord_t>(scale_(curve.back().x()));
|
||||
set_radius(support, curve.back().x());
|
||||
continue;
|
||||
}
|
||||
// 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());
|
||||
float t = (diff_z - a.y()) / (b.y() - a.y());
|
||||
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/ExPolygon.hpp"
|
||||
#include "libslic3r/SLA/SupportPoint.hpp"
|
||||
#include "libslic3r/SLA/SupportIslands/SampleConfig.hpp"
|
||||
|
||||
namespace Slic3r::sla {
|
||||
|
||||
@ -31,7 +32,7 @@ struct SupportPointGeneratorConfig{
|
||||
/// <summary>
|
||||
/// Size range for support point interface (head)
|
||||
/// </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:
|
||||
// const float pixel_area =
|
||||
@ -46,6 +47,9 @@ struct SupportPointGeneratorConfig{
|
||||
// y axis .. mean difference of height(Z)
|
||||
// Points of lines [in mm]
|
||||
std::vector<Vec2f> support_curve;
|
||||
|
||||
// Configuration for sampling island
|
||||
SampleConfig island_configuration;
|
||||
};
|
||||
|
||||
struct LayerPart; // forward decl.
|
||||
|
@ -53,6 +53,7 @@
|
||||
#include "libslic3r/SLA/RasterBase.hpp"
|
||||
#include "libslic3r/SLA/SupportTree.hpp"
|
||||
#include "libslic3r/SLA/SupportTreeStrategies.hpp"
|
||||
#include "libslic3r/SLA/SupportIslands/SampleConfigFactory.hpp"
|
||||
#include "libslic3r/SLAPrint.hpp"
|
||||
#include "libslic3r/TriangleMesh.hpp"
|
||||
|
||||
@ -627,99 +628,104 @@ void SLAPrint::Steps::support_points(SLAPrintObject &po)
|
||||
BOOST_LOG_TRIVIAL(debug) << "Support point count "
|
||||
<< mo.sla_support_points.size();
|
||||
|
||||
// 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();
|
||||
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 {
|
||||
if (mo.sla_points_status == sla::PointsStatus::UserModified) {
|
||||
// There are either some points on the front-end, or the user
|
||||
// removed them on purpose. No calculation will be done.
|
||||
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)
|
||||
|
@ -22,6 +22,8 @@
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#include "libslic3r/SLAPrint.hpp"
|
||||
|
||||
#include "libslic3r/SLA/SupportIslands/SampleConfigFactory.hpp"
|
||||
|
||||
static const double CONE_RADIUS = 0.25;
|
||||
static const double CONE_HEIGHT = 0.75;
|
||||
|
||||
@ -677,6 +679,92 @@ RENDER_AGAIN:
|
||||
}
|
||||
else { // not in editing mode:
|
||||
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");
|
||||
|
||||
@ -720,9 +808,7 @@ RENDER_AGAIN:
|
||||
// wxGetApp().obj_list()->update_and_show_object_settings_item();
|
||||
//}
|
||||
|
||||
bool generate = ImGuiPureWrap::button(m_desc.at("auto_generate"));
|
||||
|
||||
if (generate)
|
||||
if (ImGuiPureWrap::button(m_desc.at("auto_generate")))
|
||||
auto_generate();
|
||||
|
||||
ImGui::Separator();
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <libslic3r/ClipperUtils.hpp>
|
||||
#include <libslic3r/TriangleMeshSlicer.hpp>
|
||||
|
||||
#include <libslic3r/SLA/SupportIslands/SampleConfigFactory.hpp>
|
||||
#include <libslic3r/SLA/SupportIslands/SampleConfig.hpp>
|
||||
#include <libslic3r/SLA/SupportIslands/VoronoiGraphUtils.hpp>
|
||||
#include <libslic3r/SLA/SupportIslands/SampleIslandUtils.hpp>
|
||||
@ -17,7 +18,7 @@
|
||||
using namespace Slic3r;
|
||||
using namespace Slic3r::sla;
|
||||
|
||||
#define STORE_SAMPLE_INTO_SVG_FILES
|
||||
//#define STORE_SAMPLE_INTO_SVG_FILES
|
||||
|
||||
TEST_CASE("Overhanging point should be supported", "[SupGen]") {
|
||||
|
||||
@ -304,9 +305,23 @@ ExPolygon create_mountains(double 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)
|
||||
{
|
||||
bool useFrogLeg = false;
|
||||
bool useFrogLeg = false;
|
||||
// need post reorganization of longest path
|
||||
ExPolygons result = {
|
||||
// one support point
|
||||
@ -338,6 +353,9 @@ ExPolygons createTestIslands(double size)
|
||||
create_tiny_wide_test_2(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
|
||||
// three support points
|
||||
ExPolygon(PolygonUtils::create_equilateral_triangle(3 * size)),
|
||||
@ -347,14 +365,9 @@ ExPolygons createTestIslands(double size)
|
||||
create_trinagle_with_hole(size),
|
||||
create_square_with_hole(size, size / 2),
|
||||
create_square_with_hole(size, size / 3)
|
||||
};
|
||||
|
||||
if (useFrogLeg) {
|
||||
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);
|
||||
}
|
||||
};
|
||||
if (useFrogLeg)
|
||||
result.push_back(load_frog());
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -403,7 +416,7 @@ Points rasterize(const ExPolygon &island, double distance) {
|
||||
SupportIslandPoints test_island_sampling(const ExPolygon & island,
|
||||
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
|
||||
bool is_ok = true;
|
||||
@ -447,7 +460,7 @@ SupportIslandPoints test_island_sampling(const ExPolygon & island,
|
||||
}
|
||||
}
|
||||
CHECK(!points.empty());
|
||||
//CHECK(is_ok);
|
||||
CHECK(is_ok);
|
||||
|
||||
// all points must be inside of island
|
||||
for (const auto &point : points) { CHECK(island.contains(point->point)); }
|
||||
@ -539,12 +552,6 @@ TEST_CASE("speed sampling", "[hide], [SupGen]") {
|
||||
|
||||
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;
|
||||
result2.reserve(islands.size()*count);
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
@ -560,7 +567,7 @@ TEST_CASE("speed sampling", "[hide], [SupGen]") {
|
||||
|
||||
|
||||
#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();
|
||||
ExPolygon &island = islands[island_index];
|
||||
|
||||
@ -568,9 +575,6 @@ TEST_CASE("speed sampling", "[hide], [SupGen]") {
|
||||
std::string name = "sample_" + std::to_string(i) + ".svg";
|
||||
SVG svg(name, LineUtils::create_bounding_box(lines));
|
||||
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");
|
||||
for (Vec2f &p : result2[i])
|
||||
svg.draw((p * 1e6).cast<coord_t>(), "green", 1e6);
|
||||
@ -580,16 +584,17 @@ TEST_CASE("speed sampling", "[hide], [SupGen]") {
|
||||
|
||||
/// <summary>
|
||||
/// Check for correct sampling of island
|
||||
///
|
||||
/// </summary>
|
||||
TEST_CASE("Small islands should be supported in center", "[SupGen], [VoronoiSkeleton]")
|
||||
{
|
||||
double size = 3e7;
|
||||
SampleConfig cfg = create_sample_config(size);
|
||||
ExPolygons islands = createTestIslands(size);
|
||||
float head_diameter = .4f;
|
||||
SampleConfig cfg = SampleConfigFactory::create(head_diameter);
|
||||
ExPolygons islands = createTestIslands(21 * scale_(head_diameter));
|
||||
for (ExPolygon &island : islands) {
|
||||
// information for debug which island cause problem
|
||||
[[maybe_unused]] size_t debug_index = &island - &islands.front();
|
||||
|
||||
// TODO: index 17 - create field again
|
||||
auto points = test_island_sampling(island, cfg);
|
||||
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)
|
||||
{
|
||||
// Create the support point generator
|
||||
static TriangleMesh mesh;
|
||||
static AABBMesh emesh(mesh);
|
||||
static sla::SupportPointGenerator::Config autogencfg;
|
||||
//autogencfg.minimal_distance = 8.f;
|
||||
static sla::SupportPointGenerator generator{emesh, autogencfg, [] {}, [](int) {}};
|
||||
|
||||
// tear preasure
|
||||
float tp = autogencfg.tear_pressure();
|
||||
size_t layer_id = 13;
|
||||
coordf_t print_z = 11.f;
|
||||
SupportPointGenerator::MyLayer layer(layer_id, print_z);
|
||||
ExPolygon poly = island;
|
||||
BoundingBox bbox(island.contour.points);
|
||||
Vec2f centroid;
|
||||
float area = island.area();
|
||||
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;
|
||||
}
|
||||
//TEST_CASE("Cell polygon check", "") {
|
||||
// coord_t max_distance = 9;
|
||||
// Points points{Point{0,0}, Point{10,0}};
|
||||
// using VD = Slic3r::Geometry::VoronoiDiagram;
|
||||
// VD vd;
|
||||
// vd.construct_voronoi(points.begin(), points.end());
|
||||
// assert(points.size() == vd.cells().size());
|
||||
// Polygons cells(points.size());
|
||||
// for (const VD::cell_type &cell : vd.cells())
|
||||
// cells[cell.source_index()] = VoronoiGraphUtils::to_polygon(cell, points, max_distance);
|
||||
//
|
||||
// REQUIRE(cells[0].size() >= 3);
|
||||
// REQUIRE(cells[1].size() >= 3);
|
||||
// Polygons cell_overlaps = intersection(cells[0], cells[1]);
|
||||
// double area = 0;
|
||||
// for (const Polygon &cell_overlap : cell_overlaps)
|
||||
// area += cell_overlap.area();
|
||||
// CHECK(area < 1);
|
||||
//}
|
||||
|
||||
#include <libslic3r/SLA/SupportIslands/SampleConfigFactory.hpp>
|
||||
std::vector<Vec2f> sample_filip(const ExPolygon &island)
|
||||
{
|
||||
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;
|
||||
result.reserve(points.size());
|
||||
@ -675,16 +665,8 @@ void store_sample(const std::vector<Vec2f> &samples, const ExPolygon& island)
|
||||
}
|
||||
|
||||
TEST_CASE("Compare sampling test", "[hide]")
|
||||
{
|
||||
enum class Sampling {
|
||||
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;
|
||||
{
|
||||
std::function<std::vector<Vec2f>(const ExPolygon &)> sample = sample_filip;
|
||||
ExPolygons islands = createTestIslands(1e6);
|
||||
ExPolygons islands_big = createTestIslands(3e6);
|
||||
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
|
||||
sla::SupportPointGeneratorConfig autogencfg;
|
||||
float head_diam = 2 * supportcfg.head_front_radius_mm;
|
||||
autogencfg.head_diameter = {head_diam, head_diam};
|
||||
autogencfg.head_diameter = 2 * supportcfg.head_front_radius_mm;
|
||||
sla::ThrowOnCancel cancel = []() {};
|
||||
sla::StatusFunction status = [](int) {};
|
||||
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