mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-13 12:09:09 +08:00
Compare of Sampling method
This commit is contained in:
parent
24208b4daa
commit
1c489806ff
@ -1,5 +1,5 @@
|
||||
#include "ParabolaUtils.hpp"
|
||||
|
||||
#include "PointUtils.hpp"
|
||||
using namespace Slic3r::sla;
|
||||
|
||||
double ParabolaUtils::length(const ParabolaSegment ¶bola)
|
||||
@ -79,6 +79,8 @@ void ParabolaUtils::draw(SVG & svg,
|
||||
double discretization_step)
|
||||
{
|
||||
using VD = Slic3r::Geometry::VoronoiDiagram;
|
||||
if (PointUtils::is_equal(parabola.from, parabola.to)) return;
|
||||
|
||||
std::vector<Voronoi::Internal::point_type> parabola_samples(
|
||||
{parabola.from, parabola.to});
|
||||
|
||||
|
@ -16,54 +16,61 @@ public:
|
||||
// factory method to iniciate config
|
||||
static SampleConfig create(const SupportPointGenerator::Config &config)
|
||||
{
|
||||
coord_t head_diameter = scale_(config.head_diameter);
|
||||
coord_t min_distance = scale_(config.minimal_distance);
|
||||
coord_t max_distance = 3 * min_distance;
|
||||
coord_t sample_multiplicator = 10; // allign is made by selecting from samples
|
||||
|
||||
|
||||
// TODO: find valid params !!!!
|
||||
SampleConfig result;
|
||||
result.max_distance = 100 * config.head_diameter;
|
||||
result.max_distance = max_distance / sample_multiplicator;
|
||||
result.half_distance = result.max_distance / 2;
|
||||
result.head_radius = config.head_diameter / 2;
|
||||
result.minimal_distance_from_outline = config.head_diameter / 2.;
|
||||
result.head_radius = head_diameter / 2;
|
||||
result.minimal_distance_from_outline = head_diameter / 2.;
|
||||
result.minimal_support_distance = result.minimal_distance_from_outline +
|
||||
result.half_distance;
|
||||
|
||||
result.max_length_for_one_support_point =
|
||||
2 * result.minimal_distance_from_outline +
|
||||
config.head_diameter;
|
||||
head_diameter;
|
||||
coord_t max_length_for_one_support_point =
|
||||
2 * result.max_distance +
|
||||
config.head_diameter +
|
||||
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 * config.head_diameter +
|
||||
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 * result.max_distance + 2 * config.head_diameter +
|
||||
2 * max_distance + 2 * head_diameter +
|
||||
2 * result.minimal_distance_from_outline;
|
||||
coord_t max_length_for_two_support_points =
|
||||
2 * result.max_distance +
|
||||
2 * config.head_diameter +
|
||||
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);
|
||||
assert(result.max_length_for_two_support_points > result.max_length_for_one_support_point);
|
||||
|
||||
result.max_width_for_center_support_line = 2 * config.head_diameter;
|
||||
coord_t min_width_for_center_support_line =
|
||||
config.head_diameter + 2 * result.minimal_distance_from_outline;
|
||||
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 * result.max_distance + config.head_diameter;
|
||||
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 * config.head_diameter;
|
||||
assert(result.min_width_for_outline_support >= result.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 = result.max_distance;
|
||||
result.outline_sample_distance = result.max_distance/20;
|
||||
|
||||
// Align support points
|
||||
// TODO: propagate print resolution
|
||||
|
@ -16,11 +16,14 @@
|
||||
|
||||
#include <libslic3r/ClipperUtils.hpp> // allign
|
||||
|
||||
#include "libslic3r/SLA/SupportPointGenerator.hpp"
|
||||
|
||||
// comment definition of NDEBUG to enable assert()
|
||||
//#define NDEBUG
|
||||
|
||||
#define SLA_SAMPLING_STORE_FIELD_TO_SVG
|
||||
#define SLA_SAMPLING_STORE_VORONOI_GRAPH_TO_SVG
|
||||
//#define SLA_SAMPLING_STORE_VORONOI_GRAPH_TO_SVG
|
||||
//#define SLA_SAMPLING_STORE_FIELD_TO_SVG
|
||||
//#define SLA_SAMPLING_STORE_POISSON_SAMPLING_TO_SVG
|
||||
|
||||
#include <cassert>
|
||||
|
||||
@ -28,6 +31,27 @@ using namespace Slic3r::sla;
|
||||
|
||||
std::vector<Slic3r::Vec2f> SampleIslandUtils::sample_expolygon(
|
||||
const ExPolygon &expoly, float samples_per_mm2)
|
||||
{
|
||||
static const float mm2_area = scale_(1) * scale_(1);
|
||||
// Equilateral triangle area = (side * height) / 2
|
||||
float triangle_area = mm2_area / samples_per_mm2;
|
||||
// Triangle area = sqrt(3) / 4 * "triangle side"
|
||||
static const float coef1 = sqrt(3.) / 4.;
|
||||
coord_t triangle_side = static_cast<coord_t>(
|
||||
std::round(sqrt(triangle_area * coef1)));
|
||||
|
||||
Points points = sample_expolygon(expoly, triangle_side);
|
||||
|
||||
std::vector<Vec2f> result;
|
||||
result.reserve(points.size());
|
||||
std::transform(points.begin(), points.end(), std::back_inserter(result),
|
||||
[](const Point &p) { return unscale(p).cast<float>(); });
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Slic3r::Points SampleIslandUtils::sample_expolygon(const ExPolygon &expoly,
|
||||
coord_t triangle_side)
|
||||
{
|
||||
const Points &points = expoly.contour.points;
|
||||
assert(!points.empty());
|
||||
@ -41,51 +65,45 @@ std::vector<Slic3r::Vec2f> SampleIslandUtils::sample_expolygon(
|
||||
max_y = point.y();
|
||||
}
|
||||
|
||||
static const float mm2_area = scale_(1) * scale_(1);
|
||||
// Equilateral triangle area = (side * height) / 2
|
||||
float triangle_area = mm2_area / samples_per_mm2;
|
||||
// Triangle area = sqrt(3) / 4 * "triangle side"
|
||||
static const float coef1 = sqrt(3.) / 4.;
|
||||
coord_t triangle_side = static_cast<coord_t>(
|
||||
std::round(sqrt(triangle_area * coef1)));
|
||||
coord_t triangle_side_2 = triangle_side / 2;
|
||||
coord_t triangle_side_2 = triangle_side / 2;
|
||||
static const float coef2 = sqrt(3.) / 2.;
|
||||
coord_t triangle_height = static_cast<coord_t>(
|
||||
std::round(triangle_side * coef2));
|
||||
coord_t triangle_height = static_cast<coord_t>(std::round(triangle_side * coef2));
|
||||
|
||||
// IMPROVE: use line end y
|
||||
Lines lines = to_lines(expoly);
|
||||
// remove lines with y direction
|
||||
// remove lines paralel with axe x
|
||||
lines.erase(std::remove_if(lines.begin(), lines.end(),
|
||||
[](const Line &l) {
|
||||
return l.a.y() == l.b.y();
|
||||
}),
|
||||
lines.end());
|
||||
}), lines.end());
|
||||
|
||||
// change line direction from top to bottom
|
||||
for (Line &line : lines)
|
||||
if (line.a.y() > line.b.y()) std::swap(line.a, line.b);
|
||||
|
||||
// sort by a.y()
|
||||
std::sort(lines.begin(), lines.end(),
|
||||
[](const Line &l1, const Line &l2) -> bool {
|
||||
return l1.a.y() < l2.a.y();
|
||||
});
|
||||
|
||||
std::vector<Vec2f> out;
|
||||
// size_t count_sample_lines = (max_y - min_y) / triangle_height;
|
||||
// out.reserve(count_sample_lines * count_sample_lines);
|
||||
|
||||
// IMPROVE: guess size and reserve points
|
||||
Points result;
|
||||
size_t start_index = 0;
|
||||
bool is_odd = false;
|
||||
for (coord_t y = min_y + triangle_height / 2; y < max_y;
|
||||
y += triangle_height) {
|
||||
is_odd = !is_odd;
|
||||
std::vector<coord_t> intersections;
|
||||
|
||||
for (auto line = std::begin(lines); line != std::end(lines); ++line) {
|
||||
bool increase_start_index = true;
|
||||
for (auto line = std::begin(lines)+start_index; line != std::end(lines); ++line) {
|
||||
const Point &b = line->b;
|
||||
if (b.y() <= y) {
|
||||
// line = lines.erase(line);
|
||||
// removing lines is slow, start index is faster
|
||||
// line = lines.erase(line);
|
||||
if (increase_start_index) ++start_index;
|
||||
continue;
|
||||
}
|
||||
increase_start_index = false;
|
||||
const Point &a = line->a;
|
||||
if (a.y() >= y) break;
|
||||
float y_range = static_cast<float>(b.y() - a.y());
|
||||
@ -106,12 +124,12 @@ std::vector<Slic3r::Vec2f> SampleIslandUtils::sample_expolygon(
|
||||
coord_t x = div * triangle_side;
|
||||
if (is_odd) x -= triangle_side_2;
|
||||
while (x < end_x) {
|
||||
out.push_back(unscale(x, y).cast<float>());
|
||||
result.emplace_back(x, y);
|
||||
x += triangle_side;
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
return result;
|
||||
}
|
||||
|
||||
std::unique_ptr<SupportIslandPoint> SampleIslandUtils::create_point(
|
||||
@ -224,7 +242,14 @@ SupportIslandPoints SampleIslandUtils::sample_side_branch(
|
||||
distance -= neighbor->length();
|
||||
prev_node = node;
|
||||
}
|
||||
assert(fabs(distance - (sample_distance - cfg.side_distance)) < 1e-5);
|
||||
//if (cfg.side_distance > sample_distance) {
|
||||
// int count = static_cast<int>(std::floor(cfg.side_distance / sample_distance));
|
||||
// for (int i = 0; i < count; ++i) {
|
||||
// distance += sample_distance;
|
||||
// result.pop_back();
|
||||
// }
|
||||
//}
|
||||
//assert(fabs(distance - (sample_distance - cfg.side_distance)) < 1e-5);
|
||||
result.back()->type = SupportIslandPoint::Type::center_line_end;
|
||||
return std::move(result);
|
||||
}
|
||||
@ -777,8 +802,7 @@ SupportIslandPoints SampleIslandUtils::sample_expath(
|
||||
center_starts.pop();
|
||||
for (const CenterStart &start : new_starts) center_starts.push(start);
|
||||
if (field_start.has_value()){ // exist new field start?
|
||||
sample_field(field_start.value(), points, center_starts, done, lines, config);
|
||||
field_start = {};
|
||||
sample_field(*field_start, points, center_starts, done, lines, config);
|
||||
}
|
||||
}
|
||||
return points;
|
||||
@ -795,7 +819,23 @@ void SampleIslandUtils::sample_field(VoronoiGraph::Position &field_start,
|
||||
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
|
||||
|
||||
// Erode island to not sampled island around border,
|
||||
// minimal value must be -config.minimal_distance_from_outline
|
||||
Polygons polygons = offset(field.border, -2.f * config.minimal_distance_from_outline,
|
||||
ClipperLib::jtSquare);
|
||||
if (polygons.empty()) return;
|
||||
ExPolygon inner(polygons.front());
|
||||
for (size_t i = 1; i < polygons.size(); ++i) {
|
||||
Polygon &hole = polygons[i];
|
||||
inner.holes.push_back(hole);
|
||||
}
|
||||
Points inner_points = sample_expolygon(inner, config.max_distance);
|
||||
std::transform(inner_points.begin(), inner_points.end(), std::back_inserter(points),
|
||||
[](const Point &point) {
|
||||
return std::make_unique<SupportIslandPoint>(
|
||||
point, SupportIslandPoint::Type::inner);
|
||||
});
|
||||
}
|
||||
|
||||
std::vector<SampleIslandUtils::CenterStart> SampleIslandUtils::sample_center(
|
||||
@ -919,6 +959,7 @@ SampleIslandUtils::Field SampleIslandUtils::create_field(
|
||||
// line index, vector<next line index + 2x shortening points>
|
||||
std::map<size_t, WideTinyChanges> wide_tiny_changes;
|
||||
|
||||
coord_t minimal_edge_length = std::max(config.max_distance / 2, 2*config.minimal_distance_from_outline);
|
||||
// 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 =
|
||||
@ -929,7 +970,7 @@ SampleIslandUtils::Field SampleIslandUtils::create_field(
|
||||
// IMPROVE: check not only one neighbor but all path to edge
|
||||
coord_t rest_size = static_cast<coord_t>(neighbor->length() * (1. - position.ratio));
|
||||
if (VoronoiGraphUtils::is_last_neighbor(neighbor) &&
|
||||
rest_size <= config.max_distance / 2)
|
||||
rest_size <= minimal_edge_length)
|
||||
return false; // no change only rich outline
|
||||
|
||||
// function to add sorted change from wide to tiny
|
||||
@ -968,16 +1009,19 @@ SampleIslandUtils::Field SampleIslandUtils::create_field(
|
||||
return true;
|
||||
};
|
||||
|
||||
const VoronoiGraph::Node::Neighbor *neighbor = field_start.neighbor;
|
||||
const VoronoiGraph::Node::Neighbor *twin_neighbor = VoronoiGraphUtils::get_twin(neighbor);
|
||||
VoronoiGraph::Position position(twin_neighbor, 1. - field_start.ratio);
|
||||
add_wide_tiny_change(position, neighbor->node);
|
||||
const VoronoiGraph::Node::Neighbor *tiny_wide_neighbor = field_start.neighbor;
|
||||
const VoronoiGraph::Node::Neighbor *wide_tiny_neighbor = VoronoiGraphUtils::get_twin(tiny_wide_neighbor);
|
||||
VoronoiGraph::Position position(wide_tiny_neighbor, 1. - field_start.ratio);
|
||||
add_wide_tiny_change(position, tiny_wide_neighbor->node);
|
||||
|
||||
std::set<const VoronoiGraph::Node*> done;
|
||||
done.insert(twin_neighbor->node);
|
||||
done.insert(wide_tiny_neighbor->node);
|
||||
// prev node , node
|
||||
using ProcessItem = std::pair<const VoronoiGraph::Node *, const VoronoiGraph::Node *>;
|
||||
// initial proccess item from tiny part to wide part of island
|
||||
ProcessItem start(wide_tiny_neighbor->node, tiny_wide_neighbor->node);
|
||||
std::queue<ProcessItem> process;
|
||||
process.push({twin_neighbor->node, neighbor->node});
|
||||
process.push(start);
|
||||
|
||||
// all lines belongs to polygon
|
||||
std::set<size_t> field_line_indexes;
|
||||
@ -1051,6 +1095,14 @@ SampleIslandUtils::Field SampleIslandUtils::create_field(
|
||||
}
|
||||
}
|
||||
if (no_change) break;
|
||||
|
||||
// Field ends with change into first index
|
||||
if (!is_first && change_item->first == input_index &&
|
||||
change_index == 0) {
|
||||
return false;
|
||||
} else {
|
||||
is_first = false;
|
||||
}
|
||||
}
|
||||
const WideTinyChange &change = changes[change_index];
|
||||
// prevent double points
|
||||
@ -1069,8 +1121,6 @@ SampleIslandUtils::Field SampleIslandUtils::create_field(
|
||||
}
|
||||
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;
|
||||
@ -1080,8 +1130,8 @@ SampleIslandUtils::Field SampleIslandUtils::create_field(
|
||||
points.reserve(field_line_indexes.size());
|
||||
std::vector<size_t> outline_indexes;
|
||||
outline_indexes.reserve(field_line_indexes.size());
|
||||
size_t input_index1 = neighbor->edge->cell()->source_index();
|
||||
size_t input_index2 = neighbor->edge->twin()->cell()->source_index();
|
||||
size_t input_index1 = tiny_wide_neighbor->edge->cell()->source_index();
|
||||
size_t input_index2 = tiny_wide_neighbor->edge->twin()->cell()->source_index();
|
||||
size_t input_index = std::min(input_index1, input_index2);
|
||||
size_t outline_index = input_index;
|
||||
std::set<size_t> done_indexes;
|
||||
@ -1129,6 +1179,16 @@ SampleIslandUtils::Field SampleIslandUtils::create_field(
|
||||
SupportIslandPoints SampleIslandUtils::sample_outline(
|
||||
const Field &field, const SampleConfig &config)
|
||||
{
|
||||
// TODO: fix it by neighbor line angles
|
||||
// Do not create inner expoly and test all points to lay inside
|
||||
Polygons polygons = offset(field.border,-config.minimal_distance_from_outline + 5, ClipperLib::jtSquare);
|
||||
if (polygons.empty()) return {}; // no place for support point
|
||||
ExPolygon inner(polygons.front());
|
||||
for (size_t i = 1; i < polygons.size(); ++i) {
|
||||
Polygon &hole = polygons[i];
|
||||
inner.holes.push_back(hole);
|
||||
}
|
||||
|
||||
coord_t sample_distance = config.outline_sample_distance;
|
||||
coord_t outline_distance = config.minimal_distance_from_outline;
|
||||
SupportIslandPoints result;
|
||||
@ -1143,8 +1203,13 @@ SupportIslandPoints SampleIslandUtils::sample_outline(
|
||||
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<SupportOutlineIslandPoint>(
|
||||
point, source_index, SupportIslandPoint::Type::outline));
|
||||
|
||||
// TODO: improve prevent sampling out of field near sharp corner
|
||||
// use range for possible ratio
|
||||
if (inner.contains(point))
|
||||
result.emplace_back(std::make_unique<SupportOutlineIslandPoint>(
|
||||
point, source_index, SupportIslandPoint::Type::outline));
|
||||
|
||||
last_support -= sample_distance;
|
||||
} while (last_support + line_length > sample_distance);
|
||||
}
|
||||
|
@ -32,6 +32,14 @@ public:
|
||||
/// <returns>Samples - 2d unscaled coordinates [in mm]</returns>
|
||||
static std::vector<Vec2f> sample_expolygon(const ExPolygon &expoly, float samples_per_mm2);
|
||||
|
||||
/// <summary>
|
||||
/// Uniform sample expolygon area by points inside Equilateral triangle center
|
||||
/// </summary>
|
||||
/// <param name="expoly">Input area to sample.(scaled)</param>
|
||||
/// <param name="triangle_side">Distance between samples.</param>
|
||||
/// <returns>Uniform samples(scaled)</returns>
|
||||
static Points sample_expolygon(const ExPolygon &expoly, coord_t triangle_side);
|
||||
|
||||
/// <summary>
|
||||
/// Create support point on edge defined by neighbor
|
||||
/// </summary>
|
||||
|
@ -7,6 +7,39 @@ SupportIslandPoint::SupportIslandPoint(Slic3r::Point point, Type type)
|
||||
: point(std::move(point)), type(type)
|
||||
{}
|
||||
|
||||
bool SupportIslandPoint::can_move(const Type &type)
|
||||
{
|
||||
// use shorter list
|
||||
/*
|
||||
static const std::set<Type> can_move({
|
||||
Type::center_line,
|
||||
Type::center_circle,
|
||||
Type::center_circle_end,
|
||||
Type::center_circle_end2,
|
||||
Type::outline,
|
||||
Type::inner
|
||||
});
|
||||
return can_move.find(type) != can_move.end();
|
||||
/*/ // switch comment center
|
||||
static const std::set<Type> cant_move({
|
||||
Type::one_center_point,
|
||||
Type::two_points,
|
||||
Type::center_line_end,
|
||||
Type::center_line_end2,
|
||||
Type::center_line_end3,
|
||||
Type::center_line_start
|
||||
});
|
||||
return cant_move.find(type) == cant_move.end();
|
||||
//*/
|
||||
}
|
||||
|
||||
bool SupportIslandPoint::can_move() const { return can_move(type); }
|
||||
|
||||
SupportCenterIslandPoint::SupportCenterIslandPoint(
|
||||
Point point, VoronoiGraph::Position position, Type type)
|
||||
: SupportIslandPoint(point, type), position(position)
|
||||
{}
|
||||
|
||||
coord_t SupportIslandPoint::move(const Point &destination)
|
||||
{
|
||||
Point diff = destination - point;
|
||||
|
@ -11,8 +11,9 @@ namespace Slic3r::sla {
|
||||
/// <summary>
|
||||
/// DTO position with information about source of support point
|
||||
/// </summary>
|
||||
struct SupportIslandPoint
|
||||
class SupportIslandPoint
|
||||
{
|
||||
public:
|
||||
enum class Type: unsigned char {
|
||||
one_center_point,
|
||||
two_points,
|
||||
@ -26,41 +27,41 @@ struct SupportIslandPoint
|
||||
// need allign)
|
||||
center_circle_end2, // circle finish by multi points (one end per
|
||||
// circle - need allign)
|
||||
|
||||
outline, // keep position align with island outline
|
||||
inner, // point inside wide part, without restriction on move
|
||||
|
||||
undefined
|
||||
};
|
||||
|
||||
Type type;
|
||||
Slic3r::Point point; // 2 coordinate point in a layer (in one slice)
|
||||
Type type;
|
||||
Point point;
|
||||
|
||||
//SupportIslandPoint() : point(0, 0), type(Type::undefined) {}
|
||||
SupportIslandPoint(Slic3r::Point point, Type type = Type::undefined);
|
||||
public:
|
||||
/// <summary>
|
||||
/// constructor
|
||||
/// </summary>
|
||||
/// <param name="point">coordinate point inside a layer (in one slice)</param>
|
||||
/// <param name="type">type of support point</param>
|
||||
SupportIslandPoint(Point point, Type type = Type::undefined);
|
||||
|
||||
/// <summary>
|
||||
/// virtual destructor to be inheritable
|
||||
/// </summary>
|
||||
virtual ~SupportIslandPoint() = default;
|
||||
|
||||
static bool can_move(const Type &type)
|
||||
{
|
||||
// use shorter list
|
||||
/*
|
||||
static const std::set<Type> can_move({
|
||||
Type::center_line,
|
||||
Type::center_circle,
|
||||
Type::center_circle_end,
|
||||
Type::center_circle_end2});
|
||||
return can_move.find(type) != can_move.end();
|
||||
/*/ // switch comment center
|
||||
static const std::set<Type> cant_move({
|
||||
Type::one_center_point,
|
||||
Type::two_points,
|
||||
Type::center_line_end,
|
||||
Type::center_line_end2,
|
||||
Type::center_line_end3,
|
||||
Type::center_line_start});
|
||||
return cant_move.find(type) == cant_move.end();
|
||||
//*/
|
||||
}
|
||||
|
||||
virtual bool can_move() const { return can_move(type); }
|
||||
/// <summary>
|
||||
/// static function to decide if type is possible to move or not
|
||||
/// </summary>
|
||||
/// <param name="type">type to distinguish</param>
|
||||
/// <returns>True when is possible to move, otherwise FALSE</returns>
|
||||
static bool can_move(const Type &type);
|
||||
|
||||
/// <summary>
|
||||
/// static function to decide if type is possible to move or not
|
||||
/// </summary>
|
||||
/// <param name="type">type to distinguish</param>
|
||||
/// <returns>True when is possible to move, otherwise FALSE</returns>
|
||||
virtual bool can_move() const;
|
||||
|
||||
/// <summary>
|
||||
/// Move position of support point close to destination
|
||||
@ -74,8 +75,13 @@ struct SupportIslandPoint
|
||||
using SupportIslandPointPtr = std::unique_ptr<SupportIslandPoint>;
|
||||
using SupportIslandPoints = std::vector<SupportIslandPointPtr>;
|
||||
|
||||
struct SupportCenterIslandPoint : public SupportIslandPoint
|
||||
/// <summary>
|
||||
/// DTO Support point laying on voronoi graph edge
|
||||
/// Restriction to move only on Voronoi graph
|
||||
/// </summary>
|
||||
class SupportCenterIslandPoint : public SupportIslandPoint
|
||||
{
|
||||
public:
|
||||
// Define position on voronoi graph
|
||||
// Lose data when voronoi graph does NOT exist
|
||||
VoronoiGraph::Position position;
|
||||
@ -85,20 +91,26 @@ struct SupportCenterIslandPoint : public SupportIslandPoint
|
||||
// TODO: should earn when created
|
||||
const double max_distance = 1e6; // [in nm] --> 1 mm
|
||||
|
||||
SupportCenterIslandPoint(Slic3r::Point point,
|
||||
public:
|
||||
SupportCenterIslandPoint(Point point,
|
||||
VoronoiGraph::Position position,
|
||||
Type type = Type::center_line)
|
||||
: SupportIslandPoint(point, type), position(position)
|
||||
{}
|
||||
|
||||
Type type = Type::center_line);
|
||||
|
||||
bool can_move() const override{ return true; }
|
||||
coord_t move(const Point &destination) override;
|
||||
};
|
||||
|
||||
struct SupportOutlineIslandPoint : public SupportIslandPoint
|
||||
/// <summary>
|
||||
/// DTO Support point laying on Outline of island
|
||||
/// Restriction to move only on outline
|
||||
/// </summary>
|
||||
class SupportOutlineIslandPoint : public SupportIslandPoint
|
||||
{
|
||||
public:
|
||||
// index of line form island outline
|
||||
size_t index;
|
||||
|
||||
public:
|
||||
SupportOutlineIslandPoint(Slic3r::Point point,
|
||||
size_t index,
|
||||
Type type = Type::outline)
|
||||
|
@ -381,7 +381,7 @@ public:
|
||||
const Lines & lines);
|
||||
|
||||
/// <summary>
|
||||
/// calculate both point on source lines correspond to edge postion
|
||||
/// Calculate both point on source lines correspond to edge postion
|
||||
/// Faster way to get both point_on_line
|
||||
/// </summary>
|
||||
/// <param name="position">Position on edge</param>
|
||||
|
@ -546,9 +546,16 @@ TEST_CASE("speed sampling", "[SupGen]") {
|
||||
|
||||
TEST_CASE("Small islands should be supported in center", "[SupGen][VoronoiSkeleton]")
|
||||
{
|
||||
double size = 3e7;
|
||||
double size = 3e7;
|
||||
SampleConfig cfg = create_sample_config(size);
|
||||
ExPolygons islands = createTestIslands(size);
|
||||
|
||||
// TODO: remove next 3 lines, debug sharp triangle
|
||||
auto triangle = PolygonUtils::create_isosceles_triangle(8. * size, 40. * size);
|
||||
islands = {ExPolygon(triangle)};
|
||||
auto test_island = create_tiny_wide_test_2(3 * size, 2 / 3. * size);
|
||||
islands = {test_island};
|
||||
|
||||
for (ExPolygon &island : islands) {
|
||||
size_t debug_index = &island - &islands.front();
|
||||
auto points = test_island_sampling(island, cfg);
|
||||
@ -561,3 +568,109 @@ TEST_CASE("Small islands should be supported in center", "[SupGen][VoronoiSkelet
|
||||
// points should be equal to pointsR
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Vec2f> sample_old(const ExPolygon &island)
|
||||
{
|
||||
// Create the support point generator
|
||||
static TriangleMesh mesh;
|
||||
static sla::IndexedMesh 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);
|
||||
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;
|
||||
}
|
||||
|
||||
#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);
|
||||
|
||||
std::vector<Vec2f> result;
|
||||
result.reserve(points.size());
|
||||
for (auto &p : points) {
|
||||
result.push_back(p->point.cast<float>());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void store_sample(const std::vector<Vec2f> &samples, const ExPolygon& island)
|
||||
{
|
||||
static int counter = 0;
|
||||
BoundingBox bb(island);
|
||||
SVG svg(("sample_"+std::to_string(counter++)+".svg").c_str(), bb);
|
||||
|
||||
double mm = scale_(1);
|
||||
svg.draw(island, "lightgray");
|
||||
for (const auto &s : samples) {
|
||||
svg.draw(s.cast<coord_t>(), "blue", 0.2*mm);
|
||||
}
|
||||
|
||||
// draw resolution
|
||||
Point p(bb.min.x() + 1e6, bb.max.y() - 2e6);
|
||||
svg.draw_text(p, (std::to_string(samples.size()) + " samples").c_str(), "black");
|
||||
svg.draw_text(p - Point(0., 1.8e6), "Scale 1 cm ", "black");
|
||||
Point start = p - Point(0., 2.3e6);
|
||||
svg.draw(Line(start + Point(0., 5e5), start + Point(10*mm, 5e5)), "black", 2e5);
|
||||
svg.draw(Line(start + Point(0., -5e5), start + Point(10*mm, -5e5)), "black", 2e5);
|
||||
svg.draw(Line(start + Point(10*mm, 5e5), start + Point(10*mm, -5e5)), "black", 2e5);
|
||||
for (int i=0; i<10;i+=2)
|
||||
svg.draw(Line(start + Point(i*mm, 0.), start + Point((i+1)*mm, 0.)), "black", 1e6);
|
||||
}
|
||||
|
||||
TEST_CASE("Compare sampling test")
|
||||
{
|
||||
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;
|
||||
|
||||
double size1 = 1e6;
|
||||
double size2 = 3e6;
|
||||
ExPolygons islands = createTestIslands(1e6);
|
||||
ExPolygons islands_big = createTestIslands(3e6);
|
||||
islands.insert(islands.end(), islands_big.begin(), islands_big.end());
|
||||
|
||||
islands = {ExPolygon(PolygonUtils::create_rect(size1 / 2, size1))};
|
||||
|
||||
for (ExPolygon &island : islands) {
|
||||
size_t debug_index = &island - &islands.front();
|
||||
auto samples = sample(island);
|
||||
store_sample(samples, island);
|
||||
|
||||
double angle = 3.14 / 3; // cca 60 degree
|
||||
island.rotate(angle);
|
||||
samples = sample(island);
|
||||
store_sample(samples, island);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user