mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-07-31 00:22:00 +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);
|
||||
}
|
||||
|
||||
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;
|
||||
static const size_t bad_index = -1;
|
||||
|
@ -119,6 +119,15 @@ public:
|
||||
/// <returns>line direction</returns>
|
||||
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>
|
||||
using LineConnection = std::map<size_t, std::pair<size_t, size_t>>;
|
||||
/// <summary>
|
||||
|
@ -1209,69 +1209,204 @@ SampleIslandUtils::Field SampleIslandUtils::create_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(
|
||||
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);
|
||||
}
|
||||
|
||||
const ExPolygon &border = field.border;
|
||||
const Polygon &contour = border.contour;
|
||||
assert(field.source_indexes.size() >= contour.size());
|
||||
// convert map from field index to inner(line index)
|
||||
std::map<size_t, size_t> field_2_inner;
|
||||
ExPolygon inner;
|
||||
std::tie(inner, field_2_inner) = outline_offset(border, config.minimal_distance_from_outline);
|
||||
coord_t max_align_distance = config.max_align_distance;
|
||||
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<coord_t>(line_length_double);
|
||||
|
||||
using RestrictionPtr = std::shared_ptr<SupportOutlineIslandPoint::Restriction>;
|
||||
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) {
|
||||
Point dir = LineUtils::direction(line);
|
||||
Point perp = PointUtils::perp(dir);
|
||||
double size = perp.cast<double>().norm();
|
||||
Point move_from_outline = perp * (outline_distance / size);
|
||||
Point direction = LineUtils::direction(line);
|
||||
do {
|
||||
double ratio = (sample_distance - last_support) / line_length_double;
|
||||
Point point = line.a + dir * ratio + move_from_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));
|
||||
|
||||
result.emplace_back(
|
||||
std::make_unique<SupportOutlineIslandPoint>(
|
||||
Position(index, ratio), restriction,
|
||||
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;
|
||||
auto add_circle_sample = [&](const Polygon& polygon) {
|
||||
// IMPROVE: find interesting points to start sampling
|
||||
Lines lines = to_lines(polygon);
|
||||
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);
|
||||
}
|
||||
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);
|
||||
// no samples on this polygon
|
||||
|
||||
using Restriction = SupportOutlineIslandPoint::RestrictionCircleSequence;
|
||||
auto restriction = std::make_shared<Restriction>(lines, lengths, max_align_distance);
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
// 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];
|
||||
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;
|
||||
}
|
||||
|
@ -289,8 +289,21 @@ public:
|
||||
/// <returns>support for outline</returns>
|
||||
static SupportIslandPoints sample_outline(const Field & field,
|
||||
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
|
||||
public :
|
||||
static void draw(SVG & svg,
|
||||
const Field &field,
|
||||
bool draw_border_line_indexes = false,
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "SupportIslandPoint.hpp"
|
||||
#include "VoronoiGraphUtils.hpp"
|
||||
#include "LineUtils.hpp"
|
||||
|
||||
using namespace Slic3r::sla;
|
||||
|
||||
@ -39,9 +40,7 @@ coord_t SupportIslandPoint::move(const Point &destination)
|
||||
{
|
||||
Point diff = destination - point;
|
||||
point = destination;
|
||||
// TODO: check move out of island !!
|
||||
// + need island ExPolygon
|
||||
return diff.x() + diff.y(); // Manhatn distance
|
||||
return abs(diff.x()) + abs(diff.y()); // Manhatn distance
|
||||
}
|
||||
|
||||
std::string SupportIslandPoint::to_string(const Type &type)
|
||||
@ -86,9 +85,88 @@ coord_t SupportCenterIslandPoint::move(const Point &destination)
|
||||
VoronoiGraphUtils::align(position, destination,
|
||||
configuration->max_align_distance);
|
||||
Point new_point = VoronoiGraphUtils::create_edge_point(position);
|
||||
Point move = new_point - point;
|
||||
point = new_point;
|
||||
coord_t manhatn_distance = abs(move.x()) + abs(move.y());
|
||||
return manhatn_distance;
|
||||
return SupportIslandPoint::move(new_point);
|
||||
}
|
||||
|
||||
///////////////
|
||||
// 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>
|
||||
/// DTO Support point laying on Outline of island
|
||||
/// 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;
|
||||
// definition of restriction
|
||||
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:
|
||||
SupportOutlineIslandPoint(Slic3r::Point point,
|
||||
size_t index,
|
||||
Type type = Type::outline)
|
||||
: SupportIslandPoint(point, type), index(index)
|
||||
{}
|
||||
SupportOutlineIslandPoint(Position position,
|
||||
std::shared_ptr<Restriction> restriction,
|
||||
Type type = Type::outline);
|
||||
// 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
|
||||
{
|
||||
// TODO: For decide of move need information about
|
||||
// + island outlines \ May be
|
||||
// + distance from outline / offseted outlines
|
||||
// + search distance for allowed move over outlines(count, distance)
|
||||
assert(false); // Not implemented
|
||||
return 0;
|
||||
}
|
||||
/// <summary>
|
||||
/// Calculate 2d point belong to line position
|
||||
/// </summary>
|
||||
/// <param name="position">Define position on line from restriction</param>
|
||||
/// <param name="restriction">Hold lines</param>
|
||||
/// <returns>Position in 2d</returns>
|
||||
static Point calc_point(const Position & position,
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user