mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-20 05:07:51 -06:00
Merge branch 'master' into SoftFever
# Conflicts: # resources/i18n/zh_cn/BambuStudio.mo # version.inc
This commit is contained in:
commit
69e9a7454e
28 changed files with 375 additions and 274 deletions
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include <cassert>
|
||||
#include <limits>
|
||||
#include <algorithm>
|
||||
|
||||
#include <libslic3r.h>
|
||||
|
||||
|
@ -20,45 +21,35 @@ namespace Slic3r {
|
|||
|
||||
const static bool g_wipe_into_objects = false;
|
||||
|
||||
void dfs_get_all_sorted_extruders(const std::vector<std::vector<float>> & wipe_volumes,
|
||||
const std::vector<unsigned int> & all_extruders,
|
||||
std::vector<unsigned int> & sorted_extruders,
|
||||
float flush_volume,
|
||||
std::map<float, std::vector<unsigned int>> &volumes_to_extruder_order)
|
||||
{
|
||||
if (sorted_extruders.size() == all_extruders.size()) {
|
||||
volumes_to_extruder_order.insert(std::pair(flush_volume, sorted_extruders));
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto extruder_id : all_extruders) {
|
||||
if (sorted_extruders.empty()) {
|
||||
sorted_extruders.push_back(extruder_id);
|
||||
dfs_get_all_sorted_extruders(wipe_volumes, all_extruders, sorted_extruders, flush_volume, volumes_to_extruder_order);
|
||||
sorted_extruders.pop_back();
|
||||
} else {
|
||||
auto itor = std::find(sorted_extruders.begin(), sorted_extruders.end(), extruder_id);
|
||||
if (itor == sorted_extruders.end()) {
|
||||
float delta_flush_volume = wipe_volumes[sorted_extruders.back()][extruder_id];
|
||||
flush_volume += delta_flush_volume;
|
||||
sorted_extruders.push_back(extruder_id);
|
||||
dfs_get_all_sorted_extruders(wipe_volumes, all_extruders, sorted_extruders, flush_volume, volumes_to_extruder_order);
|
||||
flush_volume -= delta_flush_volume;
|
||||
sorted_extruders.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<unsigned int> get_extruders_order(const std::vector<std::vector<float>> &wipe_volumes, std::vector<unsigned int> all_extruders, unsigned int start_extruder_id)
|
||||
{
|
||||
if (all_extruders.size() > 1) {
|
||||
std::vector<unsigned int> sorted_extruders;
|
||||
auto iter = std::find(all_extruders.begin(), all_extruders.end(), start_extruder_id);
|
||||
if (iter != all_extruders.end()) { sorted_extruders.push_back(start_extruder_id); }
|
||||
std::map<float, std::vector<unsigned int>> volumes_to_extruder_order;
|
||||
dfs_get_all_sorted_extruders(wipe_volumes, all_extruders, sorted_extruders, 0, volumes_to_extruder_order);
|
||||
if (volumes_to_extruder_order.size() > 0) return volumes_to_extruder_order.begin()->second;
|
||||
int begin_index = 0;
|
||||
auto iter = std::find(all_extruders.begin(), all_extruders.end(), start_extruder_id);
|
||||
if (iter != all_extruders.end()) {
|
||||
for (int i = 0; i < all_extruders.size(); ++i) {
|
||||
if (all_extruders[i] == start_extruder_id) {
|
||||
std::swap(all_extruders[i], all_extruders[0]);
|
||||
}
|
||||
}
|
||||
begin_index = 1;
|
||||
}
|
||||
|
||||
std::pair<float, std::vector<unsigned int>> volumes_to_extruder_order;
|
||||
volumes_to_extruder_order.first = 10000 * all_extruders.size();
|
||||
std::sort(all_extruders.begin() + begin_index, all_extruders.end());
|
||||
do {
|
||||
float flush_volume = 0;
|
||||
for (int i = 0; i < all_extruders.size() - 1; ++i) {
|
||||
flush_volume += wipe_volumes[all_extruders[i]][all_extruders[i + 1]];
|
||||
}
|
||||
if (flush_volume < volumes_to_extruder_order.first) {
|
||||
volumes_to_extruder_order = std::pair(flush_volume, all_extruders);
|
||||
}
|
||||
} while (std::next_permutation(all_extruders.begin() + begin_index, all_extruders.end()));
|
||||
|
||||
if (volumes_to_extruder_order.second.size() > 0)
|
||||
return volumes_to_extruder_order.second;
|
||||
}
|
||||
return all_extruders;
|
||||
}
|
||||
|
@ -737,7 +728,10 @@ void ToolOrdering::reorder_extruders_for_minimum_flush_volume()
|
|||
for (LayerTools& lt : m_layer_tools) {
|
||||
if (lt.extruders.empty())
|
||||
continue;
|
||||
lt.extruders = get_extruders_order(wipe_volumes, lt.extruders, current_extruder_id);
|
||||
// todo: The algorithm complexity is too high(o(n2)), currently only 8 colors are supported
|
||||
if (lt.extruders.size() <= 8) {
|
||||
lt.extruders = get_extruders_order(wipe_volumes, lt.extruders, current_extruder_id);
|
||||
}
|
||||
current_extruder_id = lt.extruders.back();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -248,7 +248,7 @@ PresetsConfigSubstitutions PresetBundle::load_presets(AppConfig &config, Forward
|
|||
dir_user_presets = data_dir() + "/" + PRESET_USER_DIR + "/" + config.get("preset_folder");
|
||||
}
|
||||
else {
|
||||
dir_user_presets = data_dir() + "/" + PRESET_USER_DIR + "/default";
|
||||
dir_user_presets = data_dir() + "/" + PRESET_USER_DIR + "/" + DEFAULT_USER_FOLDER_NAME;
|
||||
}
|
||||
fs::path user_folder(data_dir() + "/" + PRESET_USER_DIR);
|
||||
if (!fs::exists(user_folder))
|
||||
|
@ -698,8 +698,11 @@ PresetsConfigSubstitutions PresetBundle::import_presets(std::vector<std::string>
|
|||
//BBS save user preset to user_id preset folder
|
||||
void PresetBundle::save_user_presets(AppConfig& config, std::vector<std::string>& need_to_delete_list)
|
||||
{
|
||||
std::string user_sub_folder = DEFAULT_USER_FOLDER_NAME;
|
||||
if (!config.get("preset_folder").empty())
|
||||
user_sub_folder = config.get("preset_folder");
|
||||
//BBS: change directory by design
|
||||
const std::string dir_user_presets = data_dir() + "/" + PRESET_USER_DIR + "/"+ config.get("preset_folder");
|
||||
const std::string dir_user_presets = data_dir() + "/" + PRESET_USER_DIR + "/"+ user_sub_folder;
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(" enter, save to %1%")%dir_user_presets;
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
#include <unordered_map>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
#define DEFAULT_USER_FOLDER_NAME "default"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
// Bundle of Print + Filament + Printer presets.
|
||||
|
|
|
@ -1513,7 +1513,7 @@ static inline Polygons detect_overhangs(
|
|||
const coordf_t max_bridge_length = scale_(object_config.max_bridge_length.value);
|
||||
const bool bridge_no_support = object_config.bridge_no_support.value;
|
||||
|
||||
if (layer_id == 0)
|
||||
if (layer_id == 0)
|
||||
{
|
||||
// Don't fill in the holes. The user may apply a higher raft_expansion if one wants a better 1st layer adhesion.
|
||||
overhang_polygons = to_polygons(layer.lslices);
|
||||
|
|
|
@ -708,7 +708,7 @@ void TreeSupport::detect_object_overhangs()
|
|||
if (m_object->tree_support_layer_count() >= m_object->layer_count())
|
||||
return;
|
||||
|
||||
// Clear and create Tree Support Layers
|
||||
// Create Tree Support Layers
|
||||
m_object->clear_tree_support_layers();
|
||||
m_object->clear_tree_support_preview_cache();
|
||||
|
||||
|
@ -721,11 +721,11 @@ void TreeSupport::detect_object_overhangs()
|
|||
const coordf_t extrusion_width = config.line_width.value;
|
||||
const coordf_t extrusion_width_scaled = scale_(extrusion_width);
|
||||
const coordf_t max_bridge_length = scale_(config.max_bridge_length.value);
|
||||
const bool bridge_no_support = max_bridge_length > 0;
|
||||
const bool bridge_no_support = max_bridge_length > 0;// config.bridge_no_support.value;
|
||||
const bool support_critical_regions_only = config.support_critical_regions_only.value;
|
||||
const int enforce_support_layers = config.enforce_support_layers.value;
|
||||
const double area_thresh_well_supported = SQ(scale_(6));
|
||||
const double length_thresh_well_supported = scale_(6);
|
||||
const double area_thresh_well_supported = SQ(scale_(6)); // min: 6x6=36mm^2
|
||||
const double length_thresh_well_supported = scale_(6); // min: 6mm
|
||||
static const double sharp_tail_max_support_height = 8.f;
|
||||
// a region is considered well supported if the number of layers below it exceeds this threshold
|
||||
const int thresh_layers_below = 10 / config.layer_height;
|
||||
|
@ -822,19 +822,20 @@ void TreeSupport::detect_object_overhangs()
|
|||
region2clusterInd.emplace(®ion, regionClusters.size() - 1);
|
||||
}
|
||||
};
|
||||
// main part of sharptail detections
|
||||
|
||||
has_sharp_tail = false;
|
||||
if (std::set<SupportType>{stTreeAuto, stHybridAuto, stTree}.count(stype))// == stTreeAuto || stype == stHybridAuto || stype == stTree)
|
||||
{
|
||||
double threshold_rad = (config.support_threshold_angle.value < EPSILON ? 30 : config.support_threshold_angle.value+1) * M_PI / 180.;
|
||||
ExPolygons regions_well_supported;
|
||||
std::map<ExPolygon, int, ExPolygonComp> region_layers_below;
|
||||
ExPolygons lower_overhang_dilated;
|
||||
|
||||
for (size_t layer_nr = 0; layer_nr < m_object->layer_count(); layer_nr++){
|
||||
ExPolygons regions_well_supported; // regions on buildplate or well supported
|
||||
std::map<ExPolygon, int, ExPolygonComp> region_layers_below; // regions and the number of layers below
|
||||
ExPolygons lower_overhang_dilated; // for small overhang
|
||||
|
||||
for (size_t layer_nr = 0; layer_nr < m_object->layer_count(); layer_nr++)
|
||||
{
|
||||
if (m_object->print()->canceled())
|
||||
break;
|
||||
|
||||
|
||||
if (!is_auto && layer_nr > enforce_support_layers)
|
||||
continue;
|
||||
|
||||
|
@ -872,7 +873,7 @@ void TreeSupport::detect_object_overhangs()
|
|||
// normal overhang
|
||||
ExPolygons lower_layer_offseted = offset_ex(lower_polys, support_offset_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS);
|
||||
ExPolygons overhang_areas = std::move(diff_ex(curr_polys, lower_layer_offseted));
|
||||
|
||||
// overhang_areas = std::move(offset2_ex(overhang_areas, -0.1 * extrusion_width_scaled, 0.1 * extrusion_width_scaled));
|
||||
overhang_areas.erase(std::remove_if(overhang_areas.begin(), overhang_areas.end(),
|
||||
[extrusion_width_scaled](ExPolygon &area) { return offset_ex(area, -0.1 * extrusion_width_scaled).empty(); }),
|
||||
overhang_areas.end());
|
||||
|
@ -960,7 +961,7 @@ void TreeSupport::detect_object_overhangs()
|
|||
|
||||
// 2.4 if the area grows fast than threshold, it get connected to other part or
|
||||
// it has a sharp slop and will be auto supported.
|
||||
ExPolygons new_overhang_expolys = diff_ex({expoly}, lower_layer_sharptails);
|
||||
ExPolygons new_overhang_expolys = diff_ex({ expoly }, lower_layer_sharptails);
|
||||
if (!offset_ex(new_overhang_expolys, -5.0 * extrusion_width_scaled).empty()) {
|
||||
is_sharp_tail = false;
|
||||
break;
|
||||
|
@ -1132,6 +1133,7 @@ void TreeSupport::detect_object_overhangs()
|
|||
// if (erode1.empty() && !inter_with_others.empty())
|
||||
// blockers[layer_nr].push_back(p_overhang->contour);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1154,13 +1156,12 @@ void TreeSupport::detect_object_overhangs()
|
|||
for (auto &area : ts_layer->overhang_areas) {
|
||||
ts_layer->overhang_types.emplace(&area, TreeSupportLayer::Detected);
|
||||
}
|
||||
// enforcers
|
||||
|
||||
if (layer_nr < enforcers.size()) {
|
||||
Polygons& enforcer = enforcers[layer_nr];
|
||||
// coconut: enforcer can't do offset2_ex, otherwise faces with angle near 90 degrees can't have enforcers, which
|
||||
// is not good. For example: tails of animals needs extra support except the lowest tip.
|
||||
//enforcer = std::move(offset2_ex(enforcer, -0.1 * extrusion_width_scaled, 0.1 * extrusion_width_scaled));
|
||||
enforcer = offset(enforcer, 0.1 * extrusion_width_scaled);
|
||||
for (const Polygon& poly : enforcer) {
|
||||
ts_layer->overhang_areas.emplace_back(poly);
|
||||
ts_layer->overhang_types.emplace(&ts_layer->overhang_areas.back(), TreeSupportLayer::Enforced);
|
||||
|
@ -1870,30 +1871,30 @@ void TreeSupport::generate_support_areas()
|
|||
if (!tree_support_enable)
|
||||
return;
|
||||
|
||||
std::vector<std::vector<Node*>> contact_nodes(m_object->layers().size());
|
||||
std::vector<std::vector<Node*>> contact_nodes(m_object->layers().size()); //Generate empty layers to store the points in.
|
||||
|
||||
profiler.stage_start(STAGE_total);
|
||||
|
||||
// Generate overhang areas
|
||||
profiler.stage_start(STAGE_DETECT_OVERHANGS);
|
||||
m_object->print()->set_status(55, _L("Support: detect overhangs"));
|
||||
detect_object_overhangs(); // Entry of step#1;
|
||||
detect_object_overhangs();
|
||||
profiler.stage_finish(STAGE_DETECT_OVERHANGS);
|
||||
|
||||
// Generate contact points of tree support
|
||||
profiler.stage_start(STAGE_GENERATE_CONTACT_NODES);
|
||||
m_object->print()->set_status(56, _L("Support: generate contact points"));
|
||||
generate_contact_points(contact_nodes); // Entry of step#2;
|
||||
generate_contact_points(contact_nodes);
|
||||
profiler.stage_finish(STAGE_GENERATE_CONTACT_NODES);
|
||||
|
||||
//Drop nodes to lower layers.
|
||||
profiler.stage_start(STAGE_DROP_DOWN_NODES);
|
||||
m_object->print()->set_status(60, _L("Support: propagate branches"));
|
||||
drop_nodes(contact_nodes); // Entry of step#3;
|
||||
drop_nodes(contact_nodes);
|
||||
profiler.stage_finish(STAGE_DROP_DOWN_NODES);
|
||||
|
||||
// Adjust support layer heights
|
||||
adjust_layer_heights(contact_nodes); // Entry of step#4;
|
||||
adjust_layer_heights(contact_nodes);
|
||||
|
||||
//Generate support areas.
|
||||
profiler.stage_start(STAGE_DRAW_CIRCLES);
|
||||
|
|
|
@ -399,7 +399,7 @@ struct SlabLines {
|
|||
std::vector<IntersectionLines> at_slice;
|
||||
// Projections of triangle set boundary lines into layer below (for projection from the top)
|
||||
// or into layer above (for projection from the bottom).
|
||||
// In both cases the intersection lines are CCW oriented.
|
||||
// In both cases the intersection liens are CCW oriented.
|
||||
std::vector<IntersectionLines> between_slices;
|
||||
};
|
||||
|
||||
|
@ -790,8 +790,7 @@ inline std::pair<SlabLines, SlabLines> slice_slabs_make_lines(
|
|||
}
|
||||
slice_facet_with_slabs<true>(vertices, indices, face_idx, neighbors, edge_ids, num_edges, zs, lines_top, lines_mutex_top);
|
||||
}
|
||||
// BBS: add vertical faces option
|
||||
if (bottom && (fo == FaceOrientation::Down || fo == FaceOrientation::Vertical || fo == FaceOrientation::Degenerate)) {
|
||||
if (bottom && (fo == FaceOrientation::Down || fo == FaceOrientation::Degenerate)) {
|
||||
Vec3i neighbors = face_neighbors[face_idx];
|
||||
// Reset neighborship of this triangle in case the other triangle is oriented backwards from this one.
|
||||
for (int i = 0; i < 3; ++ i)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue