mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-07-31 21:41:59 +08:00
Align outline points
This commit is contained in:
parent
3c4f68fa3f
commit
10c05ca01e
@ -279,7 +279,18 @@ std::optional<Slic3r::Vec2d> LineUtils::intersection(const Line &ray1, const Lin
|
|||||||
return (ray1.a.cast<double>() + t * v1);
|
return (ray1.a.cast<double>() + t * v1);
|
||||||
}
|
}
|
||||||
|
|
||||||
LineUtils::LineConnection LineUtils::create_line_connection(const Slic3r::Lines &lines)
|
double LineUtils::foot(const Line &line, const Point &point)
|
||||||
|
{
|
||||||
|
Vec2d a = line.a.cast<double>();
|
||||||
|
Vec2d vec = point.cast<double>() - a;
|
||||||
|
Vec2d b = line.b.cast<double>();
|
||||||
|
Vec2d dir = b - a;
|
||||||
|
double l2 = dir.squaredNorm();
|
||||||
|
return vec.dot(dir) / l2;
|
||||||
|
}
|
||||||
|
|
||||||
|
LineUtils::LineConnection LineUtils::create_line_connection(
|
||||||
|
const Slic3r::Lines &lines)
|
||||||
{
|
{
|
||||||
LineConnection line_connection;
|
LineConnection line_connection;
|
||||||
static const size_t bad_index = -1;
|
static const size_t bad_index = -1;
|
||||||
|
@ -119,6 +119,15 @@ public:
|
|||||||
/// <returns>line direction</returns>
|
/// <returns>line direction</returns>
|
||||||
static Point direction(const Line &line) { return line.b - line.a; }
|
static Point direction(const Line &line) { return line.b - line.a; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calculate foot point in maner of Geometry::foot_pt
|
||||||
|
/// - without unnecessary conversion
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="line">input line</param>
|
||||||
|
/// <param name="point">point to search foot on line</param>
|
||||||
|
/// <returns>ration betwen point line.a and line.b (in range from 0. to 1.)</returns>
|
||||||
|
static double foot(const Line &line, const Point& point);
|
||||||
|
|
||||||
// line index, <a connection, b connection>
|
// line index, <a connection, b connection>
|
||||||
using LineConnection = std::map<size_t, std::pair<size_t, size_t>>;
|
using LineConnection = std::map<size_t, std::pair<size_t, size_t>>;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1209,69 +1209,204 @@ SampleIslandUtils::Field SampleIslandUtils::create_field(
|
|||||||
return field;
|
return field;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<Slic3r::ExPolygon, std::map<size_t, size_t>>
|
||||||
|
SampleIslandUtils::outline_offset(const Slic3r::ExPolygon &island,
|
||||||
|
coord_t offset_distance)
|
||||||
|
{
|
||||||
|
Polygons polygons = offset(island, -offset_distance, ClipperLib::jtSquare);
|
||||||
|
if (polygons.empty()) return {}; // no place for support point
|
||||||
|
assert(polygons.front().is_counter_clockwise());
|
||||||
|
ExPolygon offseted(polygons.front());
|
||||||
|
for (size_t i = 1; i < polygons.size(); ++i) {
|
||||||
|
Polygon &hole = polygons[i];
|
||||||
|
assert(hole.is_clockwise());
|
||||||
|
offseted.holes.push_back(hole);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Connect indexes for convert during creation of offset
|
||||||
|
// !! this implementation was fast for develop BUT NOT for running !!
|
||||||
|
Lines island_lines = to_lines(island);
|
||||||
|
Lines offset_lines = to_lines(offseted);
|
||||||
|
// Convert index map from island index to offseted index
|
||||||
|
std::map<size_t, size_t> converter;
|
||||||
|
for (size_t island_line_index = 0; island_line_index < island_lines.size(); ++island_line_index) {
|
||||||
|
const Line &island_line = island_lines[island_line_index];
|
||||||
|
Vec2f dir1 = LineUtils::direction(island_line).cast<float>();
|
||||||
|
for (size_t offset_line_index = 0; offset_line_index < offset_lines.size(); ++offset_line_index) {
|
||||||
|
const Line &offset_line = offset_lines[offset_line_index];
|
||||||
|
Vec2f dir2 = LineUtils::direction(offset_line).cast<float>();
|
||||||
|
if (fabs(dir1.dot(dir2)) < 1e-4) { // in similar direction
|
||||||
|
Point middle = offset_line.a / 2 + offset_line.b / 2;
|
||||||
|
double distance = island_line.perp_distance_to(middle);
|
||||||
|
if (fabs(distance - offset_distance) < 20) {
|
||||||
|
// found offseted line
|
||||||
|
converter[island_line_index] = offset_line_index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {offseted, converter};
|
||||||
|
}
|
||||||
|
|
||||||
SupportIslandPoints SampleIslandUtils::sample_outline(
|
SupportIslandPoints SampleIslandUtils::sample_outline(
|
||||||
const Field &field, const SampleConfig &config)
|
const Field &field, const SampleConfig &config)
|
||||||
{
|
{
|
||||||
// TODO: fix it by neighbor line angles
|
const ExPolygon &border = field.border;
|
||||||
// Do not create inner expoly and test all points to lay inside
|
const Polygon &contour = border.contour;
|
||||||
Polygons polygons = offset(field.border,-config.minimal_distance_from_outline + 5, ClipperLib::jtSquare);
|
assert(field.source_indexes.size() >= contour.size());
|
||||||
if (polygons.empty()) return {}; // no place for support point
|
// convert map from field index to inner(line index)
|
||||||
ExPolygon inner(polygons.front());
|
std::map<size_t, size_t> field_2_inner;
|
||||||
for (size_t i = 1; i < polygons.size(); ++i) {
|
ExPolygon inner;
|
||||||
Polygon &hole = polygons[i];
|
std::tie(inner, field_2_inner) = outline_offset(border, config.minimal_distance_from_outline);
|
||||||
inner.holes.push_back(hole);
|
coord_t max_align_distance = config.max_align_distance;
|
||||||
}
|
|
||||||
|
|
||||||
coord_t sample_distance = config.outline_sample_distance;
|
coord_t sample_distance = config.outline_sample_distance;
|
||||||
coord_t outline_distance = config.minimal_distance_from_outline;
|
|
||||||
SupportIslandPoints result;
|
SupportIslandPoints result;
|
||||||
auto add_sample = [&](const Line &line, size_t source_index, coord_t& last_support) {
|
|
||||||
double line_length_double = line.length();
|
using RestrictionPtr = std::shared_ptr<SupportOutlineIslandPoint::Restriction>;
|
||||||
coord_t line_length = static_cast<coord_t>(line_length_double);
|
auto add_sample = [&](size_t index, const RestrictionPtr& restriction, coord_t &last_support) {
|
||||||
|
using Position = SupportOutlineIslandPoint::Position;
|
||||||
|
const Line & line = restriction->lines[index];
|
||||||
|
const double &line_length_double = restriction->lengths[index];
|
||||||
|
coord_t line_length = static_cast<coord_t>(std::round(line_length_double));
|
||||||
if (last_support + line_length > sample_distance) {
|
if (last_support + line_length > sample_distance) {
|
||||||
Point dir = LineUtils::direction(line);
|
Point direction = LineUtils::direction(line);
|
||||||
Point perp = PointUtils::perp(dir);
|
|
||||||
double size = perp.cast<double>().norm();
|
|
||||||
Point move_from_outline = perp * (outline_distance / size);
|
|
||||||
do {
|
do {
|
||||||
double ratio = (sample_distance - last_support) / line_length_double;
|
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>(
|
||||||
// TODO: improve prevent sampling out of field near sharp corner
|
Position(index, ratio), restriction,
|
||||||
// use range for possible ratio
|
SupportIslandPoint::Type::outline)
|
||||||
if (inner.contains(point))
|
);
|
||||||
result.emplace_back(std::make_unique<SupportOutlineIslandPoint>(
|
|
||||||
point, source_index, SupportIslandPoint::Type::outline));
|
|
||||||
|
|
||||||
last_support -= sample_distance;
|
last_support -= sample_distance;
|
||||||
} while (last_support + line_length > sample_distance);
|
} while (last_support + line_length > sample_distance);
|
||||||
}
|
}
|
||||||
last_support += line_length;
|
last_support += line_length;
|
||||||
};
|
};
|
||||||
Lines contour_lines = to_lines(field.border.contour);
|
auto add_circle_sample = [&](const Polygon& polygon) {
|
||||||
coord_t last_support = sample_distance / 2;
|
// IMPROVE: find interesting points to start sampling
|
||||||
for (const Line &line : contour_lines) {
|
Lines lines = to_lines(polygon);
|
||||||
size_t index = &line - &contour_lines.front();
|
std::vector<double> lengths;
|
||||||
assert(field.source_indexes.size() > index);
|
lengths.reserve(lines.size());
|
||||||
size_t source_index = field.source_indexes[index];
|
double sum_lengths = 0;
|
||||||
if (source_index == field.source_indexe_for_change) {
|
for (const Line &line : lines) {
|
||||||
last_support = sample_distance / 2;
|
double length = line.length();
|
||||||
continue;
|
sum_lengths += length;
|
||||||
|
lengths.push_back(length);
|
||||||
}
|
}
|
||||||
add_sample(line, source_index, last_support);
|
// no samples on this polygon
|
||||||
}
|
|
||||||
size_t index_offset = contour_lines.size();
|
using Restriction = SupportOutlineIslandPoint::RestrictionCircleSequence;
|
||||||
for (const Polygon &hole : field.border.holes) {
|
auto restriction = std::make_shared<Restriction>(lines, lengths, max_align_distance);
|
||||||
Lines hole_lines = to_lines(hole);
|
coord_t last_support = std::min(static_cast<coord_t>(sum_lengths), sample_distance) / 2;
|
||||||
coord_t last_support = sample_distance / 2;
|
for (size_t index = 0; index < lines.size(); ++index) {
|
||||||
for (const Line &line : hole_lines) {
|
add_sample(index, restriction, last_support);
|
||||||
size_t hole_line_index = (&line - &hole_lines.front());
|
}
|
||||||
size_t index = index_offset + hole_line_index;
|
};
|
||||||
assert(field.source_indexes.size() > index);
|
|
||||||
|
// sample line sequence
|
||||||
|
auto add_lines_samples = [&](const Lines &inner_lines,
|
||||||
|
size_t first_index,
|
||||||
|
size_t last_index) {
|
||||||
|
Lines lines;
|
||||||
|
// is over start ?
|
||||||
|
if (first_index > last_index) {
|
||||||
|
size_t count = first_index + inner_lines.size() - last_index;
|
||||||
|
lines.reserve(count);
|
||||||
|
std::copy(inner_lines.begin() + last_index,
|
||||||
|
inner_lines.end(),
|
||||||
|
std::back_inserter(lines));
|
||||||
|
std::copy(inner_lines.begin(),
|
||||||
|
inner_lines.begin() + first_index,
|
||||||
|
std::back_inserter(lines));
|
||||||
|
} else {
|
||||||
|
size_t count = last_index - first_index;
|
||||||
|
lines.reserve(count);
|
||||||
|
std::copy(inner_lines.begin() + first_index,
|
||||||
|
inner_lines.begin() + last_index,
|
||||||
|
std::back_inserter(lines));
|
||||||
|
}
|
||||||
|
|
||||||
|
// IMPROVE: find interesting points to start sampling
|
||||||
|
std::vector<double> lengths;
|
||||||
|
lengths.reserve(lines.size());
|
||||||
|
double sum_lengths = 0;
|
||||||
|
for (const Line &line : lines) {
|
||||||
|
double length = line.length();
|
||||||
|
sum_lengths += length;
|
||||||
|
lengths.push_back(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
using Restriction = SupportOutlineIslandPoint::RestrictionLineSequence;
|
||||||
|
auto restriction = std::make_shared<Restriction>(lines, lengths, max_align_distance);
|
||||||
|
|
||||||
|
// CHECK: Is correct to has always one support on outline sequence?
|
||||||
|
// or no sample small sequence at all?
|
||||||
|
coord_t last_support = std::min(static_cast<coord_t>(sum_lengths), sample_distance) / 2;
|
||||||
|
for (size_t index = 0; index < lines.size(); ++index) {
|
||||||
|
add_sample(index, restriction, last_support);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const size_t& change_index = field.source_indexe_for_change;
|
||||||
|
auto sample_polygon = [&](const Polygon &polygon,
|
||||||
|
const Polygon &inner_polygon,
|
||||||
|
size_t index_offset) {
|
||||||
|
// contain polygon tiny wide change?
|
||||||
|
size_t first_change_index = polygon.size();
|
||||||
|
for (size_t polygon_index = 0; polygon_index < polygon.size(); ++polygon_index) {
|
||||||
|
size_t index = polygon_index + index_offset;
|
||||||
|
assert(index < field.source_indexes.size());
|
||||||
size_t source_index = field.source_indexes[index];
|
size_t source_index = field.source_indexes[index];
|
||||||
add_sample(line, source_index, last_support);
|
if (source_index == change_index) {
|
||||||
|
// found change from wide to tiny part
|
||||||
|
first_change_index = polygon_index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
index_offset += hole_lines.size();
|
|
||||||
|
// is polygon without change
|
||||||
|
if (first_change_index == polygon.size()) {
|
||||||
|
add_circle_sample(inner_polygon);
|
||||||
|
} else { // exist change create line sequences
|
||||||
|
// initialize with non valid values
|
||||||
|
Lines inner_lines = to_lines(inner_polygon);
|
||||||
|
size_t inner_invalid = inner_lines.size();
|
||||||
|
// first and last index to inner lines
|
||||||
|
size_t inner_first = inner_invalid;
|
||||||
|
size_t inner_last = inner_invalid;
|
||||||
|
for (size_t polygon_index = first_change_index + 1;
|
||||||
|
polygon_index != first_change_index; ++polygon_index) {
|
||||||
|
if (polygon_index == polygon.size()) polygon_index = 0;
|
||||||
|
size_t index = polygon_index + index_offset;
|
||||||
|
assert(index < field.source_indexes.size());
|
||||||
|
size_t source_index = field.source_indexes[index];
|
||||||
|
if (source_index == change_index) {
|
||||||
|
if (inner_first == inner_invalid) continue;
|
||||||
|
// create Restriction object
|
||||||
|
add_lines_samples(inner_lines, inner_first, inner_last);
|
||||||
|
inner_first = inner_invalid;
|
||||||
|
inner_last = inner_invalid;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto convert_index_item = field_2_inner.find(polygon_index);
|
||||||
|
// check if exist inner line
|
||||||
|
if (convert_index_item == field_2_inner.end()) continue;
|
||||||
|
inner_last = convert_index_item->second - index_offset;
|
||||||
|
// initialize first index
|
||||||
|
if (inner_first == inner_invalid) inner_first = inner_last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t index_offset = 0;
|
||||||
|
sample_polygon(contour, inner.contour, index_offset);
|
||||||
|
index_offset = contour.size();
|
||||||
|
for (size_t hole_index = 0; hole_index < border.holes.size(); ++hole_index) {
|
||||||
|
const Polygon &hole = border.holes[hole_index];
|
||||||
|
sample_polygon(hole, inner.holes[hole_index], index_offset);
|
||||||
|
index_offset += hole.size();
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -289,8 +289,21 @@ public:
|
|||||||
/// <returns>support for outline</returns>
|
/// <returns>support for outline</returns>
|
||||||
static SupportIslandPoints sample_outline(const Field & field,
|
static SupportIslandPoints sample_outline(const Field & field,
|
||||||
const SampleConfig &config);
|
const SampleConfig &config);
|
||||||
|
private:
|
||||||
|
/// <summary>
|
||||||
|
/// create offsetted field
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="island">source field</param>
|
||||||
|
/// <param name="offset_distance">distance from outline</param>
|
||||||
|
/// <returns>offseted field
|
||||||
|
/// First - offseted island outline
|
||||||
|
/// Second - map for convert source field index to result border index
|
||||||
|
/// </returns>
|
||||||
|
static std::pair<Slic3r::ExPolygon, std::map<size_t, size_t>>
|
||||||
|
outline_offset(const Slic3r::ExPolygon &island, coord_t offset_distance);
|
||||||
|
|
||||||
// debug draw functions
|
// debug draw functions
|
||||||
|
public :
|
||||||
static void draw(SVG & svg,
|
static void draw(SVG & svg,
|
||||||
const Field &field,
|
const Field &field,
|
||||||
bool draw_border_line_indexes = false,
|
bool draw_border_line_indexes = false,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "SupportIslandPoint.hpp"
|
#include "SupportIslandPoint.hpp"
|
||||||
#include "VoronoiGraphUtils.hpp"
|
#include "VoronoiGraphUtils.hpp"
|
||||||
|
#include "LineUtils.hpp"
|
||||||
|
|
||||||
using namespace Slic3r::sla;
|
using namespace Slic3r::sla;
|
||||||
|
|
||||||
@ -39,9 +40,7 @@ coord_t SupportIslandPoint::move(const Point &destination)
|
|||||||
{
|
{
|
||||||
Point diff = destination - point;
|
Point diff = destination - point;
|
||||||
point = destination;
|
point = destination;
|
||||||
// TODO: check move out of island !!
|
return abs(diff.x()) + abs(diff.y()); // Manhatn distance
|
||||||
// + need island ExPolygon
|
|
||||||
return diff.x() + diff.y(); // Manhatn distance
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string SupportIslandPoint::to_string(const Type &type)
|
std::string SupportIslandPoint::to_string(const Type &type)
|
||||||
@ -86,9 +85,88 @@ coord_t SupportCenterIslandPoint::move(const Point &destination)
|
|||||||
VoronoiGraphUtils::align(position, destination,
|
VoronoiGraphUtils::align(position, destination,
|
||||||
configuration->max_align_distance);
|
configuration->max_align_distance);
|
||||||
Point new_point = VoronoiGraphUtils::create_edge_point(position);
|
Point new_point = VoronoiGraphUtils::create_edge_point(position);
|
||||||
Point move = new_point - point;
|
return SupportIslandPoint::move(new_point);
|
||||||
point = new_point;
|
|
||||||
coord_t manhatn_distance = abs(move.x()) + abs(move.y());
|
|
||||||
return manhatn_distance;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////
|
||||||
|
// Point on Outline
|
||||||
|
///////////////
|
||||||
|
|
||||||
|
SupportOutlineIslandPoint::SupportOutlineIslandPoint(
|
||||||
|
Position position, std::shared_ptr<Restriction> restriction, Type type)
|
||||||
|
: SupportIslandPoint(calc_point(position, *restriction), type)
|
||||||
|
, position(position)
|
||||||
|
, restriction(std::move(restriction))
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool SupportOutlineIslandPoint::can_move() const { return true; }
|
||||||
|
|
||||||
|
coord_t SupportOutlineIslandPoint::move(const Point &destination)
|
||||||
|
{
|
||||||
|
size_t index = position.index;
|
||||||
|
MoveResult closest = create_result(index, destination);
|
||||||
|
|
||||||
|
const double &length = restriction->lengths[position.index];
|
||||||
|
double distance = (1.0 - position.ratio) * length;
|
||||||
|
while (distance < restriction->max_align_distance) {
|
||||||
|
auto next_index = restriction->next_index(index);
|
||||||
|
if (!next_index.has_value()) break;
|
||||||
|
index = *next_index;
|
||||||
|
update_result(closest, index, destination);
|
||||||
|
distance += restriction->lengths[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
index = position.index;
|
||||||
|
distance = static_cast<coord_t>(position.ratio) * length;
|
||||||
|
while (distance < restriction->max_align_distance) {
|
||||||
|
auto prev_index = restriction->prev_index(index);
|
||||||
|
if (!prev_index.has_value()) break;
|
||||||
|
index = *prev_index;
|
||||||
|
update_result(closest, index, destination);
|
||||||
|
distance += restriction->lengths[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
// apply closest result of move
|
||||||
|
this->point = closest.point;
|
||||||
|
this->position = closest.position;
|
||||||
|
return closest.distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
Slic3r::Point SupportOutlineIslandPoint::calc_point(const Position &position, const Restriction &restriction)
|
||||||
|
{
|
||||||
|
const Line &line = restriction.lines[position.index];
|
||||||
|
Point direction = LineUtils::direction(line);
|
||||||
|
return line.a + direction * position.ratio;
|
||||||
|
}
|
||||||
|
|
||||||
|
SupportOutlineIslandPoint::MoveResult SupportOutlineIslandPoint::create_result(
|
||||||
|
size_t index, const Point &destination)
|
||||||
|
{
|
||||||
|
const Line &line = restriction->lines[index];
|
||||||
|
double line_ratio_full = LineUtils::foot(line, destination);
|
||||||
|
double line_ratio = std::clamp(line_ratio_full, 0., 1.);
|
||||||
|
Position new_position(index, line_ratio);
|
||||||
|
Point new_point = calc_point(new_position, *restriction);
|
||||||
|
double point_distance = (new_point - destination).cast<double>().norm();
|
||||||
|
return MoveResult(new_position, new_point, point_distance);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SupportOutlineIslandPoint::update_result(MoveResult & result,
|
||||||
|
size_t index,
|
||||||
|
const Point &destination)
|
||||||
|
{
|
||||||
|
const Line &line = restriction->lines[index];
|
||||||
|
double line_ratio_full = LineUtils::foot(line, destination);
|
||||||
|
double line_ratio = std::clamp(line_ratio_full, 0., 1.);
|
||||||
|
Position new_position(index, line_ratio);
|
||||||
|
Point new_point = calc_point(new_position, *restriction);
|
||||||
|
Point diff = new_point - destination;
|
||||||
|
if (abs(diff.x()) > result.distance) return;
|
||||||
|
if (abs(diff.y()) > result.distance) return;
|
||||||
|
double point_distance = diff.cast<double>().norm();
|
||||||
|
if (result.distance > point_distance) {
|
||||||
|
result.distance = point_distance;
|
||||||
|
result.position = new_position;
|
||||||
|
result.point = new_point;
|
||||||
|
}
|
||||||
|
}
|
@ -107,33 +107,157 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// DTO Support point laying on Outline of island
|
/// Support point laying on Outline of island
|
||||||
/// Restriction to move only on outline
|
/// Restriction to move only on outline
|
||||||
/// </summary>
|
/// </summary>
|
||||||
class SupportOutlineIslandPoint : public SupportIslandPoint
|
class SupportOutlineIslandPoint : public SupportIslandPoint
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// index of line form island outline
|
// definition of restriction
|
||||||
size_t index;
|
class Restriction;
|
||||||
|
|
||||||
|
struct Position
|
||||||
|
{
|
||||||
|
// index of line form island outline - index into Restriction
|
||||||
|
// adress line inside inner polygon --> SupportOutline
|
||||||
|
size_t index;
|
||||||
|
|
||||||
|
// define position on line by ratio
|
||||||
|
// from 0 (line point a)
|
||||||
|
// to 1 (line point b)
|
||||||
|
float ratio;
|
||||||
|
|
||||||
|
Position(size_t index, float ratio) : index(index), ratio(ratio) {}
|
||||||
|
};
|
||||||
|
Position position;
|
||||||
|
|
||||||
|
|
||||||
|
// store lines for allowed move - with distance from island source lines
|
||||||
|
std::shared_ptr<Restriction> restriction;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SupportOutlineIslandPoint(Slic3r::Point point,
|
SupportOutlineIslandPoint(Position position,
|
||||||
size_t index,
|
std::shared_ptr<Restriction> restriction,
|
||||||
Type type = Type::outline)
|
Type type = Type::outline);
|
||||||
: SupportIslandPoint(point, type), index(index)
|
// return true
|
||||||
{}
|
bool can_move() const override;
|
||||||
|
|
||||||
bool can_move() const override { return true; }
|
/// <summary>
|
||||||
|
/// Move nearest to destination point
|
||||||
|
/// only along restriction lines
|
||||||
|
/// + change current position
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="destination">Wanted support position</param>
|
||||||
|
/// <returns>move distance manhatn</returns>
|
||||||
|
coord_t move(const Point &destination) override;
|
||||||
|
|
||||||
coord_t move(const Point &destination) override
|
/// <summary>
|
||||||
{
|
/// Calculate 2d point belong to line position
|
||||||
// TODO: For decide of move need information about
|
/// </summary>
|
||||||
// + island outlines \ May be
|
/// <param name="position">Define position on line from restriction</param>
|
||||||
// + distance from outline / offseted outlines
|
/// <param name="restriction">Hold lines</param>
|
||||||
// + search distance for allowed move over outlines(count, distance)
|
/// <returns>Position in 2d</returns>
|
||||||
assert(false); // Not implemented
|
static Point calc_point(const Position & position,
|
||||||
return 0;
|
const Restriction &restriction);
|
||||||
}
|
|
||||||
|
/// <summary>
|
||||||
|
/// Keep data for align support point on bordred of island
|
||||||
|
/// Define possible move of point along outline
|
||||||
|
/// IMPROVE: Should contain list of Points on outline.
|
||||||
|
/// (to keep maximal distance of neighbor points on outline)
|
||||||
|
/// </summary>
|
||||||
|
class Restriction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// line restriction
|
||||||
|
// must be connected line.a == prev_line.b && line.b == next_line.a
|
||||||
|
Lines lines;
|
||||||
|
|
||||||
|
// keep stored line lengths
|
||||||
|
// same size as lines
|
||||||
|
std::vector<double> lengths;
|
||||||
|
|
||||||
|
// maximal distance for search nearest line to destination point during aligning
|
||||||
|
coord_t max_align_distance;
|
||||||
|
|
||||||
|
Restriction(Lines lines,
|
||||||
|
std::vector<double> lengths,
|
||||||
|
coord_t max_align_distance)
|
||||||
|
: lines(lines)
|
||||||
|
, lengths(lengths)
|
||||||
|
, max_align_distance(max_align_distance)
|
||||||
|
{
|
||||||
|
assert(lines.size() == lengths.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::optional<size_t> next_index(size_t index) const = 0;
|
||||||
|
virtual std::optional<size_t> prev_index(size_t index) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RestrictionLineSequence: public Restriction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// inherit constructors
|
||||||
|
using Restriction::Restriction;
|
||||||
|
|
||||||
|
virtual std::optional<size_t> next_index(size_t index) const override
|
||||||
|
{
|
||||||
|
assert(index < lines.size());
|
||||||
|
++index;
|
||||||
|
if (index >= lines.size()) return {}; // index out of range
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::optional<size_t> prev_index(size_t index) const override
|
||||||
|
{
|
||||||
|
assert(index < lines.size());
|
||||||
|
if (index >= lines.size()) return {}; // index out of range
|
||||||
|
if (index == 0) return {}; // no prev line
|
||||||
|
return index - 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class RestrictionCircleSequence : public Restriction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// inherit constructors
|
||||||
|
using Restriction::Restriction;
|
||||||
|
|
||||||
|
virtual std::optional<size_t> next_index(size_t index) const override
|
||||||
|
{
|
||||||
|
assert(index < lines.size());
|
||||||
|
if (index >= lines.size()) return {}; // index out of range
|
||||||
|
++index;
|
||||||
|
if (index == lines.size()) return 0;
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::optional<size_t> prev_index(size_t index) const override
|
||||||
|
{
|
||||||
|
assert(index < lines.size());
|
||||||
|
if (index >= lines.size()) return {}; // index out of range
|
||||||
|
if (index == 0) return lines.size() - 1;
|
||||||
|
return index - 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
// DTO for result of move
|
||||||
|
struct MoveResult
|
||||||
|
{
|
||||||
|
// define position on restriction line
|
||||||
|
Position position;
|
||||||
|
// point laying on restricted line
|
||||||
|
Point point;
|
||||||
|
// distance point on restricted line from destination point
|
||||||
|
double distance;
|
||||||
|
|
||||||
|
MoveResult(Position position, Point point, double distance)
|
||||||
|
: position(position), point(point), distance(distance)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
MoveResult create_result(size_t index, const Point &destination);
|
||||||
|
void update_result(MoveResult& result, size_t index, const Point &destination);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Slic3r::sla
|
} // namespace Slic3r::sla
|
||||||
|
Loading…
x
Reference in New Issue
Block a user