1884 {
1885 using namespace SeamPlacerImpl;
1886
1887
1888#ifdef DEBUG_FILES
1889 Slic3r::CNumericLocalesSetter locales_setter;
1891 FILE *clusters = boost::nowide::fopen(clusters_f.c_str(), "w");
1892 if (clusters == nullptr) {
1893 BOOST_LOG_TRIVIAL(error)
1894 << "stl_write_obj: Couldn't open " << clusters_f << " for writing";
1895 return;
1896 }
1898 FILE *aligns = boost::nowide::fopen(aligned_f.c_str(), "w");
1899 if (aligns == nullptr) {
1900 BOOST_LOG_TRIVIAL(error)
1901 << "stl_write_obj: Couldn't open " << clusters_f << " for writing";
1902 return;
1903 }
1904#endif
1905
1906
1907 const std::vector<PrintObjectSeamData::LayerSeams> &layers =
m_seam_per_object[po].layers;
1908
1909 double max_nozzle_diameter = 0.0;
1910 for (double diameter : po->print()->config().nozzle_diameter.values)
1911 max_nozzle_diameter = std::max(max_nozzle_diameter, diameter);
1912
1913 std::unique_ptr<SeamContour::Resolver> contour_resolver;
1914 {
1916 for (size_t i = 0; i < layers.size(); ++i) {
1917 throw_if_canceled();
1918 for (const Perimeter &perimeter : layers[i].perimeters) {
1920 contour.hole = perimeter.is_hole;
1921 contour.reliable = perimeter.contour_reliable;
1922 contour.width = perimeter.flow_width;
1923 contour.nozzle = max_nozzle_diameter;
1924 for (size_t j = perimeter.start_index; j < perimeter.end_index; ++j)
1925 contour.
points.push_back(layers[i].points[j].position.head<2>().cast<
double>());
1926 geometry[i].push_back(std::move(
contour));
1927 }
1928 }
1929 contour_resolver = std::make_unique<SeamContour::Resolver>(std::move(geometry), SeamContour::Options{}, throw_if_canceled);
1930 }
1931 std::vector<std::pair<size_t, size_t>> seams;
1932 for (size_t layer_idx = 0; layer_idx < layers.size(); ++layer_idx) {
1933 const std::vector<SeamCandidate> &layer_perimeter_points = layers[layer_idx].points;
1934 size_t current_point_index = 0;
1935 while (current_point_index < layer_perimeter_points.size()) {
1936 seams.emplace_back(layer_idx, layer_perimeter_points[current_point_index].perimeter.seam_index);
1937 current_point_index = layer_perimeter_points[current_point_index].perimeter.end_index;
1938 }
1939 }
1940
1941
1942 std::stable_sort(seams.begin(), seams.end(),
1943 [&comparator, &layers](const std::pair<size_t, size_t> &left,
1944 const std::pair<size_t, size_t> &right) {
1945 return comparator.is_first_better(layers[left.first].points[left.second],
1946 layers[right.first].points[right.second]);
1947 }
1948 );
1949
1950
1951
1952 std::vector<std::pair<size_t, size_t>> seam_string;
1953 std::vector<std::pair<size_t, size_t>> alternative_seam_string;
1954 std::vector<Vec2f> observations;
1955 std::vector<float> observation_points;
1956 std::vector<float> weights;
1957
1958 int global_index = 0;
1959 while (global_index < int(seams.size())) {
1960 throw_if_canceled();
1961 size_t layer_idx = seams[global_index].first;
1962 size_t seam_index = seams[global_index].second;
1963 global_index++;
1964 const std::vector<SeamCandidate> &layer_perimeter_points = layers[layer_idx].points;
1965 if (layer_perimeter_points[seam_index].perimeter.finalized) {
1966
1967 continue;
1968 } else {
1969 seam_string = this->
find_seam_string(po, { layer_idx, seam_index }, comparator, contour_resolver.get());
1970 size_t step_size = 1 + seam_string.size() / 20;
1971 for (size_t alternative_start = 0; alternative_start < seam_string.size(); alternative_start += step_size) {
1972 throw_if_canceled();
1973 size_t start_layer_idx = seam_string[alternative_start].first;
1974 size_t seam_idx =
1975 layers[start_layer_idx].points[seam_string[alternative_start].second].perimeter.seam_index;
1977 std::pair<size_t, size_t>(start_layer_idx, seam_idx), comparator,
1978 contour_resolver.get());
1979 if (alternative_seam_string.size() > seam_string.size()) {
1980 seam_string = std::move(alternative_seam_string);
1981 }
1982 }
1984
1985 continue;
1986 }
1987
1988
1989
1990 std::sort(seam_string.begin(), seam_string.end(),
1991 [](const std::pair<size_t, size_t> &left, const std::pair<size_t, size_t> &right) {
1992 return left.first < right.first;
1993 });
1994
1995
1996 global_index--;
1997
1998
1999 observations.resize(seam_string.size());
2000 observation_points.resize(seam_string.size());
2001 weights.resize(seam_string.size());
2002
2003 auto angle_3d = [](
const Vec3f& a,
const Vec3f& b){
2004 return std::abs(acosf(a.normalized().dot(b.normalized())));
2005 };
2006
2007 auto angle_weight = [](
float angle){
2009 };
2010
2011
2013 Vec3f last_point_pos = layers[seam_string[0].first].points[seam_string[0].second].position;
2014 for (size_t index = 0; index < seam_string.size(); ++index) {
2015 const SeamCandidate ¤t = layers[seam_string[index].first].points[seam_string[index].second];
2016 float layer_angle = 0.0f;
2017 if (index > 0 && index < seam_string.size() - 1) {
2018 layer_angle = angle_3d(
2019 current.position
2020 - layers[seam_string[index - 1].first].points[seam_string[index - 1].second].position,
2021 layers[seam_string[index + 1].first].points[seam_string[index + 1].second].position
2022 - current.position
2023 );
2024 }
2025 observations[index] = current.position.head<2>();
2026 observation_points[index] = current.position.z();
2027 weights[index] = angle_weight(current.local_ccw_angle);
2028 float curling_influence = layer_angle > 2.0 * std::abs(current.local_ccw_angle) ? -0.8f : 1.0f;
2029 if (current.type == EnforcedBlockedSeamPoint::Enforced) {
2030 curling_influence = 1.0f;
2031 weights[index] += 3.0f;
2032 }
2033 total_length += curling_influence * (last_point_pos - current.position).norm();
2034 last_point_pos = current.position;
2035 }
2036
2037 if (comparator.setup ==
spRear) {
2039 }
2040
2041
2042 size_t number_of_segments = std::max(size_t(1),
2045
2046
2047
2048 for (size_t index = 0; index < seam_string.size(); ++index) {
2049 const auto &pair = seam_string[index];
2050 const std::vector<SeamCandidate> &points = layers[pair.first].points;
2051 const SeamCandidate &candidate = points[pair.second];
2052 float t = std::min(1.0f, std::pow(std::abs(candidate.local_ccw_angle)
2054
2055 Vec3f current_pos = candidate.position;
2056 Vec2f fitted_pos = curve.get_fitted_value(current_pos.z());
2057
2058
2059 Vec3f final_position;
2060 if (candidate.type != EnforcedBlockedSeamPoint::Enforced) {
2061 final_position = t >= 1.0f ? current_pos :
2062 place_on_loop(points, pair.second, t * current_pos + (1.0f - t) *
to_3d(fitted_pos, current_pos.z()));
2063 } else if (t >= 1.0f) {
2064 final_position = current_pos;
2065 } else {
2066
2067 float protect = std::max(candidate.perimeter.flow_width, float(max_nozzle_diameter));
2068 if (protect <= 0.0f)
2069 protect = 0.5f;
2072 t = std::max(t, 0.4f * corner);
2074 t * current_pos + (1.0f - t) *
to_3d(fitted_pos, current_pos.z()));
2075 }
2076
2077 Perimeter &perimeter = layers[pair.first].points[pair.second].perimeter;
2078 perimeter.seam_index = pair.second;
2079 perimeter.final_seam_position = final_position;
2080 perimeter.finalized = true;
2081 }
2082
2083#ifdef DEBUG_FILES
2084 auto randf = []() {
2085 return float(rand()) / float(RAND_MAX);
2086 };
2087 Vec3f color { randf(), randf(), randf() };
2088 for (size_t i = 0; i < seam_string.size(); ++i) {
2089 auto orig_seam = layers[seam_string[i].first].points[seam_string[i].second];
2090 fprintf(clusters, "v %f %f %f %f %f %f \n", orig_seam.position[0],
2091 orig_seam.position[1],
2092 orig_seam.position[2], color[0], color[1],
2093 color[2]);
2094 }
2095
2096 color =
Vec3f { randf(), randf(), randf() };
2097 for (size_t i = 0; i < seam_string.size(); ++i) {
2098 const Perimeter &perimeter = layers[seam_string[i].first].points[seam_string[i].second].perimeter;
2099 fprintf(aligns, "v %f %f %f %f %f %f \n", perimeter.final_seam_position[0],
2100 perimeter.final_seam_position[1],
2101 perimeter.final_seam_position[2], color[0], color[1],
2102 color[2]);
2103 }
2104#endif
2105 }
2106 }
2107
2108#ifdef DEBUG_FILES
2109 fclose(clusters);
2110 fclose(aligns);
2111#endif
2112
2113}
Points points
Definition MultiPoint.hpp:22
static constexpr size_t seam_align_mm_per_segment
Definition SeamPlacer.hpp:160
std::unordered_map< const PrintObject *, PrintObjectSeamData > m_seam_per_object
Definition SeamPlacer.hpp:163
std::vector< std::pair< size_t, size_t > > find_seam_string(const PrintObject *po, std::pair< size_t, size_t > start_seam, const SeamPlacerImpl::SeamComparator &comparator, const SeamContour::Resolver *contours=nullptr) const
Definition SeamPlacer.cpp:1824
static constexpr float sharp_angle_snapping_threshold
Definition SeamPlacer.hpp:141
static constexpr size_t seam_align_minimum_string_seams
Definition SeamPlacer.hpp:158
PiecewiseFittedCurve< Dimension, NumberType, CubicBSplineKernel< NumberType > > fit_cubic_bspline(const std::vector< Vec< Dimension, NumberType > > &observations, std::vector< NumberType > observation_points, std::vector< NumberType > weights, size_t segments_count, size_t endpoints_level_of_freedom=0)
Definition Curves.hpp:199
std::vector< std::vector< Contour > > Layers
Definition SeamContour.hpp:23
Vec3f place_on_loop(const std::vector< SeamCandidate > &points, size_t index, const Vec3f &target)
Definition SeamPlacer.cpp:1498
constexpr float enforced_corner_angle_max
Definition SeamPlacer.cpp:1451
float enforced_corner_influence(const std::vector< SeamCandidate > &points, size_t index, float protect, float fade_end)
Definition SeamPlacer.cpp:1462
float compute_angle_penalty(float ccw_angle)
Definition SeamPlacer.cpp:82
@ spRear
Definition PrintConfig.hpp:395
std::string debug_out_path(const char *name,...)
Definition utils.cpp:382
Eigen::Matrix< typename Derived::Scalar, 3, 1, Eigen::DontAlign > to_3d(const Eigen::MatrixBase< Derived > &pt, const typename Derived::Scalar z)
Definition Point.hpp:153
Eigen::Matrix< float, 3, 1, Eigen::DontAlign > Vec3f
Definition Point.hpp:65
double angle(const Eigen::MatrixBase< Derived > &v1, const Eigen::MatrixBase< Derived2 > &v2)
Definition Point.hpp:138
double total_length(const Polygons &polylines)
Definition Polygon.hpp:127
Eigen::Matrix< float, 2, 1, Eigen::DontAlign > Vec2f
Definition Point.hpp:64
const Polygon & contour(const ExPolygon &p)
Definition AGGRaster.hpp:30
@ Perimeter
Definition Types.hpp:146