1224 {
1225 using namespace SeamPlacerImpl;
1226
1227
1228#ifdef DEBUG_FILES
1231 FILE *clusters = boost::nowide::fopen(clusters_f.c_str(), "w");
1232 if (clusters == nullptr) {
1233 BOOST_LOG_TRIVIAL(
error)
1234 << "stl_write_obj: Couldn't open " << clusters_f << " for writing";
1235 return;
1236 }
1238 FILE *aligns = boost::nowide::fopen(aligned_f.c_str(), "w");
1239 if (aligns == nullptr) {
1240 BOOST_LOG_TRIVIAL(
error)
1241 << "stl_write_obj: Couldn't open " << clusters_f << " for writing";
1242 return;
1243 }
1244#endif
1245
1246
1247 const std::vector<PrintObjectSeamData::LayerSeams> &layers =
m_seam_per_object[po].layers;
1248 std::vector<std::pair<size_t, size_t>> seams;
1249 for (size_t layer_idx = 0; layer_idx < layers.size(); ++layer_idx) {
1250 const std::vector<SeamCandidate> &layer_perimeter_points = layers[layer_idx].points;
1251 size_t current_point_index = 0;
1252 while (current_point_index < layer_perimeter_points.size()) {
1253 seams.emplace_back(layer_idx, layer_perimeter_points[current_point_index].perimeter.seam_index);
1254 current_point_index = layer_perimeter_points[current_point_index].perimeter.end_index;
1255 }
1256 }
1257
1258
1259 std::stable_sort(seams.begin(), seams.end(),
1260 [&comparator, &layers](const std::pair<size_t, size_t> &left,
1261 const std::pair<size_t, size_t> &right) {
1262 return comparator.is_first_better(layers[left.first].points[left.second],
1263 layers[right.first].points[right.second]);
1264 }
1265 );
1266
1267
1268
1269 std::vector<std::pair<size_t, size_t>> seam_string;
1270 std::vector<std::pair<size_t, size_t>> alternative_seam_string;
1271 std::vector<Vec2f> observations;
1272 std::vector<float> observation_points;
1273 std::vector<float> weights;
1274
1275 int global_index = 0;
1276 while (global_index < int(seams.size())) {
1277 size_t layer_idx = seams[global_index].first;
1278 size_t seam_index = seams[global_index].second;
1279 global_index++;
1280 const std::vector<SeamCandidate> &layer_perimeter_points = layers[layer_idx].points;
1281 if (layer_perimeter_points[seam_index].perimeter.finalized) {
1282
1283 continue;
1284 } else {
1285 seam_string = this->
find_seam_string(po, { layer_idx, seam_index }, comparator);
1286 size_t step_size = 1 + seam_string.size() / 20;
1287 for (size_t alternative_start = 0; alternative_start < seam_string.size(); alternative_start += step_size) {
1288 size_t start_layer_idx = seam_string[alternative_start].first;
1289 size_t seam_idx =
1290 layers[start_layer_idx].points[seam_string[alternative_start].second].perimeter.seam_index;
1292 std::pair<size_t, size_t>(start_layer_idx, seam_idx), comparator);
1293 if (alternative_seam_string.size() > seam_string.size()) {
1294 seam_string = std::move(alternative_seam_string);
1295 }
1296 }
1298
1299 continue;
1300 }
1301
1302
1303
1304 std::sort(seam_string.begin(), seam_string.end(),
1305 [](const std::pair<size_t, size_t> &left, const std::pair<size_t, size_t> &right) {
1306 return left.first < right.first;
1307 });
1308
1309
1310 global_index--;
1311
1312
1313 observations.resize(seam_string.size());
1314 observation_points.resize(seam_string.size());
1315 weights.resize(seam_string.size());
1316
1318 return std::abs(acosf(
a.normalized().dot(
b.normalized())));
1319 };
1320
1321 auto angle_weight = [](
float angle){
1323 };
1324
1325
1327 Vec3f last_point_pos = layers[seam_string[0].first].points[seam_string[0].second].position;
1328 for (size_t index = 0; index < seam_string.size(); ++index) {
1329 const SeamCandidate ¤t = layers[seam_string[index].first].points[seam_string[index].second];
1330 float layer_angle = 0.0f;
1331 if (index > 0 && index < seam_string.size() - 1) {
1332 layer_angle = angle_3d(
1333 current.position
1334 - layers[seam_string[index - 1].first].points[seam_string[index - 1].second].position,
1335 layers[seam_string[index + 1].first].points[seam_string[index + 1].second].position
1336 - current.position
1337 );
1338 }
1339 observations[index] = current.position.head<2>();
1340 observation_points[index] = current.position.z();
1341 weights[index] = angle_weight(current.local_ccw_angle);
1342 float curling_influence = layer_angle > 2.0 * std::abs(current.local_ccw_angle) ? -0.8f : 1.0f;
1343 if (current.type == EnforcedBlockedSeamPoint::Enforced) {
1344 curling_influence = 1.0f;
1345 weights[index] += 3.0f;
1346 }
1347 total_length += curling_influence * (last_point_pos - current.position).norm();
1348 last_point_pos = current.position;
1349 }
1350
1351 if (comparator.setup ==
spRear) {
1353 }
1354
1355
1356 size_t number_of_segments = std::max(size_t(1),
1359
1360
1361
1362 for (size_t index = 0; index < seam_string.size(); ++index) {
1363 const auto &pair = seam_string[index];
1364 float t = std::min(1.0f, std::pow(std::abs(layers[pair.first].points[pair.second].local_ccw_angle)
1366 if (layers[pair.first].points[pair.second].type == EnforcedBlockedSeamPoint::Enforced){
1367 t = std::max(0.4f, t);
1368 }
1369
1370 Vec3f current_pos = layers[pair.first].points[pair.second].position;
1371 Vec2f fitted_pos = curve.get_fitted_value(current_pos.z());
1372
1373
1374 Vec3f final_position = t * current_pos + (1.0f - t) *
to_3d(fitted_pos, current_pos.z());
1375
1376 Perimeter &perimeter = layers[pair.first].points[pair.second].perimeter;
1377 perimeter.seam_index = pair.second;
1378 perimeter.final_seam_position = final_position;
1379 perimeter.finalized = true;
1380 }
1381
1382#ifdef DEBUG_FILES
1383 auto randf = []() {
1384 return float(rand()) / float(RAND_MAX);
1385 };
1386 Vec3f color { randf(), randf(), randf() };
1387 for (size_t i = 0; i < seam_string.size(); ++i) {
1388 auto orig_seam = layers[seam_string[i].first].points[seam_string[i].second];
1389 fprintf(clusters, "v %f %f %f %f %f %f \n", orig_seam.position[0],
1390 orig_seam.position[1],
1391 orig_seam.position[2], color[0], color[1],
1392 color[2]);
1393 }
1394
1395 color =
Vec3f { randf(), randf(), randf() };
1396 for (size_t i = 0; i < seam_string.size(); ++i) {
1397 const Perimeter &perimeter = layers[seam_string[i].first].points[seam_string[i].second].perimeter;
1398 fprintf(aligns, "v %f %f %f %f %f %f \n", perimeter.final_seam_position[0],
1399 perimeter.final_seam_position[1],
1400 perimeter.final_seam_position[2], color[0], color[1],
1401 color[2]);
1402 }
1403#endif
1404 }
1405 }
1406
1407#ifdef DEBUG_FILES
1408 fclose(clusters);
1409 fclose(aligns);
1410#endif
1411
1412}
Definition LocalesUtils.hpp:18
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
Definition SeamPlacer.cpp:1165
static constexpr size_t seam_align_mm_per_segment
Definition SeamPlacer.hpp:137
std::unordered_map< const PrintObject *, PrintObjectSeamData > m_seam_per_object
Definition SeamPlacer.hpp:140
static constexpr float sharp_angle_snapping_threshold
Definition SeamPlacer.hpp:118
static constexpr size_t seam_align_minimum_string_seams
Definition SeamPlacer.hpp:135
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:193
float compute_angle_penalty(float ccw_angle)
Definition SeamPlacer.cpp:52
@ spRear
Definition PrintConfig.hpp:98
std::string debug_out_path(const char *name,...)
Definition utils.cpp:218
Eigen::Matrix< typename Derived::Scalar, 3, 1, Eigen::DontAlign > to_3d(const Eigen::MatrixBase< Derived > &pt, const typename Derived::Scalar z)
Definition Point.hpp:127
Eigen::Matrix< float, 3, 1, Eigen::DontAlign > Vec3f
Definition Point.hpp:49
double angle(const Eigen::MatrixBase< Derived > &v1, const Eigen::MatrixBase< Derived2 > &v2)
Definition Point.hpp:112
double total_length(const Polygons &polylines)
Definition Polygon.hpp:112
Eigen::Matrix< float, 2, 1, Eigen::DontAlign > Vec2f
Definition Point.hpp:48
static char error[256]
Definition tga.cpp:50