comments and bugfix
This commit is contained in:
parent
ad819850f9
commit
87c276b7a4
@ -394,6 +394,7 @@ struct GlobalModelInfo {
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
//Extract perimeter polygons of the given layer
|
||||||
Polygons extract_perimeter_polygons(const Layer *layer) {
|
Polygons extract_perimeter_polygons(const Layer *layer) {
|
||||||
Polygons polygons;
|
Polygons polygons;
|
||||||
for (const LayerRegion *layer_region : layer->regions()) {
|
for (const LayerRegion *layer_region : layer->regions()) {
|
||||||
@ -419,13 +420,17 @@ Polygons extract_perimeter_polygons(const Layer *layer) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (polygons.empty()) {
|
if (polygons.empty()) { // If there are no perimeter polygons for whatever reason (disabled perimeters .. ) insert dummy point
|
||||||
|
// it is easier than checking everywhere if the layer is not emtpy, no seam will be placed to this layer anyway
|
||||||
polygons.emplace_back(std::vector { Point { 0, 0 } });
|
polygons.emplace_back(std::vector { Point { 0, 0 } });
|
||||||
}
|
}
|
||||||
|
|
||||||
return polygons;
|
return polygons;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Insert SeamCandidates created from perimeter polygons in to the result vector.
|
||||||
|
// Compute its type (Enfrocer,Blocker), angle, and position
|
||||||
|
//each SeamCandidate also contains pointer to shared Perimeter structure representing the polygon
|
||||||
void process_perimeter_polygon(const Polygon &orig_polygon, float z_coord, std::vector<SeamCandidate> &result_vec,
|
void process_perimeter_polygon(const Polygon &orig_polygon, float z_coord, std::vector<SeamCandidate> &result_vec,
|
||||||
const GlobalModelInfo &global_model_info) {
|
const GlobalModelInfo &global_model_info) {
|
||||||
if (orig_polygon.size() == 0) {
|
if (orig_polygon.size() == 0) {
|
||||||
@ -467,17 +472,22 @@ void process_perimeter_polygon(const Polygon &orig_polygon, float z_coord, std::
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get index of previous and next perimeter point of the layer. Because SeamCandidates of all polygons of the given layer
|
||||||
|
// are sequentially stored in the vector, each perimeter contains info about start and end index. These vales are used to
|
||||||
|
// deduce index of previous and next neigbour in the corresponding perimeter.
|
||||||
std::pair<size_t, size_t> find_previous_and_next_perimeter_point(const std::vector<SeamCandidate> &perimeter_points,
|
std::pair<size_t, size_t> find_previous_and_next_perimeter_point(const std::vector<SeamCandidate> &perimeter_points,
|
||||||
size_t index) {
|
size_t point_index) {
|
||||||
const SeamCandidate ¤t = perimeter_points[index];
|
const SeamCandidate ¤t = perimeter_points[point_index];
|
||||||
int prev = index - 1;
|
int prev = point_index - 1; //for majority of points, it is true that neighbours lie behind and in front of them in the vector
|
||||||
int next = index + 1;
|
int next = point_index + 1;
|
||||||
|
|
||||||
if (index == current.perimeter->start_index) {
|
if (point_index == current.perimeter->start_index) {
|
||||||
|
// if point_index is equal to start, it means that the previous neighbour is at the end
|
||||||
prev = current.perimeter->end_index;
|
prev = current.perimeter->end_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index == current.perimeter->end_index) {
|
if (point_index == current.perimeter->end_index) {
|
||||||
|
// if point_index is equal to end, than next neighbour is at the start
|
||||||
next = current.perimeter->start_index;
|
next = current.perimeter->start_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -495,13 +505,16 @@ float calculate_overhang(const SeamCandidate &point, const SeamCandidate &under_
|
|||||||
auto b = Vec2d { under_b.position.x(), under_b.position.y() };
|
auto b = Vec2d { under_b.position.x(), under_b.position.y() };
|
||||||
auto c = Vec2d { under_c.position.x(), under_c.position.y() };
|
auto c = Vec2d { under_c.position.x(), under_c.position.y() };
|
||||||
|
|
||||||
auto oriented_line_dist = [](const Vec2d a, const Vec2d b, const Vec2d p) {
|
auto oriented_line_dist = [](const Vec2d a, const Vec2d b, const Vec2d p) { //signed distance from line
|
||||||
return -((b.x() - a.x()) * (a.y() - p.y()) - (a.x() - p.x()) * (b.y() - a.y())) / (a - b).norm();
|
return -((b.x() - a.x()) * (a.y() - p.y()) - (a.x() - p.x()) * (b.y() - a.y())) / (a - b).norm();
|
||||||
};
|
};
|
||||||
|
|
||||||
auto dist_ab = oriented_line_dist(a, b, p);
|
auto dist_ab = oriented_line_dist(a, b, p);
|
||||||
auto dist_bc = oriented_line_dist(b, c, p);
|
auto dist_bc = oriented_line_dist(b, c, p);
|
||||||
|
|
||||||
|
// from angle and signed distances from the arms of the points on the previous layer, we
|
||||||
|
// can deduce if it is overhang and give estimation of the size.
|
||||||
|
// However, the size of the overhang is rough estimation, the sign is more reliable
|
||||||
if (under_b.local_ccw_angle > 0 && dist_ab > 0 && dist_bc > 0) { //convex shape, p is inside
|
if (under_b.local_ccw_angle > 0 && dist_ab > 0 && dist_bc > 0) { //convex shape, p is inside
|
||||||
return -((p - b).norm() + dist_ab + dist_bc) / 3.0;
|
return -((p - b).norm() + dist_ab + dist_bc) / 3.0;
|
||||||
}
|
}
|
||||||
@ -513,6 +526,7 @@ float calculate_overhang(const SeamCandidate &point, const SeamCandidate &under_
|
|||||||
return ((p - b).norm() + dist_ab + dist_bc) / 3.0;
|
return ((p - b).norm() + dist_ab + dist_bc) / 3.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pick best seam point based on the given comparator
|
||||||
template<typename Comparator>
|
template<typename Comparator>
|
||||||
void pick_seam_point(std::vector<SeamCandidate> &perimeter_points, size_t start_index,
|
void pick_seam_point(std::vector<SeamCandidate> &perimeter_points, size_t start_index,
|
||||||
const Comparator &comparator) {
|
const Comparator &comparator) {
|
||||||
@ -533,6 +547,8 @@ void pick_seam_point(std::vector<SeamCandidate> &perimeter_points, size_t start_
|
|||||||
perimeter_points[start_index].perimeter->seam_index = seam_index;
|
perimeter_points[start_index].perimeter->seam_index = seam_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Computes all global model info - transforms object, performs raycasting,
|
||||||
|
// stores enforces and blockers
|
||||||
void gather_global_model_info(GlobalModelInfo &result, const PrintObject *po) {
|
void gather_global_model_info(GlobalModelInfo &result, const PrintObject *po) {
|
||||||
BOOST_LOG_TRIVIAL(debug)
|
BOOST_LOG_TRIVIAL(debug)
|
||||||
<< "SeamPlacer: build AABB tree for raycasting and gather occlusion info: start";
|
<< "SeamPlacer: build AABB tree for raycasting and gather occlusion info: start";
|
||||||
@ -578,6 +594,7 @@ void gather_global_model_info(GlobalModelInfo &result, const PrintObject *po) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Comparator of seam points. It has two necessary methods: is_first_better and is_first_not_much_worse
|
||||||
struct DefaultSeamComparator {
|
struct DefaultSeamComparator {
|
||||||
float compute_angle_penalty(float ccw_angle) const {
|
float compute_angle_penalty(float ccw_angle) const {
|
||||||
if (ccw_angle >= 0) {
|
if (ccw_angle >= 0) {
|
||||||
@ -588,6 +605,8 @@ struct DefaultSeamComparator {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Standard comparator, must respect the requirements of comparators (e.g. give same result on same inputs) for sorting usage
|
||||||
|
// should return if a is better seamCandidate than b
|
||||||
bool is_first_better(const SeamCandidate &a, const SeamCandidate &b) const {
|
bool is_first_better(const SeamCandidate &a, const SeamCandidate &b) const {
|
||||||
// Blockers/Enforcers discrimination, top priority
|
// Blockers/Enforcers discrimination, top priority
|
||||||
if (a.type > b.type) {
|
if (a.type > b.type) {
|
||||||
@ -606,6 +625,8 @@ struct DefaultSeamComparator {
|
|||||||
(b.visibility + SeamPlacer::expected_hits_per_area) * compute_angle_penalty(b.local_ccw_angle);
|
(b.visibility + SeamPlacer::expected_hits_per_area) * compute_angle_penalty(b.local_ccw_angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Comparator used during alignment. If there is close potential aligned point, it is comapred to the current
|
||||||
|
// sema point of the perimeter, to find out if the aligned point is not much worse than the current seam
|
||||||
bool is_first_not_much_worse(const SeamCandidate &a, const SeamCandidate &b) const {
|
bool is_first_not_much_worse(const SeamCandidate &a, const SeamCandidate &b) const {
|
||||||
// Blockers/Enforcers discrimination, top priority
|
// Blockers/Enforcers discrimination, top priority
|
||||||
if (a.type > b.type) {
|
if (a.type > b.type) {
|
||||||
@ -628,6 +649,9 @@ struct DefaultSeamComparator {
|
|||||||
|
|
||||||
} // namespace SeamPlacerImpl
|
} // namespace SeamPlacerImpl
|
||||||
|
|
||||||
|
// Parallel process and extract each perimeter polygon of the given print object.
|
||||||
|
// Gather SeamCandidates of each layer into vector and build KDtree over them
|
||||||
|
// Store results in the SeamPlacer varaibles m_perimeter_points_per_object and m_perimeter_points_trees_per_object
|
||||||
void SeamPlacer::gather_seam_candidates(const PrintObject *po,
|
void SeamPlacer::gather_seam_candidates(const PrintObject *po,
|
||||||
const SeamPlacerImpl::GlobalModelInfo &global_model_info) {
|
const SeamPlacerImpl::GlobalModelInfo &global_model_info) {
|
||||||
using namespace SeamPlacerImpl;
|
using namespace SeamPlacerImpl;
|
||||||
@ -701,6 +725,12 @@ tbb::parallel_for(tbb::blocked_range<size_t>(0, m_perimeter_points_per_object[po
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Estimates, if there is good seam point in the layer_idx which is close to last_point_pos
|
||||||
|
// uses comparator.is_first_not_much_worse method to compare current seam with the closest point
|
||||||
|
// (if current seam is too far away )
|
||||||
|
// If the current chosen stream is close enough, it is stored in seam_string. returns true and updates last_point_pos
|
||||||
|
// If the closest point is good enough to replace current chosen seam, it is stored in potential_string_seams, returns true and updates last_point_pos
|
||||||
|
// Otherwise does nothing, returns false
|
||||||
// sadly cannot be const because map access operator[] is not const, since it can create new object
|
// sadly cannot be const because map access operator[] is not const, since it can create new object
|
||||||
template<typename Comparator>
|
template<typename Comparator>
|
||||||
bool SeamPlacer::find_next_seam_in_string(const PrintObject *po, Vec3f &last_point_pos,
|
bool SeamPlacer::find_next_seam_in_string(const PrintObject *po, Vec3f &last_point_pos,
|
||||||
@ -743,11 +773,16 @@ bool SeamPlacer::find_next_seam_in_string(const PrintObject *po, Vec3f &last_poi
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//https://towardsdatascience.com/least-square-polynomial-fitting-using-c-eigen-package-c0673728bd01
|
// clusters already chosen seam points into strings across multiple layers, and then
|
||||||
|
// aligns the strings via polynomial fit
|
||||||
|
// Does not change the positions of the SeamCandidates themselves, instead stores
|
||||||
|
// the new aligned position into the shared Perimeter structure of each perimeter
|
||||||
|
// Note that this position does not necesarilly lay on the perimeter.
|
||||||
template<typename Comparator>
|
template<typename Comparator>
|
||||||
void SeamPlacer::align_seam_points(const PrintObject *po, const Comparator &comparator) {
|
void SeamPlacer::align_seam_points(const PrintObject *po, const Comparator &comparator) {
|
||||||
using namespace SeamPlacerImpl;
|
using namespace SeamPlacerImpl;
|
||||||
|
|
||||||
|
// Prepares Debug files for writing.
|
||||||
#ifdef DEBUG_FILES
|
#ifdef DEBUG_FILES
|
||||||
Slic3r::CNumericLocalesSetter locales_setter;
|
Slic3r::CNumericLocalesSetter locales_setter;
|
||||||
auto clusters_f = "seam_clusters_of_" + std::to_string(po->id().id) + ".obj";
|
auto clusters_f = "seam_clusters_of_" + std::to_string(po->id().id) + ".obj";
|
||||||
@ -766,7 +801,7 @@ void SeamPlacer::align_seam_points(const PrintObject *po, const Comparator &comp
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//gahter vector of all seams - pair of layer_index and seam__index within that layer
|
//gahter vector of all seams on the print_object - pair of layer_index and seam__index within that layer
|
||||||
std::vector<std::pair<size_t, size_t>> seams;
|
std::vector<std::pair<size_t, size_t>> seams;
|
||||||
for (size_t layer_idx = 0; layer_idx < m_perimeter_points_per_object[po].size(); ++layer_idx) {
|
for (size_t layer_idx = 0; layer_idx < m_perimeter_points_per_object[po].size(); ++layer_idx) {
|
||||||
std::vector<SeamCandidate> &layer_perimeter_points =
|
std::vector<SeamCandidate> &layer_perimeter_points =
|
||||||
@ -778,7 +813,7 @@ void SeamPlacer::align_seam_points(const PrintObject *po, const Comparator &comp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//sort them and then align starting with the best candidates
|
//sort them before alignment. Alignment is sensitive to intitializaion, this gives it better chance to choose something nice
|
||||||
std::sort(seams.begin(), seams.end(),
|
std::sort(seams.begin(), seams.end(),
|
||||||
[&](const std::pair<size_t, size_t> &left, const std::pair<size_t, size_t> &right) {
|
[&](const std::pair<size_t, size_t> &left, const std::pair<size_t, size_t> &right) {
|
||||||
return comparator.is_first_better(m_perimeter_points_per_object[po][left.first][left.second],
|
return comparator.is_first_better(m_perimeter_points_per_object[po][left.first][left.second],
|
||||||
@ -786,7 +821,7 @@ void SeamPlacer::align_seam_points(const PrintObject *po, const Comparator &comp
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
//align them
|
//align the sema points - start with the best, and check if they are aligned, if yes, skip, else start alignment
|
||||||
for (const std::pair<size_t, size_t> &seam : seams) {
|
for (const std::pair<size_t, size_t> &seam : seams) {
|
||||||
size_t layer_idx = seam.first;
|
size_t layer_idx = seam.first;
|
||||||
size_t seam_index = seam.second;
|
size_t seam_index = seam.second;
|
||||||
@ -796,14 +831,16 @@ void SeamPlacer::align_seam_points(const PrintObject *po, const Comparator &comp
|
|||||||
// This perimeter is already aligned, skip seam
|
// This perimeter is already aligned, skip seam
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
int skips = SeamPlacer::seam_align_tolerable_skips;
|
|
||||||
|
//initialize searching for seam string - cluster of nearby seams on previous and next layers
|
||||||
|
int skips = SeamPlacer::seam_align_tolerable_skips / 2;
|
||||||
int next_layer = layer_idx + 1;
|
int next_layer = layer_idx + 1;
|
||||||
Vec3f last_point_pos = layer_perimeter_points[seam_index].position;
|
Vec3f last_point_pos = layer_perimeter_points[seam_index].position;
|
||||||
|
|
||||||
std::vector<std::pair<size_t, size_t>> seam_string;
|
std::vector<std::pair<size_t, size_t>> seam_string;
|
||||||
std::vector<std::pair<size_t, size_t>> potential_string_seams;
|
std::vector<std::pair<size_t, size_t>> potential_string_seams;
|
||||||
|
|
||||||
//find close by points and outliers; there is a budget of skips allowed
|
//find seams or potential seams in forward direction; there is a budget of skips allowed
|
||||||
while (skips >= 0 && next_layer < int(m_perimeter_points_per_object[po].size())) {
|
while (skips >= 0 && next_layer < int(m_perimeter_points_per_object[po].size())) {
|
||||||
if (find_next_seam_in_string(po, last_point_pos, next_layer, comparator, seam_string,
|
if (find_next_seam_in_string(po, last_point_pos, next_layer, comparator, seam_string,
|
||||||
potential_string_seams)) {
|
potential_string_seams)) {
|
||||||
@ -815,45 +852,57 @@ void SeamPlacer::align_seam_points(const PrintObject *po, const Comparator &comp
|
|||||||
next_layer++;
|
next_layer++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (seam_string.size() + potential_string_seams.size() >= seam_align_minimum_string_seams) { //string long enough to be worth aligning
|
//do additional check in back direction
|
||||||
//do additional check in back direction
|
next_layer = layer_idx - 1;
|
||||||
next_layer = layer_idx - 1;
|
skips = SeamPlacer::seam_align_tolerable_skips / 2;
|
||||||
skips = SeamPlacer::seam_align_tolerable_skips;
|
last_point_pos = layer_perimeter_points[seam_index].position;
|
||||||
while (skips >= 0 && next_layer >= 0) {
|
while (skips >= 0 && next_layer >= 0) {
|
||||||
if (find_next_seam_in_string(po, last_point_pos, next_layer, comparator,
|
if (find_next_seam_in_string(po, last_point_pos, next_layer, comparator,
|
||||||
seam_string,
|
seam_string,
|
||||||
potential_string_seams)) {
|
potential_string_seams)) {
|
||||||
//String added, last_point_pos updated, nothing to be done
|
//String added, last_point_pos updated, nothing to be done
|
||||||
} else {
|
} else {
|
||||||
// Layer skipped, reduce number of available skips
|
// Layer skipped, reduce number of available skips
|
||||||
skips--;
|
skips--;
|
||||||
}
|
|
||||||
next_layer--;
|
|
||||||
}
|
}
|
||||||
|
next_layer--;
|
||||||
|
}
|
||||||
|
|
||||||
// all string seams and potential string seams gathered, now do the alignment
|
if (seam_string.size() + potential_string_seams.size() < seam_align_minimum_string_seams) {
|
||||||
seam_string.insert(seam_string.end(), potential_string_seams.begin(), potential_string_seams.end());
|
//string long enough to be worth aligning, skip
|
||||||
std::sort(seam_string.begin(), seam_string.end(),
|
continue;
|
||||||
[](const std::pair<size_t, size_t> &left, const std::pair<size_t, size_t> &right) {
|
}
|
||||||
return left.first < right.first;
|
|
||||||
});
|
|
||||||
|
|
||||||
std::vector<Vec3f> points(seam_string.size());
|
// String is long engouh, all string seams and potential string seams gathered, now do the alignment
|
||||||
for (size_t index = 0; index < seam_string.size(); ++index) {
|
// first merge potential_string_seams and seam_string; from now on, they all will be aligned
|
||||||
points[index] =
|
seam_string.insert(seam_string.end(), potential_string_seams.begin(), potential_string_seams.end());
|
||||||
m_perimeter_points_per_object[po][seam_string[index].first][seam_string[index].second].position;
|
//sort by layer index
|
||||||
}
|
std::sort(seam_string.begin(), seam_string.end(),
|
||||||
|
[](const std::pair<size_t, size_t> &left, const std::pair<size_t, size_t> &right) {
|
||||||
|
return left.first < right.first;
|
||||||
|
});
|
||||||
|
|
||||||
std::vector<Vec2f> coefficients = polyfit(points, 3);
|
// gather all positions of seams
|
||||||
for (const auto &pair : seam_string) {
|
std::vector<Vec3f> points(seam_string.size());
|
||||||
float current_height = m_perimeter_points_per_object[po][pair.first][pair.second].position.z();
|
for (size_t index = 0; index < seam_string.size(); ++index) {
|
||||||
Vec3f seam_pos = get_fitted_point(coefficients, current_height);
|
points[index] =
|
||||||
|
m_perimeter_points_per_object[po][seam_string[index].first][seam_string[index].second].position;
|
||||||
|
}
|
||||||
|
|
||||||
Perimeter *perimeter =
|
// find coefficients of polynomial fit. Z coord is treated as parameter along which to fit both X and Y coords.
|
||||||
m_perimeter_points_per_object[po][pair.first][pair.second].perimeter.get();
|
std::vector<Vec2f> coefficients = polyfit(points, 3);
|
||||||
perimeter->final_seam_position = seam_pos;
|
|
||||||
perimeter->aligned = true;
|
// Do alignment - compute fitted point for each point in the string from its Z coord, and store the position into
|
||||||
}
|
// Perimeter structure of the point; also set flag aligned to true
|
||||||
|
for (const auto &pair : seam_string) {
|
||||||
|
float current_height = m_perimeter_points_per_object[po][pair.first][pair.second].position.z();
|
||||||
|
Vec3f seam_pos = get_fitted_point(coefficients, current_height);
|
||||||
|
|
||||||
|
Perimeter *perimeter =
|
||||||
|
m_perimeter_points_per_object[po][pair.first][pair.second].perimeter.get();
|
||||||
|
perimeter->final_seam_position = seam_pos;
|
||||||
|
perimeter->aligned = true;
|
||||||
|
}
|
||||||
|
|
||||||
// //https://en.wikipedia.org/wiki/Exponential_smoothing
|
// //https://en.wikipedia.org/wiki/Exponential_smoothing
|
||||||
// //inititalization
|
// //inititalization
|
||||||
@ -875,29 +924,28 @@ void SeamPlacer::align_seam_points(const PrintObject *po, const Comparator &comp
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
#ifdef DEBUG_FILES
|
#ifdef DEBUG_FILES
|
||||||
auto randf = []() {
|
auto randf = []() {
|
||||||
return float(rand()) / float(RAND_MAX);
|
return float(rand()) / float(RAND_MAX);
|
||||||
};
|
};
|
||||||
Vec3f color { randf(), randf(), randf() };
|
Vec3f color { randf(), randf(), randf() };
|
||||||
for (size_t i = 0; i < seam_string.size(); ++i) {
|
for (size_t i = 0; i < seam_string.size(); ++i) {
|
||||||
auto orig_seam = m_perimeter_points_per_object[po][seam_string[i].first][seam_string[i].second];
|
auto orig_seam = m_perimeter_points_per_object[po][seam_string[i].first][seam_string[i].second];
|
||||||
fprintf(clusters, "v %f %f %f %f %f %f \n", orig_seam.position[0],
|
fprintf(clusters, "v %f %f %f %f %f %f \n", orig_seam.position[0],
|
||||||
orig_seam.position[1],
|
orig_seam.position[1],
|
||||||
orig_seam.position[2], color[0], color[1],
|
orig_seam.position[2], color[0], color[1],
|
||||||
color[2]);
|
color[2]);
|
||||||
}
|
|
||||||
|
|
||||||
color = Vec3f { randf(), randf(), randf() };
|
|
||||||
for (size_t i = 0; i < seam_string.size(); ++i) {
|
|
||||||
Perimeter *perimeter =
|
|
||||||
m_perimeter_points_per_object[po][seam_string[i].first][seam_string[i].second].perimeter.get();
|
|
||||||
fprintf(aligns, "v %f %f %f %f %f %f \n", perimeter->final_seam_position[0],
|
|
||||||
perimeter->final_seam_position[1],
|
|
||||||
perimeter->final_seam_position[2], color[0], color[1],
|
|
||||||
color[2]);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
color = Vec3f { randf(), randf(), randf() };
|
||||||
|
for (size_t i = 0; i < seam_string.size(); ++i) {
|
||||||
|
Perimeter *perimeter =
|
||||||
|
m_perimeter_points_per_object[po][seam_string[i].first][seam_string[i].second].perimeter.get();
|
||||||
|
fprintf(aligns, "v %f %f %f %f %f %f \n", perimeter->final_seam_position[0],
|
||||||
|
perimeter->final_seam_position[1],
|
||||||
|
perimeter->final_seam_position[2], color[0], color[1],
|
||||||
|
color[2]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ public:
|
|||||||
// this param limits the number of allowed skips
|
// this param limits the number of allowed skips
|
||||||
static constexpr size_t seam_align_tolerable_skips = 4;
|
static constexpr size_t seam_align_tolerable_skips = 4;
|
||||||
// minimum number of seams needed in cluster to make alignemnt happen
|
// minimum number of seams needed in cluster to make alignemnt happen
|
||||||
static constexpr size_t seam_align_minimum_string_seams = 4;
|
static constexpr size_t seam_align_minimum_string_seams = 6;
|
||||||
|
|
||||||
//The following data structures hold all perimeter points for all PrintObject. The structure is as follows:
|
//The following data structures hold all perimeter points for all PrintObject. The structure is as follows:
|
||||||
// Map of PrintObjects (PO) -> vector of layers of PO -> vector of perimeter points of the given layer
|
// Map of PrintObjects (PO) -> vector of layers of PO -> vector of perimeter points of the given layer
|
||||||
|
Loading…
Reference in New Issue
Block a user