mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-27 02:41:17 +00:00
Merge branch 'main' into dev/bbl-network-upd
This commit is contained in:
@@ -101,6 +101,8 @@ set(lisbslic3r_sources
|
||||
Fill/FillHoneycomb.hpp
|
||||
Fill/FillGyroid.cpp
|
||||
Fill/FillGyroid.hpp
|
||||
Fill/FillTpmsD.cpp
|
||||
Fill/FillTpmsD.hpp
|
||||
Fill/FillPlanePath.cpp
|
||||
Fill/FillPlanePath.hpp
|
||||
Fill/FillLine.cpp
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "FillRectilinear.hpp"
|
||||
#include "FillLightning.hpp"
|
||||
#include "FillConcentricInternal.hpp"
|
||||
#include "FillTpmsD.hpp"
|
||||
#include "FillConcentric.hpp"
|
||||
#include "libslic3r.h"
|
||||
|
||||
@@ -1047,6 +1048,7 @@ Polylines Layer::generate_sparse_infill_polylines_for_anchoring(FillAdaptive::Oc
|
||||
case ipHoneycomb:
|
||||
case ip3DHoneycomb:
|
||||
case ipGyroid:
|
||||
case ipTpmsD:
|
||||
case ipHilbertCurve:
|
||||
case ipArchimedeanChords:
|
||||
case ipOctagramSpiral: break;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "FillHoneycomb.hpp"
|
||||
#include "Fill3DHoneycomb.hpp"
|
||||
#include "FillGyroid.hpp"
|
||||
#include "FillTpmsD.hpp"
|
||||
#include "FillPlanePath.hpp"
|
||||
#include "FillLine.hpp"
|
||||
#include "FillRectilinear.hpp"
|
||||
@@ -41,6 +42,7 @@ Fill* Fill::new_from_type(const InfillPattern type)
|
||||
case ipHoneycomb: return new FillHoneycomb();
|
||||
case ip3DHoneycomb: return new Fill3DHoneycomb();
|
||||
case ipGyroid: return new FillGyroid();
|
||||
case ipTpmsD: return new FillTpmsD();//from creality print
|
||||
case ipRectilinear: return new FillRectilinear();
|
||||
case ipAlignedRectilinear: return new FillAlignedRectilinear();
|
||||
case ipCrossHatch: return new FillCrossHatch();
|
||||
|
||||
@@ -0,0 +1,446 @@
|
||||
#include "../ClipperUtils.hpp"
|
||||
#include "FillTpmsD.hpp"
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <tbb/parallel_for.h>
|
||||
// From Creality Print
|
||||
namespace Slic3r {
|
||||
|
||||
using namespace std;
|
||||
struct myPoint
|
||||
{
|
||||
coord_t x, y;
|
||||
};
|
||||
class LineSegmentMerger
|
||||
{
|
||||
public:
|
||||
void mergeSegments(const vector<pair<myPoint, myPoint>>& segments, vector<vector<myPoint>>& polylines2)
|
||||
{
|
||||
std::unordered_map<int, myPoint> point_id_xy;
|
||||
std::set<std::pair<int, int>> segment_ids;
|
||||
std::unordered_map<int64_t, int> map_keyxy_pointid;
|
||||
|
||||
auto get_itr = [&](coord_t x, coord_t y) {
|
||||
for (auto i : {0}) //,-2,2
|
||||
{
|
||||
for (auto j : {0}) //,-2,2
|
||||
{
|
||||
int64_t combined_key1 = static_cast<int64_t>(x + i) << 32 | static_cast<uint32_t>(y + j);
|
||||
auto itr1 = map_keyxy_pointid.find(combined_key1);
|
||||
if (itr1 != map_keyxy_pointid.end()) {
|
||||
return itr1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map_keyxy_pointid.end();
|
||||
};
|
||||
|
||||
int pointid = 0;
|
||||
for (const auto& segment : segments) {
|
||||
coord_t x = segment.first.x;
|
||||
coord_t y = segment.first.y;
|
||||
auto itr = get_itr(x, y);
|
||||
int segmentid0 = -1;
|
||||
if (itr == map_keyxy_pointid.end()) {
|
||||
int64_t combined_key = static_cast<int64_t>(x) << 32 | static_cast<uint32_t>(y);
|
||||
segmentid0 = pointid;
|
||||
point_id_xy[pointid] = segment.first;
|
||||
map_keyxy_pointid[combined_key] = pointid++;
|
||||
} else {
|
||||
segmentid0 = itr->second;
|
||||
}
|
||||
int segmentid1 = -1;
|
||||
x = segment.second.x;
|
||||
y = segment.second.y;
|
||||
itr = get_itr(x, y);
|
||||
if (itr == map_keyxy_pointid.end()) {
|
||||
int64_t combined_key = static_cast<int64_t>(x) << 32 | static_cast<uint32_t>(y);
|
||||
segmentid1 = pointid;
|
||||
point_id_xy[pointid] = segment.second;
|
||||
map_keyxy_pointid[combined_key] = pointid++;
|
||||
} else {
|
||||
segmentid1 = itr->second;
|
||||
}
|
||||
|
||||
if (segmentid0 != segmentid1) {
|
||||
segment_ids.insert(segmentid0 < segmentid1 ? std::make_pair(segmentid0, segmentid1) :
|
||||
std::make_pair(segmentid1, segmentid0));
|
||||
}
|
||||
}
|
||||
|
||||
unordered_map<int, vector<int>> graph;
|
||||
unordered_set<int> visited;
|
||||
vector<vector<int>> polylines;
|
||||
|
||||
// Build the graph
|
||||
for (const auto& segment : segment_ids) {
|
||||
graph[segment.first].push_back(segment.second);
|
||||
graph[segment.second].push_back(segment.first);
|
||||
}
|
||||
|
||||
vector<int> startnodes;
|
||||
for (const auto& node : graph) {
|
||||
if (node.second.size() == 1) {
|
||||
startnodes.push_back(node.first);
|
||||
}
|
||||
}
|
||||
|
||||
// Find all connected components
|
||||
for (const auto& point_first : startnodes) {
|
||||
if (visited.find(point_first) == visited.end()) {
|
||||
vector<int> polyline;
|
||||
dfs(point_first, graph, visited, polyline);
|
||||
polylines.push_back(std::move(polyline));
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& point : graph) {
|
||||
if (visited.find(point.first) == visited.end()) {
|
||||
vector<int> polyline;
|
||||
dfs(point.first, graph, visited, polyline);
|
||||
polylines.push_back(std::move(polyline));
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& pl : polylines) {
|
||||
vector<myPoint> tmpps;
|
||||
for (auto& pid : pl) {
|
||||
tmpps.push_back(point_id_xy[pid]);
|
||||
}
|
||||
polylines2.push_back(tmpps);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void dfs(const int& start_node,
|
||||
std::unordered_map<int, std::vector<int>>& graph,
|
||||
std::unordered_set<int>& visited,
|
||||
std::vector<int>& polyline)
|
||||
{
|
||||
std::vector<int> stack;
|
||||
stack.reserve(graph.size());
|
||||
stack.push_back(start_node);
|
||||
while (!stack.empty()) {
|
||||
int node = stack.back();
|
||||
stack.pop_back();
|
||||
if (!visited.insert(node).second) {
|
||||
continue;
|
||||
}
|
||||
polyline.push_back(node);
|
||||
auto& neighbors = graph[node];
|
||||
for (const auto& neighbor : neighbors) {
|
||||
if (visited.find(neighbor) == visited.end()) {
|
||||
stack.push_back(neighbor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
namespace MarchingSquares {
|
||||
struct Point
|
||||
{
|
||||
double x, y;
|
||||
};
|
||||
|
||||
vector<double> getGridValues(int i, int j, vector<vector<double>>& data)
|
||||
{
|
||||
vector<double> values;
|
||||
values.push_back(data[i][j + 1]);
|
||||
values.push_back(data[i + 1][j + 1]);
|
||||
values.push_back(data[i + 1][j]);
|
||||
values.push_back(data[i][j]);
|
||||
return values;
|
||||
}
|
||||
bool needContour(double value, double contourValue) { return value >= contourValue; }
|
||||
Point interpolate(std::vector<std::vector<MarchingSquares::Point>>& posxy,
|
||||
std::vector<int> p1ij,
|
||||
std::vector<int> p2ij,
|
||||
double v1,
|
||||
double v2,
|
||||
double contourValue)
|
||||
{
|
||||
Point p1;
|
||||
p1.x = posxy[p1ij[0]][p1ij[1]].x;
|
||||
p1.y = posxy[p1ij[0]][p1ij[1]].y;
|
||||
Point p2;
|
||||
p2.x = posxy[p2ij[0]][p2ij[1]].x;
|
||||
p2.y = posxy[p2ij[0]][p2ij[1]].y;
|
||||
|
||||
double mu = (contourValue - v1) / (v2 - v1);
|
||||
Point p;
|
||||
p.x = p1.x + mu * (p2.x - p1.x);
|
||||
p.y = p1.y + mu * (p2.y - p1.y);
|
||||
return p;
|
||||
}
|
||||
|
||||
void process_block(int i,
|
||||
int j,
|
||||
vector<vector<double>>& data,
|
||||
double contourValue,
|
||||
std::vector<std::vector<MarchingSquares::Point>>& posxy,
|
||||
vector<Point>& contourPoints)
|
||||
{
|
||||
vector<double> values = getGridValues(i, j, data);
|
||||
vector<bool> isNeedContour;
|
||||
for (double value : values) {
|
||||
isNeedContour.push_back(needContour(value, contourValue));
|
||||
}
|
||||
int index = 0;
|
||||
if (isNeedContour[0])
|
||||
index |= 1;
|
||||
if (isNeedContour[1])
|
||||
index |= 2;
|
||||
if (isNeedContour[2])
|
||||
index |= 4;
|
||||
if (isNeedContour[3])
|
||||
index |= 8;
|
||||
vector<Point> points;
|
||||
switch (index) {
|
||||
case 0:
|
||||
case 15: break;
|
||||
|
||||
case 1:
|
||||
points.push_back(interpolate(posxy, {i, j + 1}, {i + 1, j + 1}, values[0], values[1], contourValue));
|
||||
points.push_back(interpolate(posxy, {i, j}, {i, j + 1}, values[3], values[0], contourValue));
|
||||
|
||||
break;
|
||||
case 14:
|
||||
points.push_back(interpolate(posxy, {i, j}, {i, j + 1}, values[3], values[0], contourValue));
|
||||
points.push_back(interpolate(posxy, {i, j + 1}, {i + 1, j + 1}, values[0], values[1], contourValue));
|
||||
break;
|
||||
|
||||
case 2:
|
||||
points.push_back(interpolate(posxy, {i + 1, j + 1}, {i + 1, j}, values[1], values[2], contourValue));
|
||||
points.push_back(interpolate(posxy, {i, j + 1}, {i + 1, j + 1}, values[0], values[1], contourValue));
|
||||
|
||||
break;
|
||||
case 13:
|
||||
points.push_back(interpolate(posxy, {i, j + 1}, {i + 1, j + 1}, values[0], values[1], contourValue));
|
||||
points.push_back(interpolate(posxy, {i + 1, j + 1}, {i + 1, j}, values[1], values[2], contourValue));
|
||||
break;
|
||||
case 3:
|
||||
points.push_back(interpolate(posxy, {i + 1, j + 1}, {i + 1, j}, values[1], values[2], contourValue));
|
||||
points.push_back(interpolate(posxy, {i, j}, {i, j + 1}, values[3], values[0], contourValue));
|
||||
|
||||
break;
|
||||
case 12:
|
||||
points.push_back(interpolate(posxy, {i, j}, {i, j + 1}, values[3], values[0], contourValue));
|
||||
points.push_back(interpolate(posxy, {i + 1, j + 1}, {i + 1, j}, values[1], values[2], contourValue));
|
||||
|
||||
break;
|
||||
case 4:
|
||||
points.push_back(interpolate(posxy, {i + 1, j}, {i, j}, values[2], values[3], contourValue));
|
||||
points.push_back(interpolate(posxy, {i + 1, j + 1}, {i + 1, j}, values[1], values[2], contourValue));
|
||||
|
||||
break;
|
||||
case 11:
|
||||
points.push_back(interpolate(posxy, {i + 1, j + 1}, {i + 1, j}, values[1], values[2], contourValue));
|
||||
points.push_back(interpolate(posxy, {i + 1, j}, {i, j}, values[2], values[3], contourValue));
|
||||
break;
|
||||
case 5:
|
||||
points.push_back(interpolate(posxy, {i, j}, {i, j + 1}, values[3], values[0], contourValue));
|
||||
points.push_back(interpolate(posxy, {i, j}, {i + 1, j}, values[3], values[2], contourValue));
|
||||
|
||||
points.push_back(interpolate(posxy, {i, j + 1}, {i + 1, j + 1}, values[0], values[1], contourValue));
|
||||
points.push_back(interpolate(posxy, {i + 1, j + 1}, {i + 1, j}, values[1], values[2], contourValue));
|
||||
break;
|
||||
case 6:
|
||||
points.push_back(interpolate(posxy, {i + 1, j}, {i, j}, values[2], values[3], contourValue));
|
||||
points.push_back(interpolate(posxy, {i, j + 1}, {i + 1, j + 1}, values[0], values[1], contourValue));
|
||||
|
||||
break;
|
||||
case 9:
|
||||
points.push_back(interpolate(posxy, {i, j + 1}, {i + 1, j + 1}, values[0], values[1], contourValue));
|
||||
points.push_back(interpolate(posxy, {i + 1, j}, {i, j}, values[2], values[3], contourValue));
|
||||
break;
|
||||
case 7:
|
||||
points.push_back(interpolate(posxy, {i + 1, j}, {i, j}, values[2], values[3], contourValue));
|
||||
points.push_back(interpolate(posxy, {i, j}, {i, j + 1}, values[3], values[0], contourValue));
|
||||
|
||||
break;
|
||||
case 8:
|
||||
points.push_back(interpolate(posxy, {i, j}, {i, j + 1}, values[3], values[0], contourValue));
|
||||
points.push_back(interpolate(posxy, {i + 1, j}, {i, j}, values[2], values[3], contourValue));
|
||||
break;
|
||||
case 10:
|
||||
points.push_back(interpolate(posxy, {i, j}, {i, j + 1}, values[3], values[0], contourValue));
|
||||
points.push_back(interpolate(posxy, {i, j}, {i + 1, j}, values[3], values[2], contourValue));
|
||||
|
||||
points.push_back(interpolate(posxy, {i, j + 1}, {i + 1, j + 1}, values[0], values[1], contourValue));
|
||||
points.push_back(interpolate(posxy, {i + 1, j + 1}, {i + 1, j}, values[1], values[2], contourValue));
|
||||
break;
|
||||
}
|
||||
for (Point& p : points) {
|
||||
contourPoints.push_back(p);
|
||||
}
|
||||
}
|
||||
|
||||
void drawContour(double contourValue,
|
||||
int gridSize_w,
|
||||
int gridSize_h,
|
||||
vector<vector<double>>& data,
|
||||
std::vector<std::vector<MarchingSquares::Point>>& posxy,
|
||||
Polylines& repls)
|
||||
{
|
||||
vector<Point> contourPoints;
|
||||
int total_size = (gridSize_h - 1) * (gridSize_w - 1);
|
||||
vector<vector<Point>> contourPointss;
|
||||
contourPointss.resize(total_size);
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, total_size),
|
||||
[&contourValue, &posxy, &contourPointss, &data, &gridSize_w](const tbb::blocked_range<size_t>& range) {
|
||||
for (size_t k = range.begin(); k < range.end(); ++k) {
|
||||
int i = k / (gridSize_w - 1); //
|
||||
int j = k % (gridSize_w - 1); //
|
||||
process_block(i, j, data, contourValue, posxy, contourPointss[k]);
|
||||
}
|
||||
});
|
||||
|
||||
vector<pair<myPoint, myPoint>> segments2;
|
||||
myPoint p1, p2;
|
||||
for (int k = 0; k < total_size; k++) {
|
||||
for (int i = 0; i < contourPointss[k].size() / 2; i++) {
|
||||
p1.x = scale_(contourPointss[k][i * 2].x);
|
||||
p1.y = scale_(contourPointss[k][i * 2].y);
|
||||
p2.x = scale_(contourPointss[k][i * 2 + 1].x);
|
||||
p2.y = scale_(contourPointss[k][i * 2 + 1].y);
|
||||
segments2.push_back({p1, p2});
|
||||
}
|
||||
}
|
||||
|
||||
LineSegmentMerger merger;
|
||||
vector<vector<myPoint>> result;
|
||||
merger.mergeSegments(segments2, result);
|
||||
|
||||
for (vector<myPoint>& p : result) {
|
||||
Polyline repltmp;
|
||||
for (myPoint& pt : p) {
|
||||
repltmp.points.push_back(Slic3r::Point(pt.x, pt.y));
|
||||
}
|
||||
repltmp.simplify(scale_(0.05f));
|
||||
repls.push_back(repltmp);
|
||||
}
|
||||
}
|
||||
} // namespace MarchingSquares
|
||||
|
||||
static float sin_table[360];
|
||||
static float cos_table[360];
|
||||
static bool g_is_init = false;
|
||||
|
||||
#define PIratio 57.29577951308232 // 180/PI
|
||||
static void initialize_lookup_tables()
|
||||
{
|
||||
for (int i = 0; i < 360; ++i) {
|
||||
float angle = i * (M_PI / 180.0);
|
||||
sin_table[i] = std::sin(angle);
|
||||
cos_table[i] = std::cos(angle);
|
||||
}
|
||||
}
|
||||
|
||||
static float get_sin(float angle)
|
||||
{
|
||||
angle = angle * PIratio;
|
||||
int index = static_cast<int>(std::fmod(angle, 360) + 360) % 360;
|
||||
return sin_table[index];
|
||||
}
|
||||
|
||||
static float get_cos(float angle)
|
||||
{
|
||||
angle = angle * PIratio;
|
||||
int index = static_cast<int>(std::fmod(angle, 360) + 360) % 360;
|
||||
return cos_table[index];
|
||||
}
|
||||
|
||||
FillTpmsD::FillTpmsD()
|
||||
{
|
||||
if (!g_is_init) {
|
||||
initialize_lookup_tables();
|
||||
g_is_init = true;
|
||||
}
|
||||
}
|
||||
void FillTpmsD::_fill_surface_single(const FillParams& params,
|
||||
unsigned int thickness_layers,
|
||||
const std::pair<float, Point>& direction,
|
||||
ExPolygon expolygon,
|
||||
Polylines& polylines_out)
|
||||
{
|
||||
auto infill_angle = float(this->angle - (CorrectionAngle * 2 * M_PI) / 360.);
|
||||
if (std::abs(infill_angle) >= EPSILON)
|
||||
expolygon.rotate(-infill_angle);
|
||||
|
||||
float vari_T = 2.98 * spacing / params.density; // Infill density adjustment factor for TPMS-D
|
||||
|
||||
BoundingBox bb = expolygon.contour.bounding_box();
|
||||
auto cenpos = unscale(bb.center());
|
||||
auto boxsize = unscale(bb.size());
|
||||
float xlen = boxsize.x();
|
||||
float ylen = boxsize.y();
|
||||
|
||||
float delta = 0.25f;
|
||||
float myperiod = 2 * PI / vari_T;
|
||||
float c_z = myperiod * this->z;
|
||||
float cos_z = get_cos(c_z);
|
||||
float sin_z = get_sin(c_z);
|
||||
|
||||
auto scalar_field = [&](float x, float y) {
|
||||
// TPMS-D
|
||||
float a_x = myperiod * x;
|
||||
float b_y = myperiod * y;
|
||||
float r = get_cos(a_x) * get_cos(b_y) * cos_z - get_sin(a_x) * get_sin(b_y) * sin_z;
|
||||
return r;
|
||||
};
|
||||
|
||||
std::vector<std::vector<MarchingSquares::Point>> posxy;
|
||||
int i = 0, j = 0;
|
||||
std::vector<MarchingSquares::Point> allptpos;
|
||||
for (float y = -(ylen) / 2.0f - 2; y < (ylen) / 2.0f + 2; y = y + delta, i++) {
|
||||
j = 0;
|
||||
std::vector<MarchingSquares::Point> colposxy;
|
||||
for (float x = -(xlen) / 2.0f - 2; x < (xlen) / 2.0f + 2; x = x + delta, j++) {
|
||||
MarchingSquares::Point pt;
|
||||
pt.x = cenpos.x() + x;
|
||||
pt.y = cenpos.y() + y;
|
||||
colposxy.push_back(pt);
|
||||
}
|
||||
posxy.push_back(colposxy);
|
||||
}
|
||||
|
||||
std::vector<std::vector<double>> data(posxy.size(), std::vector<double>(posxy[0].size()));
|
||||
|
||||
int width = posxy[0].size();
|
||||
int height = posxy.size();
|
||||
int total_size = (height) * (width);
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, total_size),
|
||||
[&width, &scalar_field, &data, &posxy](const tbb::blocked_range<size_t>& range) {
|
||||
for (size_t k = range.begin(); k < range.end(); ++k) {
|
||||
int i = k / (width);
|
||||
int j = k % (width);
|
||||
data[i][j] = scalar_field(posxy[i][j].x, posxy[i][j].y);
|
||||
}
|
||||
});
|
||||
|
||||
Polylines polylines;
|
||||
MarchingSquares::drawContour(0, j, i, data, posxy, polylines);
|
||||
|
||||
polylines = intersection_pl(polylines, expolygon);
|
||||
|
||||
if (!polylines.empty()) {
|
||||
// connect lines
|
||||
size_t polylines_out_first_idx = polylines_out.size();
|
||||
if (params.dont_connect())
|
||||
append(polylines_out, chain_polylines(polylines));
|
||||
else
|
||||
this->connect_infill(std::move(polylines), expolygon, polylines_out, this->spacing, params);
|
||||
// new paths must be rotated back
|
||||
if (std::abs(infill_angle) >= EPSILON) {
|
||||
for (auto it = polylines_out.begin() + polylines_out_first_idx; it != polylines_out.end(); ++it)
|
||||
it->rotate(infill_angle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifndef slic3r_FillTpmsD_hpp_
|
||||
#define slic3r_FillTpmsD_hpp_
|
||||
|
||||
#include "../libslic3r.h"
|
||||
#include "FillBase.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class FillTpmsD : public Fill
|
||||
{
|
||||
public:
|
||||
FillTpmsD();
|
||||
Fill* clone() const override { return new FillTpmsD(*this); }
|
||||
|
||||
// require bridge flow since most of this pattern hangs in air
|
||||
bool use_bridge_flow() const override { return false; }
|
||||
|
||||
// Correction applied to regular infill angle to maximize printing
|
||||
// speed in default configuration (degrees)
|
||||
static constexpr float CorrectionAngle = -45.;
|
||||
|
||||
void _fill_surface_single(const FillParams& params,
|
||||
unsigned int thickness_layers,
|
||||
const std::pair<float, Point>& direction,
|
||||
ExPolygon expolygon,
|
||||
Polylines& polylines_out) override;
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // slic3r_FillTpmsD_hpp_
|
||||
+54
-13
@@ -5177,6 +5177,25 @@ double GCode::get_overhang_degree_corr_speed(float normal_speed, double path_deg
|
||||
return speed_out;
|
||||
}
|
||||
|
||||
bool GCode::_needSAFC(const ExtrusionPath &path)
|
||||
{
|
||||
if (!m_small_area_infill_flow_compensator || !m_config.small_area_infill_flow_compensation.value)
|
||||
return false;
|
||||
|
||||
static const InfillPattern supported_patterns[] = {
|
||||
InfillPattern::ipRectilinear,
|
||||
InfillPattern::ipAlignedRectilinear,
|
||||
InfillPattern::ipMonotonic,
|
||||
InfillPattern::ipMonotonicLine,
|
||||
};
|
||||
|
||||
return std::any_of(std::begin(supported_patterns), std::end(supported_patterns), [&](const InfillPattern pattern) {
|
||||
return this->on_first_layer() && this->config().bottom_surface_pattern == pattern ||
|
||||
path.role() == erSolidInfill && this->config().internal_solid_infill_pattern == pattern ||
|
||||
path.role() == erTopSolidInfill && this->config().top_surface_pattern == pattern;
|
||||
});
|
||||
}
|
||||
|
||||
std::string GCode::_extrude(const ExtrusionPath &path, std::string description, double speed)
|
||||
{
|
||||
std::string gcode;
|
||||
@@ -5385,12 +5404,37 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||
//}
|
||||
if (EXTRUDER_CONFIG(filament_max_volumetric_speed) > 0) {
|
||||
// cap speed with max_volumetric_speed anyway (even if user is not using autospeed)
|
||||
speed = std::min(
|
||||
speed,
|
||||
EXTRUDER_CONFIG(filament_max_volumetric_speed) / _mm3_per_mm
|
||||
);
|
||||
speed = std::min(speed, EXTRUDER_CONFIG(filament_max_volumetric_speed) / _mm3_per_mm);
|
||||
}
|
||||
// ORCA: resonance‑avoidance on short external perimeters
|
||||
{
|
||||
double ref_speed = speed; // stash the pre‑cap speed
|
||||
if (path.role() == erExternalPerimeter
|
||||
&& m_config.resonance_avoidance.value) {
|
||||
|
||||
// if our original speed was above “max”, disable RA for this loop
|
||||
if (ref_speed > m_config.max_resonance_avoidance_speed.value) {
|
||||
m_resonance_avoidance = false;
|
||||
}
|
||||
|
||||
// re‑apply volumetric cap
|
||||
if (EXTRUDER_CONFIG(filament_max_volumetric_speed) > 0) {
|
||||
speed = std::min(
|
||||
speed,
|
||||
EXTRUDER_CONFIG(filament_max_volumetric_speed) / _mm3_per_mm
|
||||
);
|
||||
}
|
||||
|
||||
// if still in avoidance mode and under “max”, clamp to “min”
|
||||
if (m_resonance_avoidance
|
||||
&& speed <= m_config.max_resonance_avoidance_speed.value) {
|
||||
speed = std::min(speed, m_config.min_resonance_avoidance_speed.value);
|
||||
}
|
||||
|
||||
// reset flag for next segment
|
||||
m_resonance_avoidance = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool variable_speed = false;
|
||||
std::vector<ProcessedPoint> new_points {};
|
||||
@@ -5731,8 +5775,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||
continue;
|
||||
path_length += line_length;
|
||||
auto dE = e_per_mm * line_length;
|
||||
if (!this->on_first_layer() && m_small_area_infill_flow_compensator
|
||||
&& m_config.small_area_infill_flow_compensation.value) {
|
||||
if (_needSAFC(path)) {
|
||||
auto oldE = dE;
|
||||
dE = m_small_area_infill_flow_compensator->modify_flow(line_length, dE, path.role());
|
||||
|
||||
@@ -5773,8 +5816,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||
if (line_length < EPSILON)
|
||||
continue;
|
||||
auto dE = e_per_mm * line_length;
|
||||
if (!this->on_first_layer() && m_small_area_infill_flow_compensator
|
||||
&& m_config.small_area_infill_flow_compensation.value) {
|
||||
if (_needSAFC(path)) {
|
||||
auto oldE = dE;
|
||||
dE = m_small_area_infill_flow_compensator->modify_flow(line_length, dE, path.role());
|
||||
|
||||
@@ -5797,8 +5839,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||
continue;
|
||||
const Vec2d center_offset = this->point_to_gcode(arc.center) - this->point_to_gcode(arc.start_point);
|
||||
auto dE = e_per_mm * arc_length;
|
||||
if (!this->on_first_layer() && m_small_area_infill_flow_compensator
|
||||
&& m_config.small_area_infill_flow_compensation.value) {
|
||||
if (_needSAFC(path)) {
|
||||
auto oldE = dE;
|
||||
dE = m_small_area_infill_flow_compensator->modify_flow(arc_length, dE, path.role());
|
||||
|
||||
@@ -5952,8 +5993,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||
last_set_speed = F;
|
||||
}
|
||||
auto dE = e_per_mm * line_length;
|
||||
if (!this->on_first_layer() && m_small_area_infill_flow_compensator
|
||||
&& m_config.small_area_infill_flow_compensation.value) {
|
||||
if (_needSAFC(path)) {
|
||||
auto oldE = dE;
|
||||
dE = m_small_area_infill_flow_compensator->modify_flow(line_length, dE, path.role());
|
||||
|
||||
@@ -6334,7 +6374,8 @@ std::string GCode::retract(bool toolchange, bool is_last_retraction, LiftType li
|
||||
(the extruder might be already retracted fully or partially). We call these
|
||||
methods even if we performed wipe, since this will ensure the entire retraction
|
||||
length is honored in case wipe path was too short. */
|
||||
if (role != erTopSolidInfill || EXTRUDER_CONFIG(retract_on_top_layer))
|
||||
if ((!this->on_first_layer() || this->config().bottom_surface_pattern != InfillPattern::ipHilbertCurve) &&
|
||||
(role != erTopSolidInfill || this->config().top_surface_pattern != InfillPattern::ipHilbertCurve))
|
||||
gcode += toolchange ? m_writer.retract_for_toolchange() : m_writer.retract();
|
||||
|
||||
gcode += m_writer.reset_e();
|
||||
|
||||
@@ -165,6 +165,7 @@ public:
|
||||
GCode() :
|
||||
m_origin(Vec2d::Zero()),
|
||||
m_enable_loop_clipping(true),
|
||||
m_resonance_avoidance(true),
|
||||
m_enable_cooling_markers(false),
|
||||
m_enable_extrusion_role_markers(false),
|
||||
m_last_processor_extrusion_role(erNone),
|
||||
@@ -506,6 +507,8 @@ private:
|
||||
AvoidCrossingPerimeters m_avoid_crossing_perimeters;
|
||||
RetractWhenCrossingPerimeters m_retract_when_crossing_perimeters;
|
||||
bool m_enable_loop_clipping;
|
||||
//resonance avoidance
|
||||
bool m_resonance_avoidance;
|
||||
// If enabled, the G-code generator will put following comments at the ends
|
||||
// of the G-code lines: _EXTRUDE_SET_SPEED, _WIPE, _OVERHANG_FAN_START, _OVERHANG_FAN_END
|
||||
// Those comments are received and consumed (removed from the G-code) by the CoolingBuffer.pm Perl module.
|
||||
@@ -602,6 +605,7 @@ private:
|
||||
int get_bed_temperature(const int extruder_id, const bool is_first_layer, const BedType bed_type) const;
|
||||
|
||||
std::string _extrude(const ExtrusionPath &path, std::string description = "", double speed = -1);
|
||||
bool _needSAFC(const ExtrusionPath &path);
|
||||
double get_overhang_degree_corr_speed(float speed, double path_degree);
|
||||
void print_machine_envelope(GCodeOutputStream &file, Print &print);
|
||||
void _print_first_layer_bed_temperature(GCodeOutputStream &file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait);
|
||||
|
||||
@@ -383,6 +383,7 @@ coordf_t Layer::get_sparse_infill_max_void_area()
|
||||
case ipRectilinear:
|
||||
case ipLine:
|
||||
case ipGyroid:
|
||||
case ipTpmsD:
|
||||
case ipAlignedRectilinear:
|
||||
case ipOctagramSpiral:
|
||||
case ipHilbertCurve:
|
||||
|
||||
@@ -837,7 +837,7 @@ static std::vector<std::string> s_Preset_print_options {
|
||||
"hole_to_polyhole", "hole_to_polyhole_threshold", "hole_to_polyhole_twisted", "mmu_segmented_region_max_width", "mmu_segmented_region_interlocking_depth",
|
||||
"small_area_infill_flow_compensation", "small_area_infill_flow_compensation_model",
|
||||
"seam_slope_type", "seam_slope_conditional", "scarf_angle_threshold", "scarf_joint_speed", "scarf_joint_flow_ratio", "seam_slope_start_height", "seam_slope_entire_loop", "seam_slope_min_length", "seam_slope_steps", "seam_slope_inner_walls", "scarf_overhang_threshold",
|
||||
"interlocking_beam", "interlocking_orientation", "interlocking_beam_layer_count", "interlocking_depth", "interlocking_boundary_avoidance", "interlocking_beam_width","calib_flowrate_topinfill_special_order"
|
||||
"interlocking_beam", "interlocking_orientation", "interlocking_beam_layer_count", "interlocking_depth", "interlocking_boundary_avoidance", "interlocking_beam_width","calib_flowrate_topinfill_special_order",
|
||||
};
|
||||
|
||||
static std::vector<std::string> s_Preset_filament_options {
|
||||
@@ -878,6 +878,8 @@ static std::vector<std::string> s_Preset_machine_limits_options {
|
||||
"machine_min_extruding_rate", "machine_min_travel_rate",
|
||||
"machine_max_jerk_x", "machine_max_jerk_y", "machine_max_jerk_z", "machine_max_jerk_e",
|
||||
"machine_max_junction_deviation",
|
||||
//resonance avoidance ported from qidi slicer
|
||||
"resonance_avoidance", "min_resonance_avoidance_speed", "max_resonance_avoidance_speed",
|
||||
};
|
||||
|
||||
static std::vector<std::string> s_Preset_printer_options {
|
||||
|
||||
@@ -150,7 +150,6 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
||||
"retraction_minimum_travel",
|
||||
"retract_before_wipe",
|
||||
"retract_when_changing_layer",
|
||||
"retract_on_top_layer",
|
||||
"retraction_length",
|
||||
"retract_length_toolchange",
|
||||
"z_hop",
|
||||
@@ -1039,7 +1038,7 @@ StringObjectException Print::check_multi_filament_valid(const Print& print)
|
||||
filament_types.push_back(print_config.filament_type.get_at(extruder_idx));
|
||||
|
||||
if (!check_multi_filaments_compatibility(filament_types))
|
||||
return { L("Cannot print multiple filaments which have large difference of temperature together. Otherwise, the extruder and nozzle may be blocked or damaged during printing") };
|
||||
return {L("Cannot print multiple filaments which have large difference of temperature together. Otherwise, the extruder and nozzle may be blocked or damaged during printing.")};
|
||||
|
||||
return {std::string()};
|
||||
}
|
||||
@@ -1209,7 +1208,7 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
|
||||
|
||||
double gap_layers = slicing_params.gap_object_support / slicing_params.layer_height;
|
||||
if (gap_layers - (int)gap_layers > EPSILON) {
|
||||
return { L("The prime tower requires \"support gap\" to be multiple of layer height"), object };
|
||||
return {L("The prime tower requires \"support gap\" to be multiple of layer height."), object};
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1222,14 +1221,14 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
|
||||
const SlicingParameters &slicing_params = object->slicing_parameters();
|
||||
if (std::abs(slicing_params.first_print_layer_height - slicing_params0.first_print_layer_height) > EPSILON ||
|
||||
std::abs(slicing_params.layer_height - slicing_params0.layer_height ) > EPSILON)
|
||||
return {L("The prime tower requires that all objects have the same layer heights"), object, "initial_layer_print_height"};
|
||||
return {L("The prime tower requires that all objects have the same layer heights."), object, "initial_layer_print_height"};
|
||||
if (slicing_params.raft_layers() != slicing_params0.raft_layers())
|
||||
return {L("The prime tower requires that all objects are printed over the same number of raft layers"), object, "raft_layers"};
|
||||
return {L("The prime tower requires that all objects are printed over the same number of raft layers."), object, "raft_layers"};
|
||||
// BBS: support gap can be multiple of object layer height, remove _L()
|
||||
#if 0
|
||||
if (slicing_params0.gap_object_support != slicing_params.gap_object_support ||
|
||||
slicing_params0.gap_support_object != slicing_params.gap_support_object)
|
||||
return {L("The prime tower is only supported for multiple objects if they are printed with the same support_top_z_distance"), object};
|
||||
return {L("The prime tower is only supported for multiple objects if they are printed with the same support_top_z_distance."), object};
|
||||
#endif
|
||||
if (!equal_layering(slicing_params, slicing_params0))
|
||||
return { L("The prime tower requires that all objects are sliced with the same layer heights."), object };
|
||||
@@ -1264,7 +1263,7 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
|
||||
//if (i % 2 == 0 && layer_height_profiles[tallest_object_idx][i] > layer_height_profiles[idx_object][layer_height_profiles[idx_object].size() - 2])
|
||||
// break;
|
||||
if (std::abs(layer_height_profiles[idx_object][i] - layer_height_profiles[tallest_object_idx][i]) > eps)
|
||||
return {L("The prime tower is only supported if all objects have the same variable layer height")};
|
||||
return {L("The prime tower is only supported if all objects have the same variable layer height.")};
|
||||
++i;
|
||||
}
|
||||
}
|
||||
@@ -1373,12 +1372,12 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
|
||||
first_layer_min_nozzle_diameter = min_nozzle_diameter;
|
||||
}
|
||||
if (initial_layer_print_height > first_layer_min_nozzle_diameter)
|
||||
return {L("Layer height cannot exceed nozzle diameter"), object, "initial_layer_print_height"};
|
||||
return {L("Layer height cannot exceed nozzle diameter."), object, "initial_layer_print_height"};
|
||||
|
||||
// validate layer_height
|
||||
double layer_height = object->config().layer_height.value;
|
||||
if (layer_height > min_nozzle_diameter)
|
||||
return {L("Layer height cannot exceed nozzle diameter"), object, "layer_height"};
|
||||
return {L("Layer height cannot exceed nozzle diameter."), object, "layer_height"};
|
||||
|
||||
// Validate extrusion widths.
|
||||
std::string err_msg;
|
||||
|
||||
+271
-240
File diff suppressed because it is too large
Load Diff
@@ -58,7 +58,7 @@ enum AuthorizationType {
|
||||
};
|
||||
|
||||
enum InfillPattern : int {
|
||||
ipConcentric, ipRectilinear, ipGrid, ip2DLattice, ipLine, ipCubic, ipTriangles, ipStars, ipGyroid, ipHoneycomb, ipAdaptiveCubic, ipMonotonic, ipMonotonicLine, ipAlignedRectilinear, ip3DHoneycomb,
|
||||
ipConcentric, ipRectilinear, ipGrid, ip2DLattice, ipLine, ipCubic, ipTriangles, ipStars, ipGyroid, ipTpmsD, ipHoneycomb, ipAdaptiveCubic, ipMonotonic, ipMonotonicLine, ipAlignedRectilinear, ip3DHoneycomb,
|
||||
ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral, ipSupportCubic, ipSupportBase, ipConcentricInternal,
|
||||
ipLightning, ipCrossHatch, ipQuarterCubic,
|
||||
ipCount,
|
||||
@@ -1062,8 +1062,6 @@ PRINT_CONFIG_CLASS_DEFINE(
|
||||
((ConfigOptionFloatOrPercent, scarf_joint_speed))
|
||||
((ConfigOptionFloat, scarf_joint_flow_ratio))
|
||||
((ConfigOptionPercent, scarf_overhang_threshold))
|
||||
|
||||
|
||||
)
|
||||
|
||||
PRINT_CONFIG_CLASS_DEFINE(
|
||||
@@ -1098,6 +1096,11 @@ PRINT_CONFIG_CLASS_DEFINE(
|
||||
((ConfigOptionFloats, machine_min_travel_rate))
|
||||
// M205 S... [mm/sec]
|
||||
((ConfigOptionFloats, machine_min_extruding_rate))
|
||||
|
||||
//resonance avoidance ported from qidi slicer
|
||||
((ConfigOptionBool, resonance_avoidance))
|
||||
((ConfigOptionFloat, min_resonance_avoidance_speed))
|
||||
((ConfigOptionFloat, max_resonance_avoidance_speed))
|
||||
)
|
||||
|
||||
// This object is mapped to Perl as Slic3r::Config::GCode.
|
||||
@@ -1308,7 +1311,6 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
|
||||
((ConfigOptionFloat, resolution))
|
||||
((ConfigOptionFloats, retraction_minimum_travel))
|
||||
((ConfigOptionBools, retract_when_changing_layer))
|
||||
((ConfigOptionBools, retract_on_top_layer))
|
||||
((ConfigOptionFloat, skirt_distance))
|
||||
((ConfigOptionInt, skirt_height))
|
||||
((ConfigOptionInt, skirt_loops))
|
||||
|
||||
@@ -750,7 +750,7 @@ void PressureAdvanceWizard::on_cali_save()
|
||||
CalibUtils::set_PA_calib_result({ new_pa_cali_result }, false);
|
||||
}
|
||||
|
||||
MessageDialog msg_dlg(nullptr, _L("Flow Dynamics Calibration result has been saved to the printer"), wxEmptyString, wxOK);
|
||||
MessageDialog msg_dlg(nullptr, _L("Flow Dynamics Calibration result has been saved to the printer."), wxEmptyString, wxOK);
|
||||
msg_dlg.ShowModal();
|
||||
}
|
||||
else if (curr_obj->get_printer_series() == PrinterSeries::SERIES_P1P) {
|
||||
@@ -817,7 +817,7 @@ void PressureAdvanceWizard::on_cali_save()
|
||||
|
||||
}
|
||||
|
||||
MessageDialog msg_dlg(nullptr, _L("Flow Dynamics Calibration result has been saved to the printer"), wxEmptyString, wxOK);
|
||||
MessageDialog msg_dlg(nullptr, _L("Flow Dynamics Calibration result has been saved to the printer."), wxEmptyString, wxOK);
|
||||
msg_dlg.ShowModal();
|
||||
}
|
||||
else {
|
||||
@@ -1170,7 +1170,7 @@ void FlowRateWizard::on_cali_save()
|
||||
}
|
||||
}
|
||||
|
||||
MessageDialog msg_dlg(nullptr, _L("Flow rate calibration result has been saved to preset"), wxEmptyString, wxOK);
|
||||
MessageDialog msg_dlg(nullptr, _L("Flow rate calibration result has been saved to preset."), wxEmptyString, wxOK);
|
||||
msg_dlg.ShowModal();
|
||||
}
|
||||
else if (m_cali_method == CalibrationMethod::CALI_METHOD_MANUAL) {
|
||||
@@ -1216,7 +1216,7 @@ void FlowRateWizard::on_cali_save()
|
||||
return;
|
||||
}
|
||||
|
||||
MessageDialog msg_dlg(nullptr, _L("Flow rate calibration result has been saved to preset"), wxEmptyString, wxOK);
|
||||
MessageDialog msg_dlg(nullptr, _L("Flow rate calibration result has been saved to preset."), wxEmptyString, wxOK);
|
||||
msg_dlg.ShowModal();
|
||||
}
|
||||
else {
|
||||
@@ -1499,7 +1499,7 @@ void MaxVolumetricSpeedWizard::on_cali_save()
|
||||
return;
|
||||
}
|
||||
|
||||
MessageDialog msg_dlg(nullptr, _L("Max volumetric speed calibration result has been saved to preset"), wxEmptyString, wxOK);
|
||||
MessageDialog msg_dlg(nullptr, _L("Max volumetric speed calibration result has been saved to preset."), wxEmptyString, wxOK);
|
||||
msg_dlg.ShowModal();
|
||||
show_step(start_step);
|
||||
}
|
||||
|
||||
@@ -1567,7 +1567,7 @@ void CalibrationFlowCoarseSavePage::set_curr_flow_ratio(const float value) {
|
||||
bool CalibrationFlowCoarseSavePage::get_result(float* out_value, wxString* out_name) {
|
||||
// Check if the value is valid
|
||||
if (m_optimal_block_coarse->GetSelection() == -1 || m_coarse_flow_ratio <= 0.0 || m_coarse_flow_ratio >= 2.0) {
|
||||
MessageDialog msg_dlg(nullptr, _L("Please choose a block with smoothest top surface"), wxEmptyString, wxICON_WARNING | wxOK);
|
||||
MessageDialog msg_dlg(nullptr, _L("Please choose a block with smoothest top surface."), wxEmptyString, wxICON_WARNING | wxOK);
|
||||
msg_dlg.ShowModal();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -216,11 +216,11 @@ void CalibrationFlowRateStartPage::create_page(wxWindow* parent)
|
||||
m_top_sizer->Add(m_page_caption, 0, wxEXPAND, 0);
|
||||
create_when(parent,
|
||||
_L("When to use Flow Rate Calibration"),
|
||||
_L("After using Flow Dynamics Calibration, there might still be some extrusion issues, such as:\
|
||||
\n1. Over-Extrusion: Excess material on your printed object, forming blobs or zits, or the layers seem thicker than expected and not uniform.\
|
||||
\n2. Under-Extrusion: Very thin layers, weak infill strength, or gaps in the top layer of the model, even when printing slowly.\
|
||||
\n3. Poor Surface Quality: The surface of your prints seems rough or uneven.\
|
||||
\n4. Weak Structural Integrity: Prints break easily or don't seem as sturdy as they should be."));
|
||||
_L("After using Flow Dynamics Calibration, there might still be some extrusion issues, such as:\n"
|
||||
"1. Over-Extrusion: Excess material on your printed object, forming blobs or zits, or the layers seem thicker than expected and not uniform\n"
|
||||
"2. Under-Extrusion: Very thin layers, weak infill strength, or gaps in the top layer of the model, even when printing slowly\n"
|
||||
"3. Poor Surface Quality: The surface of your prints seems rough or uneven\n"
|
||||
"4. Weak Structural Integrity: Prints break easily or don't seem as sturdy as they should be"));
|
||||
|
||||
m_top_sizer->Add(m_when_title);
|
||||
m_top_sizer->Add(m_when_content);
|
||||
|
||||
@@ -38,27 +38,28 @@
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
static const std::vector<std::string> filament_vendors =
|
||||
static const std::vector<std::string> filament_vendors =
|
||||
{"3Dgenius", "3DJake", "3DXTECH", "3D BEST-Q", "3D Hero",
|
||||
"3D-Fuel", "Aceaddity", "AddNorth", "Amazon Basics", "AMOLEN",
|
||||
"Ankermake", "Anycubic", "Atomic", "AzureFilm", "BASF",
|
||||
"Bblife", "BCN3D", "Beyond Plastic", "California Filament", "Capricorn",
|
||||
"CC3D", "colorFabb", "Comgrow", "Cookiecad", "Creality",
|
||||
"CERPRiSE", "Das Filament", "DO3D", "DOW", "DSM",
|
||||
"Duramic", "ELEGOO", "Eryone", "Essentium", "eSUN",
|
||||
"Extrudr", "Fiberforce", "Fiberlogy", "FilaCube", "Filamentive",
|
||||
"Fillamentum", "FLASHFORGE", "Formfutura", "Francofil", "FusRock",
|
||||
"FilamentOne", "Fil X", "GEEETECH", "Giantarm", "Gizmo Dorks",
|
||||
"GreenGate3D", "HATCHBOX", "Hello3D", "IC3D", "IEMAI",
|
||||
"IIID Max", "INLAND", "iProspect", "iSANMATE", "Justmaker",
|
||||
"Keene Village Plastics", "Kexcelled", "LDO", "MakerBot", "MatterHackers",
|
||||
"MIKA3D", "NinjaTek", "Nobufil", "Novamaker", "OVERTURE",
|
||||
"OVVNYXE", "Polymaker", "Priline", "Printed Solid", "Protopasta",
|
||||
"Prusament", "Push Plastic", "R3D", "Re-pet3D", "Recreus",
|
||||
"Regen", "RatRig", "Sain SMART", "SliceWorx", "Snapmaker",
|
||||
"SnoLabs", "Spectrum", "SUNLU", "TTYT3D", "Tianse",
|
||||
"UltiMaker", "Valment", "Verbatim", "VO3D", "Voxelab",
|
||||
"VOXELPLA", "YOOPAI", "Yousu", "Ziro", "Zyltech"};
|
||||
"CERPRiSE", "Das Filament", "DO3D", "DOW", "DREMC",
|
||||
"DSM", "Duramic", "ELEGOO", "Eryone", "Essentium",
|
||||
"eSUN", "Extrudr", "Fiberforce", "Fiberlogy", "FilaCube",
|
||||
"Filamentive", "Fillamentum", "FLASHFORGE", "Formfutura", "Francofil",
|
||||
"FusRock", "FilamentOne", "Fil X", "GEEETECH", "Giantarm",
|
||||
"Gizmo Dorks", "GreenGate3D", "HATCHBOX", "Hello3D", "IC3D",
|
||||
"IEMAI", "IIID Max", "INLAND", "iProspect", "iSANMATE",
|
||||
"Justmaker", "Keene Village Plastics", "Kexcelled", "LDO", "MakerBot",
|
||||
"MatterHackers", "MIKA3D", "NinjaTek", "Nobufil", "Novamaker",
|
||||
"OVERTURE", "OVVNYXE", "Polymaker", "Priline", "Printed Solid",
|
||||
"Protopasta", "Prusament", "Push Plastic", "R3D", "Re-pet3D",
|
||||
"Recreus", "Regen", "RatRig", "Sain SMART", "SliceWorx",
|
||||
"Snapmaker", "SnoLabs", "Spectrum", "SUNLU", "TTYT3D",
|
||||
"Tianse", "UltiMaker", "Valment", "Verbatim", "VO3D",
|
||||
"Voxelab", "VOXELPLA", "YOOPAI", "Yousu", "Ziro",
|
||||
"Zyltech"};
|
||||
|
||||
static const std::vector<std::string> filament_types = {"PLA", "rPLA", "PLA+", "PLA Tough", "PETG", "ABS", "ASA", "FLEX", "HIPS", "PA", "PACF",
|
||||
"NYLON", "PVA", "PVB", "PC", "PCABS", "PCTG", "PCCF", "PHA", "PP", "PEI", "PET",
|
||||
|
||||
@@ -4154,7 +4154,7 @@ void GUI_App::on_http_error(wxCommandEvent &evt)
|
||||
|
||||
// Version limit
|
||||
if (code == HttpErrorVersionLimited) {
|
||||
MessageDialog msg_dlg(nullptr, _L("The version of Orca Slicer is too low and needs to be updated to the latest version before it can be used normally"), "", wxAPPLY | wxOK);
|
||||
MessageDialog msg_dlg(nullptr, _L("The version of Orca Slicer is too low and needs to be updated to the latest version before it can be used normally."), "", wxAPPLY | wxOK);
|
||||
if (msg_dlg.ShowModal() == wxOK) {
|
||||
}
|
||||
|
||||
|
||||
@@ -2631,15 +2631,15 @@ void MainFrame::init_menubar_as_editor()
|
||||
"", nullptr, [this](){return can_deselect(); }, this);
|
||||
//editMenu->AppendSeparator();
|
||||
//append_menu_check_item(editMenu, wxID_ANY, _L("Show Model Mesh(TODO)"),
|
||||
// _L("Display triangles of models"), [this](wxCommandEvent& evt) {
|
||||
// _L("Display triangles of models."), [this](wxCommandEvent& evt) {
|
||||
// wxGetApp().app_config->set_bool("show_model_mesh", evt.GetInt() == 1);
|
||||
// }, nullptr, [this]() {return can_select(); }, [this]() { return wxGetApp().app_config->get("show_model_mesh").compare("true") == 0; }, this);
|
||||
//append_menu_check_item(editMenu, wxID_ANY, _L("Show Model Shadow(TODO)"), _L("Display shadow of objects"),
|
||||
//append_menu_check_item(editMenu, wxID_ANY, _L("Show Model Shadow(TODO)"), _L("Display shadow of objects."),
|
||||
// [this](wxCommandEvent& evt) {
|
||||
// wxGetApp().app_config->set_bool("show_model_shadow", evt.GetInt() == 1);
|
||||
// }, nullptr, [this]() {return can_select(); }, [this]() { return wxGetApp().app_config->get("show_model_shadow").compare("true") == 0; }, this);
|
||||
//editMenu->AppendSeparator();
|
||||
//append_menu_check_item(editMenu, wxID_ANY, _L("Show Printable Box(TODO)"), _L("Display printable box"),
|
||||
//append_menu_check_item(editMenu, wxID_ANY, _L("Show Printable Box(TODO)"), _L("Display printable box."),
|
||||
// [this](wxCommandEvent& evt) {
|
||||
// wxGetApp().app_config->set_bool("show_printable_box", evt.GetInt() == 1);
|
||||
// }, nullptr, [this]() {return can_select(); }, [this]() { return wxGetApp().app_config->get("show_printable_box").compare("true") == 0; }, this);
|
||||
@@ -2681,7 +2681,7 @@ void MainFrame::init_menubar_as_editor()
|
||||
else
|
||||
viewMenu->Check(wxID_CAMERA_ORTHOGONAL + camera_id_base, true);
|
||||
}, perspective_item->GetId());
|
||||
append_menu_check_item(viewMenu, wxID_ANY, _L("Auto Perspective"), _L("Automatically switch between orthographic and perspective when changing from top/bottom/side views"),
|
||||
append_menu_check_item(viewMenu, wxID_ANY, _L("Auto Perspective"), _L("Automatically switch between orthographic and perspective when changing from top/bottom/side views."),
|
||||
[this](wxCommandEvent&) {
|
||||
wxGetApp().app_config->set_bool("auto_perspective", !wxGetApp().app_config->get_bool("auto_perspective"));
|
||||
m_plater->get_current_canvas3D()->post_event(SimpleEvent(wxEVT_PAINT));
|
||||
@@ -2690,7 +2690,7 @@ void MainFrame::init_menubar_as_editor()
|
||||
[this]() { return wxGetApp().app_config->get_bool("auto_perspective"); }, this);
|
||||
|
||||
viewMenu->AppendSeparator();
|
||||
append_menu_check_item(viewMenu, wxID_ANY, _L("Show &G-code Window") + sep + "C", _L("Show G-code window in Preview scene"),
|
||||
append_menu_check_item(viewMenu, wxID_ANY, _L("Show &G-code Window") + sep + "C", _L("Show G-code window in Preview scene."),
|
||||
[this](wxCommandEvent &) {
|
||||
wxGetApp().toggle_show_gcode_window();
|
||||
m_plater->get_current_canvas3D()->post_event(SimpleEvent(wxEVT_PAINT));
|
||||
@@ -2699,7 +2699,7 @@ void MainFrame::init_menubar_as_editor()
|
||||
[this]() { return wxGetApp().show_gcode_window(); }, this);
|
||||
|
||||
append_menu_check_item(
|
||||
viewMenu, wxID_ANY, _L("Show 3D Navigator"), _L("Show 3D navigator in Prepare and Preview scene"),
|
||||
viewMenu, wxID_ANY, _L("Show 3D Navigator"), _L("Show 3D navigator in Prepare and Preview scene."),
|
||||
[this](wxCommandEvent&) {
|
||||
wxGetApp().toggle_show_3d_navigator();
|
||||
m_plater->get_current_canvas3D()->post_event(SimpleEvent(wxEVT_PAINT));
|
||||
@@ -2717,11 +2717,11 @@ void MainFrame::init_menubar_as_editor()
|
||||
this);
|
||||
|
||||
viewMenu->AppendSeparator();
|
||||
append_menu_check_item(viewMenu, wxID_ANY, _L("Show &Labels") + "\t" + ctrl + "E", _L("Show object labels in 3D scene"),
|
||||
append_menu_check_item(viewMenu, wxID_ANY, _L("Show &Labels") + "\t" + ctrl + "E", _L("Show object labels in 3D scene."),
|
||||
[this](wxCommandEvent&) { m_plater->show_view3D_labels(!m_plater->are_view3D_labels_shown()); m_plater->get_current_canvas3D()->post_event(SimpleEvent(wxEVT_PAINT)); }, this,
|
||||
[this]() { return m_plater->is_view3D_shown(); }, [this]() { return m_plater->are_view3D_labels_shown(); }, this);
|
||||
|
||||
append_menu_check_item(viewMenu, wxID_ANY, _L("Show &Overhang"), _L("Show object overhang highlight in 3D scene"),
|
||||
append_menu_check_item(viewMenu, wxID_ANY, _L("Show &Overhang"), _L("Show object overhang highlight in 3D scene."),
|
||||
[this](wxCommandEvent &) {
|
||||
m_plater->show_view3D_overhang(!m_plater->is_view3D_overhang_shown());
|
||||
m_plater->get_current_canvas3D()->post_event(SimpleEvent(wxEVT_PAINT));
|
||||
@@ -2729,7 +2729,7 @@ void MainFrame::init_menubar_as_editor()
|
||||
this, [this]() { return m_plater->is_view3D_shown(); }, [this]() { return m_plater->is_view3D_overhang_shown(); }, this);
|
||||
|
||||
append_menu_check_item(
|
||||
viewMenu, wxID_ANY, _L("Show Selected Outline (beta)"), _L("Show outline around selected object in 3D scene"),
|
||||
viewMenu, wxID_ANY, _L("Show Selected Outline (beta)"), _L("Show outline around selected object in 3D scene."),
|
||||
[this](wxCommandEvent&) {
|
||||
wxGetApp().toggle_show_outline();
|
||||
m_plater->get_current_canvas3D()->post_event(SimpleEvent(wxEVT_PAINT));
|
||||
@@ -2738,13 +2738,13 @@ void MainFrame::init_menubar_as_editor()
|
||||
[this]() { return wxGetApp().show_outline(); }, this);
|
||||
|
||||
/*viewMenu->AppendSeparator();
|
||||
append_menu_check_item(viewMenu, wxID_ANY, _L("Show &Wireframe") + "\tCtrl+Shift+Enter", _L("Show wireframes in 3D scene"),
|
||||
append_menu_check_item(viewMenu, wxID_ANY, _L("Show &Wireframe") + "\tCtrl+Shift+Enter", _L("Show wireframes in 3D scene."),
|
||||
[this](wxCommandEvent&) { m_plater->toggle_show_wireframe(); m_plater->get_current_canvas3D()->post_event(SimpleEvent(wxEVT_PAINT)); }, this,
|
||||
[this]() { return m_plater->is_wireframe_enabled(); }, [this]() { return m_plater->is_show_wireframe(); }, this);*/
|
||||
|
||||
//viewMenu->AppendSeparator();
|
||||
////BBS orthogonal view
|
||||
//append_menu_check_item(viewMenu, wxID_ANY, _L("Show Edges(TODO)"), _L("Show Edges"),
|
||||
//append_menu_check_item(viewMenu, wxID_ANY, _L("Show Edges(TODO)"), _L("Show Edges."),
|
||||
// [this](wxCommandEvent& evt) {
|
||||
// wxGetApp().app_config->set("show_build_edges", evt.GetInt() == 1 ? "true" : "false");
|
||||
// }, nullptr, [this]() {return can_select(); }, [this]() {
|
||||
|
||||
@@ -1274,7 +1274,7 @@ void NotificationManager::UpdatedItemsInfoNotification::add_type(InfoItemType ty
|
||||
case InfoItemType::MmuSegmentation: text += format(_L_PLURAL("%1$d Object has color painting.", "%1$d Objects have color painting.",(*it).second), (*it).second) + "\n"; break;
|
||||
// BBS
|
||||
//case InfoItemType::Sinking: text += format(("%1$d Object has partial sinking.", "%1$d Objects have partial sinking.", (*it).second), (*it).second) + "\n"; break;
|
||||
case InfoItemType::CutConnectors: text += format(_L_PLURAL("%1$d object was loaded as a part of cut object.", "%1$d objects were loaded as parts of cut object", (*it).second), (*it).second) + "\n"; break;
|
||||
case InfoItemType::CutConnectors: text += format(_L_PLURAL("%1$d object was loaded as a part of cut object.", "%1$d objects were loaded as parts of cut object.", (*it).second), (*it).second) + "\n"; break;
|
||||
default: BOOST_LOG_TRIVIAL(error) << "Unknown InfoItemType: " << (*it).second; break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3644,7 +3644,7 @@ void StatusPanel::on_ams_setting_click(SimpleEvent &event)
|
||||
m_ams_setting_dlg->update_ams_img(DeviceManager::get_printer_ams_img(obj->printer_type));
|
||||
std::string ams_id = m_ams_control->GetCurentShowAms();
|
||||
if (obj->amsList.size() == 0) {
|
||||
/* wxString txt = _L("AMS settings are not supported for external spool");
|
||||
/* wxString txt = _L("AMS settings are not supported for external spool.");
|
||||
MessageDialog msg_dlg(nullptr, txt, wxEmptyString, wxICON_WARNING | wxOK);
|
||||
msg_dlg.ShowModal();*/
|
||||
return;
|
||||
@@ -3672,7 +3672,7 @@ void StatusPanel::on_filament_extrusion_cali(wxCommandEvent &event)
|
||||
std::string ams_id = m_ams_control->GetCurentAms();
|
||||
std::string tray_id = m_ams_control->GetCurrentCan(ams_id);
|
||||
if (tray_id.empty() && ams_id.compare(std::to_string(VIRTUAL_TRAY_ID)) != 0) {
|
||||
wxString txt = _L("Please select an AMS slot before calibration");
|
||||
wxString txt = _L("Please select an AMS slot before calibration.");
|
||||
MessageDialog msg_dlg(nullptr, txt, wxEmptyString, wxICON_WARNING | wxOK);
|
||||
msg_dlg.ShowModal();
|
||||
return;
|
||||
|
||||
+17
-2
@@ -2206,6 +2206,7 @@ void TabPrint::build()
|
||||
optgroup->append_single_option_line("support_interface_speed");
|
||||
optgroup = page->new_optgroup(L("Overhang speed"), L"param_overhang_speed", 15);
|
||||
optgroup->append_single_option_line("enable_overhang_speed", "slow-down-for-overhang");
|
||||
|
||||
// Orca: DEPRECATED
|
||||
// optgroup->append_single_option_line("overhang_speed_classic", "slow-down-for-overhang");
|
||||
optgroup->append_single_option_line("slowdown_for_curled_perimeters");
|
||||
@@ -4166,6 +4167,17 @@ PageShp TabPrinter::build_kinematics_page()
|
||||
}
|
||||
auto optgroup = page->new_optgroup(L("Advanced"), "param_advanced");
|
||||
optgroup->append_single_option_line("emit_machine_limits_to_gcode");
|
||||
|
||||
// resonance avoidance ported over from qidi slicer
|
||||
optgroup = page->new_optgroup(L("Resonance Avoidance"));
|
||||
optgroup->append_single_option_line("resonance_avoidance");
|
||||
// Resonance‑avoidance speed inputs
|
||||
{
|
||||
Line resonance_line = {L("Resonance Avoidance Speed"), L("")};
|
||||
resonance_line.append_option(optgroup->get_option("min_resonance_avoidance_speed"));
|
||||
resonance_line.append_option(optgroup->get_option("max_resonance_avoidance_speed"));
|
||||
optgroup->append_line(resonance_line);
|
||||
}
|
||||
|
||||
const std::vector<std::string> speed_axes{
|
||||
"machine_max_speed_x",
|
||||
@@ -4424,7 +4436,6 @@ if (is_marlin_flavor)
|
||||
optgroup->append_single_option_line("deretraction_speed", "", extruder_idx);
|
||||
optgroup->append_single_option_line("retraction_minimum_travel", "", extruder_idx);
|
||||
optgroup->append_single_option_line("retract_when_changing_layer", "", extruder_idx);
|
||||
optgroup->append_single_option_line("retract_on_top_layer", "", extruder_idx);
|
||||
optgroup->append_single_option_line("wipe", "", extruder_idx);
|
||||
optgroup->append_single_option_line("wipe_distance", "", extruder_idx);
|
||||
optgroup->append_single_option_line("retract_before_wipe", "", extruder_idx);
|
||||
@@ -4644,7 +4655,7 @@ void TabPrinter::toggle_options()
|
||||
// user can customize other retraction options if retraction is enabled
|
||||
//BBS
|
||||
bool retraction = have_retract_length || use_firmware_retraction;
|
||||
std::vector<std::string> vec = {"z_hop", "retract_when_changing_layer", "retract_on_top_layer"};
|
||||
std::vector<std::string> vec = {"z_hop", "retract_when_changing_layer"};
|
||||
for (auto el : vec)
|
||||
toggle_option(el, retraction, i);
|
||||
|
||||
@@ -4709,6 +4720,10 @@ void TabPrinter::toggle_options()
|
||||
for (int i = 0; i < max_field; ++i)
|
||||
toggle_option("machine_max_junction_deviation", gcf == gcfMarlinFirmware, i);
|
||||
toggle_line("machine_max_junction_deviation", gcf == gcfMarlinFirmware);
|
||||
|
||||
bool resonance_avoidance = m_config->opt_bool("resonance_avoidance");
|
||||
toggle_option("min_resonance_avoidance_speed", resonance_avoidance);
|
||||
toggle_option("max_resonance_avoidance_speed", resonance_avoidance);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user