mirror of
https://github.com/FULU-Foundation/OrcaSlicer-bambulab.git
synced 2026-07-29 12:54:31 +03:00
Merged with dev
This commit is contained in:
@@ -54,9 +54,9 @@ static std::vector<coordf_t> perpendPoints(const coordf_t offset, const size_t b
|
||||
// components that are outside these limits are set to the limits.
|
||||
static inline void trim(Pointfs &pts, coordf_t minX, coordf_t minY, coordf_t maxX, coordf_t maxY)
|
||||
{
|
||||
for (Pointfs::iterator it = pts.begin(); it != pts.end(); ++ it) {
|
||||
it->x = clamp(minX, maxX, it->x);
|
||||
it->y = clamp(minY, maxY, it->y);
|
||||
for (Vec2d &pt : pts) {
|
||||
pt(0) = clamp(minX, maxX, pt(0));
|
||||
pt(1) = clamp(minY, maxY, pt(1));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ static inline Pointfs zip(const std::vector<coordf_t> &x, const std::vector<coor
|
||||
Pointfs out;
|
||||
out.reserve(x.size());
|
||||
for (size_t i = 0; i < x.size(); ++ i)
|
||||
out.push_back(Pointf(x[i], y[i]));
|
||||
out.push_back(Vec2d(x[i], y[i]));
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ static Polylines makeGrid(coord_t z, coord_t gridSize, size_t gridWidth, size_t
|
||||
result.push_back(Polyline());
|
||||
Polyline &polyline = result.back();
|
||||
for (Pointfs::const_iterator it = it_polylines->begin(); it != it_polylines->end(); ++ it)
|
||||
polyline.points.push_back(Point(coord_t(it->x * scaleFactor), coord_t(it->y * scaleFactor)));
|
||||
polyline.points.push_back(Point(coord_t((*it)(0) * scaleFactor), coord_t((*it)(1) * scaleFactor)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -153,13 +153,13 @@ void Fill3DHoneycomb::_fill_surface_single(
|
||||
Polylines polylines = makeGrid(
|
||||
scale_(this->z),
|
||||
distance,
|
||||
ceil(bb.size().x / distance) + 1,
|
||||
ceil(bb.size().y / distance) + 1,
|
||||
ceil(bb.size()(0) / distance) + 1,
|
||||
ceil(bb.size()(1) / distance) + 1,
|
||||
((this->layer_id/thickness_layers) % 2) + 1);
|
||||
|
||||
// move pattern in place
|
||||
for (Polylines::iterator it = polylines.begin(); it != polylines.end(); ++ it)
|
||||
it->translate(bb.min.x, bb.min.y);
|
||||
it->translate(bb.min(0), bb.min(1));
|
||||
|
||||
// clip pattern to boundaries
|
||||
polylines = intersection_pl(polylines, (Polygons)expolygon);
|
||||
@@ -187,7 +187,7 @@ void Fill3DHoneycomb::_fill_surface_single(
|
||||
const Point &last_point = pts_end.back();
|
||||
// TODO: we should also check that both points are on a fill_boundary to avoid
|
||||
// connecting paths on the boundaries of internal regions
|
||||
if (first_point.distance_to(last_point) <= 1.5 * distance &&
|
||||
if ((last_point - first_point).cast<double>().norm() <= 1.5 * distance &&
|
||||
expolygon_off.contains(Line(last_point, first_point))) {
|
||||
// Append the polyline.
|
||||
pts_end.insert(pts_end.end(), it_polyline->points.begin(), it_polyline->points.end());
|
||||
|
||||
@@ -121,11 +121,11 @@ public:
|
||||
return aligned;
|
||||
}
|
||||
static Point _align_to_grid(Point coord, Point spacing)
|
||||
{ return Point(_align_to_grid(coord.x, spacing.x), _align_to_grid(coord.y, spacing.y)); }
|
||||
{ return Point(_align_to_grid(coord(0), spacing(0)), _align_to_grid(coord(1), spacing(1))); }
|
||||
static coord_t _align_to_grid(coord_t coord, coord_t spacing, coord_t base)
|
||||
{ return base + _align_to_grid(coord - base, spacing); }
|
||||
static Point _align_to_grid(Point coord, Point spacing, Point base)
|
||||
{ return Point(_align_to_grid(coord.x, spacing.x, base.x), _align_to_grid(coord.y, spacing.y, base.y)); }
|
||||
{ return Point(_align_to_grid(coord(0), spacing(0), base(0)), _align_to_grid(coord(1), spacing(1), base(1))); }
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
@@ -20,8 +20,8 @@ void FillConcentric::_fill_surface_single(
|
||||
coord_t distance = coord_t(min_spacing / params.density);
|
||||
|
||||
if (params.density > 0.9999f && !params.dont_adjust) {
|
||||
distance = this->_adjust_solid_spacing(bounding_box.size().x, distance);
|
||||
this->spacing = unscale(distance);
|
||||
distance = this->_adjust_solid_spacing(bounding_box.size()(0), distance);
|
||||
this->spacing = unscale<double>(distance);
|
||||
}
|
||||
|
||||
Polygons loops = (Polygons)expolygon;
|
||||
|
||||
@@ -9,74 +9,117 @@
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
static inline Polyline make_wave_vertical(
|
||||
double width, double height, double x0,
|
||||
double segmentSize, double scaleFactor,
|
||||
double z_cos, double z_sin, bool flip)
|
||||
static inline double f(double x, double z_sin, double z_cos, bool vertical, bool flip)
|
||||
{
|
||||
Polyline polyline;
|
||||
polyline.points.emplace_back(Point(coord_t(clamp(0., width, x0) * scaleFactor), 0));
|
||||
double phase_offset_sin = (z_cos < 0 ? M_PI : 0) + M_PI;
|
||||
double phase_offset_cos = (z_cos < 0 ? M_PI : 0) + M_PI + (flip ? M_PI : 0.);
|
||||
for (double y = 0.; y < height + segmentSize; y += segmentSize) {
|
||||
y = std::min(y, height);
|
||||
double a = sin(y + phase_offset_sin);
|
||||
if (vertical) {
|
||||
double phase_offset = (z_cos < 0 ? M_PI : 0) + M_PI;
|
||||
double a = sin(x + phase_offset);
|
||||
double b = - z_cos;
|
||||
double res = z_sin * cos(y + phase_offset_cos);
|
||||
double res = z_sin * cos(x + phase_offset + (flip ? M_PI : 0.));
|
||||
double r = sqrt(sqr(a) + sqr(b));
|
||||
double x = clamp(0., width, asin(a/r) + asin(res/r) + M_PI + x0);
|
||||
polyline.points.emplace_back(convert_to<Point>(Pointf(x, y) * scaleFactor));
|
||||
return asin(a/r) + asin(res/r) + M_PI;
|
||||
}
|
||||
if (flip)
|
||||
std::reverse(polyline.points.begin(), polyline.points.end());
|
||||
return polyline;
|
||||
}
|
||||
|
||||
static inline Polyline make_wave_horizontal(
|
||||
double width, double height, double y0,
|
||||
double segmentSize, double scaleFactor,
|
||||
double z_cos, double z_sin, bool flip)
|
||||
{
|
||||
Polyline polyline;
|
||||
polyline.points.emplace_back(Point(0, coord_t(clamp(0., height, y0) * scaleFactor)));
|
||||
double phase_offset_sin = (z_sin < 0 ? M_PI : 0) + (flip ? 0 : M_PI);
|
||||
double phase_offset_cos = z_sin < 0 ? M_PI : 0.;
|
||||
for (double x=0.; x < width + segmentSize; x += segmentSize) {
|
||||
x = std::min(x, width);
|
||||
double a = cos(x + phase_offset_cos);
|
||||
else {
|
||||
double phase_offset = z_sin < 0 ? M_PI : 0.;
|
||||
double a = cos(x + phase_offset);
|
||||
double b = - z_sin;
|
||||
double res = z_cos * sin(x + phase_offset_sin);
|
||||
double res = z_cos * sin(x + phase_offset + (flip ? 0 : M_PI));
|
||||
double r = sqrt(sqr(a) + sqr(b));
|
||||
double y = clamp(0., height, asin(a/r) + asin(res/r) + 0.5 * M_PI + y0);
|
||||
polyline.points.emplace_back(convert_to<Point>(Pointf(x, y) * scaleFactor));
|
||||
return (asin(a/r) + asin(res/r) + 0.5 * M_PI);
|
||||
}
|
||||
if (flip)
|
||||
std::reverse(polyline.points.begin(), polyline.points.end());
|
||||
}
|
||||
|
||||
static inline Polyline make_wave(
|
||||
const std::vector<Vec2d>& one_period, double width, double height, double offset, double scaleFactor,
|
||||
double z_cos, double z_sin, bool vertical)
|
||||
{
|
||||
std::vector<Vec2d> points = one_period;
|
||||
double period = points.back()(0);
|
||||
points.pop_back();
|
||||
int n = points.size();
|
||||
do {
|
||||
points.emplace_back(Vec2d(points[points.size()-n](0) + period, points[points.size()-n](1)));
|
||||
} while (points.back()(0) < width);
|
||||
points.back()(0) = width;
|
||||
|
||||
// and construct the final polyline to return:
|
||||
Polyline polyline;
|
||||
for (auto& point : points) {
|
||||
point(1) += offset;
|
||||
point(1) = clamp(0., height, double(point(1)));
|
||||
if (vertical)
|
||||
std::swap(point(0), point(1));
|
||||
polyline.points.emplace_back((point * scaleFactor).cast<coord_t>());
|
||||
}
|
||||
|
||||
return polyline;
|
||||
}
|
||||
|
||||
static Polylines make_gyroid_waves(double gridZ, double density, double layer_width, double width, double height)
|
||||
static std::vector<Vec2d> make_one_period(double width, double scaleFactor, double z_cos, double z_sin, bool vertical, bool flip)
|
||||
{
|
||||
double scaleFactor = scale_(layer_width) / density;
|
||||
double segmentSize = 0.5 * density;
|
||||
std::vector<Vec2d> points;
|
||||
double dx = M_PI_4; // very coarse spacing to begin with
|
||||
double limit = std::min(2*M_PI, width);
|
||||
for (double x = 0.; x < limit + EPSILON; x += dx) { // so the last point is there too
|
||||
x = std::min(x, limit);
|
||||
points.emplace_back(Vec2d(x,f(x, z_sin,z_cos, vertical, flip)));
|
||||
}
|
||||
|
||||
// now we will check all internal points and in case some are too far from the line connecting its neighbours,
|
||||
// we will add one more point on each side:
|
||||
const double tolerance = .1;
|
||||
for (unsigned int i=1;i<points.size()-1;++i) {
|
||||
auto& lp = points[i-1]; // left point
|
||||
auto& tp = points[i]; // this point
|
||||
Vec2d lrv = tp - lp;
|
||||
auto& rp = points[i+1]; // right point
|
||||
// calculate distance of the point to the line:
|
||||
double dist_mm = unscale<double>(scaleFactor) * std::abs(cross2(rp, lp) - cross2(rp - lp, tp)) / lrv.norm();
|
||||
if (dist_mm > tolerance) { // if the difference from straight line is more than this
|
||||
double x = 0.5f * (points[i-1](0) + points[i](0));
|
||||
points.emplace_back(Vec2d(x, f(x, z_sin, z_cos, vertical, flip)));
|
||||
x = 0.5f * (points[i+1](0) + points[i](0));
|
||||
points.emplace_back(Vec2d(x, f(x, z_sin, z_cos, vertical, flip)));
|
||||
// we added the points to the end, but need them all in order
|
||||
std::sort(points.begin(), points.end(), [](const Vec2d &lhs, const Vec2d &rhs){ return lhs < rhs; });
|
||||
// decrement i so we also check the first newly added point
|
||||
--i;
|
||||
}
|
||||
}
|
||||
return points;
|
||||
}
|
||||
|
||||
static Polylines make_gyroid_waves(double gridZ, double density_adjusted, double line_spacing, double width, double height)
|
||||
{
|
||||
const double scaleFactor = scale_(line_spacing) / density_adjusted;
|
||||
//scale factor for 5% : 8 712 388
|
||||
// 1z = 10^-6 mm ?
|
||||
double z = gridZ / scaleFactor;
|
||||
double z_sin = sin(z);
|
||||
double z_cos = cos(z);
|
||||
Polylines result;
|
||||
if (abs(z_sin) <= abs(z_cos)) {
|
||||
// Vertical wave
|
||||
double x0 = M_PI * (int)((- 0.5 * M_PI) / M_PI - 1.);
|
||||
bool flip = ((int)(x0 / M_PI + 1.) & 1) != 0;
|
||||
for (; x0 < width - 0.5 * M_PI; x0 += M_PI, flip = ! flip)
|
||||
result.emplace_back(make_wave_vertical(width, height, x0, segmentSize, scaleFactor, z_cos, z_sin, flip));
|
||||
} else {
|
||||
// Horizontal wave
|
||||
bool flip = true;
|
||||
for (double y0 = 0.; y0 < width; y0 += M_PI, flip = !flip)
|
||||
result.emplace_back(make_wave_horizontal(width, height, y0, segmentSize, scaleFactor, z_cos, z_sin, flip));
|
||||
const double z = gridZ / scaleFactor;
|
||||
const double z_sin = sin(z);
|
||||
const double z_cos = cos(z);
|
||||
|
||||
bool vertical = (std::abs(z_sin) <= std::abs(z_cos));
|
||||
double lower_bound = 0.;
|
||||
double upper_bound = height;
|
||||
bool flip = true;
|
||||
if (vertical) {
|
||||
flip = false;
|
||||
lower_bound = -M_PI;
|
||||
upper_bound = width - M_PI_2;
|
||||
std::swap(width,height);
|
||||
}
|
||||
|
||||
std::vector<Vec2d> one_period = make_one_period(width, scaleFactor, z_cos, z_sin, vertical, flip); // creates one period of the waves, so it doesn't have to be recalculated all the time
|
||||
Polylines result;
|
||||
|
||||
for (double y0 = lower_bound; y0 < upper_bound+EPSILON; y0 += 2*M_PI) // creates odd polylines
|
||||
result.emplace_back(make_wave(one_period, width, height, y0, scaleFactor, z_cos, z_sin, vertical));
|
||||
|
||||
flip = !flip; // even polylines are a bit shifted
|
||||
one_period = make_one_period(width, scaleFactor, z_cos, z_sin, vertical, flip); // updates the one period sample
|
||||
for (double y0 = lower_bound + M_PI; y0 < upper_bound+EPSILON; y0 += 2*M_PI) // creates even polylines
|
||||
result.emplace_back(make_wave(one_period, width, height, y0, scaleFactor, z_cos, z_sin, vertical));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -87,24 +130,27 @@ void FillGyroid::_fill_surface_single(
|
||||
ExPolygon &expolygon,
|
||||
Polylines &polylines_out)
|
||||
{
|
||||
// no rotation is supported for this infill pattern
|
||||
// no rotation is supported for this infill pattern (yet)
|
||||
BoundingBox bb = expolygon.contour.bounding_box();
|
||||
coord_t distance = coord_t(scale_(this->spacing) / (params.density*this->scaling));
|
||||
// Density adjusted to have a good %of weight.
|
||||
double density_adjusted = std::max(0., params.density * 2.);
|
||||
// Distance between the gyroid waves in scaled coordinates.
|
||||
coord_t distance = coord_t(scale_(this->spacing) / density_adjusted);
|
||||
|
||||
// align bounding box to a multiple of our grid module
|
||||
bb.merge(_align_to_grid(bb.min, Point(2*M_PI*distance, 2*M_PI*distance)));
|
||||
|
||||
bb.merge(_align_to_grid(bb.min, Point(2.*M_PI*distance, 2.*M_PI*distance)));
|
||||
|
||||
// generate pattern
|
||||
Polylines polylines = make_gyroid_waves(
|
||||
scale_(this->z),
|
||||
params.density*this->scaling,
|
||||
density_adjusted,
|
||||
this->spacing,
|
||||
ceil(bb.size().x / distance) + 1.,
|
||||
ceil(bb.size().y / distance) + 1.);
|
||||
ceil(bb.size()(0) / distance) + 1.,
|
||||
ceil(bb.size()(1) / distance) + 1.);
|
||||
|
||||
// move pattern in place
|
||||
for (Polyline &polyline : polylines)
|
||||
polyline.translate(bb.min.x, bb.min.y);
|
||||
polyline.translate(bb.min(0), bb.min(1));
|
||||
|
||||
// clip pattern to boundaries
|
||||
polylines = intersection_pl(polylines, (Polygons)expolygon);
|
||||
@@ -133,7 +179,7 @@ void FillGyroid::_fill_surface_single(
|
||||
// TODO: we should also check that both points are on a fill_boundary to avoid
|
||||
// connecting paths on the boundaries of internal regions
|
||||
// TODO: avoid crossing current infill path
|
||||
if (first_point.distance_to(last_point) <= 5 * distance &&
|
||||
if ((last_point - first_point).cast<double>().norm() <= 5 * distance &&
|
||||
expolygon_off.contains(Line(last_point, first_point))) {
|
||||
// Append the polyline.
|
||||
pts_end.insert(pts_end.end(), polyline.points.begin(), polyline.points.end());
|
||||
|
||||
@@ -17,10 +17,6 @@ public:
|
||||
virtual bool use_bridge_flow() const { return true; }
|
||||
|
||||
protected:
|
||||
|
||||
// mult of density, to have a good %of weight for each density parameter
|
||||
float scaling = 1.75;
|
||||
|
||||
virtual void _fill_surface_single(
|
||||
const FillParams ¶ms,
|
||||
unsigned int thickness_layers,
|
||||
|
||||
@@ -50,13 +50,13 @@ void FillHoneycomb::_fill_surface_single(
|
||||
bounding_box.merge(_align_to_grid(bounding_box.min, Point(m.hex_width, m.pattern_height)));
|
||||
}
|
||||
|
||||
coord_t x = bounding_box.min.x;
|
||||
while (x <= bounding_box.max.x) {
|
||||
coord_t x = bounding_box.min(0);
|
||||
while (x <= bounding_box.max(0)) {
|
||||
Polygon p;
|
||||
coord_t ax[2] = { x + m.x_offset, x + m.distance - m.x_offset };
|
||||
for (size_t i = 0; i < 2; ++ i) {
|
||||
std::reverse(p.points.begin(), p.points.end()); // turn first half upside down
|
||||
for (coord_t y = bounding_box.min.y; y <= bounding_box.max.y; y += m.y_short + m.hex_side + m.y_short + m.hex_side) {
|
||||
for (coord_t y = bounding_box.min(1); y <= bounding_box.max(1); y += m.y_short + m.hex_side + m.y_short + m.hex_side) {
|
||||
p.points.push_back(Point(ax[1], y + m.y_offset));
|
||||
p.points.push_back(Point(ax[0], y + m.y_short - m.y_offset));
|
||||
p.points.push_back(Point(ax[0], y + m.y_short + m.hex_side + m.y_offset));
|
||||
@@ -101,7 +101,7 @@ void FillHoneycomb::_fill_surface_single(
|
||||
for (Polylines::iterator it_path = chained.begin(); it_path != chained.end(); ++ it_path) {
|
||||
if (! paths.empty()) {
|
||||
// distance between first point of this path and last point of last path
|
||||
double distance = paths.back().last_point().distance_to(it_path->first_point());
|
||||
double distance = (it_path->first_point() - paths.back().last_point()).cast<double>().norm();
|
||||
if (distance <= m.hex_width) {
|
||||
paths.back().points.insert(paths.back().points.end(), it_path->points.begin(), it_path->points.end());
|
||||
continue;
|
||||
|
||||
@@ -24,14 +24,14 @@ void FillPlanePath::_fill_surface_single(
|
||||
Point shift = this->_centered() ?
|
||||
bounding_box.center() :
|
||||
bounding_box.min;
|
||||
expolygon.translate(-shift.x, -shift.y);
|
||||
bounding_box.translate(-shift.x, -shift.y);
|
||||
expolygon.translate(-shift(0), -shift(1));
|
||||
bounding_box.translate(-shift(0), -shift(1));
|
||||
|
||||
Pointfs pts = _generate(
|
||||
coord_t(ceil(coordf_t(bounding_box.min.x) / distance_between_lines)),
|
||||
coord_t(ceil(coordf_t(bounding_box.min.y) / distance_between_lines)),
|
||||
coord_t(ceil(coordf_t(bounding_box.max.x) / distance_between_lines)),
|
||||
coord_t(ceil(coordf_t(bounding_box.max.y) / distance_between_lines)));
|
||||
coord_t(ceil(coordf_t(bounding_box.min(0)) / distance_between_lines)),
|
||||
coord_t(ceil(coordf_t(bounding_box.min(1)) / distance_between_lines)),
|
||||
coord_t(ceil(coordf_t(bounding_box.max(0)) / distance_between_lines)),
|
||||
coord_t(ceil(coordf_t(bounding_box.max(1)) / distance_between_lines)));
|
||||
|
||||
Polylines polylines;
|
||||
if (pts.size() >= 2) {
|
||||
@@ -41,8 +41,8 @@ void FillPlanePath::_fill_surface_single(
|
||||
polyline.points.reserve(pts.size());
|
||||
for (Pointfs::iterator it = pts.begin(); it != pts.end(); ++ it)
|
||||
polyline.points.push_back(Point(
|
||||
coord_t(floor(it->x * distance_between_lines + 0.5)),
|
||||
coord_t(floor(it->y * distance_between_lines + 0.5))));
|
||||
coord_t(floor((*it)(0) * distance_between_lines + 0.5)),
|
||||
coord_t(floor((*it)(1) * distance_between_lines + 0.5))));
|
||||
// intersection(polylines_src, offset((Polygons)expolygon, scale_(0.02)), &polylines);
|
||||
polylines = intersection_pl(polylines, to_polygons(expolygon));
|
||||
|
||||
@@ -62,7 +62,7 @@ void FillPlanePath::_fill_surface_single(
|
||||
|
||||
// paths must be repositioned and rotated back
|
||||
for (Polylines::iterator it = polylines.begin(); it != polylines.end(); ++ it) {
|
||||
it->translate(shift.x, shift.y);
|
||||
it->translate(shift(0), shift(1));
|
||||
it->rotate(direction.first);
|
||||
}
|
||||
}
|
||||
@@ -86,12 +86,12 @@ Pointfs FillArchimedeanChords::_generate(coord_t min_x, coord_t min_y, coord_t m
|
||||
coordf_t r = 1;
|
||||
Pointfs out;
|
||||
//FIXME Vojtech: If used as a solid infill, there is a gap left at the center.
|
||||
out.push_back(Pointf(0, 0));
|
||||
out.push_back(Pointf(1, 0));
|
||||
out.push_back(Vec2d(0, 0));
|
||||
out.push_back(Vec2d(1, 0));
|
||||
while (r < rmax) {
|
||||
theta += 1. / r;
|
||||
r = a + b * theta;
|
||||
out.push_back(Pointf(r * cos(theta), r * sin(theta)));
|
||||
out.push_back(Vec2d(r * cos(theta), r * sin(theta)));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
@@ -162,7 +162,7 @@ Pointfs FillHilbertCurve::_generate(coord_t min_x, coord_t min_y, coord_t max_x,
|
||||
line.reserve(sz2);
|
||||
for (size_t i = 0; i < sz2; ++ i) {
|
||||
Point p = hilbert_n_to_xy(i);
|
||||
line.push_back(Pointf(p.x + min_x, p.y + min_y));
|
||||
line.push_back(Vec2d(p(0) + min_x, p(1) + min_y));
|
||||
}
|
||||
return line;
|
||||
}
|
||||
@@ -175,27 +175,27 @@ Pointfs FillOctagramSpiral::_generate(coord_t min_x, coord_t min_y, coord_t max_
|
||||
coordf_t r = 0;
|
||||
coordf_t r_inc = sqrt(2.);
|
||||
Pointfs out;
|
||||
out.push_back(Pointf(0, 0));
|
||||
out.push_back(Vec2d(0, 0));
|
||||
while (r < rmax) {
|
||||
r += r_inc;
|
||||
coordf_t rx = r / sqrt(2.);
|
||||
coordf_t r2 = r + rx;
|
||||
out.push_back(Pointf( r, 0.));
|
||||
out.push_back(Pointf( r2, rx));
|
||||
out.push_back(Pointf( rx, rx));
|
||||
out.push_back(Pointf( rx, r2));
|
||||
out.push_back(Pointf(0., r));
|
||||
out.push_back(Pointf(-rx, r2));
|
||||
out.push_back(Pointf(-rx, rx));
|
||||
out.push_back(Pointf(-r2, rx));
|
||||
out.push_back(Pointf(-r, 0.));
|
||||
out.push_back(Pointf(-r2, -rx));
|
||||
out.push_back(Pointf(-rx, -rx));
|
||||
out.push_back(Pointf(-rx, -r2));
|
||||
out.push_back(Pointf(0., -r));
|
||||
out.push_back(Pointf( rx, -r2));
|
||||
out.push_back(Pointf( rx, -rx));
|
||||
out.push_back(Pointf( r2+r_inc, -rx));
|
||||
out.push_back(Vec2d( r, 0.));
|
||||
out.push_back(Vec2d( r2, rx));
|
||||
out.push_back(Vec2d( rx, rx));
|
||||
out.push_back(Vec2d( rx, r2));
|
||||
out.push_back(Vec2d(0., r));
|
||||
out.push_back(Vec2d(-rx, r2));
|
||||
out.push_back(Vec2d(-rx, rx));
|
||||
out.push_back(Vec2d(-r2, rx));
|
||||
out.push_back(Vec2d(-r, 0.));
|
||||
out.push_back(Vec2d(-r2, -rx));
|
||||
out.push_back(Vec2d(-rx, -rx));
|
||||
out.push_back(Vec2d(-rx, -r2));
|
||||
out.push_back(Vec2d(0., -r));
|
||||
out.push_back(Vec2d( rx, -r2));
|
||||
out.push_back(Vec2d( rx, -rx));
|
||||
out.push_back(Vec2d( r2+r_inc, -rx));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -26,8 +26,8 @@ void FillRectilinear::_fill_surface_single(
|
||||
|
||||
// define flow spacing according to requested density
|
||||
if (params.density > 0.9999f && !params.dont_adjust) {
|
||||
this->_line_spacing = this->_adjust_solid_spacing(bounding_box.size().x, this->_line_spacing);
|
||||
this->spacing = unscale(this->_line_spacing);
|
||||
this->_line_spacing = this->_adjust_solid_spacing(bounding_box.size()(0), this->_line_spacing);
|
||||
this->spacing = unscale<double>(this->_line_spacing);
|
||||
} else {
|
||||
// extend bounding box so that our pattern will be aligned with other layers
|
||||
// Transform the reference point to the rotated coordinate system.
|
||||
@@ -38,14 +38,14 @@ void FillRectilinear::_fill_surface_single(
|
||||
}
|
||||
|
||||
// generate the basic pattern
|
||||
coord_t x_max = bounding_box.max.x + SCALED_EPSILON;
|
||||
coord_t x_max = bounding_box.max(0) + SCALED_EPSILON;
|
||||
Lines lines;
|
||||
for (coord_t x = bounding_box.min.x; x <= x_max; x += this->_line_spacing)
|
||||
lines.push_back(this->_line(lines.size(), x, bounding_box.min.y, bounding_box.max.y));
|
||||
for (coord_t x = bounding_box.min(0); x <= x_max; x += this->_line_spacing)
|
||||
lines.push_back(this->_line(lines.size(), x, bounding_box.min(1), bounding_box.max(1)));
|
||||
if (this->_horizontal_lines()) {
|
||||
coord_t y_max = bounding_box.max.y + SCALED_EPSILON;
|
||||
for (coord_t y = bounding_box.min.y; y <= y_max; y += this->_line_spacing)
|
||||
lines.push_back(Line(Point(bounding_box.min.x, y), Point(bounding_box.max.x, y)));
|
||||
coord_t y_max = bounding_box.max(1) + SCALED_EPSILON;
|
||||
for (coord_t y = bounding_box.min(1); y <= y_max; y += this->_line_spacing)
|
||||
lines.push_back(Line(Point(bounding_box.min(0), y), Point(bounding_box.max(0), y)));
|
||||
}
|
||||
|
||||
// clip paths against a slightly larger expolygon, so that the first and last paths
|
||||
@@ -72,10 +72,10 @@ void FillRectilinear::_fill_surface_single(
|
||||
for (Polylines::iterator it_polyline = polylines.begin(); it_polyline != polylines.end(); ++ it_polyline) {
|
||||
Point *first_point = &it_polyline->points.front();
|
||||
Point *last_point = &it_polyline->points.back();
|
||||
if (first_point->y > last_point->y)
|
||||
if (first_point->y() > last_point->y())
|
||||
std::swap(first_point, last_point);
|
||||
first_point->y -= extra;
|
||||
last_point->y += extra;
|
||||
first_point->y() -= extra;
|
||||
last_point->y() += extra;
|
||||
}
|
||||
|
||||
size_t n_polylines_out_old = polylines_out.size();
|
||||
@@ -103,10 +103,10 @@ void FillRectilinear::_fill_surface_single(
|
||||
const Point &first_point = it_polyline->points.front();
|
||||
const Point &last_point = pts_end.back();
|
||||
// Distance in X, Y.
|
||||
const Vector distance = first_point.vector_to(last_point);
|
||||
const Vector distance = last_point - first_point;
|
||||
// TODO: we should also check that both points are on a fill_boundary to avoid
|
||||
// connecting paths on the boundaries of internal regions
|
||||
if (this->_can_connect(std::abs(distance.x), std::abs(distance.y)) &&
|
||||
if (this->_can_connect(std::abs(distance(0)), std::abs(distance(1))) &&
|
||||
expolygon_off.contains(Line(last_point, first_point))) {
|
||||
// Append the polyline.
|
||||
pts_end.insert(pts_end.end(), it_polyline->points.begin(), it_polyline->points.end());
|
||||
@@ -122,7 +122,7 @@ void FillRectilinear::_fill_surface_single(
|
||||
// paths must be rotated back
|
||||
for (Polylines::iterator it = polylines_out.begin() + n_polylines_out_old; it != polylines_out.end(); ++ it) {
|
||||
// No need to translate, the absolute position is irrelevant.
|
||||
// it->translate(- direction.second.x, - direction.second.y);
|
||||
// it->translate(- direction.second(0), - direction.second(1));
|
||||
it->rotate(direction.first);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,12 +42,12 @@ static inline coordf_t segment_length(const Polygon &poly, size_t seg1, const Po
|
||||
Point px = (i == 0) ? p1 : p2;
|
||||
Point pa = poly.points[((seg == 0) ? poly.points.size() : seg) - 1];
|
||||
Point pb = poly.points[seg];
|
||||
if (pa.x > pb.x)
|
||||
std::swap(pa.x, pb.x);
|
||||
if (pa.y > pb.y)
|
||||
std::swap(pa.y, pb.y);
|
||||
assert(px.x >= pa.x && px.x <= pb.x);
|
||||
assert(px.y >= pa.y && px.y <= pb.y);
|
||||
if (pa(0) > pb(0))
|
||||
std::swap(pa(0), pb(0));
|
||||
if (pa(1) > pb(1))
|
||||
std::swap(pa(1), pb(1));
|
||||
assert(px(0) >= pa(0) && px(0) <= pb(0));
|
||||
assert(px(1) >= pa(1) && px(1) <= pb(1));
|
||||
}
|
||||
#endif /* SLIC3R_DEBUG */
|
||||
const Point *pPrev = &p1;
|
||||
@@ -55,14 +55,14 @@ static inline coordf_t segment_length(const Polygon &poly, size_t seg1, const Po
|
||||
coordf_t len = 0;
|
||||
if (seg1 <= seg2) {
|
||||
for (size_t i = seg1; i < seg2; ++ i, pPrev = pThis)
|
||||
len += pPrev->distance_to(*(pThis = &poly.points[i]));
|
||||
len += (*pPrev - *(pThis = &poly.points[i])).cast<double>().norm();
|
||||
} else {
|
||||
for (size_t i = seg1; i < poly.points.size(); ++ i, pPrev = pThis)
|
||||
len += pPrev->distance_to(*(pThis = &poly.points[i]));
|
||||
len += (*pPrev - *(pThis = &poly.points[i])).cast<double>().norm();
|
||||
for (size_t i = 0; i < seg2; ++ i, pPrev = pThis)
|
||||
len += pPrev->distance_to(*(pThis = &poly.points[i]));
|
||||
len += (*pPrev - *(pThis = &poly.points[i])).cast<double>().norm();
|
||||
}
|
||||
len += pPrev->distance_to(p2);
|
||||
len += (*pPrev - p2).cast<double>().norm();
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -791,15 +791,15 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP
|
||||
|
||||
// define flow spacing according to requested density
|
||||
if (params.full_infill() && !params.dont_adjust) {
|
||||
line_spacing = this->_adjust_solid_spacing(bounding_box.size().x, line_spacing);
|
||||
this->spacing = unscale(line_spacing);
|
||||
line_spacing = this->_adjust_solid_spacing(bounding_box.size()(0), line_spacing);
|
||||
this->spacing = unscale<double>(line_spacing);
|
||||
} else {
|
||||
// extend bounding box so that our pattern will be aligned with other layers
|
||||
// Transform the reference point to the rotated coordinate system.
|
||||
Point refpt = rotate_vector.second.rotated(- rotate_vector.first);
|
||||
// _align_to_grid will not work correctly with positive pattern_shift.
|
||||
coord_t pattern_shift_scaled = coord_t(scale_(pattern_shift)) % line_spacing;
|
||||
refpt.x -= (pattern_shift_scaled >= 0) ? pattern_shift_scaled : (line_spacing + pattern_shift_scaled);
|
||||
refpt(0) -= (pattern_shift_scaled >= 0) ? pattern_shift_scaled : (line_spacing + pattern_shift_scaled);
|
||||
bounding_box.merge(_align_to_grid(
|
||||
bounding_box.min,
|
||||
Point(line_spacing, line_spacing),
|
||||
@@ -808,8 +808,8 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP
|
||||
|
||||
// Intersect a set of euqally spaced vertical lines wiht expolygon.
|
||||
// n_vlines = ceil(bbox_width / line_spacing)
|
||||
size_t n_vlines = (bounding_box.max.x - bounding_box.min.x + line_spacing - 1) / line_spacing;
|
||||
coord_t x0 = bounding_box.min.x;
|
||||
size_t n_vlines = (bounding_box.max(0) - bounding_box.min(0) + line_spacing - 1) / line_spacing;
|
||||
coord_t x0 = bounding_box.min(0);
|
||||
if (params.full_infill())
|
||||
x0 += (line_spacing + SCALED_EPSILON) / 2;
|
||||
|
||||
@@ -842,8 +842,8 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP
|
||||
const Point &p1 = contour[iPrev];
|
||||
const Point &p2 = contour[iSegment];
|
||||
// Which of the equally spaced vertical lines is intersected by this segment?
|
||||
coord_t l = p1.x;
|
||||
coord_t r = p2.x;
|
||||
coord_t l = p1(0);
|
||||
coord_t r = p2(0);
|
||||
if (l > r)
|
||||
std::swap(l, r);
|
||||
// il, ir are the left / right indices of vertical lines intersecting a segment
|
||||
@@ -869,33 +869,33 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP
|
||||
assert(l <= this_x);
|
||||
assert(r >= this_x);
|
||||
// Calculate the intersection position in y axis. x is known.
|
||||
if (p1.x == this_x) {
|
||||
if (p2.x == this_x) {
|
||||
if (p1(0) == this_x) {
|
||||
if (p2(0) == this_x) {
|
||||
// Ignore strictly vertical segments.
|
||||
continue;
|
||||
}
|
||||
is.pos_p = p1.y;
|
||||
is.pos_p = p1(1);
|
||||
is.pos_q = 1;
|
||||
} else if (p2.x == this_x) {
|
||||
is.pos_p = p2.y;
|
||||
} else if (p2(0) == this_x) {
|
||||
is.pos_p = p2(1);
|
||||
is.pos_q = 1;
|
||||
} else {
|
||||
// First calculate the intersection parameter 't' as a rational number with non negative denominator.
|
||||
if (p2.x > p1.x) {
|
||||
is.pos_p = this_x - p1.x;
|
||||
is.pos_q = p2.x - p1.x;
|
||||
if (p2(0) > p1(0)) {
|
||||
is.pos_p = this_x - p1(0);
|
||||
is.pos_q = p2(0) - p1(0);
|
||||
} else {
|
||||
is.pos_p = p1.x - this_x;
|
||||
is.pos_q = p1.x - p2.x;
|
||||
is.pos_p = p1(0) - this_x;
|
||||
is.pos_q = p1(0) - p2(0);
|
||||
}
|
||||
assert(is.pos_p >= 0 && is.pos_p <= is.pos_q);
|
||||
// Make an intersection point from the 't'.
|
||||
is.pos_p *= int64_t(p2.y - p1.y);
|
||||
is.pos_p += p1.y * int64_t(is.pos_q);
|
||||
is.pos_p *= int64_t(p2(1) - p1(1));
|
||||
is.pos_p += p1(1) * int64_t(is.pos_q);
|
||||
}
|
||||
// +-1 to take rounding into account.
|
||||
assert(is.pos() + 1 >= std::min(p1.y, p2.y));
|
||||
assert(is.pos() <= std::max(p1.y, p2.y) + 1);
|
||||
assert(is.pos() + 1 >= std::min(p1(1), p2(1)));
|
||||
assert(is.pos() <= std::max(p1(1), p2(1)) + 1);
|
||||
segs[i].intersections.push_back(is);
|
||||
}
|
||||
}
|
||||
@@ -919,7 +919,7 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP
|
||||
const Points &contour = poly_with_offset.contour(iContour).points;
|
||||
size_t iSegment = sil.intersections[i].iSegment;
|
||||
size_t iPrev = ((iSegment == 0) ? contour.size() : iSegment) - 1;
|
||||
coord_t dir = contour[iSegment].x - contour[iPrev].x;
|
||||
coord_t dir = contour[iSegment](0) - contour[iPrev](0);
|
||||
bool low = dir > 0;
|
||||
sil.intersections[i].type = poly_with_offset.is_contour_outer(iContour) ?
|
||||
(low ? SegmentIntersection::OUTER_LOW : SegmentIntersection::OUTER_HIGH) :
|
||||
@@ -1066,7 +1066,7 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP
|
||||
intrsctn.consumed_vertical_up :
|
||||
seg.intersections[i-1].consumed_vertical_up;
|
||||
if (! consumed) {
|
||||
coordf_t dist2 = sqr(coordf_t(pointLast.x - seg.pos)) + sqr(coordf_t(pointLast.y - intrsctn.pos()));
|
||||
coordf_t dist2 = sqr(coordf_t(pointLast(0) - seg.pos)) + sqr(coordf_t(pointLast(1) - intrsctn.pos()));
|
||||
if (dist2 < dist2min) {
|
||||
dist2min = dist2;
|
||||
i_vline = i_vline2;
|
||||
@@ -1356,8 +1356,8 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP
|
||||
// Handle nearly zero length edges.
|
||||
if (polyline_current->points.size() <= 1 ||
|
||||
(polyline_current->points.size() == 2 &&
|
||||
std::abs(polyline_current->points.front().x - polyline_current->points.back().x) < SCALED_EPSILON &&
|
||||
std::abs(polyline_current->points.front().y - polyline_current->points.back().y) < SCALED_EPSILON))
|
||||
std::abs(polyline_current->points.front()(0) - polyline_current->points.back()(0)) < SCALED_EPSILON &&
|
||||
std::abs(polyline_current->points.front()(1) - polyline_current->points.back()(1)) < SCALED_EPSILON))
|
||||
polylines_out.pop_back();
|
||||
intrsctn = NULL;
|
||||
i_intersection = -1;
|
||||
@@ -1383,7 +1383,7 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP
|
||||
// paths must be rotated back
|
||||
for (Polylines::iterator it = polylines_out.begin() + n_polylines_out_initial; it != polylines_out.end(); ++ it) {
|
||||
// No need to translate, the absolute position is irrelevant.
|
||||
// it->translate(- rotate_vector.second.x, - rotate_vector.second.y);
|
||||
// it->translate(- rotate_vector.second(0), - rotate_vector.second(1));
|
||||
assert(! it->has_duplicate_points());
|
||||
it->rotate(rotate_vector.first);
|
||||
//FIXME rather simplify the paths to avoid very short edges?
|
||||
|
||||
@@ -217,30 +217,30 @@ Point SegmentIntersection::pos() const
|
||||
const Point &seg_start = poly.points[(this->iSegment == 0) ? poly.points.size() - 1 : this->iSegment - 1];
|
||||
const Point &seg_end = poly.points[this->iSegment];
|
||||
// Point, vector of the segment.
|
||||
const Pointf p1 = convert_to<Pointf>(seg_start);
|
||||
const Pointf v1 = convert_to<Pointf>(seg_end - seg_start);
|
||||
const Vec2d p1(seg_start.cast<coordf_t>());
|
||||
const Vec2d v1((seg_end - seg_start).cast<coordf_t>());
|
||||
// Point, vector of this hatching line.
|
||||
const Pointf p2 = convert_to<Pointf>(line->pos);
|
||||
const Pointf v2 = convert_to<Pointf>(line->dir);
|
||||
const Vec2d p2(line->pos.cast<coordf_t>());
|
||||
const Vec2d v2(line->dir.cast<coordf_t>());
|
||||
// Intersect the two rays.
|
||||
double denom = v1.x * v2.y - v2.x * v1.y;
|
||||
double denom = v1(0) * v2(1) - v2(0) * v1(1);
|
||||
Point out;
|
||||
if (denom == 0.) {
|
||||
// Lines are collinear. As the pos() method is not supposed to be called on collinear vectors,
|
||||
// the source vectors are not quite collinear. Return the center of the contour segment.
|
||||
out = seg_start + seg_end;
|
||||
out.x >>= 1;
|
||||
out.y >>= 1;
|
||||
out(0) >>= 1;
|
||||
out(1) >>= 1;
|
||||
} else {
|
||||
// Find the intersection point.
|
||||
double t = (v2.x * (p1.y - p2.y) - v2.y * (p1.x - p2.x)) / denom;
|
||||
double t = (v2(0) * (p1(1) - p2(1)) - v2(1) * (p1(0) - p2(0))) / denom;
|
||||
if (t < 0.)
|
||||
out = seg_start;
|
||||
else if (t > 1.)
|
||||
out = seg_end;
|
||||
else {
|
||||
out.x = coord_t(floor(p1.x + t * v1.x + 0.5));
|
||||
out.y = coord_t(floor(p1.y + t * v1.y + 0.5));
|
||||
out(0) = coord_t(floor(p1(0) + t * v1(0) + 0.5));
|
||||
out(1) = coord_t(floor(p1(1) + t * v1(1) + 0.5));
|
||||
}
|
||||
}
|
||||
return out;
|
||||
@@ -276,13 +276,13 @@ int SegmentIntersection::ordering_along_line(const SegmentIntersection &other) c
|
||||
// other.iSegment succeeds this->iSegment
|
||||
assert(seg_end_a == seg_start_b);
|
||||
// Avoid calling the 128bit x 128bit multiplication below if this->line intersects the common point.
|
||||
if (cross(this->line->dir, seg_end_b - this->line->pos) == 0)
|
||||
if (cross2(Vec2i64(this->line->dir.cast<int64_t>()), (seg_end_b - this->line->pos).cast<int64_t>()) == 0)
|
||||
return 0;
|
||||
} else if ((other.iSegment + 1) % poly_a.points.size() == this->iSegment) {
|
||||
// this->iSegment succeeds other.iSegment
|
||||
assert(seg_start_a == seg_end_b);
|
||||
// Avoid calling the 128bit x 128bit multiplication below if this->line intersects the common point.
|
||||
if (cross(this->line->dir, seg_start_a - this->line->pos) == 0)
|
||||
if (cross2(Vec2i64(this->line->dir.cast<int64_t>()), (seg_start_a - this->line->pos).cast<int64_t>()) == 0)
|
||||
return 0;
|
||||
} else {
|
||||
// General case.
|
||||
@@ -290,35 +290,35 @@ int SegmentIntersection::ordering_along_line(const SegmentIntersection &other) c
|
||||
}
|
||||
|
||||
// First test, whether both points of one segment are completely in one half-plane of the other line.
|
||||
const Point vec_b = seg_end_b - seg_start_b;
|
||||
int side_start = signum(cross(vec_b, seg_start_a - seg_start_b));
|
||||
int side_end = signum(cross(vec_b, seg_end_a - seg_start_b));
|
||||
const Vec2i64 vec_b = (seg_end_b - seg_start_b).cast<int64_t>();
|
||||
int side_start = signum(cross2(vec_b, (seg_start_a - seg_start_b).cast<int64_t>()));
|
||||
int side_end = signum(cross2(vec_b, (seg_end_a - seg_start_b).cast<int64_t>()));
|
||||
int side = side_start * side_end;
|
||||
if (side > 0)
|
||||
// This segment is completely inside one half-plane of the other line, therefore the ordering is trivial.
|
||||
return signum(cross(vec_b, this->line->dir)) * side_start;
|
||||
return signum(cross2(vec_b, this->line->dir.cast<int64_t>())) * side_start;
|
||||
|
||||
const Point vec_a = seg_end_a - seg_start_a;
|
||||
int side_start2 = signum(cross(vec_a, seg_start_b - seg_start_a));
|
||||
int side_end2 = signum(cross(vec_a, seg_end_b - seg_start_a));
|
||||
const Vec2i64 vec_a = (seg_end_a - seg_start_a).cast<int64_t>();
|
||||
int side_start2 = signum(cross2(vec_a, (seg_start_b - seg_start_a).cast<int64_t>()));
|
||||
int side_end2 = signum(cross2(vec_a, (seg_end_b - seg_start_a).cast<int64_t>()));
|
||||
int side2 = side_start2 * side_end2;
|
||||
//if (side == 0 && side2 == 0)
|
||||
// The segments share one of their end points.
|
||||
if (side2 > 0)
|
||||
// This segment is completely inside one half-plane of the other line, therefore the ordering is trivial.
|
||||
return signum(cross(this->line->dir, vec_a)) * side_start2;
|
||||
return signum(cross2(this->line->dir.cast<int64_t>(), vec_a)) * side_start2;
|
||||
|
||||
// The two segments intersect and they are not sucessive segments of the same contour.
|
||||
// Ordering of the points depends on the position of the segment intersection (left / right from this->line),
|
||||
// therefore a simple test over the input segment end points is not sufficient.
|
||||
|
||||
// Find the parameters of intersection of the two segmetns with this->line.
|
||||
int64_t denom1 = cross(this->line->dir, vec_a);
|
||||
int64_t denom2 = cross(this->line->dir, vec_b);
|
||||
Point vx_a = seg_start_a - this->line->pos;
|
||||
Point vx_b = seg_start_b - this->line->pos;
|
||||
int64_t t1_times_denom1 = int64_t(vx_a.x) * int64_t(vec_a.y) - int64_t(vx_a.y) * int64_t(vec_a.x);
|
||||
int64_t t2_times_denom2 = int64_t(vx_b.x) * int64_t(vec_b.y) - int64_t(vx_b.y) * int64_t(vec_b.x);
|
||||
int64_t denom1 = cross2(this->line->dir.cast<int64_t>(), vec_a);
|
||||
int64_t denom2 = cross2(this->line->dir.cast<int64_t>(), vec_b);
|
||||
Vec2i64 vx_a = (seg_start_a - this->line->pos).cast<int64_t>();
|
||||
Vec2i64 vx_b = (seg_start_b - this->line->pos).cast<int64_t>();
|
||||
int64_t t1_times_denom1 = vx_a(0) * vec_a(1) - vx_a(1) * vec_a(0);
|
||||
int64_t t2_times_denom2 = vx_b(0) * vec_b(1) - vx_b(1) * vec_b(0);
|
||||
assert(denom1 != 0);
|
||||
assert(denom2 != 0);
|
||||
return Int128::compare_rationals_filtered(t1_times_denom1, denom1, t2_times_denom2, denom2);
|
||||
@@ -330,7 +330,7 @@ bool SegmentIntersection::operator<(const SegmentIntersection &other) const
|
||||
#ifdef _DEBUG
|
||||
Point p1 = this->pos();
|
||||
Point p2 = other.pos();
|
||||
int64_t d = dot(this->line->dir, p2 - p1);
|
||||
int64_t d = this->line->dir.cast<int64_t>().dot((p2 - p1).cast<int64_t>());
|
||||
#endif /* _DEBUG */
|
||||
int ordering = this->ordering_along_line(other);
|
||||
#ifdef _DEBUG
|
||||
@@ -389,16 +389,16 @@ static bool prepare_infill_hatching_segments(
|
||||
// Define the flow spacing according to requested density.
|
||||
if (params.full_infill() && ! params.dont_adjust) {
|
||||
// Full infill, adjust the line spacing to fit an integer number of lines.
|
||||
out.line_spacing = Fill::_adjust_solid_spacing(bounding_box.size().x, line_spacing);
|
||||
out.line_spacing = Fill::_adjust_solid_spacing(bounding_box.size()(0), line_spacing);
|
||||
// Report back the adjusted line spacing.
|
||||
fill_dir_params.spacing = float(unscale(line_spacing));
|
||||
fill_dir_params.spacing = unscale<double>(line_spacing);
|
||||
} else {
|
||||
// Extend bounding box so that our pattern will be aligned with the other layers.
|
||||
// Transform the reference point to the rotated coordinate system.
|
||||
Point refpt = rotate_vector.second.rotated(- out.angle);
|
||||
// _align_to_grid will not work correctly with positive pattern_shift.
|
||||
coord_t pattern_shift_scaled = coord_t(scale_(fill_dir_params.pattern_shift)) % line_spacing;
|
||||
refpt.x -= (pattern_shift_scaled >= 0) ? pattern_shift_scaled : (line_spacing + pattern_shift_scaled);
|
||||
refpt(0) -= (pattern_shift_scaled >= 0) ? pattern_shift_scaled : (line_spacing + pattern_shift_scaled);
|
||||
bounding_box.merge(Fill::_align_to_grid(
|
||||
bounding_box.min,
|
||||
Point(line_spacing, line_spacing),
|
||||
@@ -407,13 +407,13 @@ static bool prepare_infill_hatching_segments(
|
||||
|
||||
// Intersect a set of euqally spaced vertical lines wiht expolygon.
|
||||
// n_vlines = ceil(bbox_width / line_spacing)
|
||||
size_t n_vlines = (bounding_box.max.x - bounding_box.min.x + line_spacing - 1) / line_spacing;
|
||||
coord_t x0 = bounding_box.min.x;
|
||||
size_t n_vlines = (bounding_box.max(0) - bounding_box.min(0) + line_spacing - 1) / line_spacing;
|
||||
coord_t x0 = bounding_box.min(0);
|
||||
if (params.full_infill())
|
||||
x0 += coord_t((line_spacing + SCALED_EPSILON) / 2);
|
||||
|
||||
out.line_spacing = line_spacing;
|
||||
out.start_point = Point(x0, bounding_box.min.y);
|
||||
out.start_point = Point(x0, bounding_box.min(1));
|
||||
out.start_point.rotate(out.angle);
|
||||
|
||||
#ifdef SLIC3R_DEBUG
|
||||
@@ -436,10 +436,10 @@ static bool prepare_infill_hatching_segments(
|
||||
for (size_t i = 0; i < n_vlines; ++ i) {
|
||||
auto &seg = out.segs[i];
|
||||
seg.idx = i;
|
||||
// seg.x = x0 + coord_t(i) * line_spacing;
|
||||
// seg(0) = x0 + coord_t(i) * line_spacing;
|
||||
coord_t x = x0 + coord_t(i) * line_spacing;
|
||||
seg.pos.x = coord_t(floor(cos_a * x - sin_a * bounding_box.min.y + 0.5));
|
||||
seg.pos.y = coord_t(floor(cos_a * bounding_box.min.y + sin_a * x + 0.5));
|
||||
seg.pos(0) = coord_t(floor(cos_a * x - sin_a * bounding_box.min(1) + 0.5));
|
||||
seg.pos(1) = coord_t(floor(cos_a * bounding_box.min(1) + sin_a * x + 0.5));
|
||||
seg.dir = out.direction;
|
||||
}
|
||||
|
||||
@@ -454,7 +454,7 @@ static bool prepare_infill_hatching_segments(
|
||||
const Point *pr = &contour[iSegment];
|
||||
// Orient the segment to the direction vector.
|
||||
const Point v = *pr - *pl;
|
||||
int orientation = Int128::sign_determinant_2x2_filtered(v.x, v.y, out.direction.x, out.direction.y);
|
||||
int orientation = Int128::sign_determinant_2x2_filtered(v(0), v(1), out.direction(0), out.direction(1));
|
||||
if (orientation == 0)
|
||||
// Ignore strictly vertical segments.
|
||||
continue;
|
||||
@@ -462,26 +462,26 @@ static bool prepare_infill_hatching_segments(
|
||||
// Always orient the input segment consistently towards the hatching direction.
|
||||
std::swap(pl, pr);
|
||||
// Which of the equally spaced vertical lines is intersected by this segment?
|
||||
coord_t l = (coord_t)floor(cos_a * pl->x + sin_a * pl->y - SCALED_EPSILON);
|
||||
coord_t r = (coord_t)ceil (cos_a * pr->x + sin_a * pr->y + SCALED_EPSILON);
|
||||
coord_t l = (coord_t)floor(cos_a * (*pl)(0) + sin_a * (*pl)(1) - SCALED_EPSILON);
|
||||
coord_t r = (coord_t)ceil (cos_a * (*pr)(0) + sin_a * (*pr)(1) + SCALED_EPSILON);
|
||||
assert(l < r - SCALED_EPSILON);
|
||||
// il, ir are the left / right indices of vertical lines intersecting a segment
|
||||
int il = std::max<int>(0, (l - x0 + line_spacing) / line_spacing);
|
||||
int ir = std::min<int>(int(out.segs.size()) - 1, (r - x0) / line_spacing);
|
||||
// The previous tests were done with floating point arithmetics over an epsilon-extended interval.
|
||||
// Now do the same tests with exact arithmetics over the exact interval.
|
||||
while (il <= ir && Int128::orient(out.segs[il].pos, out.segs[il].pos + out.direction, *pl) < 0)
|
||||
while (il <= ir && int128::orient(out.segs[il].pos, out.segs[il].pos + out.direction, *pl) < 0)
|
||||
++ il;
|
||||
while (il <= ir && Int128::orient(out.segs[ir].pos, out.segs[ir].pos + out.direction, *pr) > 0)
|
||||
while (il <= ir && int128::orient(out.segs[ir].pos, out.segs[ir].pos + out.direction, *pr) > 0)
|
||||
-- ir;
|
||||
// Here it is ensured, that
|
||||
// 1) out.seg is not parallel to (pl, pr)
|
||||
// 2) all lines from il to ir intersect <pl, pr>.
|
||||
assert(il >= 0 && ir < int(out.segs.size()));
|
||||
for (int i = il; i <= ir; ++ i) {
|
||||
// assert(out.segs[i].x == i * line_spacing + x0);
|
||||
// assert(l <= out.segs[i].x);
|
||||
// assert(r >= out.segs[i].x);
|
||||
// assert(out.segs[i](0) == i * line_spacing + x0);
|
||||
// assert(l <= out.segs[i](0));
|
||||
// assert(r >= out.segs[i](0));
|
||||
SegmentIntersection is;
|
||||
is.line = &out.segs[i];
|
||||
is.expoly_with_offset = &poly_with_offset;
|
||||
@@ -489,12 +489,12 @@ static bool prepare_infill_hatching_segments(
|
||||
is.iSegment = iSegment;
|
||||
// Test whether the calculated intersection point falls into the bounding box of the input segment.
|
||||
// +-1 to take rounding into account.
|
||||
assert(Int128::orient(out.segs[i].pos, out.segs[i].pos + out.direction, *pl) >= 0);
|
||||
assert(Int128::orient(out.segs[i].pos, out.segs[i].pos + out.direction, *pr) <= 0);
|
||||
assert(is.pos().x + 1 >= std::min(pl->x, pr->x));
|
||||
assert(is.pos().y + 1 >= std::min(pl->y, pr->y));
|
||||
assert(is.pos().x <= std::max(pl->x, pr->x) + 1);
|
||||
assert(is.pos().y <= std::max(pl->y, pr->y) + 1);
|
||||
assert(int128::orient(out.segs[i].pos, out.segs[i].pos + out.direction, *pl) >= 0);
|
||||
assert(int128::orient(out.segs[i].pos, out.segs[i].pos + out.direction, *pr) <= 0);
|
||||
assert(is.pos()(0) + 1 >= std::min((*pl)(0), (*pr)(0)));
|
||||
assert(is.pos()(1) + 1 >= std::min((*pl)(1), (*pr)(1)));
|
||||
assert(is.pos()(0) <= std::max((*pl)(0), (*pr)(0)) + 1);
|
||||
assert(is.pos()(1) <= std::max((*pl)(1), (*pr)(1)) + 1);
|
||||
out.segs[i].intersections.push_back(is);
|
||||
}
|
||||
}
|
||||
@@ -510,7 +510,7 @@ static bool prepare_infill_hatching_segments(
|
||||
for (size_t i = 1; i < sil.intersections.size(); ++ i) {
|
||||
Point p1 = sil.intersections[i - 1].pos();
|
||||
Point p2 = sil.intersections[i].pos();
|
||||
int64_t d = dot(sil.dir, p2 - p1);
|
||||
int64_t d = sil.dir.cast<int64_t>().dot((p2 - p1).cast<int64_t>());
|
||||
assert(d >= - int64_t(SCALED_EPSILON));
|
||||
}
|
||||
#endif /* _DEBUG */
|
||||
@@ -527,7 +527,7 @@ static bool prepare_infill_hatching_segments(
|
||||
const Points &contour = poly_with_offset.contour(iContour).points;
|
||||
size_t iSegment = sil.intersections[i].iSegment;
|
||||
size_t iPrev = ((iSegment == 0) ? contour.size() : iSegment) - 1;
|
||||
int dir = Int128::cross(contour[iSegment] - contour[iPrev], sil.dir);
|
||||
int dir = int128::cross(contour[iSegment] - contour[iPrev], sil.dir);
|
||||
bool low = dir > 0;
|
||||
sil.intersections[i].type = poly_with_offset.is_contour_outer(iContour) ?
|
||||
(low ? SegmentIntersection::OUTER_LOW : SegmentIntersection::OUTER_HIGH) :
|
||||
@@ -659,12 +659,12 @@ static inline coordf_t segment_length(const Polygon &poly, size_t seg1, const Po
|
||||
Point px = (i == 0) ? p1 : p2;
|
||||
Point pa = poly.points[((seg == 0) ? poly.points.size() : seg) - 1];
|
||||
Point pb = poly.points[seg];
|
||||
if (pa.x > pb.x)
|
||||
std::swap(pa.x, pb.x);
|
||||
if (pa.y > pb.y)
|
||||
std::swap(pa.y, pb.y);
|
||||
assert(px.x >= pa.x && px.x <= pb.x);
|
||||
assert(px.y >= pa.y && px.y <= pb.y);
|
||||
if (pa(0) > pb(0))
|
||||
std::swap(pa(0), pb(0));
|
||||
if (pa(1) > pb(1))
|
||||
std::swap(pa(1), pb(1));
|
||||
assert(px(0) >= pa(0) && px(0) <= pb(0));
|
||||
assert(px(1) >= pa(1) && px(1) <= pb(1));
|
||||
}
|
||||
#endif /* SLIC3R_DEBUG */
|
||||
const Point *pPrev = &p1;
|
||||
@@ -672,14 +672,14 @@ static inline coordf_t segment_length(const Polygon &poly, size_t seg1, const Po
|
||||
coordf_t len = 0;
|
||||
if (seg1 <= seg2) {
|
||||
for (size_t i = seg1; i < seg2; ++ i, pPrev = pThis)
|
||||
len += pPrev->distance_to(*(pThis = &poly.points[i]));
|
||||
len += (*pPrev - *(pThis = &poly.points[i])).cast<double>().norm();
|
||||
} else {
|
||||
for (size_t i = seg1; i < poly.points.size(); ++ i, pPrev = pThis)
|
||||
len += pPrev->distance_to(*(pThis = &poly.points[i]));
|
||||
len += (*pPrev - *(pThis = &poly.points[i])).cast<double>().norm();
|
||||
for (size_t i = 0; i < seg2; ++ i, pPrev = pThis)
|
||||
len += pPrev->distance_to(*(pThis = &poly.points[i]));
|
||||
len += (*pPrev - *(pThis = &poly.points[i])).cast<double>().norm();
|
||||
}
|
||||
len += pPrev->distance_to(p2);
|
||||
len += (*pPrev - p2).cast<double>().norm();
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -1191,7 +1191,7 @@ static bool fill_hatching_segments_legacy(
|
||||
intrsctn.consumed_vertical_up :
|
||||
seg.intersections[i-1].consumed_vertical_up;
|
||||
if (! consumed) {
|
||||
coordf_t dist2 = pointLast.distance_to(intrsctn.pos());
|
||||
coordf_t dist2 = (intrsctn.pos() - pointLast).cast<double>().norm();
|
||||
if (dist2 < dist2min) {
|
||||
dist2min = dist2;
|
||||
i_vline = i_vline2;
|
||||
@@ -1481,8 +1481,8 @@ static bool fill_hatching_segments_legacy(
|
||||
// Handle nearly zero length edges.
|
||||
if (polyline_current->points.size() <= 1 ||
|
||||
(polyline_current->points.size() == 2 &&
|
||||
std::abs(polyline_current->points.front().x - polyline_current->points.back().x) < SCALED_EPSILON &&
|
||||
std::abs(polyline_current->points.front().y - polyline_current->points.back().y) < SCALED_EPSILON))
|
||||
std::abs(polyline_current->points.front()(0) - polyline_current->points.back()(0)) < SCALED_EPSILON &&
|
||||
std::abs(polyline_current->points.front()(1) - polyline_current->points.back()(1)) < SCALED_EPSILON))
|
||||
polylines_out.pop_back();
|
||||
intrsctn = NULL;
|
||||
i_intersection = -1;
|
||||
@@ -1510,7 +1510,7 @@ static bool fill_hatching_segments_legacy(
|
||||
// paths must be rotated back
|
||||
for (Polylines::iterator it = polylines_out.begin() + n_polylines_out_initial; it != polylines_out.end(); ++ it) {
|
||||
// No need to translate, the absolute position is irrelevant.
|
||||
// it->translate(- rotate_vector.second.x, - rotate_vector.second.y);
|
||||
// it->translate(- rotate_vector.second(0), - rotate_vector.second(1));
|
||||
assert(! it->has_duplicate_points());
|
||||
//it->rotate(rotate_vector.first);
|
||||
//FIXME rather simplify the paths to avoid very short edges?
|
||||
|
||||
Reference in New Issue
Block a user