Skip to content

Commit

Permalink
rc for 2.3.57.12
Browse files Browse the repository at this point in the history
  • Loading branch information
remi durand committed Mar 31, 2022
2 parents a0d7ae3 + 14ce3ad commit 173e6c6
Show file tree
Hide file tree
Showing 25 changed files with 374 additions and 128 deletions.
3 changes: 3 additions & 0 deletions doc/How to build - Mac OS.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,16 @@ XCode is available through Apple's App Store, the other three tools are availabl
### How to get the source code

You have to gitclone the repository

Open 'terminal' and enter each line, one at a time.
```
git clone https://github.com/supermerill/SuperSlicer.git
```

and then you have to clone the profiles submodules

```
cd SuperSlicer
cd resources/profiles
git submodule update
```
Expand Down
31 changes: 30 additions & 1 deletion src/libslic3r/AppConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,37 @@ void AppConfig::set_defaults()
if (get("drop_project_action").empty())
set("drop_project_action", "1");

if (get("freecad_path").empty())
if (get("freecad_path").empty() || get("freecad_path") == ".") {
set("freecad_path", ".");
//try to find it
#ifdef _WIN32
//windows
boost::filesystem::path prg_files = "C:/Program Files";
boost::filesystem::path freecad_path;
if (boost::filesystem::exists(prg_files)) {
for (boost::filesystem::directory_entry& prg_dir : boost::filesystem::directory_iterator(prg_files)) {
if (prg_dir.status().type() == boost::filesystem::file_type::directory_file
&& boost::starts_with(prg_dir.path().filename().string(), "FreeCAD")
&& (freecad_path.empty() || freecad_path.filename().string() < prg_dir.path().filename().string())) {
freecad_path = prg_dir.path();
}
}
}
if (!freecad_path.empty())
set("freecad_path", freecad_path.string());
#else
#ifdef __APPLE__
//apple
if (boost::filesystem::exists("/Applications/FreeCAD.app/Contents/Frameworks/FreeCAD"))
set("freecad_path", "/Applications/FreeCAD.app/Contents/Frameworks/FreeCAD");

#else
// linux
if (boost::filesystem::exists("/usr/local/bin/FreeCAD"))
set("freecad_path", "/usr/local/bin/FreeCAD");
#endif
#endif
}

if (get("show_overwrite_dialog").empty())
set("show_overwrite_dialog", "1");
Expand Down
10 changes: 9 additions & 1 deletion src/libslic3r/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -820,7 +820,7 @@ ConfigSubstitutions ConfigBase::load_from_ini(const std::string &file, ForwardCo
return this->load(tree, compatibility_rule);
} catch (const ConfigurationError &e) {
throw ConfigurationError(format("Failed loading configuration file \"%1%\": %2%", file, e.what()));
}
}
}

ConfigSubstitutions ConfigBase::load(const boost::property_tree::ptree &tree, ForwardCompatibilitySubstitutionRule compatibility_rule)
Expand Down Expand Up @@ -933,6 +933,14 @@ size_t ConfigBase::load_from_gcode_string(const char* str, ConfigSubstitutionCon
}
catch (UnknownOptionException & /* e */) {
// ignore
} catch (BadOptionValueException & e) {
if (substitutions.rule == ForwardCompatibilitySubstitutionRule::Disable)
throw e;
// log the error
const ConfigDef* def = this->def();
if (def == nullptr) throw e;
const ConfigOptionDef* optdef = def->get(std::string(key, key_end));
substitutions.substitutions.emplace_back(optdef, std::string(value, end), ConfigOptionUniquePtr(optdef->default_value->clone()));
}
end = start;
}
Expand Down
6 changes: 6 additions & 0 deletions src/libslic3r/GCode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1326,6 +1326,9 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
if ((initial_extruder_id = tool_ordering.first_extruder()) != static_cast<uint16_t>(-1))
break;
}
if (initial_extruder_id == static_cast<unsigned int>(-1))
// No object to print was found, cancel the G-code export.
throw Slic3r::SlicingError(_(L("No extrusions were generated for objects.")));
// We don't allow switching of extruders per layer by Model::custom_gcode_per_print_z in sequential mode.
// Use the extruder IDs collected from Regions.
std::set<uint16_t> extruder_set = print.extruders();
Expand All @@ -1337,6 +1340,9 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
// If the tool ordering has been pre-calculated by Print class for wipe tower already, reuse it.
tool_ordering = print.tool_ordering();
tool_ordering.assign_custom_gcodes(print);
if (tool_ordering.all_extruders().empty())
// No object to print was found, cancel the G-code export.
throw Slic3r::SlicingError(_(L("No extrusions were generated for objects.")));
has_wipe_tower = print.has_wipe_tower() && tool_ordering.has_wipe_tower();
initial_extruder_id = (has_wipe_tower && ! print.config().single_extruder_multi_material_priming) ?
// The priming towers will be skipped.
Expand Down
19 changes: 13 additions & 6 deletions src/libslic3r/GCode/SeamPlacer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -340,35 +340,42 @@ Point SeamPlacer::get_seam(const Layer& layer, SeamPosition seam_position,
// Look for all lambda-seam-modifiers below current z, choose the highest one
ModelVolume* v_lambda_seam = nullptr;
Vec3d lambda_pos;
double lambda_z;
double lambda_dist;
double lambda_radius;
//get model_instance (like from po->model_object()->instances, but we don't have the index for that array)
const ModelInstance* model_instance = po->instances()[print_object_instance_idx].model_instance;
for (ModelVolume* v : po->model_object()->volumes) {
if (v->is_seam_position()) {
//xy in object coordinates, z in plater coordinates
Vec3d test_lambda_pos = model_instance->transform_vector(v->get_offset(), true);
// created/moved shpere have offset in their transformation, and loaded ones have their loaded transformation in the source transformation.
Vec3d test_lambda_pos = model_instance->transform_vector((v->get_transformation() * v->source.transform).get_offset(), false);
// remove shift, as we used the transform_vector(.., FALSE). that way, we have a correct z vs the layer height, and same for the x and y vs polygon.
test_lambda_pos.x() -= unscaled(po->instances()[print_object_instance_idx].shift.x());
test_lambda_pos.y() -= unscaled(po->instances()[print_object_instance_idx].shift.y());

double test_lambda_z = std::abs(layer.print_z - test_lambda_pos.z());
Point xy_lambda(scale_(test_lambda_pos.x()), scale_(test_lambda_pos.y()));
Point nearest = polygon.point_projection(xy_lambda);
Vec3d polygon_3dpoint{ unscaled(nearest.x()), unscaled(nearest.y()), (double)layer.print_z };
double test_lambda_dist = (polygon_3dpoint - test_lambda_pos).norm();
double sphere_radius = po->model_object()->instance_bounding_box(0, true).size().x() / 2;
//if (test_lambda_dist > sphere_radius)
// continue;

//use this one if the first or nearer (in z)
if (v_lambda_seam == nullptr || lambda_dist > test_lambda_dist) {

//use this one if the first or nearer (in z, or in xy if same z)
if (v_lambda_seam == nullptr
|| ( lambda_z > test_lambda_z )
|| ( lambda_z == test_lambda_z && lambda_dist > test_lambda_dist ) ){
v_lambda_seam = v;
lambda_pos = test_lambda_pos;
lambda_radius = sphere_radius;
lambda_dist = test_lambda_dist;
lambda_z = test_lambda_z;
}
}
}

if (v_lambda_seam != nullptr) {
lambda_pos = model_instance->transform_vector(v_lambda_seam->get_offset(), true);
// Found, get the center point and apply rotation and scaling of Model instance. Continues to spAligned if not found or Weight set to Zero.
last_pos = Point::new_scale(lambda_pos.x(), lambda_pos.y());
// Weight is set by user and stored in the radius of the sphere
Expand Down
135 changes: 125 additions & 10 deletions src/libslic3r/MedialAxis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@
#include <list>

namespace Slic3r {
int count_error = 0;

//int Slic3r::MedialAxis::staticid = 0;

void
MedialAxis::build(Polylines &polylines)
Expand Down Expand Up @@ -667,6 +664,7 @@ MedialAxis::fusion_corners(ThickPolylines &pp)
//if (polyline.points.size() != 2) continue; // maybe we should have something to merge X-point to 2-point if it's near enough.
if (polyline.endpoints.first) polyline.reverse();
else if (!polyline.endpoints.second) continue;
if (polyline.width.back() > min_width) continue;

//check my length is small
coord_t length = (coord_t)polyline.length();
Expand Down Expand Up @@ -1210,6 +1208,7 @@ MedialAxis::remove_too_thin_extrusion(ThickPolylines& pp)
bool changes = false;
for (size_t i = 0; i < pp.size(); ++i) {
ThickPolyline& polyline = pp[i];
bool polyline_changes = false;
// remove bits with too small extrusion
while (polyline.points.size() > 1 && polyline.width.front() < this->min_width && polyline.endpoints.first) {
//try to split if possible
Expand All @@ -1226,11 +1225,13 @@ MedialAxis::remove_too_thin_extrusion(ThickPolylines& pp)
polyline.width.erase(polyline.width.begin());
}
changes = true;
polyline_changes = true;
break;
}
polyline.points.erase(polyline.points.begin());
polyline.width.erase(polyline.width.begin());
changes = true;
polyline_changes = true;
}
while (polyline.points.size() > 1 && polyline.width.back() < this->min_width && polyline.endpoints.second) {
//try to split if possible
Expand All @@ -1247,14 +1248,16 @@ MedialAxis::remove_too_thin_extrusion(ThickPolylines& pp)
polyline.width.erase(polyline.width.end() - 1);
}
changes = true;
polyline_changes = true;
break;
}
polyline.points.erase(polyline.points.end() - 1);
polyline.width.erase(polyline.width.end() - 1);
changes = true;
polyline_changes = true;
}
//remove points and bits that comes from a "main line"
if (polyline.points.size() < 2 || (changes && polyline.length() < this->max_width && polyline.points.size() ==2)) {
if (polyline.points.size() < 2 || (polyline_changes && polyline.length() < this->max_width && polyline.points.size() ==2)) {
//remove self if too small
pp.erase(pp.begin() + i);
--i;
Expand All @@ -1263,6 +1266,110 @@ MedialAxis::remove_too_thin_extrusion(ThickPolylines& pp)
if (changes) concatThickPolylines(pp);
}

void
MedialAxis::concatenate_small_polylines(ThickPolylines& pp)
{

/*
new goal: ensure that if there is a too short segment, it will be connected with a sufficiently long one, to save it
*/
coordf_t shortest_size = (coordf_t)this->min_length;
std::set<size_t> deleted;
std::vector<size_t> idx_per_size;
//TODO: cache the length
for (size_t i = 0; i < pp.size(); ++i) {
ThickPolyline& polyline = pp[i];
if (polyline.endpoints.first && polyline.endpoints.second) continue; // optimization
if (polyline.length() <= shortest_size)
idx_per_size.push_back(i);
}
std::sort(idx_per_size.begin(), idx_per_size.end(), [&pp](size_t a, size_t b) -> bool {return pp[a].length() > pp[b].length(); });
for (size_t idx_sorted = 0; idx_sorted < idx_per_size.size(); ++idx_sorted) {
if (deleted.find(idx_per_size[idx_sorted]) != deleted.end()) continue;
//all these polylines need to be saved
ThickPolyline& polyline = pp[idx_per_size[idx_sorted]];

ThickPolyline* best_candidate = nullptr;
float best_dot = -1;
coordf_t best_length = -1;
size_t best_idx = 0;

// find another polyline starting here
for (size_t j = 0; j < pp.size(); ++j) {
if (deleted.find(j) != deleted.end()) continue;
if (j == idx_per_size[idx_sorted]) continue;
ThickPolyline& other = pp[j];
if (other.endpoints.first && other.endpoints.second) continue;
coordf_t other_length = other.length();
if (other_length + polyline.length() <= shortest_size) continue; // need to be long enough to save it
bool me_reverse = false;
bool other_reverse = false;
if (polyline.last_point().coincides_with_epsilon(other.last_point())) {
other_reverse = true;
} else if (polyline.first_point().coincides_with_epsilon(other.last_point())) {
me_reverse = true;
other_reverse = true;
} else if (polyline.first_point().coincides_with_epsilon(other.first_point())) {
me_reverse = true;
} else if (!polyline.last_point().coincides_with_epsilon(other.first_point())) {
continue;
}

//find the straitest
Vec2d v_poly(me_reverse ? polyline.lines().front().vector().x() : polyline.lines().back().vector().x(),
me_reverse ? polyline.lines().front().vector().y() : polyline.lines().back().vector().y());
v_poly *= (1 / std::sqrt(v_poly.x() * v_poly.x() + v_poly.y() * v_poly.y()));
Vec2d v_other(other_reverse ? other.lines().back().vector().x() : other.lines().front().vector().x(),
other_reverse ? other.lines().back().vector().y() : other.lines().front().vector().y());
v_other *= (1 / std::sqrt(v_other.x() * v_other.x() + v_other.y() * v_other.y()));
float other_dot = std::abs(float(v_poly.x() * v_other.x() + v_poly.y() * v_other.y()));
// use the straitest one
// but if almost equal, use the shortest one
if (std::abs(other_dot - best_dot) < 0.01) {
if (best_length < 0 || best_length > other_length) {
best_candidate = &other;
best_idx = j;
best_dot = other_dot;
best_length = other_length;
}
} else if (other_dot > best_dot) {
best_candidate = &other;
best_idx = j;
best_dot = other_dot;
best_length = other_length;
}
}
if (best_candidate != nullptr && best_candidate->points.size() > 1) {
if (polyline.last_point().coincides_with_epsilon(best_candidate->last_point())) {
best_candidate->reverse();
} else if (polyline.first_point().coincides_with_epsilon(best_candidate->last_point())) {
polyline.reverse();
best_candidate->reverse();
} else if (polyline.first_point().coincides_with_epsilon(best_candidate->first_point())) {
polyline.reverse();
}
//intersections may create over-extrusion because the included circle can be a bit larger. We have to make it short again if needed.
if (polyline.points.size() > 1 && best_candidate->points.size() > 1
&& polyline.width.back() > polyline.width[polyline.width.size() - 2]
&& polyline.width.back() > best_candidate->width[1]) {
polyline.width.back() = std::min(polyline.width[polyline.width.size() - 2], best_candidate->width[1]);
}
//be far enough
int far_idx = 1;
while (far_idx < best_candidate->points.size() && polyline.last_point().coincides_with_epsilon(best_candidate->points[far_idx]))
far_idx++;
polyline.points.insert(polyline.points.end(), best_candidate->points.begin() + far_idx, best_candidate->points.end());
polyline.width.insert(polyline.width.end(), best_candidate->width.begin() + far_idx, best_candidate->width.end());
polyline.endpoints.second = best_candidate->endpoints.second;
assert(polyline.width.size() == polyline.points.size());
deleted.insert(best_idx);
}
}
//delete items to delete (iterate in reverse order to not invalidate the idxs
for (auto rit = deleted.rbegin(); rit != deleted.rend(); rit++)
pp.erase(pp.begin() + (*rit));
}

void
MedialAxis::concatenate_polylines_with_crossing(ThickPolylines& pp)
{
Expand Down Expand Up @@ -1402,7 +1509,7 @@ MedialAxis::remove_too_thin_points(ThickPolylines& pp)
}

void
MedialAxis::remove_too_short_polylines(ThickPolylines& pp, const coord_t min_size)
MedialAxis::remove_too_short_polylines(ThickPolylines& pp)
{
// reduce the flow at the intersection ( + ) points
//FIXME: TODO: note that crossings are unnafected right now. they may need a different codepath directly in their method
Expand Down Expand Up @@ -1468,7 +1575,7 @@ MedialAxis::remove_too_short_polylines(ThickPolylines& pp, const coord_t min_siz
while (changes) {
changes = false;

coordf_t shortest_size = (coordf_t) min_size;
coordf_t shortest_size = (coordf_t)this->min_length;
size_t shortest_idx = -1;
for (size_t i = 0; i < pp.size(); ++i) {
ThickPolyline& polyline = pp[i];
Expand Down Expand Up @@ -1499,8 +1606,6 @@ MedialAxis::remove_too_short_polylines(ThickPolylines& pp, const coord_t min_siz
changes = true;
while (changes) {
changes = false;

coordf_t shortest_size = (coordf_t)min_size;
size_t shortest_idx = -1;
for (size_t polyidx = 0; polyidx < pp.size(); ++polyidx) {
ThickPolyline& tp = pp[polyidx];
Expand Down Expand Up @@ -2000,18 +2105,28 @@ MedialAxis::build(ThickPolylines &polylines_out)
// svg.Close();
//}
//TODO: reduce the flow at the intersection ( + ) points on crossing?
concatenate_small_polylines(pp);
//{
// std::stringstream stri;
// stri << "medial_axis_6_concat_small_" << id << ".svg";
// SVG svg(stri.str());
// svg.draw(*bounds, "grey");
// svg.draw(this->expolygon, "green");
// svg.draw(pp, "red");
// svg.Close();
//}
concatenate_polylines_with_crossing(pp);
//{
// std::stringstream stri;
// stri << "medial_axis_6_concat_" << id << ".svg";
// stri << "medial_axis_7_concat_" << id << ".svg";
// SVG svg(stri.str());
// svg.draw(*bounds, "grey");
// svg.draw(this->expolygon, "green");
// svg.draw(pp, "red");
// svg.Close();
//}

remove_too_short_polylines(pp, max_w * 2);
remove_too_short_polylines(pp);
//{
// std::stringstream stri;
// stri << "medial_axis_8_tooshort_" << id << ".svg";
Expand Down
Loading

0 comments on commit 173e6c6

Please sign in to comment.