mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-05-20 20:03:47 +00:00
@@ -7,7 +7,6 @@
|
|||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <tbb/parallel_for.h>
|
#include <tbb/parallel_for.h>
|
||||||
#include <mutex>
|
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
@@ -157,8 +156,8 @@ vector<double> getGridValues(int i, int j, vector<vector<double>>& data)
|
|||||||
values.push_back(data[i][j]);
|
values.push_back(data[i][j]);
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
bool needContour(double value, double contourValue) { return value >= contourValue; }
|
static bool needContour(double value, double contourValue) { return value >= contourValue; }
|
||||||
Point interpolate(std::vector<std::vector<MarchingSquares::Point>>& posxy,
|
static Point interpolate(std::vector<std::vector<MarchingSquares::Point>>& posxy,
|
||||||
std::vector<int> p1ij,
|
std::vector<int> p1ij,
|
||||||
std::vector<int> p2ij,
|
std::vector<int> p2ij,
|
||||||
double v1,
|
double v1,
|
||||||
@@ -186,7 +185,7 @@ Point interpolate(std::vector<std::vector<MarchingSquares::Point>>& posxy,
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void process_block(int i,
|
static void process_block(int i,
|
||||||
int j,
|
int j,
|
||||||
vector<vector<double>>& data,
|
vector<vector<double>>& data,
|
||||||
double contourValue,
|
double contourValue,
|
||||||
@@ -288,43 +287,7 @@ void process_block(int i,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Chaikin Smooth ---
|
static void drawContour(double contourValue,
|
||||||
|
|
||||||
static Polyline chaikin_smooth(Polyline poly, int iterations , double weight )
|
|
||||||
{
|
|
||||||
if (poly.points.size() < 3) return poly;
|
|
||||||
|
|
||||||
const double w1 = 1.0 - weight;
|
|
||||||
decltype(poly.points) buffer;
|
|
||||||
buffer.reserve(poly.points.size() * 2);
|
|
||||||
|
|
||||||
for (int it = 0; it < iterations; ++it) {
|
|
||||||
buffer.clear();
|
|
||||||
buffer.push_back(poly.points.front());
|
|
||||||
|
|
||||||
for (size_t i = 0; i < poly.points.size() - 1; ++i) {
|
|
||||||
const auto &p0 = poly.points[i];
|
|
||||||
const auto &p1 = poly.points[i + 1];
|
|
||||||
|
|
||||||
buffer.emplace_back(
|
|
||||||
p0.x() * w1 + p1.x() * weight,
|
|
||||||
p0.y() * w1 + p1.y() * weight
|
|
||||||
);
|
|
||||||
buffer.emplace_back(
|
|
||||||
p0.x() * weight + p1.x() * w1,
|
|
||||||
p0.y() * weight + p1.y() * w1
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer.push_back(poly.points.back());
|
|
||||||
poly.points.swap(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
return poly;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void drawContour(double contourValue,
|
|
||||||
int gridSize_w,
|
int gridSize_w,
|
||||||
int gridSize_h,
|
int gridSize_h,
|
||||||
vector<vector<double>>& data,
|
vector<vector<double>>& data,
|
||||||
@@ -382,62 +345,18 @@ void drawContour(double contourValue,
|
|||||||
for (myPoint& pt : p) {
|
for (myPoint& pt : p) {
|
||||||
repltmp.points.push_back(Slic3r::Point(pt.x, pt.y));
|
repltmp.points.push_back(Slic3r::Point(pt.x, pt.y));
|
||||||
}
|
}
|
||||||
// symplify tolerance based on density
|
|
||||||
const float min_tolerance = 0.005f;
|
|
||||||
const float max_tolerance = 0.2f;
|
|
||||||
float simplify_tolerance = (0.005f / params.density);
|
|
||||||
simplify_tolerance = std::clamp(simplify_tolerance, min_tolerance, max_tolerance);
|
|
||||||
repltmp.simplify(scale_(simplify_tolerance));
|
|
||||||
repltmp = chaikin_smooth(repltmp, 2, 0.25);
|
|
||||||
repls.push_back(repltmp);
|
repls.push_back(repltmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace MarchingSquares
|
} // namespace MarchingSquares
|
||||||
|
|
||||||
static float sin_table[360];
|
|
||||||
static float cos_table[360];
|
|
||||||
static std::once_flag trig_tables_once_flag;
|
|
||||||
|
|
||||||
#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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline static void ensure_trig_tables_initialized()
|
|
||||||
{
|
|
||||||
std::call_once(trig_tables_once_flag, initialize_lookup_tables);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static float get_sin(float angle)
|
|
||||||
{
|
|
||||||
angle = angle * PIratio;
|
|
||||||
int index = static_cast<int>(std::fmod(angle, 360) + 360) % 360;
|
|
||||||
return sin_table[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static float get_cos(float angle)
|
|
||||||
{
|
|
||||||
angle = angle * PIratio;
|
|
||||||
int index = static_cast<int>(std::fmod(angle, 360) + 360) % 360;
|
|
||||||
return cos_table[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
void FillTpmsFK::_fill_surface_single(const FillParams& params,
|
void FillTpmsFK::_fill_surface_single(const FillParams& params,
|
||||||
unsigned int thickness_layers,
|
unsigned int thickness_layers,
|
||||||
const std::pair<float, Point>& direction,
|
const std::pair<float, Point>& direction,
|
||||||
ExPolygon expolygon,
|
ExPolygon expolygon,
|
||||||
Polylines& polylines_out)
|
Polylines& polylines_out)
|
||||||
{
|
{
|
||||||
ensure_trig_tables_initialized();
|
|
||||||
|
|
||||||
auto infill_angle = float(this->angle + (CorrectionAngle * 2 * M_PI) / 360.);
|
auto infill_angle = float(this->angle + (CorrectionAngle * 2 * M_PI) / 360.);
|
||||||
if(std::abs(infill_angle) >= EPSILON)
|
if(std::abs(infill_angle) >= EPSILON)
|
||||||
expolygon.rotate(-infill_angle);
|
expolygon.rotate(-infill_angle);
|
||||||
@@ -452,40 +371,29 @@ void FillTpmsFK::_fill_surface_single(const FillParams& params,
|
|||||||
float xlen = boxsize.x();
|
float xlen = boxsize.x();
|
||||||
float ylen = boxsize.y();
|
float ylen = boxsize.y();
|
||||||
|
|
||||||
const float delta = 0.5f; // mesh step (adjust for quality/performance)
|
const float delta = 0.4f; // mesh step (adjust for quality/performance)
|
||||||
|
|
||||||
float myperiod = 2 * PI / vari_T;
|
float myperiod = 2 * PI / vari_T;
|
||||||
float c_z = myperiod * this->z; // z height
|
float c_z = myperiod * this->z; // z height
|
||||||
|
|
||||||
// scalar field Fischer-Koch
|
// scalar field Fischer-Koch
|
||||||
auto scalar_field = [&](float x, float y) {
|
auto scalar_field = [&](float x, float y) -> float {
|
||||||
float a_x = myperiod * x;
|
const float a_x = myperiod * x;
|
||||||
float b_y = myperiod * y;
|
const float b_y = myperiod * y;
|
||||||
|
|
||||||
// Fischer - Koch S equation:
|
// Fischer - Koch S equation:
|
||||||
// cos(2x)sin(y)cos(z) + cos(2y)sin(z)cos(x) + cos(2z)sin(x)cos(y) = 0
|
// cos(2x)sin(y)cos(z) + cos(2y)sin(z)cos(x) + cos(2z)sin(x)cos(y) = 0
|
||||||
const float cos2ax = get_cos(2*a_x);
|
return cosf(2 * a_x) * sinf(b_y) * cosf(c_z)
|
||||||
const float cos2by = get_cos(2*b_y);
|
+ cosf(2 * b_y) * sinf(c_z) * cosf(a_x)
|
||||||
const float cos2cz = get_cos(2*c_z);
|
+ cosf(2 * c_z) * sinf(a_x) * cosf(b_y);
|
||||||
const float sinby = get_sin(b_y);
|
|
||||||
const float cosax = get_cos(a_x);
|
|
||||||
const float sinax = get_sin(a_x);
|
|
||||||
const float cosby = get_cos(b_y);
|
|
||||||
const float sincz = get_sin(c_z);
|
|
||||||
const float coscz = get_cos(c_z);
|
|
||||||
|
|
||||||
return cos2ax * sinby * coscz
|
|
||||||
+ cos2by * sincz * cosax
|
|
||||||
+ cos2cz * sinax * cosby;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Mesh generation
|
// Mesh generation
|
||||||
std::vector<std::vector<MarchingSquares::Point>> posxy;
|
std::vector<std::vector<MarchingSquares::Point>> posxy;
|
||||||
int i = 0, j = 0;
|
int i = 0, j = 0;
|
||||||
for (float y = -(ylen) / 2.0f - 2; y < (ylen) / 2.0f + 2; y = y + delta, i++) {
|
for (float y = -(ylen) / 2.0f - 0.5f; y < (ylen) / 2.0f + 0.5f; y = y + delta, i++) {
|
||||||
j = 0;
|
j = 0;
|
||||||
std::vector<MarchingSquares::Point> colposxy;
|
std::vector<MarchingSquares::Point> colposxy;
|
||||||
for (float x = -(xlen) / 2.0f - 2; x < (xlen) / 2.0f + 2; x = x + delta, j++) {
|
for (float x = -(xlen) / 2.0f - 0.5f; x < (xlen) / 2.0f + 0.5f; x = x + delta, j++) {
|
||||||
MarchingSquares::Point pt;
|
MarchingSquares::Point pt;
|
||||||
pt.x = cenpos.x() + x;
|
pt.x = cenpos.x() + x;
|
||||||
pt.y = cenpos.y() + y;
|
pt.y = cenpos.y() + y;
|
||||||
@@ -510,33 +418,36 @@ void FillTpmsFK::_fill_surface_single(const FillParams& params,
|
|||||||
|
|
||||||
|
|
||||||
Polylines polylines;
|
Polylines polylines;
|
||||||
const double contour_value = 0.075; // offset from zero to avoid numerical issues
|
const double contour_value = 0; // offset from theoretical surface
|
||||||
MarchingSquares::drawContour(contour_value, width , height , data, posxy, polylines, params);
|
MarchingSquares::drawContour(contour_value, width , height , data, posxy, polylines, params);
|
||||||
|
|
||||||
if (!polylines.empty()) {
|
|
||||||
// Apply multiline offset if needed
|
// Apply multiline offset if needed
|
||||||
multiline_fill(polylines, params, spacing);
|
multiline_fill(polylines, params, spacing);
|
||||||
|
|
||||||
|
|
||||||
polylines = intersection_pl(polylines, expolygon);
|
polylines = intersection_pl(polylines, expolygon);
|
||||||
|
|
||||||
|
if (! polylines.empty()) {
|
||||||
// Remove very small bits, but be careful to not remove infill lines connecting thin walls!
|
// Remove very small bits, but be careful to not remove infill lines connecting thin walls!
|
||||||
// The infill perimeter lines should be separated by around a single infill line width.
|
// The infill perimeter lines should be separated by around a single infill line width.
|
||||||
const double minlength = scale_(0.8 * this->spacing);
|
const double minlength = scale_(0.8 * this->spacing);
|
||||||
polylines.erase(
|
polylines.erase(
|
||||||
std::remove_if(polylines.begin(), polylines.end(), [minlength](const Polyline &pl) { return pl.length() < minlength; }),
|
std::remove_if(polylines.begin(), polylines.end(), [minlength](const Polyline &pl) { return pl.length() < minlength; }),
|
||||||
polylines.end());
|
polylines.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! polylines.empty()) {
|
||||||
// connect lines
|
// connect lines
|
||||||
size_t polylines_out_first_idx = polylines_out.size();
|
size_t polylines_out_first_idx = polylines_out.size();
|
||||||
chain_or_connect_infill(std::move(polylines), expolygon, polylines_out, this->spacing, params);
|
|
||||||
|
//chain_or_connect_infill(std::move(polylines), expolygon, polylines_out, this->spacing, params);
|
||||||
|
//chain_infill not situable for this pattern due to internal "islands", this also affect performance a lot.
|
||||||
|
connect_infill(std::move(polylines), expolygon, polylines_out, this->spacing, params);
|
||||||
|
|
||||||
// new paths must be rotated back
|
// new paths must be rotated back
|
||||||
if (std::abs(infill_angle) >= EPSILON) {
|
if (std::abs(infill_angle) >= EPSILON) {
|
||||||
for (auto it = polylines_out.begin() + polylines_out_first_idx; it != polylines_out.end(); ++ it)
|
for (auto it = polylines_out.begin() + polylines_out_first_idx; it != polylines_out.end(); ++ it)
|
||||||
it->rotate(infill_angle);
|
it->rotate(infill_angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user