mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-16 00:55:54 +08:00
Fix duplicit point after alignment
+ fix detection if first_neighbor exist in process queue
This commit is contained in:
parent
15f7b23966
commit
cd4d75fa7d
@ -309,17 +309,57 @@ bool is_points_in_distance(const Point & p,
|
|||||||
}
|
}
|
||||||
#endif // NDEBUG
|
#endif // NDEBUG
|
||||||
|
|
||||||
|
void move_duplicit_positions(SupportIslandPoints &supports, const Points &prev_position) {
|
||||||
|
// remove duplicit points when exist
|
||||||
|
Points aligned = to_points(supports);
|
||||||
|
std::vector<size_t> sorted(aligned.size());
|
||||||
|
std::iota(sorted.begin(), sorted.end(), 0);
|
||||||
|
auto cmp_index = [&aligned](size_t a_index, size_t b_index) {
|
||||||
|
// sort by x and than by y
|
||||||
|
const Point &a = aligned[a_index];
|
||||||
|
const Point &b = aligned[b_index];
|
||||||
|
return a.x() < b.x() || (a.x() == b.x() && a.y() < b.y());
|
||||||
|
};
|
||||||
|
std::sort(sorted.begin(), sorted.end(), cmp_index);
|
||||||
|
|
||||||
|
auto get_duplicit_index = [](const std::vector<size_t> &sorted, const Points& aligned) {
|
||||||
|
const Point *prev_p = &aligned[sorted.front()];
|
||||||
|
for (size_t i = 1; i < sorted.size(); ++i){
|
||||||
|
if (const Point &p = aligned[sorted[i]]; *prev_p == p) {
|
||||||
|
return sorted[i];
|
||||||
|
} else {
|
||||||
|
prev_p = &p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sorted.size();
|
||||||
|
};
|
||||||
|
|
||||||
|
do {
|
||||||
|
size_t duplicit_index = get_duplicit_index(sorted, aligned);
|
||||||
|
if (duplicit_index >= sorted.size())
|
||||||
|
return; // without duplicit points
|
||||||
|
|
||||||
|
// divide last move to half
|
||||||
|
Point new_pos = prev_position[duplicit_index] / 2 + aligned[duplicit_index] / 2;
|
||||||
|
coord_t move_distance = supports[duplicit_index]->move(new_pos);
|
||||||
|
assert(move_distance > 0); // It must move
|
||||||
|
aligned[duplicit_index] = supports[duplicit_index]->point; // update aligned position
|
||||||
|
// IMPROVE: Resort duplicit index use std::rotate
|
||||||
|
std::sort(sorted.begin(), sorted.end(), cmp_index);
|
||||||
|
} while (true); // end when no duplicit index
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// once align
|
/// once align
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="samples">In/Out support points to be alligned(min 3 points)</param>
|
/// <param name="supports">In/Out support points to be alligned(min 3 points)</param>
|
||||||
/// <param name="island">Area for sampling, border for position of samples</param>
|
/// <param name="island">Area for sampling, border for position of samples</param>
|
||||||
/// <param name="config"> Sampling configuration
|
/// <param name="config"> Sampling configuration
|
||||||
/// Maximal distance between neighbor points +
|
/// Maximal distance between neighbor points +
|
||||||
/// Term criteria for align: Minimal sample move and Maximal count of iteration</param>
|
/// Term criteria for align: Minimal sample move and Maximal count of iteration</param>
|
||||||
/// <returns>Maximal distance of move during aligning.</returns>
|
/// <returns>Maximal distance of move during aligning.</returns>
|
||||||
coord_t align_once(
|
coord_t align_once(
|
||||||
SupportIslandPoints &samples,
|
SupportIslandPoints &supports,
|
||||||
const ExPolygon &island,
|
const ExPolygon &island,
|
||||||
const SampleConfig &config)
|
const SampleConfig &config)
|
||||||
{
|
{
|
||||||
@ -327,8 +367,7 @@ coord_t align_once(
|
|||||||
// https://stackoverflow.com/questions/23823345/how-to-construct-a-voronoi-diagram-inside-a-polygon
|
// https://stackoverflow.com/questions/23823345/how-to-construct-a-voronoi-diagram-inside-a-polygon
|
||||||
// IMPROVE1: add accessor to point coordinate do not copy points
|
// IMPROVE1: add accessor to point coordinate do not copy points
|
||||||
// IMPROVE2: add filter for create cell polygon only for moveable samples
|
// IMPROVE2: add filter for create cell polygon only for moveable samples
|
||||||
Points points = to_points(samples);
|
Points points = to_points(supports);
|
||||||
assert(!has_duplicate_points(points));
|
|
||||||
Polygons cell_polygons = create_voronoi_cells_cgal(points, config.max_distance);
|
Polygons cell_polygons = create_voronoi_cells_cgal(points, config.max_distance);
|
||||||
|
|
||||||
#ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGN_ONCE_TO_SVG_PATH
|
#ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGN_ONCE_TO_SVG_PATH
|
||||||
@ -348,9 +387,9 @@ coord_t align_once(
|
|||||||
|
|
||||||
// Maximal move during align each loop of align it should decrease
|
// Maximal move during align each loop of align it should decrease
|
||||||
coord_t max_move = 0;
|
coord_t max_move = 0;
|
||||||
for (size_t i = 0; i < samples.size(); i++) {
|
for (size_t i = 0; i < supports.size(); i++) {
|
||||||
const Polygon &cell_polygon = cell_polygons[i];
|
const Polygon &cell_polygon = cell_polygons[i];
|
||||||
SupportIslandPointPtr &sample = samples[i];
|
SupportIslandPointPtr &support = supports[i];
|
||||||
|
|
||||||
#ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGN_ONCE_TO_SVG_PATH
|
#ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGN_ONCE_TO_SVG_PATH
|
||||||
if (!sample->can_move()) { // draww freezed support points
|
if (!sample->can_move()) { // draww freezed support points
|
||||||
@ -359,7 +398,7 @@ coord_t align_once(
|
|||||||
SupportIslandPoint::to_string(sample->type).c_str(), color_static_point.c_str());
|
SupportIslandPoint::to_string(sample->type).c_str(), color_static_point.c_str());
|
||||||
}
|
}
|
||||||
#endif // SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGN_ONCE_TO_SVG_PATH
|
#endif // SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGN_ONCE_TO_SVG_PATH
|
||||||
if (!sample->can_move())
|
if (!support->can_move())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// polygon must be at least triangle
|
// polygon must be at least triangle
|
||||||
@ -375,10 +414,10 @@ coord_t align_once(
|
|||||||
// intersection island and cell made by suppot point
|
// intersection island and cell made by suppot point
|
||||||
// must generate polygon containing initial source for voronoi cell
|
// must generate polygon containing initial source for voronoi cell
|
||||||
// otherwise it is invalid voronoi diagram
|
// otherwise it is invalid voronoi diagram
|
||||||
assert(island_cell->contains(sample->point));
|
assert(island_cell->contains(support->point));
|
||||||
} else {
|
} else {
|
||||||
for (const Polygon &intersection : intersections) {
|
for (const Polygon &intersection : intersections) {
|
||||||
if (intersection.contains(sample->point)) {
|
if (intersection.contains(support->point)) {
|
||||||
island_cell = &intersection;
|
island_cell = &intersection;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -415,7 +454,7 @@ coord_t align_once(
|
|||||||
#endif // SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGN_ONCE_TO_SVG_PATH
|
#endif // SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGN_ONCE_TO_SVG_PATH
|
||||||
|
|
||||||
// say samples to use its restriction to change posion close to center
|
// say samples to use its restriction to change posion close to center
|
||||||
coord_t act_move = sample->move(island_cell_center);
|
coord_t act_move = support->move(island_cell_center);
|
||||||
if (max_move < act_move)
|
if (max_move < act_move)
|
||||||
max_move = act_move;
|
max_move = act_move;
|
||||||
|
|
||||||
@ -425,6 +464,8 @@ coord_t align_once(
|
|||||||
SupportIslandPoint::to_string(sample->type).c_str(), color_new_point.c_str());
|
SupportIslandPoint::to_string(sample->type).c_str(), color_new_point.c_str());
|
||||||
#endif // SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGN_ONCE_TO_SVG_PATH
|
#endif // SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGN_ONCE_TO_SVG_PATH
|
||||||
}
|
}
|
||||||
|
|
||||||
|
move_duplicit_positions(supports, points);
|
||||||
return max_move;
|
return max_move;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -433,6 +474,10 @@ void align_samples(SupportIslandPoints &samples, const ExPolygon &island, const
|
|||||||
if (samples.size() == 1)
|
if (samples.size() == 1)
|
||||||
return; // Do not align one support
|
return; // Do not align one support
|
||||||
|
|
||||||
|
// Can't create voronoi for duplicit points
|
||||||
|
// Fix previous algo to not produce duplicit points
|
||||||
|
assert(!has_duplicate_points(to_points(samples)));
|
||||||
|
|
||||||
bool exist_moveable = false;
|
bool exist_moveable = false;
|
||||||
for (const auto &sample : samples) {
|
for (const auto &sample : samples) {
|
||||||
if (sample->can_move()) {
|
if (sample->can_move()) {
|
||||||
@ -536,6 +581,7 @@ void create_supports_for_thin_part(
|
|||||||
// Process queue
|
// Process queue
|
||||||
SupportIns process;
|
SupportIns process;
|
||||||
process.push_back(SupportIn{twin_support_in, twin_start});
|
process.push_back(SupportIn{twin_support_in, twin_start});
|
||||||
|
bool is_first_neighbor = true; // help to skip checking first neighbor exist in process
|
||||||
|
|
||||||
// Loop over thin part of island to create support points on the voronoi skeleton.
|
// Loop over thin part of island to create support points on the voronoi skeleton.
|
||||||
while (curr.neighbor != nullptr || !process.empty()) {
|
while (curr.neighbor != nullptr || !process.empty()) {
|
||||||
@ -579,7 +625,7 @@ void create_supports_for_thin_part(
|
|||||||
|
|
||||||
// detect loop on island part
|
// detect loop on island part
|
||||||
const Neighbor *twin = VoronoiGraphUtils::get_twin(*curr.neighbor);
|
const Neighbor *twin = VoronoiGraphUtils::get_twin(*curr.neighbor);
|
||||||
if (curr.neighbor != part.center.neighbor){ // not first neighbor
|
if (!is_first_neighbor) { // not first neighbor
|
||||||
if (auto process_it = std::find_if(process.begin(), process.end(),
|
if (auto process_it = std::find_if(process.begin(), process.end(),
|
||||||
[twin](const SupportIn &p) { return p.neighbor == twin; });
|
[twin](const SupportIn &p) { return p.neighbor == twin; });
|
||||||
process_it != process.end()) { // self loop detected
|
process_it != process.end()) { // self loop detected
|
||||||
@ -592,6 +638,8 @@ void create_supports_for_thin_part(
|
|||||||
curr.neighbor = nullptr;
|
curr.neighbor = nullptr;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
is_first_neighbor = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// next neighbor is short cut to not push back and pop new_starts
|
// next neighbor is short cut to not push back and pop new_starts
|
||||||
|
@ -357,9 +357,7 @@ ExPolygons createTestIslands(double size)
|
|||||||
bool useFrogLeg = false;
|
bool useFrogLeg = false;
|
||||||
// need post reorganization of longest path
|
// need post reorganization of longest path
|
||||||
ExPolygons result = {
|
ExPolygons result = {
|
||||||
|
|
||||||
// debug
|
// debug
|
||||||
create_tiny_between_holes(3 * size, 2 / 3. * size),
|
|
||||||
|
|
||||||
// one support point
|
// one support point
|
||||||
ExPolygon(PolygonUtils::create_equilateral_triangle(size)),
|
ExPolygon(PolygonUtils::create_equilateral_triangle(size)),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user