oversample polygons where necessary, due to seam enforcers & blockers

This commit is contained in:
PavelMikus 2022-03-02 15:41:20 +01:00
parent 87c276b7a4
commit 8f7b86915a

View File

@ -6,6 +6,7 @@
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
#include <random> #include <random>
#include <algorithm> #include <algorithm>
#include <queue>
//For polynomial fitting //For polynomial fitting
#include <Eigen/Dense> #include <Eigen/Dense>
@ -299,14 +300,18 @@ struct GlobalModelInfo {
raycast_hits_tree(HitInfoCoordinateFunctor { &geometry_raycast_hits }) { raycast_hits_tree(HitInfoCoordinateFunctor { &geometry_raycast_hits }) {
} }
bool is_enforced(const Vec3f &position) const { bool is_enforced(const Vec3f &position, float radius) const {
float radius = SeamPlacer::enforcer_blocker_sqr_distance_tolerance; if (enforcers.empty()) {
return false;
}
return AABBTreeIndirect::is_any_triangle_in_radius(enforcers.vertices, enforcers.indices, return AABBTreeIndirect::is_any_triangle_in_radius(enforcers.vertices, enforcers.indices,
enforcers_tree, position, radius); enforcers_tree, position, radius);
} }
bool is_blocked(const Vec3f &position) const { bool is_blocked(const Vec3f &position, float radius) const {
float radius = SeamPlacer::enforcer_blocker_sqr_distance_tolerance; if (blockers.empty()) {
return false;
}
return AABBTreeIndirect::is_any_triangle_in_radius(blockers.vertices, blockers.indices, return AABBTreeIndirect::is_any_triangle_in_radius(blockers.vertices, blockers.indices,
blockers_tree, position, radius); blockers_tree, position, radius);
} }
@ -431,6 +436,7 @@ Polygons extract_perimeter_polygons(const Layer *layer) {
// Insert SeamCandidates created from perimeter polygons in to the result vector. // Insert SeamCandidates created from perimeter polygons in to the result vector.
// Compute its type (Enfrocer,Blocker), angle, and position // Compute its type (Enfrocer,Blocker), angle, and position
//each SeamCandidate also contains pointer to shared Perimeter structure representing the polygon //each SeamCandidate also contains pointer to shared Perimeter structure representing the polygon
// if Custom Seam modifiers are present, oversamples the polygon if necessary to better fit user intentions
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) {
@ -450,27 +456,60 @@ void process_perimeter_polygon(const Polygon &orig_polygon, float z_coord, std::
SeamPlacer::polygon_local_angles_arm_distance); SeamPlacer::polygon_local_angles_arm_distance);
std::shared_ptr<Perimeter> perimeter = std::make_shared<Perimeter>(); std::shared_ptr<Perimeter> perimeter = std::make_shared<Perimeter>();
perimeter->start_index = result_vec.size(); std::queue<Vec3f> orig_polygon_points { };
perimeter->end_index = result_vec.size() + polygon.size() - 1;
for (size_t index = 0; index < polygon.size(); ++index) { for (size_t index = 0; index < polygon.size(); ++index) {
Vec2f unscaled_p = unscale(polygon[index]).cast<float>(); Vec2f unscaled_p = unscale(polygon[index]).cast<float>();
Vec3f unscaled_position = Vec3f { unscaled_p.x(), unscaled_p.y(), z_coord }; orig_polygon_points.emplace(unscaled_p.x(), unscaled_p.y(), z_coord);
}
Vec3f first = orig_polygon_points.front();
std::queue<Vec3f> oversampled_points { };
size_t orig_angle_index = 0;
perimeter->start_index = result_vec.size();
while (!orig_polygon_points.empty() || !oversampled_points.empty()) {
EnforcedBlockedSeamPoint type = EnforcedBlockedSeamPoint::Neutral; EnforcedBlockedSeamPoint type = EnforcedBlockedSeamPoint::Neutral;
Vec3f position;
float local_ccw_angle = 0;
bool orig_point = false;
if (!oversampled_points.empty()) {
position = oversampled_points.front();
oversampled_points.pop();
} else {
position = orig_polygon_points.front();
orig_polygon_points.pop();
local_ccw_angle = was_clockwise ? -local_angles[orig_angle_index] : local_angles[orig_angle_index];
orig_angle_index++;
orig_point = true;
}
if (global_model_info.is_enforced(unscaled_position)) { if (global_model_info.is_enforced(position, SeamPlacer::enforcer_blocker_sqr_distance_tolerance)) {
type = EnforcedBlockedSeamPoint::Enforced; type = EnforcedBlockedSeamPoint::Enforced;
} }
if (global_model_info.is_blocked(unscaled_position)) { if (global_model_info.is_blocked(position, SeamPlacer::enforcer_blocker_sqr_distance_tolerance)) {
type = EnforcedBlockedSeamPoint::Blocked; type = EnforcedBlockedSeamPoint::Blocked;
} }
float local_ccw_angle = was_clockwise ? -local_angles[index] : local_angles[index]; if (orig_point) {
Vec3f pos_of_next = orig_polygon_points.empty() ? first : orig_polygon_points.front();
result_vec.emplace_back(unscaled_position, perimeter, local_ccw_angle, type); float distance_to_next = (position - pos_of_next).norm();
if (global_model_info.is_enforced(position, distance_to_next)
|| global_model_info.is_blocked(position, distance_to_next)) {
Vec3f vec_to_next = (pos_of_next - position).normalized();
float step_size = SeamPlacer::enforcer_blocker_sqr_distance_tolerance;
float step = step_size;
while (step < distance_to_next) {
oversampled_points.push(position + vec_to_next * step);
step += step_size;
} }
} }
}
result_vec.emplace_back(position, perimeter, local_ccw_angle, type);
}
perimeter->end_index = result_vec.size() - 1;
}
// Get index of previous and next perimeter point of the layer. Because SeamCandidates of all polygons of the given layer // 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 // are sequentially stored in the vector, each perimeter contains info about start and end index. These vales are used to
@ -963,6 +1002,8 @@ void SeamPlacer::init(const Print &print) {
for (const PrintObject *po : print.objects()) { for (const PrintObject *po : print.objects()) {
SeamPosition configured_seam_preference = po->config().seam_position.value;
GlobalModelInfo global_model_info { }; GlobalModelInfo global_model_info { };
gather_global_model_info(global_model_info, po); gather_global_model_info(global_model_info, po);
@ -972,11 +1013,13 @@ void SeamPlacer::init(const Print &print) {
BOOST_LOG_TRIVIAL(debug) BOOST_LOG_TRIVIAL(debug)
<< "SeamPlacer: gather_seam_candidates: end"; << "SeamPlacer: gather_seam_candidates: end";
if (configured_seam_preference != spAligned) {
BOOST_LOG_TRIVIAL(debug) BOOST_LOG_TRIVIAL(debug)
<< "SeamPlacer: calculate_candidates_visibility : start"; << "SeamPlacer: calculate_candidates_visibility : start";
calculate_candidates_visibility(po, global_model_info); calculate_candidates_visibility(po, global_model_info);
BOOST_LOG_TRIVIAL(debug) BOOST_LOG_TRIVIAL(debug)
<< "SeamPlacer: calculate_candidates_visibility : end"; << "SeamPlacer: calculate_candidates_visibility : end";
}
BOOST_LOG_TRIVIAL(debug) BOOST_LOG_TRIVIAL(debug)
<< "SeamPlacer: calculate_overhangs : start"; << "SeamPlacer: calculate_overhangs : start";
@ -1002,12 +1045,13 @@ void SeamPlacer::init(const Print &print) {
BOOST_LOG_TRIVIAL(debug) BOOST_LOG_TRIVIAL(debug)
<< "SeamPlacer: pick_seam_point : end"; << "SeamPlacer: pick_seam_point : end";
if (configured_seam_preference != spRandom) {
BOOST_LOG_TRIVIAL(debug) BOOST_LOG_TRIVIAL(debug)
<< "SeamPlacer: align_seam_points : start"; << "SeamPlacer: align_seam_points : start";
align_seam_points(po, DefaultSeamComparator { }); align_seam_points(po, DefaultSeamComparator { });
BOOST_LOG_TRIVIAL(debug) BOOST_LOG_TRIVIAL(debug)
<< "SeamPlacer: align_seam_points : end"; << "SeamPlacer: align_seam_points : end";
}
} }
} }