diff --git a/src/libslic3r/SLA/SupportIslands/PointUtils.hpp b/src/libslic3r/SLA/SupportIslands/PointUtils.hpp
index 549d9ddea6..2a640ea678 100644
--- a/src/libslic3r/SLA/SupportIslands/PointUtils.hpp
+++ b/src/libslic3r/SLA/SupportIslands/PointUtils.hpp
@@ -31,10 +31,10 @@ public:
static bool is_majorit_x(const Vec2d &point);
///
- /// Create perpendicular vector
+ /// Create perpendicular vector[-y,x]
///
/// input vector from zero to point coordinate
- /// Perpendicular vector
+ /// Perpendicular[-vector.y, vector.x]
static Point perp(const Point &vector);
///
diff --git a/src/libslic3r/SLA/SupportIslands/PolygonUtils.cpp b/src/libslic3r/SLA/SupportIslands/PolygonUtils.cpp
index ef664d02b2..fe1bb64462 100644
--- a/src/libslic3r/SLA/SupportIslands/PolygonUtils.cpp
+++ b/src/libslic3r/SLA/SupportIslands/PolygonUtils.cpp
@@ -29,9 +29,9 @@ Slic3r::Polygon PolygonUtils::create_regular(size_t count_points,
Slic3r::Polygon PolygonUtils::create_equilateral_triangle(double edge_size)
{
- return {{.0, .0},
- {edge_size, .0},
- {edge_size / 2., sqrt(edge_size * edge_size - edge_size * edge_size / 4)}};
+ coord_t x = edge_size / 2;
+ coord_t y = sqrt(edge_size * edge_size - edge_size * edge_size / 4) / 2;
+ return {{-x, -y}, {x, -y}, {0, y}};
}
Slic3r::Polygon PolygonUtils::create_isosceles_triangle(double side, double height)
diff --git a/src/libslic3r/SLA/SupportIslands/SampleConfig.hpp b/src/libslic3r/SLA/SupportIslands/SampleConfig.hpp
index 657f3d49f7..7896d6eb7e 100644
--- a/src/libslic3r/SLA/SupportIslands/SampleConfig.hpp
+++ b/src/libslic3r/SLA/SupportIslands/SampleConfig.hpp
@@ -49,6 +49,10 @@ struct SampleConfig
// Maximal count of align iteration
size_t count_iteration = 100;
+
+ // Sample outline of Field by this value
+ // Less than max_distance
+ coord_t outline_sample_distance = 2;
// Maximal distance over Voronoi diagram edges to find closest point during aligning Support point
coord_t max_align_distance = 0.;
diff --git a/src/libslic3r/SLA/SupportIslands/SampleConfigFactory.hpp b/src/libslic3r/SLA/SupportIslands/SampleConfigFactory.hpp
index f32c32089f..5eed026486 100644
--- a/src/libslic3r/SLA/SupportIslands/SampleConfigFactory.hpp
+++ b/src/libslic3r/SLA/SupportIslands/SampleConfigFactory.hpp
@@ -63,6 +63,8 @@ public:
result.min_width_for_outline_support = result.max_width_for_center_support_line - 2 * config.head_diameter;
assert(result.min_width_for_outline_support >= result.max_width_for_center_support_line);
+ result.outline_sample_distance = result.max_distance;
+
// Align support points
// TODO: propagate print resolution
result.minimal_move = 1000; // [in nanometers], devide from print resolution to quater pixel
diff --git a/src/libslic3r/SLA/SupportIslands/SampleIslandUtils.cpp b/src/libslic3r/SLA/SupportIslands/SampleIslandUtils.cpp
index d59f003ff5..b931823bfe 100644
--- a/src/libslic3r/SLA/SupportIslands/SampleIslandUtils.cpp
+++ b/src/libslic3r/SLA/SupportIslands/SampleIslandUtils.cpp
@@ -602,6 +602,22 @@ SupportIslandPoints SampleIslandUtils::sample_center_circle(
return result;
}
+void SampleIslandUtils::sample_field(
+ VoronoiGraph::Position& field_start,
+ SupportIslandPoints& points,
+ CenterStarts& center_starts,
+ std::set& done,
+ const Lines & lines,
+ const SampleConfig &config)
+{
+ auto field = create_field(field_start, center_starts, done, lines, config);
+ SupportIslandPoints outline_support = sample_outline(field, config);
+ points.insert(points.end(), std::move_iterator(outline_support.begin()),
+ std::move_iterator(outline_support.end()));
+ // TODO: sample field inside
+
+}
+
SupportIslandPoints SampleIslandUtils::sample_expath(
const VoronoiGraph::ExPath &path,
const Lines & lines,
@@ -637,70 +653,75 @@ SupportIslandPoints SampleIslandUtils::sample_expath(
// TODO: 3) Triangle of points
// eval outline and find three point create almost equilateral triangle
- // IMPROVE: Erase continous sampling: Extract path and than sample uniformly whole path
+ // IMPROVE: Erase continous sampling: Extract path and than sample uniformly whole path
+
CenterStarts center_starts;
const VoronoiGraph::Node *start_node = path.nodes.front();
// CHECK> Front of path is outline node
assert(start_node->neighbors.size() == 1);
const VoronoiGraph::Node::Neighbor *neighbor = &start_node->neighbors.front();
- center_starts.emplace(neighbor, config.minimal_distance_from_outline);
-
std::set done; // already done nodes
- done.insert(start_node);
-
SupportIslandPoints points; // result
+ if (neighbor->max_width > config.max_width_for_center_support_line) {
+ VoronoiGraph::Position field_start = VoronoiGraphUtils::get_position_with_distance(
+ neighbor, config.min_width_for_outline_support, lines);
+ double center_sample_distance = neighbor->edge_length * field_start.ratio;
+ if (center_sample_distance > config.max_distance / 2.) {
+ // sample field from node, start without change on begining
+ sample_field(field_start, points, center_starts, done, lines, config);
+ } else {
+ const VoronoiGraph::Node::Neighbor *twin = VoronoiGraphUtils::get_twin(neighbor);
+ done.insert(neighbor->node);
+ coord_t support_in = neighbor->edge_length - center_sample_distance +
+ config.max_distance / 2;
+ center_starts.push(CenterStart(twin, support_in, {neighbor->node}));
+ sample_field(field_start, points, center_starts, done, lines, config);
+ }
+ } else {
+ done.insert(start_node);
+ center_starts.push(CenterStart(neighbor, config.minimal_distance_from_outline));
+ }
while (!center_starts.empty()) {
- FieldStart field_start;
- std::vector new_starts = sample(center_starts.front(),
- config, done, points,
- field_start);
+ std::optional field_start = {};
+ std::vector new_starts =
+ sample_center(center_starts.front(), config, done, points, lines, field_start);
center_starts.pop();
for (const CenterStart &start : new_starts) center_starts.push(start);
- if (field_start.neighbor != nullptr) {
- // TODO: create field
- auto field = create_field(field_start, center_starts, lines, config);
+ if (field_start.has_value()){ // exist new field start?
+ sample_field(field_start.value(), points, center_starts, done, lines, config);
+ field_start = {};
}
}
- // Fix first point type
- if (!points.empty()) {
- auto &front = points.front();
- if (front->type == SupportIslandPoint::Type::center_line)
- front->type = SupportIslandPoint::Type::center_line_start;
- }
- // TODO: remove next line, only for debug
- points.push_back(create_point_on_path(path.nodes, config.minimal_distance_from_outline));
- return std::move(points);
+ return points;
}
-std::vector SampleIslandUtils::sample(
+std::vector SampleIslandUtils::sample_center(
const CenterStart & start,
const SampleConfig & config,
std::set &done,
SupportIslandPoints & results,
- FieldStart & field_start)
+ const Lines & lines,
+ std::optional &field_start)
{
const VoronoiGraph::Node::Neighbor *neighbor = start.neighbor;
const VoronoiGraph::Node *node = neighbor->node;
if (done.find(node) != done.end()) return {};
done.insert(node);
-
VoronoiGraph::Nodes path = start.path;
std::vector new_starts;
double support_in = start.support_in;
- while (neighbor->max_width <= config.max_width_for_center_support_line) {
+ do {
double edge_length = neighbor->edge_length;
- while (edge_length > support_in) {
+ while (edge_length >= support_in) {
double ratio = support_in / edge_length;
results.push_back(
- create_point(neighbor, ratio,
- SupportIslandPoint::Type::center_line));
+ create_point(neighbor, ratio,
+ SupportIslandPoint::Type::center_line));
support_in += config.max_distance;
}
- if (support_in > edge_length)
- support_in -= edge_length;
-
+ support_in -= edge_length;
const VoronoiGraph::Node *node = neighbor->node;
path.push_back(node);
const VoronoiGraph::Node::Neighbor *next_neighbor = nullptr;
@@ -733,9 +754,18 @@ std::vector SampleIslandUtils::sample(
} else {
neighbor = next_neighbor;
}
+ } while (neighbor->max_width <= config.max_width_for_center_support_line);
+
+ field_start = VoronoiGraphUtils::get_position_with_distance(
+ neighbor, config.min_width_for_outline_support, lines);
+ double edge_length = neighbor->edge_length;
+ double sample_length = edge_length * field_start->ratio;
+ while (sample_length > support_in) {
+ double ratio = support_in / edge_length;
+ results.push_back(create_point(neighbor, ratio,
+ SupportIslandPoint::Type::center_line));
+ support_in += config.max_distance;
}
- field_start.neighbor = neighbor;
- field_start.last_support = config.max_distance - support_in;
return new_starts;
}
@@ -764,12 +794,14 @@ SupportIslandPoints SampleIslandUtils::sample_voronoi_graph(
}
SampleIslandUtils::Field SampleIslandUtils::create_field(
- const FieldStart &field_start,
+ const VoronoiGraph::Position & field_start,
CenterStarts & tiny_starts,
+ std::set &tiny_done,
const Lines & lines,
const SampleConfig &config)
{
using VD = Slic3r::Geometry::VoronoiDiagram;
+ const coord_t min_width = config.min_width_for_outline_support;
// DTO represents one island change from wide to tiny part
// it is stored inside map under source line index
@@ -804,21 +836,25 @@ SampleIslandUtils::Field SampleIslandUtils::create_field(
// store shortening of outline segments
// line index, vector
std::map wide_tiny_changes;
- const coord_t min_width = config.min_width_for_outline_support;
+
// cut lines at place where neighbor has width = min_width_for_outline_support
// neighbor must be in direction from wide part to tiny part of island
- auto add_wide_tiny_change = [&](const VoronoiGraph::Node::Neighbor *neighbor){
- VoronoiGraph::Position position =
- VoronoiGraphUtils::get_position_with_distance(neighbor, min_width, lines);
- Point p1, p2;
- std::tie(p1, p2) = VoronoiGraphUtils::point_on_lines(position, lines);
- const VD::edge_type *edge = neighbor->edge;
- size_t i1 = edge->cell()->source_index();
- size_t i2 = edge->twin()->cell()->source_index();
+ auto add_wide_tiny_change =
+ [&](const VoronoiGraph::Position &position,
+ const VoronoiGraph::Node * source_node)->bool {
+ const VoronoiGraph::Node::Neighbor *neighbor = position.neighbor;
- auto add = [&](const Point &p1, const Point &p2, size_t i1, size_t i2) {
+ // TODO: check not only one neighbor but all path to edge
+ if (VoronoiGraphUtils::is_last_neighbor(neighbor) &&
+ neighbor->edge_length * (1. - position.ratio) <= config.max_distance / 2)
+ return false;
+
+ // function to add sorted change from wide to tiny
+ // stored uder line index or line shorten in point b
+ auto add = [&](const Point &p1, const Point &p2, size_t i1,
+ size_t i2) {
WideTinyChange change(p1, p2, i2);
- auto item = wide_tiny_changes.find(i1);
+ auto item = wide_tiny_changes.find(i1);
if (item == wide_tiny_changes.end()) {
wide_tiny_changes[i1] = {change};
} else {
@@ -826,22 +862,35 @@ SampleIslandUtils::Field SampleIslandUtils::create_field(
VectorUtils::insert_sorted(item->second, change, pred);
}
};
+
+ Point p1, p2;
+ std::tie(p1, p2) = VoronoiGraphUtils::point_on_lines(position,
+ lines);
+ const VD::edge_type *edge = neighbor->edge;
+ size_t i1 = edge->cell()->source_index();
+ size_t i2 = edge->twin()->cell()->source_index();
+
const Line &l1 = lines[i1];
if (VoronoiGraphUtils::is_opposit_direction(edge, l1)) {
- // line1 is shorten on side line1.a --> line2 is shorten on side line2.b
+ // line1 is shorten on side line1.a --> line2 is shorten on
+ // side line2.b
add(p2, p1, i2, i1);
} else {
// line1 is shorten on side line1.b
add(p1, p2, i1, i2);
}
+ coord_t support_in = neighbor->edge_length * position.ratio + config.max_distance/2;
+ CenterStart tiny_start(neighbor, support_in, {source_node});
+ tiny_starts.push(tiny_start);
+ tiny_done.insert(source_node);
+ return true;
};
+
const VoronoiGraph::Node::Neighbor *neighbor = field_start.neighbor;
const VoronoiGraph::Node::Neighbor *twin_neighbor = VoronoiGraphUtils::get_twin(neighbor);
- // is input wide tiny change
- // first input could be from border of Voronoi Graph
- if (twin_neighbor->node->neighbors.size() != 1) {
- add_wide_tiny_change(twin_neighbor);
- }
+ VoronoiGraph::Position position(twin_neighbor, 1. - field_start.ratio);
+ add_wide_tiny_change(position, neighbor->node);
+
std::set done;
done.insert(twin_neighbor->node);
std::queue process;
@@ -864,9 +913,11 @@ SampleIslandUtils::Field SampleIslandUtils::create_field(
size_t index2 = edge->twin()->cell()->source_index();
field_line_indexes.insert(index1);
field_line_indexes.insert(index2);
- if (neighbor.max_width < config.min_width_for_outline_support) {
- add_wide_tiny_change(&neighbor);
- continue;
+ if (VoronoiGraphUtils::is_last_neighbor(&neighbor) || neighbor.max_width < min_width) {
+ VoronoiGraph::Position position =
+ VoronoiGraphUtils::get_position_with_distance(&neighbor, min_width, lines);
+ if(add_wide_tiny_change(position, node))
+ continue;
}
if (done.find(neighbor.node) != done.end()) continue; // loop back
if (next_node == nullptr) {
@@ -884,6 +935,7 @@ SampleIslandUtils::Field SampleIslandUtils::create_field(
std::map b_connection =
LineUtils::create_line_connection_over_b(lines);
+ std::vector source_indexes;
auto inser_point_b = [&](size_t& index, Points& points, std::set& done)
{
const Line &line = lines[index];
@@ -892,29 +944,21 @@ SampleIslandUtils::Field SampleIslandUtils::create_field(
assert(connection_item != b_connection.end());
done.insert(index);
index = connection_item->second;
+ source_indexes.push_back(index);
};
-
- Points points;
- points.reserve(field_line_indexes.size());
- std::vector outline_indexes;
- outline_indexes.reserve(field_line_indexes.size());
- size_t input_index = neighbor->edge->cell()->source_index();
- size_t outline_index = input_index;
- std::set done_indexes;
- std::vector source_indexes;
size_t source_indexe_for_change = lines.size();
- // Continue along line indexes and create polygon field
- do {
- auto change_item = wide_tiny_changes.find(outline_index);
- while(change_item != wide_tiny_changes.end()) {
+ auto insert_changes = [&](size_t &index, Points &points, std::set &done, size_t input_index)->bool {
+ bool is_first = points.empty();
+ auto change_item = wide_tiny_changes.find(index);
+ while (change_item != wide_tiny_changes.end()) {
const WideTinyChanges &changes = change_item->second;
assert(!changes.empty());
size_t change_index = 0;
if (!points.empty()) {
- const Point &last_point = points.back();
- LineUtils::SortFromAToB pred(lines[outline_index]);
- bool no_change = false;
+ const Point & last_point = points.back();
+ LineUtils::SortFromAToB pred(lines[index]);
+ bool no_change = false;
while (pred.compare(changes[change_index].new_b, last_point)) {
++change_index;
if (change_index >= changes.size()) {
@@ -924,29 +968,44 @@ SampleIslandUtils::Field SampleIslandUtils::create_field(
}
if (no_change) break;
}
- const WideTinyChange& change = changes[change_index];
+ const WideTinyChange &change = changes[change_index];
// prevent double points
- if (points.empty() || !PointUtils::is_equal(points.back(),change.new_b)){
+ if (points.empty() ||
+ !PointUtils::is_equal(points.back(), change.new_b)) {
points.push_back(change.new_b);
source_indexes.push_back(source_indexe_for_change);
} else {
source_indexes.back() = source_indexe_for_change;
}
// prevent double points
- if (!PointUtils::is_equal(lines[change.next_line_index].b, change.next_new_a)){
+ if (!PointUtils::is_equal(lines[change.next_line_index].b,
+ change.next_new_a)) {
points.push_back(change.next_new_a);
source_indexes.push_back(change.next_line_index);
- }
- done_indexes.insert(outline_index);
- outline_index = change.next_line_index;
- change_item = wide_tiny_changes.find(outline_index);
+ }
+ done.insert(index);
+ index = change.next_line_index;
+ // end of conture
+ if (!is_first && index == input_index) return false;
+ change_item = wide_tiny_changes.find(index);
}
+ return true;
+ };
+
+ Points points;
+ points.reserve(field_line_indexes.size());
+ std::vector outline_indexes;
+ outline_indexes.reserve(field_line_indexes.size());
+ size_t input_index = neighbor->edge->cell()->source_index();
+ size_t outline_index = input_index;
+ std::set done_indexes;
+ do {
+ if (!insert_changes(outline_index, points, done_indexes, input_index))
+ break;
inser_point_b(outline_index, points, done_indexes);
- source_indexes.push_back(outline_index);
} while (outline_index != input_index);
Field field;
- field.source_indexes = std::move(source_indexes);
field.border.contour = Polygon(points);
// finding holes
if (done_indexes.size() < field_line_indexes.size()) {
@@ -961,39 +1020,101 @@ SampleIslandUtils::Field SampleIslandUtils::create_field(
field.border.holes.emplace_back(hole_points);
}
}
+ field.source_indexe_for_change = source_indexe_for_change;
+ field.source_indexes = std::move(source_indexes);
#ifdef SLA_SAMPLING_STORE_FIELD_TO_SVG
{
- bool draw_border_line_indexes = false;
- bool draw_source_line_indexes = true;
- bool draw_field_source_indexes = true;
- const char *field_color = "red";
const char *source_line_color = "black";
- const char *border_line_color = "blue";
-
- static int counter = 0;
+ bool draw_source_line_indexes = true;
+ bool draw_border_line_indexes = false;
+ bool draw_field_source_indexes = true;
+ static int counter = 0;
std::string file_name = "field_" + std::to_string(counter++) + ".svg";
SVG svg(file_name, LineUtils::create_bounding_box(lines));
- svg.draw(field.border, field_color);
- LineUtils::draw(svg,lines, source_line_color,0., draw_source_line_indexes);
- Lines border_lines = to_lines(field.border);
- LineUtils::draw(svg, border_lines, border_line_color, 0., draw_border_line_indexes);
- if (draw_field_source_indexes)
- for (auto &line : border_lines) {
- size_t index = &line - &border_lines.front();
- // start of holes
- if (index >= field.source_indexes.size()) break;
- Point middle_point = (line.a + line.b) / 2;
- std::string text = std::to_string(field.source_indexes[index]);
- svg.draw_text(middle_point, text.c_str(), field_color);
- }
+ LineUtils::draw(svg, lines, source_line_color, 0., draw_source_line_indexes);
+ draw(svg, field, draw_border_line_indexes, draw_field_source_indexes);
}
#endif //SLA_SAMPLING_STORE_FIELD_TO_SVG
-
return field;
}
+SupportIslandPoints SampleIslandUtils::sample_outline(
+ const Field &field, const SampleConfig &config)
+{
+ coord_t sample_distance = config.outline_sample_distance;
+ coord_t outline_distance = config.minimal_distance_from_outline;
+ SupportIslandPoints result;
+ auto add_sample = [&](const Line &line, size_t source_index, coord_t& last_support) {
+ double line_length_double = line.length();
+ coord_t line_length = static_cast(line_length_double);
+ if (last_support + line_length > sample_distance) {
+ Point dir = LineUtils::direction(line);
+ Point perp = PointUtils::perp(dir);
+ double size = perp.cast().norm();
+ Point move_from_outline = perp * (outline_distance / size);
+ do {
+ double ratio = (sample_distance - last_support) / line_length_double;
+ Point point = line.a + dir * ratio + move_from_outline;
+ result.emplace_back(std::make_unique(
+ point, source_index, SupportIslandPoint::Type::outline));
+ last_support -= sample_distance;
+ } while (last_support + line_length > sample_distance);
+ }
+ last_support += line_length;
+ };
+ Lines contour_lines = to_lines(field.border.contour);
+ coord_t last_support = sample_distance / 2;
+ for (const Line &line : contour_lines) {
+ size_t index = &line - &contour_lines.front();
+ assert(field.source_indexes.size() > index);
+ size_t source_index = field.source_indexes[index];
+ if (source_index == field.source_indexe_for_change) {
+ last_support = sample_distance / 2;
+ continue;
+ }
+ add_sample(line, source_index, last_support);
+ }
+ size_t index_offset = contour_lines.size();
+ for (const Polygon &hole : field.border.holes) {
+ Lines hole_lines = to_lines(hole);
+ coord_t last_support = sample_distance / 2;
+ for (const Line &line : hole_lines) {
+ size_t hole_line_index = (&line - &hole_lines.front());
+ size_t index = index_offset + hole_line_index;
+ assert(field.source_indexes.size() > index);
+ size_t source_index = field.source_indexes[index];
+ add_sample(line, source_index, last_support);
+ }
+ index_offset += hole_lines.size();
+ }
+ return result;
+}
+
+void SampleIslandUtils::draw(SVG & svg,
+ const Field &field,
+ bool draw_border_line_indexes,
+ bool draw_field_source_indexes)
+{
+ const char *field_color = "red";
+ const char *border_line_color = "blue";
+ const char *source_index_text_color = "blue";
+ svg.draw(field.border, field_color);
+ Lines border_lines = to_lines(field.border);
+ LineUtils::draw(svg, border_lines, border_line_color, 0.,
+ draw_border_line_indexes);
+ if (draw_field_source_indexes)
+ for (auto &line : border_lines) {
+ size_t index = &line - &border_lines.front();
+ // start of holes
+ if (index >= field.source_indexes.size()) break;
+ Point middle_point = (line.a + line.b) / 2;
+ std::string text = std::to_string(field.source_indexes[index]);
+ svg.draw_text(middle_point, text.c_str(), source_index_text_color);
+ }
+}
+
void SampleIslandUtils::draw(SVG & svg,
const SupportIslandPoints &supportIslandPoints,
double size,
diff --git a/src/libslic3r/SLA/SupportIslands/SampleIslandUtils.hpp b/src/libslic3r/SLA/SupportIslands/SampleIslandUtils.hpp
index 9794f2bbb7..884c5d6575 100644
--- a/src/libslic3r/SLA/SupportIslands/SampleIslandUtils.hpp
+++ b/src/libslic3r/SLA/SupportIslands/SampleIslandUtils.hpp
@@ -2,6 +2,7 @@
#define slic3r_SLA_SuppotstIslands_SampleIslandUtils_hpp_
#include
+#include
#include
#include
@@ -173,12 +174,6 @@ public:
/// Distance move of original point
static coord_t align_support(SupportIslandPoint &support, const Point &wanted, double max_distance);
- static void draw(SVG & svg,
- const SupportIslandPoints &supportIslandPoints,
- double size,
- const char *color = "lightgreen",
- bool write_type = true);
-
///
/// DTO hold information for start sampling VD in center
///
@@ -201,26 +196,7 @@ public:
using CenterStarts = std::queue;
///
- /// DTO extend VG neighbor with information about last sample
- ///
- struct FieldStart
- {
- // define edge where start field
- const VoronoiGraph::Node::Neighbor *neighbor = nullptr;
-
- // distance to last support
- // when last support lay on neighbor edge it is negative value
- coord_t last_support = 0; // [nano meters]
-
- FieldStart() = default;
- FieldStart(const VoronoiGraph::Node::Neighbor *neighbor,
- coord_t last_support)
- : neighbor(neighbor), last_support(last_support)
- {}
- };
-
- ///
- /// Sample VG in center.
+ /// Sample VG in center --> sample tiny part of island
/// Detection of wide neighbor which start field
/// Creating of new starts (from VG cross -> multi neighbors)
///
@@ -228,17 +204,19 @@ public:
/// Parameters for sampling
/// Already done nodes
/// Result of sampling
+ /// Source line for VD. To decide position of change from tiny to wide part
/// Output: Wide neighbor, start of field
/// New start of sampling
- static std::vector sample(
+ static std::vector sample_center(
const CenterStart & start,
const SampleConfig & config,
std::set &done,
SupportIslandPoints & results,
- FieldStart& field_start);
+ const Lines &lines,
+ std::optional &field_start);
///
- /// DTO represents area to sample
+ /// DTO represents Wide parts of island to sample
/// extend polygon with information about source lines
///
struct Field
@@ -250,22 +228,60 @@ public:
// indexes to source island lines
// in case (index > lines.size()) it means fill the gap from tiny part of island
std::vector source_indexes;
+ // value for source index of change from wide to tiny part of island
+ size_t source_indexe_for_change;
};
+ ///
+ /// Create & sample field -- wide part of island
+ ///
+ /// Start neighbor, first occur of wide neighbor.
+ /// Append new founded tiny parts of island.
+ /// Already sampled node sets. Filled only node inside field imediate after change
+ /// Source lines for VG --> outline of island.
+ /// Containe Minimal width in field and sample distance for center line
+ static void sample_field(VoronoiGraph::Position &field_start,
+ SupportIslandPoints & points,
+ CenterStarts & center_starts,
+ std::set &done,
+ const Lines & lines,
+ const SampleConfig & config);
///
/// Create field from input neighbor
///
/// Start neighbor, first occur of wide neighbor.
/// Append new founded tiny parts of island.
+ /// Already sampled node sets. Filled only node inside field imediate after change
/// Source lines for VG --> outline of island.
- /// Parameters for sampling.
+ /// Containe Minimal width in field and sample distance for center line
/// New created field
- static Field create_field(const FieldStart & field_start,
- CenterStarts &tiny_starts,
- const Lines & lines,
+ static Field create_field(const VoronoiGraph::Position &field_start,
+ CenterStarts & tiny_starts,
+ std::set &tiny_done,
+ const Lines & lines,
const SampleConfig &config);
+ ///
+ /// create support points on border of field
+ ///
+ /// Input field
+ /// Parameters for sampling.
+ /// support for outline
+ static SupportIslandPoints sample_outline(const Field & field,
+ const SampleConfig &config);
+
+ // debug draw functions
+ static void draw(SVG & svg,
+ const Field &field,
+ bool draw_border_line_indexes = false,
+ bool draw_field_source_indexes = true);
+
+ static void draw(SVG & svg,
+ const SupportIslandPoints &supportIslandPoints,
+ double size,
+ const char *color = "lightgreen",
+ bool write_type = true);
};
} // namespace Slic3r::sla
diff --git a/src/libslic3r/SLA/SupportIslands/VoronoiGraphUtils.cpp b/src/libslic3r/SLA/SupportIslands/VoronoiGraphUtils.cpp
index d9a9619d84..544aa2629b 100644
--- a/src/libslic3r/SLA/SupportIslands/VoronoiGraphUtils.cpp
+++ b/src/libslic3r/SLA/SupportIslands/VoronoiGraphUtils.cpp
@@ -1177,6 +1177,10 @@ void VoronoiGraphUtils::draw(SVG & svg,
draw(svg, path.nodes, width, mainPathColor);
}
+bool VoronoiGraphUtils::is_last_neighbor(const VoronoiGraph::Node::Neighbor *neighbor)
+{
+ return (neighbor->node->neighbors.size() == 1);
+}
void VoronoiGraphUtils::draw(const Polygon &polygon,
const Lines & lines,
diff --git a/src/libslic3r/SLA/SupportIslands/VoronoiGraphUtils.hpp b/src/libslic3r/SLA/SupportIslands/VoronoiGraphUtils.hpp
index 3c2b512b9f..b804ed8b26 100644
--- a/src/libslic3r/SLA/SupportIslands/VoronoiGraphUtils.hpp
+++ b/src/libslic3r/SLA/SupportIslands/VoronoiGraphUtils.hpp
@@ -409,6 +409,13 @@ public:
static double get_max_width(const VoronoiGraph::Nodes &path);
static double get_max_width(const VoronoiGraph::Node *node);
+ ///
+ /// Check if neighbor is end of VG
+ ///
+ /// Neighbor to test
+ /// True when neighbor node has only one neighbor
+ static bool is_last_neighbor(const VoronoiGraph::Node::Neighbor *neighbor);
+
public: // draw function for debug
static void draw(SVG &svg, const VoronoiGraph &graph, coord_t width, bool pointer_caption = false);
static void draw(SVG & svg,
diff --git a/tests/sla_print/sla_supptgen_tests.cpp b/tests/sla_print/sla_supptgen_tests.cpp
index 8c68cd0d9b..4612661bd9 100644
--- a/tests/sla_print/sla_supptgen_tests.cpp
+++ b/tests/sla_print/sla_supptgen_tests.cpp
@@ -222,7 +222,7 @@ ExPolygon create_tiny_wide_test(double wide, double tiny)
{
double hole_size = wide;
double width = (3 + 1) * wide + 3 * hole_size;
- double height = wide + 2*tiny + 2*hole_size;
+ double height = 2*wide + 2*tiny + 3*hole_size;
auto outline = PolygonUtils::create_rect( width, height);
auto hole = PolygonUtils::create_rect(hole_size, hole_size);
hole.reverse();
@@ -231,7 +231,7 @@ ExPolygon create_tiny_wide_test(double wide, double tiny)
auto hole4 = hole; // copy
int hole_move_x = wide + hole_size;
- int hole_move_y = wide / 2 + hole_size / 2;
+ int hole_move_y = wide + hole_size;
hole.translate(hole_move_x, hole_move_y);
hole2.translate(-hole_move_x, hole_move_y);
hole3.translate(hole_move_x, -hole_move_y);
@@ -243,8 +243,15 @@ ExPolygon create_tiny_wide_test(double wide, double tiny)
hole5.translate(0, hole_move_y);
hole6.translate(0, -hole_move_y);
+ auto hole7 = PolygonUtils::create_equilateral_triangle(hole_size);
+ hole7.reverse();
+ auto hole8 = PolygonUtils::create_circle(hole_size/2, 7, Point(hole_move_x,0));
+ hole8.reverse();
+ auto hole9 = PolygonUtils::create_circle(hole_size/2, 5, Point(-hole_move_x,0));
+ hole9.reverse();
+
ExPolygon result(outline);
- result.holes = {hole, hole2, hole3, hole4, hole5, hole6};
+ result.holes = {hole, hole2, hole3, hole4, hole5, hole6, hole7, hole8, hole9};
return result;
}
@@ -415,6 +422,7 @@ SampleConfig create_sample_config(double size) {
cfg.max_length_for_two_support_points = 4*size;
cfg.max_width_for_center_support_line = size;
cfg.min_width_for_outline_support = cfg.max_width_for_center_support_line;
+ cfg.outline_sample_distance = cfg.max_distance;
cfg.minimal_move = std::max(1000., size/1000);
cfg.count_iteration = 100;