mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-14 06:35:58 +08:00
Fix calculation of width on VD
This commit is contained in:
parent
51ce8fbd62
commit
214f1acea6
@ -316,7 +316,8 @@ LineUtils::LineConnection LineUtils::create_line_connection(const Slic3r::Lines
|
||||
if (!inserts(prev_index, index)) {
|
||||
bool found_index = false;
|
||||
bool found_prev_index = false;
|
||||
std::remove_if(not_finished.begin(), not_finished.end(),
|
||||
not_finished.erase(std::remove_if(not_finished.begin(),
|
||||
not_finished.end(),
|
||||
[&](const size_t ¬_finished_index) {
|
||||
if (!found_index && inserts(index, not_finished_index)) {
|
||||
found_index = true;
|
||||
@ -327,7 +328,8 @@ LineUtils::LineConnection LineUtils::create_line_connection(const Slic3r::Lines
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}),
|
||||
not_finished.end());
|
||||
if (!found_index) not_finished.push_back(index);
|
||||
if (!found_prev_index) not_finished.push_back(prev_index);
|
||||
}
|
||||
@ -337,6 +339,16 @@ LineUtils::LineConnection LineUtils::create_line_connection(const Slic3r::Lines
|
||||
return line_connection;
|
||||
}
|
||||
|
||||
Slic3r::BoundingBox LineUtils::create_bounding_box(const Lines &lines) {
|
||||
Points pts;
|
||||
pts.reserve(lines.size()*2);
|
||||
for (const Line &line : lines) {
|
||||
pts.push_back(line.a);
|
||||
pts.push_back(line.b);
|
||||
}
|
||||
return BoundingBox(pts);
|
||||
}
|
||||
|
||||
std::map<size_t, size_t> LineUtils::create_line_connection_over_b(const Lines &lines)
|
||||
{
|
||||
static const size_t bad_index = -1;
|
||||
@ -352,24 +364,37 @@ std::map<size_t, size_t> LineUtils::create_line_connection_over_b(const Lines &l
|
||||
return true;
|
||||
};
|
||||
|
||||
std::vector<size_t> not_finished;
|
||||
std::vector<size_t> not_finished_a;
|
||||
std::vector<size_t> not_finished_b;
|
||||
size_t prev_index = lines.size() - 1;
|
||||
for (size_t index = 0; index < lines.size(); ++index) {
|
||||
if (!inserts(prev_index, index)) {
|
||||
bool found = false;
|
||||
std::remove_if(not_finished.begin(), not_finished.end(),
|
||||
bool found_b = false;
|
||||
not_finished_b.erase(std::remove_if(not_finished_b.begin(), not_finished_b.end(),
|
||||
[&](const size_t ¬_finished_index) {
|
||||
if (!found && inserts(prev_index, not_finished_index)) {
|
||||
found = true;
|
||||
if (!found_b && inserts(prev_index, not_finished_index)) {
|
||||
found_b = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
if(!found) not_finished.push_back(prev_index);
|
||||
}),not_finished_b.end());
|
||||
if (!found_b) not_finished_a.push_back(prev_index);
|
||||
|
||||
bool found_a = false;
|
||||
not_finished_a.erase(std::remove_if(not_finished_a.begin(), not_finished_a.end(),
|
||||
[&](const size_t ¬_finished_index) {
|
||||
if (!found_a && inserts(not_finished_index, index)) {
|
||||
found_a = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}),not_finished_a.end());
|
||||
if (!found_a) not_finished_b.push_back(index);
|
||||
}
|
||||
prev_index = index;
|
||||
}
|
||||
assert(not_finished.empty());
|
||||
assert(not_finished_a.empty());
|
||||
assert(not_finished_b.empty());
|
||||
return line_connection;
|
||||
}
|
||||
|
||||
|
@ -128,6 +128,13 @@ public:
|
||||
/// <returns>map of connected lines.</returns>
|
||||
static LineConnection create_line_connection(const Lines &lines);
|
||||
|
||||
/// <summary>
|
||||
/// create bounding box around lines
|
||||
/// </summary>
|
||||
/// <param name="lines">input lines</param>
|
||||
/// <returns>Bounding box</returns>
|
||||
static BoundingBox create_bounding_box(const Lines &lines);
|
||||
|
||||
/// <summary>
|
||||
/// Create data structure from exPolygon lines to store connected line indexes
|
||||
/// </summary>
|
||||
|
@ -18,7 +18,7 @@ bool PointUtils::is_majorit_x(const Vec2d &point)
|
||||
|
||||
Slic3r::Point PointUtils::perp(const Point &vector)
|
||||
{
|
||||
return Point(-vector.x(), vector.y());
|
||||
return Point(-vector.y(), vector.x());
|
||||
}
|
||||
|
||||
bool PointUtils::is_same_direction(const Point &dir1, const Point &dir2)
|
||||
|
@ -783,18 +783,19 @@ SampleIslandUtils::Field SampleIslandUtils::create_field(
|
||||
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();
|
||||
const Line &l1 = lines[i1];
|
||||
const Line &l2 = lines[i2];
|
||||
Point p1, p2;
|
||||
std::tie(p1, p2) = VoronoiGraphUtils::point_on_lines(position, l1, l2);
|
||||
if (VoronoiGraphUtils::is_opposit_direction(edge, l1)) {
|
||||
// line1 is shorten on side line1.a --> line2 is shorten on side line2.b
|
||||
assert(wide_tiny_changes.find(i2) == wide_tiny_changes.end());
|
||||
wide_tiny_changes.insert({i2, WideTinyChange(p2, p1, i1)});
|
||||
} else {
|
||||
// line1 is shorten on side line1.b
|
||||
assert(wide_tiny_changes.find(i1) == wide_tiny_changes.end());
|
||||
wide_tiny_changes.insert({i1, WideTinyChange(p1, p2, i2)});
|
||||
}
|
||||
};
|
||||
@ -811,30 +812,32 @@ SampleIslandUtils::Field SampleIslandUtils::create_field(
|
||||
std::set<size_t> field_line_indexes;
|
||||
while (!process.empty()) {
|
||||
const VoronoiGraph::Node *node = process.front();
|
||||
const VoronoiGraph::Node *prev_node = nullptr;
|
||||
process.pop();
|
||||
if (done.find(node) != done.end()) continue;
|
||||
do {
|
||||
done.insert(node);
|
||||
const auto &neighbors = node->neighbors;
|
||||
node = nullptr;
|
||||
for (const VoronoiGraph::Node::Neighbor &neighbor : neighbors) {
|
||||
if (done.find(neighbor.node) != done.end()) continue;
|
||||
const VD::edge_type *edge = neighbor.edge;
|
||||
const VoronoiGraph::Node *next_node = nullptr;
|
||||
for (const VoronoiGraph::Node::Neighbor &neighbor: node->neighbors) {
|
||||
if (neighbor.node == prev_node) continue;
|
||||
const VD::edge_type *edge = neighbor.edge;
|
||||
size_t index1 = edge->cell()->source_index();
|
||||
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) {
|
||||
if (neighbor.max_width < config.min_width_for_outline_support) {
|
||||
add_wide_tiny_change(&neighbor);
|
||||
continue;
|
||||
}
|
||||
if (node == nullptr) {
|
||||
node = neighbor.node;
|
||||
if (done.find(neighbor.node) != done.end()) continue; // loop back
|
||||
if (next_node == nullptr) {
|
||||
next_node = neighbor.node;
|
||||
} else {
|
||||
process.push(neighbor.node);
|
||||
}
|
||||
}
|
||||
prev_node = node;
|
||||
node = next_node;
|
||||
} while (node != nullptr);
|
||||
}
|
||||
|
||||
|
32
src/libslic3r/SLA/SupportIslands/SupportIslandPoint.cpp
Normal file
32
src/libslic3r/SLA/SupportIslands/SupportIslandPoint.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
#include "SupportIslandPoint.hpp"
|
||||
#include "VoronoiGraphUtils.hpp"
|
||||
|
||||
using namespace Slic3r::sla;
|
||||
|
||||
SupportIslandPoint::SupportIslandPoint(Slic3r::Point point, Type type)
|
||||
: point(std::move(point)), type(type)
|
||||
{}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
coord_t SupportCenterIslandPoint::move(const Point &destination)
|
||||
{
|
||||
// TODO: For decide of move need information about
|
||||
// + search distance for allowed move over VG(count or distance)
|
||||
|
||||
// move only along VD
|
||||
position = VoronoiGraphUtils::align(position, destination, max_distance);
|
||||
|
||||
Point new_point = VoronoiGraphUtils::create_edge_point(position);
|
||||
Point move = new_point - point;
|
||||
point = new_point;
|
||||
return abs(move.x()) + abs(move.y());
|
||||
}
|
||||
|
@ -377,8 +377,17 @@ double VoronoiGraphUtils::calculate_length(
|
||||
double VoronoiGraphUtils::calculate_max_width(
|
||||
const VD::edge_type &edge, const Lines &lines)
|
||||
{
|
||||
Point v0 = to_point(edge.vertex0());
|
||||
Point v1 = to_point(edge.vertex1());
|
||||
auto get_squared_distance = [&](const VD::vertex_type *vertex,
|
||||
const Point &point) -> double {
|
||||
Point point_v = to_point(vertex);
|
||||
Vec2d vector = (point - point_v).cast<double>();
|
||||
return vector.x() * vector.x() + vector.y() * vector.y();
|
||||
};
|
||||
auto max_width = [&](const Point& point)->double{
|
||||
return 2. *
|
||||
sqrt(std::max(get_squared_distance(edge.vertex0(), point),
|
||||
get_squared_distance(edge.vertex1(), point)));
|
||||
};
|
||||
|
||||
if (edge.is_linear()) {
|
||||
// edge line could be initialized by 2 points
|
||||
@ -393,11 +402,7 @@ double VoronoiGraphUtils::calculate_max_width(
|
||||
boost::polygon::SOURCE_CATEGORY_SEGMENT_END_POINT);
|
||||
source_point = source_line.b;
|
||||
}
|
||||
Point vec0 = source_point - v0;
|
||||
Point vec1 = source_point - v1;
|
||||
double distance0 = sqrt(vec0.x() * vec0.x() + vec0.y() * vec0.y());
|
||||
double distance1 = sqrt(vec0.x() * vec0.x() + vec0.y() * vec0.y());
|
||||
return 2 * std::max(distance0, distance1);
|
||||
return max_width(source_point);
|
||||
}
|
||||
assert(edge.cell()->contains_segment());
|
||||
assert(!edge.twin()->cell()->contains_point());
|
||||
@ -405,6 +410,8 @@ double VoronoiGraphUtils::calculate_max_width(
|
||||
|
||||
const Line &line = lines[edge.cell()->source_index()];
|
||||
|
||||
Point v0 = to_point(edge.vertex0());
|
||||
Point v1 = to_point(edge.vertex1());
|
||||
double distance0 = line.perp_distance_to(v0);
|
||||
double distance1 = line.perp_distance_to(v1);
|
||||
return 2 * std::max(distance0, distance1);
|
||||
@ -413,11 +420,7 @@ double VoronoiGraphUtils::calculate_max_width(
|
||||
Parabola parabola = get_parabola(edge, lines);
|
||||
// distance to point and line is same
|
||||
// vector from edge vertex to parabola focus point
|
||||
Point vec0 = parabola.focus - v0;
|
||||
Point vec1 = parabola.focus - v1;
|
||||
double distance0 = sqrt(vec0.x() * vec0.x() + vec0.y() * vec0.y());
|
||||
double distance1 = sqrt(vec0.x() * vec0.x() + vec0.y() * vec0.y());
|
||||
return 2 * std::max(distance0, distance1);
|
||||
return max_width(parabola.focus);
|
||||
}
|
||||
|
||||
VoronoiGraph VoronoiGraphUtils::create_skeleton(const VD &vd, const Lines &lines)
|
||||
@ -881,35 +884,39 @@ VoronoiGraph::Position VoronoiGraphUtils::get_position_with_distance(
|
||||
return result;
|
||||
}
|
||||
|
||||
Slic3r::Point VoronoiGraphUtils::point_on_line(
|
||||
const VoronoiGraph::Position &position, const Line &line)
|
||||
{
|
||||
const VD::edge_type* edge = position.neighbor->edge;
|
||||
assert(edge->is_linear());
|
||||
Point edge_point = create_edge_point(position);
|
||||
Point dir = to_point(edge->vertex0()) - to_point(edge->vertex1());
|
||||
Line edge_line(edge_point, edge_point + PointUtils::perp(dir));
|
||||
std::optional<Vec2d> intersection = LineUtils::intersection(line, edge_line);
|
||||
assert(intersection.has_value());
|
||||
return intersection->cast<coord_t>();
|
||||
}
|
||||
|
||||
std::pair<Slic3r::Point, Slic3r::Point> VoronoiGraphUtils::point_on_lines(
|
||||
const VoronoiGraph::Position &position,
|
||||
const Line & first,
|
||||
const Line & second)
|
||||
const VoronoiGraph::Position &position, const Lines &lines)
|
||||
{
|
||||
const VD::edge_type *edge = position.neighbor->edge;
|
||||
assert(edge->is_linear());
|
||||
|
||||
// TODO: solve point on parabola
|
||||
//assert(edge->is_linear());
|
||||
bool is_linear = edge->is_linear();
|
||||
|
||||
Point edge_point = create_edge_point(position);
|
||||
Point dir = to_point(edge->vertex0()) - to_point(edge->vertex1());
|
||||
Line edge_line(edge_point, edge_point + PointUtils::perp(dir));
|
||||
std::optional<Vec2d> first_intersection = LineUtils::intersection(first, edge_line);
|
||||
assert(first_intersection.has_value());
|
||||
std::optional<Vec2d> second_intersection = LineUtils::intersection(second, edge_line);
|
||||
assert(second_intersection.has_value());
|
||||
return {first_intersection->cast<coord_t>(),
|
||||
second_intersection->cast<coord_t>()};
|
||||
Line intersecting_line(edge_point, edge_point + PointUtils::perp(dir));
|
||||
|
||||
auto point_on_line = [&](const VD::edge_type *edge) -> Point {
|
||||
assert(edge->is_finite());
|
||||
const VD::cell_type *cell = edge->cell();
|
||||
size_t line_index = cell->source_index();
|
||||
const Line &line = lines[line_index];
|
||||
using namespace boost::polygon;
|
||||
bool is_single_point = cell->source_category() ==
|
||||
SOURCE_CATEGORY_SINGLE_POINT;
|
||||
if (cell->source_category() == SOURCE_CATEGORY_SEGMENT_START_POINT) {
|
||||
return line.a;
|
||||
}
|
||||
if (cell->source_category() == SOURCE_CATEGORY_SEGMENT_END_POINT) {
|
||||
return line.b;
|
||||
}
|
||||
std::optional<Vec2d> intersection = LineUtils::intersection(line, intersecting_line);
|
||||
assert(intersection.has_value());
|
||||
return intersection->cast<coord_t>();
|
||||
};
|
||||
|
||||
return {point_on_line(edge), point_on_line(edge->twin())};
|
||||
}
|
||||
|
||||
VoronoiGraph::Position VoronoiGraphUtils::align(
|
||||
@ -1074,18 +1081,34 @@ double VoronoiGraphUtils::get_max_width(const VoronoiGraph::Node *node)
|
||||
|
||||
void VoronoiGraphUtils::draw(SVG & svg,
|
||||
const VoronoiGraph &graph,
|
||||
coord_t width)
|
||||
coord_t width,
|
||||
bool pointer_caption)
|
||||
{
|
||||
auto print_address = [&](const Point& p, const char* prefix, void * addr, const char* color){
|
||||
if (pointer_caption) {
|
||||
std::stringstream ss;
|
||||
ss << prefix << std::hex << (int) addr;
|
||||
std::string s = ss.str();
|
||||
svg.draw_text(p, s.c_str(), color);
|
||||
}
|
||||
};
|
||||
|
||||
for (const auto &[key, value] : graph.data) {
|
||||
svg.draw(Point(key->x(), key->y()), "lightgray", width);
|
||||
Point p(key->x(), key->y());
|
||||
svg.draw(p, "lightgray", width);
|
||||
print_address(p, "v_",(void*)key, "lightgray");
|
||||
for (const auto &n : value.neighbors) {
|
||||
if (n.edge->vertex0() > n.edge->vertex1()) continue;
|
||||
Point from = to_point(n.edge->vertex0());
|
||||
Point to = to_point(n.edge->vertex1());
|
||||
bool is_second = n.edge->vertex0() > n.edge->vertex1();
|
||||
Point center = (from + to) / 2;
|
||||
Point p = center + ((is_second) ? Point(0., -2e6) :
|
||||
Point(0., 2e6));
|
||||
print_address(p, "n_", (void *) &n, "gray");
|
||||
if (is_second) continue;
|
||||
svg.draw_text(center + Point(-6e6, 0.), ("w="+std::to_string(n.max_width)).c_str(), "gray");
|
||||
svg.draw(Line(from, to), "gray", width);
|
||||
|
||||
Point center = from + to;
|
||||
center *= .5;
|
||||
// svg.draw_text(center,
|
||||
// (std::to_string(std::round(n.edge_length/3e5)/100.)).c_str(), "gray");
|
||||
}
|
||||
|
@ -359,26 +359,18 @@ public:
|
||||
coord_t width,
|
||||
const Lines & lines);
|
||||
|
||||
/// <summary>
|
||||
/// Calculate point on line correspond to edge position
|
||||
/// </summary>
|
||||
/// <param name="position">Position on edge</param>
|
||||
/// <param name="line">Line must be source of edge</param>
|
||||
/// <returns>Point lay on line defined by position on edge</returns>
|
||||
static Point point_on_line(const VoronoiGraph::Position& position, const Line& line);
|
||||
|
||||
/// <summary>
|
||||
/// 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>
|
||||
/// <param name="line">Line must be source of edge</param>
|
||||
/// <param name="line">Line must be source of edge</param>
|
||||
/// <returns>pair of point lay on lines cirrespond to position</returns>
|
||||
/// <param name="lines">Source lines of VD</param>
|
||||
/// <returns>pair of point lay on outline lines correspond to position on edge
|
||||
/// first -> source line of edge cell
|
||||
/// second -> source line of edge twin cell </returns>
|
||||
static std::pair<Point, Point> point_on_lines(
|
||||
const VoronoiGraph::Position &position,
|
||||
const Line & first,
|
||||
const Line & second);
|
||||
const Lines & lines);
|
||||
|
||||
/// <summary>
|
||||
/// align "position" close to point "to"
|
||||
@ -418,7 +410,7 @@ public:
|
||||
static double get_max_width(const VoronoiGraph::Node *node);
|
||||
|
||||
public: // draw function for debug
|
||||
static void draw(SVG &svg, const VoronoiGraph &graph, coord_t width);
|
||||
static void draw(SVG &svg, const VoronoiGraph &graph, coord_t width, bool pointer_caption = false);
|
||||
static void draw(SVG & svg,
|
||||
const VoronoiGraph::Nodes &path,
|
||||
coord_t width,
|
||||
|
@ -218,6 +218,29 @@ Slic3r::Polygon create_V_shape(double height, double line_width, double angle =
|
||||
return polygons.front();
|
||||
}
|
||||
|
||||
ExPolygon create_tiny_wide_test(double wide, double tiny)
|
||||
{
|
||||
double hole_size = wide;
|
||||
double width = (2 + 1) * wide + 2 * hole_size;
|
||||
double height = wide + 2*tiny + 2*hole_size;
|
||||
auto outline = PolygonUtils::create_rect( width, height);
|
||||
auto hole = PolygonUtils::create_rect(hole_size, hole_size);
|
||||
hole.reverse();
|
||||
auto hole2 = hole;// copy
|
||||
auto hole3 = hole; // copy
|
||||
auto hole4 = hole; // copy
|
||||
|
||||
int hole_move_x = wide / 2 + hole_size / 2;
|
||||
int hole_move_y = wide / 2 + hole_size / 2;
|
||||
hole.translate({hole_move_x, hole_move_y});
|
||||
hole2.translate({-hole_move_x, hole_move_y});
|
||||
hole3.translate({hole_move_x, -hole_move_y});
|
||||
hole4.translate({-hole_move_x, -hole_move_y});
|
||||
ExPolygon result(outline);
|
||||
result.holes = {hole, hole2, hole3, hole4};
|
||||
return result;
|
||||
}
|
||||
|
||||
ExPolygons createTestIslands(double size)
|
||||
{
|
||||
bool useFrogLeg = false;
|
||||
|
Loading…
x
Reference in New Issue
Block a user