Removed Point::scale(),translate(),coincides_with(),distance_to(),

distance_to_squared(),perp_distance_to(),negative(),vector_to(),
translate(), distance_to() etc,
replaced with the Eigen equivalents.
This commit is contained in:
bubnikv 2018-08-17 14:14:24 +02:00
parent 3b89717149
commit 1ba64da3fe
45 changed files with 526 additions and 792 deletions

View file

@ -68,8 +68,8 @@ BoundingBox BoundingBox::rotated(double angle, const Point &center) const
template <class PointClass> void template <class PointClass> void
BoundingBoxBase<PointClass>::scale(double factor) BoundingBoxBase<PointClass>::scale(double factor)
{ {
this->min.scale(factor); this->min *= factor;
this->max.scale(factor); this->max *= factor;
} }
template void BoundingBoxBase<Point>::scale(double factor); template void BoundingBoxBase<Point>::scale(double factor);
template void BoundingBoxBase<Pointf>::scale(double factor); template void BoundingBoxBase<Pointf>::scale(double factor);
@ -188,8 +188,9 @@ template double BoundingBox3Base<Pointf3>::radius() const;
template <class PointClass> void template <class PointClass> void
BoundingBoxBase<PointClass>::offset(coordf_t delta) BoundingBoxBase<PointClass>::offset(coordf_t delta)
{ {
this->min.translate(-delta, -delta); PointClass v(delta, delta);
this->max.translate(delta, delta); this->min -= v;
this->max += v;
} }
template void BoundingBoxBase<Point>::offset(coordf_t delta); template void BoundingBoxBase<Point>::offset(coordf_t delta);
template void BoundingBoxBase<Pointf>::offset(coordf_t delta); template void BoundingBoxBase<Pointf>::offset(coordf_t delta);
@ -197,8 +198,9 @@ template void BoundingBoxBase<Pointf>::offset(coordf_t delta);
template <class PointClass> void template <class PointClass> void
BoundingBox3Base<PointClass>::offset(coordf_t delta) BoundingBox3Base<PointClass>::offset(coordf_t delta)
{ {
this->min.translate(-delta, -delta, -delta); PointClass v(delta, delta, delta);
this->max.translate(delta, delta, delta); this->min -= v;
this->max += v;
} }
template void BoundingBox3Base<Pointf3>::offset(coordf_t delta); template void BoundingBox3Base<Pointf3>::offset(coordf_t delta);

View file

@ -46,8 +46,8 @@ public:
void scale(double factor); void scale(double factor);
PointClass size() const; PointClass size() const;
double radius() const; double radius() const;
void translate(coordf_t x, coordf_t y) { assert(this->defined); this->min.translate(x, y); this->max.translate(x, y); } void translate(coordf_t x, coordf_t y) { assert(this->defined); PointClass v(x, y); this->min += v; this->max += v; }
void translate(const Pointf &pos) { this->translate(pos.x(), pos.y()); } void translate(const Pointf &v) { this->min += v; this->max += v; }
void offset(coordf_t delta); void offset(coordf_t delta);
PointClass center() const; PointClass center() const;
bool contains(const PointClass &point) const { bool contains(const PointClass &point) const {
@ -90,8 +90,8 @@ public:
void merge(const BoundingBox3Base<PointClass> &bb); void merge(const BoundingBox3Base<PointClass> &bb);
PointClass size() const; PointClass size() const;
double radius() const; double radius() const;
void translate(coordf_t x, coordf_t y, coordf_t z) { this->min.translate(x, y, z); this->max.translate(x, y, z); } void translate(coordf_t x, coordf_t y, coordf_t z) { assert(this->defined); PointClass v(x, y, z); this->min += v; this->max += v; }
void translate(const Pointf3 &pos) { this->translate(pos.x(), pos.y(), pos.z()); } void translate(const Pointf3 &v) { this->min += v; this->max += v; }
void offset(coordf_t delta); void offset(coordf_t delta);
PointClass center() const; PointClass center() const;
coordf_t max_size() const; coordf_t max_size() const;

View file

@ -282,10 +282,12 @@ BridgeDetector::unsupported_edges(double angle, Polylines* unsupported) const
extrusions would be anchored within such length (i.e. a slightly non-parallel bridging extrusions would be anchored within such length (i.e. a slightly non-parallel bridging
direction might still benefit from anchors if long enough) direction might still benefit from anchors if long enough)
double angle_tolerance = PI / 180.0 * 5.0; */ double angle_tolerance = PI / 180.0 * 5.0; */
for (Lines::const_iterator line = unsupported_lines.begin(); line != unsupported_lines.end(); ++line) { for (const Line &line : unsupported_lines)
if (!Slic3r::Geometry::directions_parallel(line->direction(), angle)) if (! Slic3r::Geometry::directions_parallel(line.direction(), angle)) {
unsupported->push_back(*line); unsupported->emplace_back(Polyline());
} unsupported->back().points.emplace_back(line.a);
unsupported->back().points.emplace_back(line.b);
}
} }
/* /*

View file

@ -634,8 +634,8 @@ _clipper_ln(ClipperLib::ClipType clipType, const Lines &subject, const Polygons
// convert Lines to Polylines // convert Lines to Polylines
Polylines polylines; Polylines polylines;
polylines.reserve(subject.size()); polylines.reserve(subject.size());
for (Lines::const_iterator line = subject.begin(); line != subject.end(); ++line) for (const Line &line : subject)
polylines.push_back(*line); polylines.emplace_back(Polyline(line.a, line.b));
// perform operation // perform operation
polylines = _clipper_pl(clipType, polylines, clip, safety_offset_); polylines = _clipper_pl(clipType, polylines, clip, safety_offset_);

View file

@ -767,7 +767,7 @@ void EdgeGrid::Grid::calculate_sdf()
const Slic3r::Point &p1 = pts[ipt]; const Slic3r::Point &p1 = pts[ipt];
const Slic3r::Point &p2 = pts[(ipt + 1 == pts.size()) ? 0 : ipt + 1]; const Slic3r::Point &p2 = pts[(ipt + 1 == pts.size()) ? 0 : ipt + 1];
// Segment vector // Segment vector
const Slic3r::Point v_seg = p1.vector_to(p2); const Slic3r::Point v_seg = p2 - p1;
// l2 of v_seg // l2 of v_seg
const int64_t l2_seg = int64_t(v_seg.x()) * int64_t(v_seg.x()) + int64_t(v_seg.y()) * int64_t(v_seg.y()); const int64_t l2_seg = int64_t(v_seg.x()) * int64_t(v_seg.x()) + int64_t(v_seg.y()) * int64_t(v_seg.y());
// For each corner of this cell and its 1 ring neighbours: // For each corner of this cell and its 1 ring neighbours:
@ -781,7 +781,7 @@ void EdgeGrid::Grid::calculate_sdf()
continue; continue;
float &d_min = m_signed_distance_field[corner_r * ncols + corner_c]; float &d_min = m_signed_distance_field[corner_r * ncols + corner_c];
Slic3r::Point pt(m_bbox.min.x() + corner_c * m_resolution, m_bbox.min.y() + corner_r * m_resolution); Slic3r::Point pt(m_bbox.min.x() + corner_c * m_resolution, m_bbox.min.y() + corner_r * m_resolution);
Slic3r::Point v_pt = p1.vector_to(pt); Slic3r::Point v_pt = pt - p1;
// dot(p2-p1, pt-p1) // dot(p2-p1, pt-p1)
int64_t t_pt = int64_t(v_seg.x()) * int64_t(v_pt.x()) + int64_t(v_seg.y()) * int64_t(v_pt.y()); int64_t t_pt = int64_t(v_seg.x()) * int64_t(v_pt.x()) + int64_t(v_seg.y()) * int64_t(v_pt.y());
if (t_pt < 0) { if (t_pt < 0) {
@ -790,7 +790,7 @@ void EdgeGrid::Grid::calculate_sdf()
if (dabs < d_min) { if (dabs < d_min) {
// Previous point. // Previous point.
const Slic3r::Point &p0 = pts[(ipt == 0) ? (pts.size() - 1) : ipt - 1]; const Slic3r::Point &p0 = pts[(ipt == 0) ? (pts.size() - 1) : ipt - 1];
Slic3r::Point v_seg_prev = p0.vector_to(p1); Slic3r::Point v_seg_prev = p1 - p0;
int64_t t2_pt = int64_t(v_seg_prev.x()) * int64_t(v_pt.x()) + int64_t(v_seg_prev.y()) * int64_t(v_pt.y()); int64_t t2_pt = int64_t(v_seg_prev.x()) * int64_t(v_pt.x()) + int64_t(v_seg_prev.y()) * int64_t(v_pt.y());
if (t2_pt > 0) { if (t2_pt > 0) {
// Inside the wedge between the previous and the next segment. // Inside the wedge between the previous and the next segment.
@ -1164,8 +1164,8 @@ bool EdgeGrid::Grid::signed_distance_edges(const Point &pt, coord_t search_radiu
// End points of the line segment. // End points of the line segment.
const Slic3r::Point &p1 = pts[ipt]; const Slic3r::Point &p1 = pts[ipt];
const Slic3r::Point &p2 = pts[(ipt + 1 == pts.size()) ? 0 : ipt + 1]; const Slic3r::Point &p2 = pts[(ipt + 1 == pts.size()) ? 0 : ipt + 1];
Slic3r::Point v_seg = p1.vector_to(p2); Slic3r::Point v_seg = p2 - p1;
Slic3r::Point v_pt = p1.vector_to(pt); Slic3r::Point v_pt = pt - p1;
// dot(p2-p1, pt-p1) // dot(p2-p1, pt-p1)
int64_t t_pt = int64_t(v_seg.x()) * int64_t(v_pt.x()) + int64_t(v_seg.y()) * int64_t(v_pt.y()); int64_t t_pt = int64_t(v_seg.x()) * int64_t(v_pt.x()) + int64_t(v_seg.y()) * int64_t(v_pt.y());
// l2 of seg // l2 of seg
@ -1176,7 +1176,7 @@ bool EdgeGrid::Grid::signed_distance_edges(const Point &pt, coord_t search_radiu
if (dabs < d_min) { if (dabs < d_min) {
// Previous point. // Previous point.
const Slic3r::Point &p0 = pts[(ipt == 0) ? (pts.size() - 1) : ipt - 1]; const Slic3r::Point &p0 = pts[(ipt == 0) ? (pts.size() - 1) : ipt - 1];
Slic3r::Point v_seg_prev = p0.vector_to(p1); Slic3r::Point v_seg_prev = p1 - p0;
int64_t t2_pt = int64_t(v_seg_prev.x()) * int64_t(v_pt.x()) + int64_t(v_seg_prev.y()) * int64_t(v_pt.y()); int64_t t2_pt = int64_t(v_seg_prev.x()) * int64_t(v_pt.x()) + int64_t(v_seg_prev.y()) * int64_t(v_pt.y());
if (t2_pt > 0) { if (t2_pt > 0) {
// Inside the wedge between the previous and the next segment. // Inside the wedge between the previous and the next segment.

View file

@ -34,54 +34,43 @@ ExPolygon::operator Polylines() const
return to_polylines(*this); return to_polylines(*this);
} }
void void ExPolygon::scale(double factor)
ExPolygon::scale(double factor)
{ {
contour.scale(factor); contour.scale(factor);
for (Polygons::iterator it = holes.begin(); it != holes.end(); ++it) { for (Polygon &hole : holes)
(*it).scale(factor); hole.scale(factor);
}
} }
void void ExPolygon::translate(double x, double y)
ExPolygon::translate(double x, double y)
{ {
contour.translate(x, y); contour.translate(x, y);
for (Polygons::iterator it = holes.begin(); it != holes.end(); ++it) { for (Polygon &hole : holes)
(*it).translate(x, y); hole.translate(x, y);
}
} }
void void ExPolygon::rotate(double angle)
ExPolygon::rotate(double angle)
{ {
contour.rotate(angle); contour.rotate(angle);
for (Polygons::iterator it = holes.begin(); it != holes.end(); ++it) { for (Polygon &hole : holes)
(*it).rotate(angle); hole.rotate(angle);
}
} }
void void ExPolygon::rotate(double angle, const Point &center)
ExPolygon::rotate(double angle, const Point &center)
{ {
contour.rotate(angle, center); contour.rotate(angle, center);
for (Polygons::iterator it = holes.begin(); it != holes.end(); ++it) { for (Polygon &hole : holes)
(*it).rotate(angle, center); hole.rotate(angle, center);
}
} }
double double ExPolygon::area() const
ExPolygon::area() const
{ {
double a = this->contour.area(); double a = this->contour.area();
for (Polygons::const_iterator it = this->holes.begin(); it != this->holes.end(); ++it) { for (const Polygon &hole : holes)
a -= -(*it).area(); // holes have negative area a -= - hole.area(); // holes have negative area
}
return a; return a;
} }
bool bool ExPolygon::is_valid() const
ExPolygon::is_valid() const
{ {
if (!this->contour.is_valid() || !this->contour.is_counter_clockwise()) return false; if (!this->contour.is_valid() || !this->contour.is_counter_clockwise()) return false;
for (Polygons::const_iterator it = this->holes.begin(); it != this->holes.end(); ++it) { for (Polygons::const_iterator it = this->holes.begin(); it != this->holes.end(); ++it) {
@ -90,20 +79,17 @@ ExPolygon::is_valid() const
return true; return true;
} }
bool bool ExPolygon::contains(const Line &line) const
ExPolygon::contains(const Line &line) const
{ {
return this->contains((Polyline)line); return this->contains(Polyline(line.a, line.b));
} }
bool bool ExPolygon::contains(const Polyline &polyline) const
ExPolygon::contains(const Polyline &polyline) const
{ {
return diff_pl((Polylines)polyline, *this).empty(); return diff_pl((Polylines)polyline, *this).empty();
} }
bool bool ExPolygon::contains(const Polylines &polylines) const
ExPolygon::contains(const Polylines &polylines) const
{ {
#if 0 #if 0
BoundingBox bbox = get_extents(polylines); BoundingBox bbox = get_extents(polylines);
@ -120,8 +106,7 @@ ExPolygon::contains(const Polylines &polylines) const
return pl_out.empty(); return pl_out.empty();
} }
bool bool ExPolygon::contains(const Point &point) const
ExPolygon::contains(const Point &point) const
{ {
if (!this->contour.contains(point)) return false; if (!this->contour.contains(point)) return false;
for (Polygons::const_iterator it = this->holes.begin(); it != this->holes.end(); ++it) { for (Polygons::const_iterator it = this->holes.begin(); it != this->holes.end(); ++it) {
@ -131,8 +116,7 @@ ExPolygon::contains(const Point &point) const
} }
// inclusive version of contains() that also checks whether point is on boundaries // inclusive version of contains() that also checks whether point is on boundaries
bool bool ExPolygon::contains_b(const Point &point) const
ExPolygon::contains_b(const Point &point) const
{ {
return this->contains(point) || this->has_boundary_point(point); return this->contains(point) || this->has_boundary_point(point);
} }
@ -243,25 +227,24 @@ ExPolygon::medial_axis(double max_width, double min_width, ThickPolylines* polyl
Point new_front = polyline.points.front(); Point new_front = polyline.points.front();
Point new_back = polyline.points.back(); Point new_back = polyline.points.back();
if (polyline.endpoints.first && !this->has_boundary_point(new_front)) { if (polyline.endpoints.first && !this->has_boundary_point(new_front)) {
Line line(polyline.points.front(), polyline.points[1]); Vec2d p1 = polyline.points.front().cast<double>();
Vec2d p2 = polyline.points[1].cast<double>();
// prevent the line from touching on the other side, otherwise intersection() might return that solution // prevent the line from touching on the other side, otherwise intersection() might return that solution
if (polyline.points.size() == 2) line.b = line.midpoint(); if (polyline.points.size() == 2)
p2 = (p1 + p2) * 0.5;
line.extend_start(max_width); // Extend the start of the segment.
(void)this->contour.intersection(line, &new_front); p1 -= (p2 - p1).normalized() * max_width;
this->contour.intersection(Line(p1.cast<coord_t>(), p2.cast<coord_t>()), &new_front);
} }
if (polyline.endpoints.second && !this->has_boundary_point(new_back)) { if (polyline.endpoints.second && !this->has_boundary_point(new_back)) {
Line line( Vec2d p1 = (polyline.points.end() - 2)->cast<double>();
*(polyline.points.end() - 2), Vec2d p2 = polyline.points.back().cast<double>();
polyline.points.back()
);
// prevent the line from touching on the other side, otherwise intersection() might return that solution // prevent the line from touching on the other side, otherwise intersection() might return that solution
if (polyline.points.size() == 2) line.a = line.midpoint(); if (polyline.points.size() == 2)
line.extend_end(max_width); p1 = (p1 + p2) * 0.5;
// Extend the start of the segment.
(void)this->contour.intersection(line, &new_back); p2 += (p2 - p1).normalized() * max_width;
this->contour.intersection(Line(p1.cast<coord_t>(), p2.cast<coord_t>()), &new_back);
} }
polyline.points.front() = new_front; polyline.points.front() = new_front;
polyline.points.back() = new_back; polyline.points.back() = new_back;

View file

@ -220,7 +220,7 @@ void ExtrusionLoop::split_at(const Point &point, bool prefer_non_overhang)
double min_non_overhang = std::numeric_limits<double>::max(); double min_non_overhang = std::numeric_limits<double>::max();
for (ExtrusionPaths::const_iterator path = this->paths.begin(); path != this->paths.end(); ++path) { for (ExtrusionPaths::const_iterator path = this->paths.begin(); path != this->paths.end(); ++path) {
Point p_tmp = point.projection_onto(path->polyline); Point p_tmp = point.projection_onto(path->polyline);
double dist = point.distance_to(p_tmp); double dist = (p_tmp - point).cast<double>().norm();
if (dist < min) { if (dist < min) {
p = p_tmp; p = p_tmp;
min = dist; min = dist;

View file

@ -50,10 +50,15 @@ public:
src.clear(); src.clear();
} }
} }
void append(const ExtrusionPaths &paths) { void append(const ExtrusionPaths &paths) {
this->entities.reserve(this->entities.size() + paths.size()); this->entities.reserve(this->entities.size() + paths.size());
for (ExtrusionPaths::const_iterator path = paths.begin(); path != paths.end(); ++path) for (const ExtrusionPath &path : paths)
this->entities.push_back(path->clone()); this->entities.emplace_back(path.clone());
}
void append(ExtrusionPaths &&paths) {
this->entities.reserve(this->entities.size() + paths.size());
for (ExtrusionPath &path : paths)
this->entities.emplace_back(new ExtrusionPath(std::move(path)));
} }
void replace(size_t i, const ExtrusionEntity &entity); void replace(size_t i, const ExtrusionEntity &entity);
void remove(size_t i); void remove(size_t i);

View file

@ -187,7 +187,7 @@ void Fill3DHoneycomb::_fill_surface_single(
const Point &last_point = pts_end.back(); const Point &last_point = pts_end.back();
// TODO: we should also check that both points are on a fill_boundary to avoid // TODO: we should also check that both points are on a fill_boundary to avoid
// connecting paths on the boundaries of internal regions // 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))) { expolygon_off.contains(Line(last_point, first_point))) {
// Append the polyline. // Append the polyline.
pts_end.insert(pts_end.end(), it_polyline->points.begin(), it_polyline->points.end()); pts_end.insert(pts_end.end(), it_polyline->points.begin(), it_polyline->points.end());

View file

@ -49,7 +49,7 @@ static inline Polyline make_wave(
point.y() = clamp(0., height, double(point.y())); point.y() = clamp(0., height, double(point.y()));
if (vertical) if (vertical)
std::swap(point.x(), point.y()); std::swap(point.x(), point.y());
polyline.points.emplace_back(convert_to<Point>(point * scaleFactor)); polyline.points.emplace_back((point * scaleFactor).cast<coord_t>());
} }
return polyline; return polyline;
@ -177,7 +177,7 @@ void FillGyroid::_fill_surface_single(
// TODO: we should also check that both points are on a fill_boundary to avoid // TODO: we should also check that both points are on a fill_boundary to avoid
// connecting paths on the boundaries of internal regions // connecting paths on the boundaries of internal regions
// TODO: avoid crossing current infill path // 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))) { expolygon_off.contains(Line(last_point, first_point))) {
// Append the polyline. // Append the polyline.
pts_end.insert(pts_end.end(), polyline.points.begin(), polyline.points.end()); pts_end.insert(pts_end.end(), polyline.points.begin(), polyline.points.end());

View file

@ -101,7 +101,7 @@ void FillHoneycomb::_fill_surface_single(
for (Polylines::iterator it_path = chained.begin(); it_path != chained.end(); ++ it_path) { for (Polylines::iterator it_path = chained.begin(); it_path != chained.end(); ++ it_path) {
if (! paths.empty()) { if (! paths.empty()) {
// distance between first point of this path and last point of last path // 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) { if (distance <= m.hex_width) {
paths.back().points.insert(paths.back().points.end(), it_path->points.begin(), it_path->points.end()); paths.back().points.insert(paths.back().points.end(), it_path->points.begin(), it_path->points.end());
continue; continue;

View file

@ -103,7 +103,7 @@ void FillRectilinear::_fill_surface_single(
const Point &first_point = it_polyline->points.front(); const Point &first_point = it_polyline->points.front();
const Point &last_point = pts_end.back(); const Point &last_point = pts_end.back();
// Distance in X, Y. // 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 // TODO: we should also check that both points are on a fill_boundary to avoid
// connecting paths on the boundaries of internal regions // 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.x()), std::abs(distance.y())) &&

View file

@ -55,14 +55,14 @@ static inline coordf_t segment_length(const Polygon &poly, size_t seg1, const Po
coordf_t len = 0; coordf_t len = 0;
if (seg1 <= seg2) { if (seg1 <= seg2) {
for (size_t i = seg1; i < seg2; ++ i, pPrev = pThis) 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 { } else {
for (size_t i = seg1; i < poly.points.size(); ++ i, pPrev = pThis) 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) 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; return len;
} }

View file

@ -217,11 +217,11 @@ Point SegmentIntersection::pos() const
const Point &seg_start = poly.points[(this->iSegment == 0) ? poly.points.size() - 1 : this->iSegment - 1]; const Point &seg_start = poly.points[(this->iSegment == 0) ? poly.points.size() - 1 : this->iSegment - 1];
const Point &seg_end = poly.points[this->iSegment]; const Point &seg_end = poly.points[this->iSegment];
// Point, vector of the segment. // Point, vector of the segment.
const Pointf p1 = convert_to<Pointf>(seg_start); const Pointf p1(seg_start.cast<coordf_t>());
const Pointf v1 = convert_to<Pointf>(seg_end - seg_start); const Pointf v1((seg_end - seg_start).cast<coordf_t>());
// Point, vector of this hatching line. // Point, vector of this hatching line.
const Pointf p2 = convert_to<Pointf>(line->pos); const Pointf p2(line->pos.cast<coordf_t>());
const Pointf v2 = convert_to<Pointf>(line->dir); const Pointf v2(line->dir.cast<coordf_t>());
// Intersect the two rays. // Intersect the two rays.
double denom = v1.x() * v2.y() - v2.x() * v1.y(); double denom = v1.x() * v2.y() - v2.x() * v1.y();
Point out; Point out;
@ -276,13 +276,13 @@ int SegmentIntersection::ordering_along_line(const SegmentIntersection &other) c
// other.iSegment succeeds this->iSegment // other.iSegment succeeds this->iSegment
assert(seg_end_a == seg_start_b); assert(seg_end_a == seg_start_b);
// Avoid calling the 128bit x 128bit multiplication below if this->line intersects the common point. // 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; return 0;
} else if ((other.iSegment + 1) % poly_a.points.size() == this->iSegment) { } else if ((other.iSegment + 1) % poly_a.points.size() == this->iSegment) {
// this->iSegment succeeds other.iSegment // this->iSegment succeeds other.iSegment
assert(seg_start_a == seg_end_b); assert(seg_start_a == seg_end_b);
// Avoid calling the 128bit x 128bit multiplication below if this->line intersects the common point. // 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; return 0;
} else { } else {
// General case. // 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. // 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; const Vec2i64 vec_b = (seg_end_b - seg_start_b).cast<int64_t>();
int side_start = signum(cross(vec_b, seg_start_a - seg_start_b)); int side_start = signum(cross2(vec_b, (seg_start_a - seg_start_b).cast<int64_t>()));
int side_end = signum(cross(vec_b, seg_end_a - seg_start_b)); int side_end = signum(cross2(vec_b, (seg_end_a - seg_start_b).cast<int64_t>()));
int side = side_start * side_end; int side = side_start * side_end;
if (side > 0) if (side > 0)
// This segment is completely inside one half-plane of the other line, therefore the ordering is trivial. // 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; const Vec2i64 vec_a = (seg_end_a - seg_start_a).cast<int64_t>();
int side_start2 = signum(cross(vec_a, seg_start_b - seg_start_a)); int side_start2 = signum(cross2(vec_a, (seg_start_b - seg_start_a).cast<int64_t>()));
int side_end2 = signum(cross(vec_a, seg_end_b - seg_start_a)); int side_end2 = signum(cross2(vec_a, (seg_end_b - seg_start_a).cast<int64_t>()));
int side2 = side_start2 * side_end2; int side2 = side_start2 * side_end2;
//if (side == 0 && side2 == 0) //if (side == 0 && side2 == 0)
// The segments share one of their end points. // The segments share one of their end points.
if (side2 > 0) if (side2 > 0)
// This segment is completely inside one half-plane of the other line, therefore the ordering is trivial. // 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. // 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), // 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. // 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. // Find the parameters of intersection of the two segmetns with this->line.
int64_t denom1 = cross(this->line->dir, vec_a); int64_t denom1 = cross2(this->line->dir.cast<int64_t>(), vec_a);
int64_t denom2 = cross(this->line->dir, vec_b); int64_t denom2 = cross2(this->line->dir.cast<int64_t>(), vec_b);
Point vx_a = seg_start_a - this->line->pos; Vec2i64 vx_a = (seg_start_a - this->line->pos).cast<int64_t>();
Point vx_b = seg_start_b - this->line->pos; Vec2i64 vx_b = (seg_start_b - this->line->pos).cast<int64_t>();
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 t1_times_denom1 = vx_a.x() * vec_a.y() - vx_a.y() * 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 t2_times_denom2 = vx_b.x() * vec_b.y() - vx_b.y() * vec_b.x();
assert(denom1 != 0); assert(denom1 != 0);
assert(denom2 != 0); assert(denom2 != 0);
return Int128::compare_rationals_filtered(t1_times_denom1, denom1, t2_times_denom2, denom2); 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 #ifdef _DEBUG
Point p1 = this->pos(); Point p1 = this->pos();
Point p2 = other.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 */ #endif /* _DEBUG */
int ordering = this->ordering_along_line(other); int ordering = this->ordering_along_line(other);
#ifdef _DEBUG #ifdef _DEBUG
@ -510,7 +510,7 @@ static bool prepare_infill_hatching_segments(
for (size_t i = 1; i < sil.intersections.size(); ++ i) { for (size_t i = 1; i < sil.intersections.size(); ++ i) {
Point p1 = sil.intersections[i - 1].pos(); Point p1 = sil.intersections[i - 1].pos();
Point p2 = sil.intersections[i].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)); assert(d >= - int64_t(SCALED_EPSILON));
} }
#endif /* _DEBUG */ #endif /* _DEBUG */
@ -672,14 +672,14 @@ static inline coordf_t segment_length(const Polygon &poly, size_t seg1, const Po
coordf_t len = 0; coordf_t len = 0;
if (seg1 <= seg2) { if (seg1 <= seg2) {
for (size_t i = seg1; i < seg2; ++ i, pPrev = pThis) 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 { } else {
for (size_t i = seg1; i < poly.points.size(); ++ i, pPrev = pThis) 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) 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; return len;
} }
@ -1191,7 +1191,7 @@ static bool fill_hatching_segments_legacy(
intrsctn.consumed_vertical_up : intrsctn.consumed_vertical_up :
seg.intersections[i-1].consumed_vertical_up; seg.intersections[i-1].consumed_vertical_up;
if (! consumed) { if (! consumed) {
coordf_t dist2 = pointLast.distance_to(intrsctn.pos()); coordf_t dist2 = (intrsctn.pos() - pointLast).cast<double>().norm();
if (dist2 < dist2min) { if (dist2 < dist2min) {
dist2min = dist2; dist2min = dist2;
i_vline = i_vline2; i_vline = i_vline2;

View file

@ -53,7 +53,7 @@ Polyline AvoidCrossingPerimeters::travel_to(const GCode &gcodegen, const Point &
Polyline result = (use_external ? m_external_mp.get() : m_layer_mp.get())-> Polyline result = (use_external ? m_external_mp.get() : m_layer_mp.get())->
shortest_path(gcodegen.last_pos() + scaled_origin, point + scaled_origin); shortest_path(gcodegen.last_pos() + scaled_origin, point + scaled_origin);
if (use_external) if (use_external)
result.translate(scaled_origin.negative()); result.translate(- scaled_origin);
return result; return result;
} }
@ -681,7 +681,7 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
for (const ExPolygon &expoly : layer->slices.expolygons) for (const ExPolygon &expoly : layer->slices.expolygons)
for (const Point &copy : object->_shifted_copies) { for (const Point &copy : object->_shifted_copies) {
islands.emplace_back(expoly.contour); islands.emplace_back(expoly.contour);
islands.back().translate(copy); islands.back().translate(- copy);
} }
//FIXME Mege the islands in parallel. //FIXME Mege the islands in parallel.
m_avoid_crossing_perimeters.init_external_mp(union_ex(islands)); m_avoid_crossing_perimeters.init_external_mp(union_ex(islands));
@ -699,7 +699,7 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
for (unsigned int extruder_id : print.extruders()) { for (unsigned int extruder_id : print.extruders()) {
const Pointf &extruder_offset = print.config.extruder_offset.get_at(extruder_id); const Pointf &extruder_offset = print.config.extruder_offset.get_at(extruder_id);
Polygon s(outer_skirt); Polygon s(outer_skirt);
s.translate(-scale_(extruder_offset.x()), -scale_(extruder_offset.y())); s.translate(Point::new_scale(- extruder_offset.x(), - extruder_offset.y()));
skirts.emplace_back(std::move(s)); skirts.emplace_back(std::move(s));
} }
m_ooze_prevention.enable = true; m_ooze_prevention.enable = true;
@ -1547,7 +1547,7 @@ void GCode::set_origin(const Pointf &pointf)
scale_(m_origin.x() - pointf.x()), scale_(m_origin.x() - pointf.x()),
scale_(m_origin.y() - pointf.y()) scale_(m_origin.y() - pointf.y())
); );
m_last_pos.translate(translate); m_last_pos += translate;
m_wipe.path.translate(translate); m_wipe.path.translate(translate);
m_origin = pointf; m_origin = pointf;
} }
@ -1678,8 +1678,8 @@ static Points::iterator project_point_to_polygon_and_insert(Polygon &polygon, co
j = 0; j = 0;
const Point &p1 = polygon.points[i]; const Point &p1 = polygon.points[i];
const Point &p2 = polygon.points[j]; const Point &p2 = polygon.points[j];
const Slic3r::Point v_seg = p1.vector_to(p2); const Slic3r::Point v_seg = p2 - p1;
const Slic3r::Point v_pt = p1.vector_to(pt); const Slic3r::Point v_pt = pt - p1;
const int64_t l2_seg = int64_t(v_seg.x()) * int64_t(v_seg.x()) + int64_t(v_seg.y()) * int64_t(v_seg.y()); const int64_t l2_seg = int64_t(v_seg.x()) * int64_t(v_seg.x()) + int64_t(v_seg.y()) * int64_t(v_seg.y());
int64_t t_pt = int64_t(v_seg.x()) * int64_t(v_pt.x()) + int64_t(v_seg.y()) * int64_t(v_pt.y()); int64_t t_pt = int64_t(v_seg.x()) * int64_t(v_pt.x()) + int64_t(v_seg.y()) * int64_t(v_pt.y());
if (t_pt < 0) { if (t_pt < 0) {
@ -1714,7 +1714,7 @@ static Points::iterator project_point_to_polygon_and_insert(Polygon &polygon, co
} }
assert(i_min != size_t(-1)); assert(i_min != size_t(-1));
if (pt_min.distance_to(polygon.points[i_min]) > eps) { if ((pt_min - polygon.points[i_min]).cast<double>().norm() > eps) {
// Insert a new point on the segment i_min, i_min+1. // Insert a new point on the segment i_min, i_min+1.
return polygon.points.insert(polygon.points.begin() + (i_min + 1), pt_min); return polygon.points.insert(polygon.points.begin() + (i_min + 1), pt_min);
} }
@ -1726,8 +1726,8 @@ std::vector<float> polygon_parameter_by_length(const Polygon &polygon)
// Parametrize the polygon by its length. // Parametrize the polygon by its length.
std::vector<float> lengths(polygon.points.size()+1, 0.); std::vector<float> lengths(polygon.points.size()+1, 0.);
for (size_t i = 1; i < polygon.points.size(); ++ i) for (size_t i = 1; i < polygon.points.size(); ++ i)
lengths[i] = lengths[i-1] + float(polygon.points[i].distance_to(polygon.points[i-1])); lengths[i] = lengths[i-1] + (polygon.points[i] - polygon.points[i-1]).cast<float>().norm();
lengths.back() = lengths[lengths.size()-2] + float(polygon.points.front().distance_to(polygon.points.back())); lengths.back() = lengths[lengths.size()-2] + (polygon.points.front() - polygon.points.back()).cast<float>().norm();
return lengths; return lengths;
} }
@ -1775,8 +1775,8 @@ std::vector<float> polygon_angles_at_vertices(const Polygon &polygon, const std:
const Point &p0 = polygon.points[idx_prev]; const Point &p0 = polygon.points[idx_prev];
const Point &p1 = polygon.points[idx_curr]; const Point &p1 = polygon.points[idx_curr];
const Point &p2 = polygon.points[idx_next]; const Point &p2 = polygon.points[idx_next];
const Point v1 = p0.vector_to(p1); const Point v1 = p1 - p0;
const Point v2 = p1.vector_to(p2); const Point v2 = p2 - p1;
int64_t dot = int64_t(v1.x())*int64_t(v2.x()) + int64_t(v1.y())*int64_t(v2.y()); int64_t dot = int64_t(v1.x())*int64_t(v2.x()) + int64_t(v1.y())*int64_t(v2.y());
int64_t cross = int64_t(v1.x())*int64_t(v2.y()) - int64_t(v1.y())*int64_t(v2.x()); int64_t cross = int64_t(v1.x())*int64_t(v2.y()) - int64_t(v1.y())*int64_t(v2.x());
float angle = float(atan2(double(cross), double(dot))); float angle = float(atan2(double(cross), double(dot)));
@ -2031,19 +2031,17 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
// create the destination point along the first segment and rotate it // create the destination point along the first segment and rotate it
// we make sure we don't exceed the segment length because we don't know // we make sure we don't exceed the segment length because we don't know
// the rotation of the second segment so we might cross the object boundary // the rotation of the second segment so we might cross the object boundary
Line first_segment( Vec2d p1 = paths.front().polyline.points.front().cast<double>();
paths.front().polyline.points[0], Vec2d p2 = paths.front().polyline.points[1].cast<double>();
paths.front().polyline.points[1] Vec2d v = p2 - p1;
); double nd = scale_(EXTRUDER_CONFIG(nozzle_diameter));
double distance = std::min<double>( double l2 = v.squaredNorm();
scale_(EXTRUDER_CONFIG(nozzle_diameter)), // Shift by no more than a nozzle diameter.
first_segment.length() //FIXME Hiding the seams will not work nicely for very densely discretized contours!
); Point pt = ((nd * nd >= l2) ? p2 : (p1 + v * (nd / sqrt(l2)))).cast<coord_t>();
Point point = first_segment.point_at(distance); pt.rotate(angle, paths.front().polyline.points.front());
point.rotate(angle, first_segment.a);
// generate the travel move // generate the travel move
gcode += m_writer.travel_to_xy(this->point_to_gcode(point), "move inwards before travel"); gcode += m_writer.travel_to_xy(this->point_to_gcode(pt), "move inwards before travel");
} }
return gcode; return gcode;

View file

@ -1042,12 +1042,12 @@ MedialAxis::validate_edge(const VD::edge_type* edge)
calculate the distance to that endpoint instead. */ calculate the distance to that endpoint instead. */
coordf_t w0 = cell_r->contains_segment() coordf_t w0 = cell_r->contains_segment()
? line.a.distance_to(segment_r)*2 ? segment_r.distance_to(line.a)*2
: line.a.distance_to(this->retrieve_endpoint(cell_r))*2; : (this->retrieve_endpoint(cell_r) - line.a).cast<double>().norm()*2;
coordf_t w1 = cell_l->contains_segment() coordf_t w1 = cell_l->contains_segment()
? line.b.distance_to(segment_l)*2 ? segment_l.distance_to(line.b)*2
: line.b.distance_to(this->retrieve_endpoint(cell_l))*2; : (this->retrieve_endpoint(cell_l) - line.b).cast<double>().norm()*2;
if (cell_l->contains_segment() && cell_r->contains_segment()) { if (cell_l->contains_segment() && cell_r->contains_segment()) {
// calculate the relative angle between the two boundary segments // calculate the relative angle between the two boundary segments

View file

@ -7,8 +7,7 @@
namespace Slic3r { namespace Slic3r {
std::string std::string Line::wkt() const
Line::wkt() const
{ {
std::ostringstream ss; std::ostringstream ss;
ss << "LINESTRING(" << this->a.x() << " " << this->a.y() << "," ss << "LINESTRING(" << this->a.x() << " " << this->a.y() << ","
@ -16,124 +15,58 @@ Line::wkt() const
return ss.str(); return ss.str();
} }
Line::operator Lines() const bool Line::intersection_infinite(const Line &other, Point* point) const
{ {
Lines lines; Vec2d a1 = this->a.cast<double>();
lines.push_back(*this); Vec2d a2 = other.a.cast<double>();
return lines; Vec2d v12 = (other.a - this->a).cast<double>();
} Vec2d v1 = (this->b - this->a).cast<double>();
Vec2d v2 = (other.b - other.a).cast<double>();
Line::operator Polyline() const double denom = cross2(v1, v2);
{ if (std::fabs(denom) < EPSILON)
Polyline pl;
pl.points.push_back(this->a);
pl.points.push_back(this->b);
return pl;
}
void
Line::scale(double factor)
{
this->a.scale(factor);
this->b.scale(factor);
}
void
Line::translate(double x, double y)
{
this->a.translate(x, y);
this->b.translate(x, y);
}
void
Line::rotate(double angle, const Point &center)
{
this->a.rotate(angle, center);
this->b.rotate(angle, center);
}
void
Line::reverse()
{
std::swap(this->a, this->b);
}
double
Line::length() const
{
return this->a.distance_to(this->b);
}
Point
Line::midpoint() const
{
return Point((this->a.x() + this->b.x()) / 2.0, (this->a.y() + this->b.y()) / 2.0);
}
void
Line::point_at(double distance, Point* point) const
{
double len = this->length();
*point = this->a;
if (this->a.x() != this->b.x())
point->x() = this->a.x() + (this->b.x() - this->a.x()) * distance / len;
if (this->a.y() != this->b.y())
point->y() = this->a.y() + (this->b.y() - this->a.y()) * distance / len;
}
Point
Line::point_at(double distance) const
{
Point p;
this->point_at(distance, &p);
return p;
}
bool
Line::intersection_infinite(const Line &other, Point* point) const
{
Vector x = this->a.vector_to(other.a);
Vector d1 = this->vector();
Vector d2 = other.vector();
double cross = d1.x() * d2.y() - d1.y() * d2.x();
if (std::fabs(cross) < EPSILON)
return false; return false;
double t1 = cross2(v12, v2) / denom;
double t1 = (x.x() * d2.y() - x.y() * d2.x())/cross; *point = (a1 + t1 * v1).cast<coord_t>();
point->x() = this->a.x() + d1.x() * t1;
point->y() = this->a.y() + d1.y() * t1;
return true; return true;
} }
bool /* distance to the closest point of line */
Line::coincides_with(const Line &line) const double Line::distance_to(const Point &point) const
{ {
return this->a == line.a && this->b == line.b; const Line &line = *this;
const Vec2d v = (line.b - line.a).cast<double>();
const Vec2d va = (point - line.a).cast<double>();
const double l2 = v.squaredNorm(); // avoid a sqrt
if (l2 == 0.0)
// line.a == line.b case
return va.norm();
// Consider the line extending the segment, parameterized as line.a + t (line.b - line.a).
// We find projection of this point onto the line.
// It falls where t = [(this-line.a) . (line.b-line.a)] / |line.b-line.a|^2
const double t = va.dot(v) / l2;
if (t < 0.0) return va.norm(); // beyond the 'a' end of the segment
else if (t > 1.0) return (point - line.b).cast<double>().norm(); // beyond the 'b' end of the segment
return (t * v - va).norm();
} }
double double Line::perp_distance_to(const Point &point) const
Line::distance_to(const Point &point) const
{ {
return point.distance_to(*this); const Line &line = *this;
const Vec2d v = (line.b - line.a).cast<double>();
const Vec2d va = (point - line.a).cast<double>();
if (line.a == line.b)
return va.norm();
return std::abs(cross2(v, va)) / v.norm();
} }
double double Line::orientation() const
Line::atan2_() const
{
return atan2(this->b.y() - this->a.y(), this->b.x() - this->a.x());
}
double
Line::orientation() const
{ {
double angle = this->atan2_(); double angle = this->atan2_();
if (angle < 0) angle = 2*PI + angle; if (angle < 0) angle = 2*PI + angle;
return angle; return angle;
} }
double double Line::direction() const
Line::direction() const
{ {
double atan2 = this->atan2_(); double atan2 = this->atan2_();
return (fabs(atan2 - PI) < EPSILON) ? 0 return (fabs(atan2 - PI) < EPSILON) ? 0
@ -141,105 +74,42 @@ Line::direction() const
: atan2; : atan2;
} }
bool bool Line::parallel_to(double angle) const
Line::parallel_to(double angle) const { {
return Slic3r::Geometry::directions_parallel(this->direction(), angle); return Slic3r::Geometry::directions_parallel(this->direction(), angle);
} }
bool bool Line::intersection(const Line &l2, Point *intersection) const
Line::parallel_to(const Line &line) const {
return this->parallel_to(line.direction());
}
Vector
Line::vector() const
{ {
return Vector(this->b.x() - this->a.x(), this->b.y() - this->a.y()); const Line &l1 = *this;
} const Vec2d v1 = (l1.b - l1.a).cast<double>();
const Vec2d v2 = (l2.b - l2.a).cast<double>();
Vector const Vec2d v12 = (l1.a - l2.a).cast<double>();
Line::normal() const double denom = cross2(v1, v2);
{ double nume_a = cross2(v2, v12);
return Vector((this->b.y() - this->a.y()), -(this->b.x() - this->a.x())); double nume_b = cross2(v1, v12);
} if (fabs(denom) < EPSILON)
#if 0
void // Lines are collinear. Return true if they are coincident (overlappign).
Line::extend_end(double distance) return ! (fabs(nume_a) < EPSILON && fabs(nume_b) < EPSILON);
{ #else
// relocate last point by extending the segment by the specified length return false;
Line line = *this; #endif
line.reverse(); double t1 = nume_a / denom;
this->b = line.point_at(-distance); double t2 = nume_b / denom;
} if (t1 >= 0 && t1 <= 1.0f && t2 >= 0 && t2 <= 1.0f) {
void
Line::extend_start(double distance)
{
// relocate first point by extending the first segment by the specified length
this->a = this->point_at(-distance);
}
bool
Line::intersection(const Line& line, Point* intersection) const
{
double denom = ((double)(line.b.y() - line.a.y())*(this->b.x() - this->a.x())) -
((double)(line.b.x() - line.a.x())*(this->b.y() - this->a.y()));
double nume_a = ((double)(line.b.x() - line.a.x())*(this->a.y() - line.a.y())) -
((double)(line.b.y() - line.a.y())*(this->a.x() - line.a.x()));
double nume_b = ((double)(this->b.x() - this->a.x())*(this->a.y() - line.a.y())) -
((double)(this->b.y() - this->a.y())*(this->a.x() - line.a.x()));
if (fabs(denom) < EPSILON) {
if (fabs(nume_a) < EPSILON && fabs(nume_b) < EPSILON) {
return false; // coincident
}
return false; // parallel
}
double ua = nume_a / denom;
double ub = nume_b / denom;
if (ua >= 0 && ua <= 1.0f && ub >= 0 && ub <= 1.0f)
{
// Get the intersection point. // Get the intersection point.
intersection->x() = this->a.x() + ua*(this->b.x() - this->a.x()); (*intersection) = (l1.a.cast<double>() + t1 * v1).cast<coord_t>();
intersection->y() = this->a.y() + ua*(this->b.y() - this->a.y());
return true; return true;
} }
return false; // not intersecting return false; // not intersecting
} }
double
Line::ccw(const Point& point) const
{
return point.ccw(*this);
}
double Line3::length() const
{
return (b - a).norm();
}
Vector3 Line3::vector() const
{
return Vector3(b - a);
}
Pointf3 Linef3::intersect_plane(double z) const Pointf3 Linef3::intersect_plane(double z) const
{ {
Vec3d v = this->b - this->a; auto v = (this->b - this->a).cast<double>();
double t = (z - this->a.z()) / v.z(); double t = (z - this->a.z()) / v.z();
return Pointf3(this->a.x() + v.x() * t, this->a.y() + v.y() * t, z); return Pointf3(this->a.x() + v.x() * t, this->a.y() + v.y() * t, z);
} }
void
Linef3::scale(double factor)
{
this->a.scale(factor);
this->b.scale(factor);
}
} }

View file

@ -18,77 +18,77 @@ typedef std::vector<ThickLine> ThickLines;
class Line class Line
{ {
public: public:
Point a; Line() {}
Point b; explicit Line(Point _a, Point _b): a(_a), b(_b) {}
Line() {};
explicit Line(Point _a, Point _b): a(_a), b(_b) {};
std::string wkt() const; std::string wkt() const;
operator Lines() const; explicit operator Lines() const { Lines lines; lines.emplace_back(*this); return lines; }
operator Polyline() const; void scale(double factor) { this->a *= factor; this->b *= factor; }
void scale(double factor); void translate(double x, double y) { Vector v(x, y); this->a += v; this->b += v; }
void translate(double x, double y); void rotate(double angle, const Point &center) { this->a.rotate(angle, center); this->b.rotate(angle, center); }
void rotate(double angle, const Point &center); void reverse() { std::swap(this->a, this->b); }
void reverse(); double length() const { return (b - a).cast<double>().norm(); }
double length() const; Point midpoint() const { return (this->a + this->b) / 2; }
Point midpoint() const; bool intersection_infinite(const Line &other, Point* point) const;
void point_at(double distance, Point* point) const; bool coincides_with(const Line &line) const { return this->a == line.a && this->b == line.b; }
Point point_at(double distance) const;
bool intersection_infinite(const Line &other, Point* point) const;
bool coincides_with(const Line &line) const;
double distance_to(const Point &point) const; double distance_to(const Point &point) const;
bool parallel_to(double angle) const; double perp_distance_to(const Point &point) const;
bool parallel_to(const Line &line) const; bool parallel_to(double angle) const;
double atan2_() const; bool parallel_to(const Line &line) const { return this->parallel_to(line.direction()); }
double atan2_() const { return atan2(this->b.y() - this->a.y(), this->b.x() - this->a.x()); }
double orientation() const; double orientation() const;
double direction() const; double direction() const;
Vector vector() const; Vector vector() const { return this->b - this->a; }
Vector normal() const; Vector normal() const { return Vector((this->b.y() - this->a.y()), -(this->b.x() - this->a.x())); }
void extend_end(double distance); bool intersection(const Line& line, Point* intersection) const;
void extend_start(double distance); double ccw(const Point& point) const { return point.ccw(*this); }
bool intersection(const Line& line, Point* intersection) const;
double ccw(const Point& point) const; Point a;
Point b;
}; };
class ThickLine : public Line class ThickLine : public Line
{ {
public: public:
coordf_t a_width, b_width; ThickLine() : a_width(0), b_width(0) {}
ThickLine(Point a, Point b) : Line(a, b), a_width(0), b_width(0) {}
ThickLine() : a_width(0), b_width(0) {}; ThickLine(Point a, Point b, double wa, double wb) : Line(a, b), a_width(wa), b_width(wb) {}
ThickLine(Point _a, Point _b) : Line(_a, _b), a_width(0), b_width(0) {};
coordf_t a_width, b_width;
}; };
class Line3 class Line3
{ {
public: public:
Point3 a;
Point3 b;
Line3() {} Line3() {}
Line3(const Point3& _a, const Point3& _b) : a(_a), b(_b) {} Line3(const Point3& _a, const Point3& _b) : a(_a), b(_b) {}
double length() const; double length() const { return (this->a - this->b).cast<double>().norm(); }
Vector3 vector() const; Vector3 vector() const { return this->b - this->a; }
Point3 a;
Point3 b;
}; };
class Linef class Linef
{ {
public: public:
Linef() {}
explicit Linef(Pointf _a, Pointf _b): a(_a), b(_b) {}
Pointf a; Pointf a;
Pointf b; Pointf b;
Linef() {};
explicit Linef(Pointf _a, Pointf _b): a(_a), b(_b) {};
}; };
class Linef3 class Linef3
{ {
public: public:
Linef3() {}
explicit Linef3(Pointf3 _a, Pointf3 _b): a(_a), b(_b) {}
Pointf3 intersect_plane(double z) const;
void scale(double factor) { this->a *= factor; this->b *= factor; }
Pointf3 a; Pointf3 a;
Pointf3 b; Pointf3 b;
Linef3() {};
explicit Linef3(Pointf3 _a, Pointf3 _b): a(_a), b(_b) {};
Pointf3 intersect_plane(double z) const;
void scale(double factor);
}; };
} // namespace Slic3r } // namespace Slic3r

View file

@ -256,12 +256,10 @@ void Model::center_instances_around_point(const Pointf &point)
for (size_t i = 0; i < o->instances.size(); ++ i) for (size_t i = 0; i < o->instances.size(); ++ i)
bb.merge(o->instance_bounding_box(i, false)); bb.merge(o->instance_bounding_box(i, false));
Sizef3 size = bb.size(); Pointf shift = point - 0.5 * bb.size().xy() - bb.min.xy();
coordf_t shift_x = -bb.min.x() + point.x() - size.x()/2;
coordf_t shift_y = -bb.min.y() + point.y() - size.y()/2;
for (ModelObject *o : this->objects) { for (ModelObject *o : this->objects) {
for (ModelInstance *i : o->instances) for (ModelInstance *i : o->instances)
i->offset.translate(shift_x, shift_y); i->offset += shift;
o->invalidate_bounding_box(); o->invalidate_bounding_box();
} }
} }
@ -685,7 +683,7 @@ void Model::duplicate(size_t copies_num, coordf_t dist, const BoundingBoxf* bb)
for (const ModelInstance *i : instances) { for (const ModelInstance *i : instances) {
for (const Pointf &pos : positions) { for (const Pointf &pos : positions) {
ModelInstance *instance = o->add_instance(*i); ModelInstance *instance = o->add_instance(*i);
instance->offset.translate(pos); instance->offset += pos;
} }
} }
o->invalidate_bounding_box(); o->invalidate_bounding_box();
@ -1075,16 +1073,15 @@ void ModelObject::center_around_origin()
vector.y() -= size.y()/2; vector.y() -= size.y()/2;
this->translate(vector); this->translate(vector);
this->origin_translation.translate(vector); this->origin_translation += vector;
if (!this->instances.empty()) { if (!this->instances.empty()) {
for (ModelInstance *i : this->instances) { for (ModelInstance *i : this->instances) {
// apply rotation and scaling to vector as well before translating instance, // apply rotation and scaling to vector as well before translating instance,
// in order to leave final position unaltered // in order to leave final position unaltered
Vectorf v = vector.negative().xy(); Vectorf v = - vector.xy();
v.rotate(i->rotation); v.rotate(i->rotation);
v.scale(i->scaling_factor); i->offset += v * i->scaling_factor;
i->offset.translate(v);
} }
this->invalidate_bounding_box(); this->invalidate_bounding_box();
} }

View file

@ -58,7 +58,7 @@ Polyline MotionPlanner::shortest_path(const Point &from, const Point &to)
{ {
// If we have an empty configuration space, return a straight move. // If we have an empty configuration space, return a straight move.
if (m_islands.empty()) if (m_islands.empty())
return Line(from, to); return Polyline(from, to);
// Are both points in the same island? // Are both points in the same island?
int island_idx_from = -1; int island_idx_from = -1;
@ -74,7 +74,7 @@ Polyline MotionPlanner::shortest_path(const Point &from, const Point &to)
// Since both points are in the same island, is a direct move possible? // Since both points are in the same island, is a direct move possible?
// If so, we avoid generating the visibility environment. // If so, we avoid generating the visibility environment.
if (island.m_island.contains(Line(from, to))) if (island.m_island.contains(Line(from, to)))
return Line(from, to); return Polyline(from, to);
// Both points are inside a single island, but the straight line crosses the island boundary. // Both points are inside a single island, but the straight line crosses the island boundary.
island_idx = idx; island_idx = idx;
break; break;
@ -90,7 +90,7 @@ Polyline MotionPlanner::shortest_path(const Point &from, const Point &to)
if (env.m_env.expolygons.empty()) { if (env.m_env.expolygons.empty()) {
// if this environment is empty (probably because it's too small), perform straight move // if this environment is empty (probably because it's too small), perform straight move
// and avoid running the algorithms on empty dataset // and avoid running the algorithms on empty dataset
return Line(from, to); return Polyline(from, to);
} }
// Now check whether points are inside the environment. // Now check whether points are inside the environment.
@ -224,7 +224,7 @@ const MotionPlannerGraph& MotionPlanner::init_graph(int island_idx)
else else
v1_idx = i_v1->second; v1_idx = i_v1->second;
// Euclidean distance is used as weight for the graph edge // Euclidean distance is used as weight for the graph edge
graph->add_edge(v0_idx, v1_idx, p0.distance_to(p1)); graph->add_edge(v0_idx, v1_idx, (p1 - p0).cast<double>().norm());
} }
} }
} }
@ -238,7 +238,7 @@ static inline size_t nearest_waypoint_index(const Point &start_point, const Poin
size_t idx = size_t(-1); size_t idx = size_t(-1);
double dmin = std::numeric_limits<double>::infinity(); double dmin = std::numeric_limits<double>::infinity();
for (const Point &p : middle_points) { for (const Point &p : middle_points) {
double d = start_point.distance_to(p) + p.distance_to(end_point); double d = (p - start_point).cast<double>().norm() + (end_point - p).cast<double>().norm();
if (d < dmin) { if (d < dmin) {
idx = &p - middle_points.data(); idx = &p - middle_points.data();
dmin = d; dmin = d;

View file

@ -11,18 +11,20 @@ MultiPoint::operator Points() const
void MultiPoint::scale(double factor) void MultiPoint::scale(double factor)
{ {
for (Point &pt : points) for (Point &pt : points)
pt.scale(factor); pt *= factor;
} }
void MultiPoint::translate(double x, double y) void MultiPoint::translate(double x, double y)
{ {
Vector v(x, y);
for (Point &pt : points) for (Point &pt : points)
pt.translate(x, y); pt += v;
} }
void MultiPoint::translate(const Point &vector) void MultiPoint::translate(const Point &v)
{ {
this->translate(vector.x(), vector.y()); for (Point &pt : points)
pt += v;
} }
void MultiPoint::rotate(double cos_angle, double sin_angle) void MultiPoint::rotate(double cos_angle, double sin_angle)
@ -79,7 +81,7 @@ MultiPoint::find_point(const Point &point) const
bool bool
MultiPoint::has_boundary_point(const Point &point) const MultiPoint::has_boundary_point(const Point &point) const
{ {
double dist = point.distance_to(point.projection_onto(*this)); double dist = (point.projection_onto(*this) - point).cast<double>().norm();
return dist < SCALED_EPSILON; return dist < SCALED_EPSILON;
} }
@ -137,10 +139,10 @@ bool MultiPoint::first_intersection(const Line& line, Point* intersection) const
if (l.intersection(line, &ip)) { if (l.intersection(line, &ip)) {
if (! found) { if (! found) {
found = true; found = true;
dmin = ip.distance_to(line.a); dmin = (line.a - ip).cast<double>().norm();
*intersection = ip; *intersection = ip;
} else { } else {
double d = ip.distance_to(line.a); double d = (line.a - ip).cast<double>().norm();
if (d < dmin) { if (d < dmin) {
dmin = d; dmin = d;
*intersection = ip; *intersection = ip;
@ -176,7 +178,7 @@ MultiPoint::_douglas_peucker(const Points &points, const double tolerance)
Line full(points.front(), points.back()); Line full(points.front(), points.back());
for (Points::const_iterator it = points.begin() + 1; it != points.end(); ++it) { for (Points::const_iterator it = points.begin() + 1; it != points.end(); ++it) {
// we use shortest distance, not perpendicular distance // we use shortest distance, not perpendicular distance
double d = it->distance_to(full); double d = full.distance_to(*it);
if (d > dmax) { if (d > dmax) {
index = it - points.begin(); index = it - points.begin();
dmax = d; dmax = d;
@ -215,7 +217,7 @@ void MultiPoint3::translate(double x, double y)
void MultiPoint3::translate(const Point& vector) void MultiPoint3::translate(const Point& vector)
{ {
translate(vector.x(), vector.y()); this->translate(vector.x(), vector.y());
} }
double MultiPoint3::length() const double MultiPoint3::length() const

View file

@ -18,10 +18,11 @@ public:
Points points; Points points;
operator Points() const; operator Points() const;
MultiPoint() {}; MultiPoint() {}
MultiPoint(const MultiPoint &other) : points(other.points) {} MultiPoint(const MultiPoint &other) : points(other.points) {}
MultiPoint(MultiPoint &&other) : points(std::move(other.points)) {} MultiPoint(MultiPoint &&other) : points(std::move(other.points)) {}
explicit MultiPoint(const Points &_points): points(_points) {} MultiPoint(std::initializer_list<Point> list) : points(list) {}
explicit MultiPoint(const Points &_points) : points(_points) {}
MultiPoint& operator=(const MultiPoint &other) { points = other.points; return *this; } MultiPoint& operator=(const MultiPoint &other) { points = other.points; return *this; }
MultiPoint& operator=(MultiPoint &&other) { points = std::move(other.points); return *this; } MultiPoint& operator=(MultiPoint &&other) { points = std::move(other.points); return *this; }
void scale(double factor); void scale(double factor);
@ -43,9 +44,9 @@ public:
int idx = -1; int idx = -1;
if (! this->points.empty()) { if (! this->points.empty()) {
idx = 0; idx = 0;
double dist_min = this->points.front().distance_to(point); double dist_min = (point - this->points.front()).cast<double>().norm();
for (int i = 1; i < int(this->points.size()); ++ i) { for (int i = 1; i < int(this->points.size()); ++ i) {
double d = this->points[i].distance_to(point); double d = (this->points[i] - point).cast<double>().norm();
if (d < dist_min) { if (d < dist_min) {
dist_min = d; dist_min = d;
idx = i; idx = i;

View file

@ -366,99 +366,103 @@ ExtrusionEntityCollection PerimeterGenerator::_traverse_loops(
return entities; return entities;
} }
ExtrusionEntityCollection PerimeterGenerator::_variable_width(const ThickPolylines &polylines, ExtrusionRole role, Flow flow) const static inline ExtrusionPaths thick_polyline_to_extrusion_paths(const ThickPolyline &thick_polyline, ExtrusionRole role, Flow &flow, const float tolerance)
{ {
// this value determines granularity of adaptive width, as G-code does not allow ExtrusionPaths paths;
// variable extrusion within a single move; this value shall only affect the amount ExtrusionPath path(role);
// of segments, and any pruning shall be performed before we apply this tolerance ThickLines lines = thick_polyline.thicklines();
const double tolerance = scale_(0.05);
ExtrusionEntityCollection coll; for (int i = 0; i < (int)lines.size(); ++i) {
for (const ThickPolyline &p : polylines) { const ThickLine& line = lines[i];
ExtrusionPaths paths;
ExtrusionPath path(role);
ThickLines lines = p.thicklines();
for (int i = 0; i < (int)lines.size(); ++i) { const coordf_t line_len = line.length();
const ThickLine& line = lines[i]; if (line_len < SCALED_EPSILON) continue;
const coordf_t line_len = line.length(); double thickness_delta = fabs(line.a_width - line.b_width);
if (line_len < SCALED_EPSILON) continue; if (thickness_delta > tolerance) {
const unsigned short segments = ceil(thickness_delta / tolerance);
double thickness_delta = fabs(line.a_width - line.b_width); const coordf_t seg_len = line_len / segments;
if (thickness_delta > tolerance) { Points pp;
const unsigned short segments = ceil(thickness_delta / tolerance); std::vector<coordf_t> width;
const coordf_t seg_len = line_len / segments; {
Points pp; pp.push_back(line.a);
std::vector<coordf_t> width; width.push_back(line.a_width);
{ for (size_t j = 1; j < segments; ++j) {
pp.push_back(line.a); pp.push_back((line.a.cast<double>() + (line.b - line.a).cast<double>().normalized() * (j * seg_len)).cast<coord_t>());
width.push_back(line.a_width);
for (size_t j = 1; j < segments; ++j) {
pp.push_back(line.point_at(j*seg_len));
coordf_t w = line.a_width + (j*seg_len) * (line.b_width-line.a_width) / line_len;
width.push_back(w);
width.push_back(w);
}
pp.push_back(line.b);
width.push_back(line.b_width);
assert(pp.size() == segments + 1); coordf_t w = line.a_width + (j*seg_len) * (line.b_width-line.a_width) / line_len;
assert(width.size() == segments*2); width.push_back(w);
width.push_back(w);
} }
pp.push_back(line.b);
width.push_back(line.b_width);
// delete this line and insert new ones assert(pp.size() == segments + 1);
lines.erase(lines.begin() + i); assert(width.size() == segments*2);
for (size_t j = 0; j < segments; ++j) {
ThickLine new_line(pp[j], pp[j+1]);
new_line.a_width = width[2*j];
new_line.b_width = width[2*j+1];
lines.insert(lines.begin() + i + j, new_line);
}
-- i;
continue;
} }
const double w = fmax(line.a_width, line.b_width); // delete this line and insert new ones
if (path.polyline.points.empty()) { lines.erase(lines.begin() + i);
path.polyline.append(line.a); for (size_t j = 0; j < segments; ++j) {
ThickLine new_line(pp[j], pp[j+1]);
new_line.a_width = width[2*j];
new_line.b_width = width[2*j+1];
lines.insert(lines.begin() + i + j, new_line);
}
-- i;
continue;
}
const double w = fmax(line.a_width, line.b_width);
if (path.polyline.points.empty()) {
path.polyline.append(line.a);
path.polyline.append(line.b);
// Convert from spacing to extrusion width based on the extrusion model
// of a square extrusion ended with semi circles.
flow.width = unscale(w) + flow.height * (1. - 0.25 * PI);
#ifdef SLIC3R_DEBUG
printf(" filling %f gap\n", flow.width);
#endif
path.mm3_per_mm = flow.mm3_per_mm();
path.width = flow.width;
path.height = flow.height;
} else {
thickness_delta = fabs(scale_(flow.width) - w);
if (thickness_delta <= tolerance) {
// the width difference between this line and the current flow width is
// within the accepted tolerance
path.polyline.append(line.b); path.polyline.append(line.b);
// Convert from spacing to extrusion width based on the extrusion model
// of a square extrusion ended with semi circles.
flow.width = unscale(w) + flow.height * (1. - 0.25 * PI);
#ifdef SLIC3R_DEBUG
printf(" filling %f gap\n", flow.width);
#endif
path.mm3_per_mm = flow.mm3_per_mm();
path.width = flow.width;
path.height = flow.height;
} else { } else {
thickness_delta = fabs(scale_(flow.width) - w); // we need to initialize a new line
if (thickness_delta <= tolerance) { paths.emplace_back(std::move(path));
// the width difference between this line and the current flow width is path = ExtrusionPath(role);
// within the accepted tolerance -- i;
path.polyline.append(line.b);
} else {
// we need to initialize a new line
paths.emplace_back(std::move(path));
path = ExtrusionPath(role);
-- i;
}
} }
} }
if (path.polyline.is_valid()) }
paths.emplace_back(std::move(path)); if (path.polyline.is_valid())
paths.emplace_back(std::move(path));
return paths;
}
ExtrusionEntityCollection PerimeterGenerator::_variable_width(const ThickPolylines &polylines, ExtrusionRole role, Flow flow) const
{
// This value determines granularity of adaptive width, as G-code does not allow
// variable extrusion within a single move; this value shall only affect the amount
// of segments, and any pruning shall be performed before we apply this tolerance.
ExtrusionEntityCollection coll;
const double tolerance = scale_(0.05);
for (const ThickPolyline &p : polylines) {
ExtrusionPaths paths = thick_polyline_to_extrusion_paths(p, role, flow, tolerance);
// Append paths to collection. // Append paths to collection.
if (! paths.empty()) { if (! paths.empty()) {
if (paths.front().first_point() == paths.back().last_point()) if (paths.front().first_point() == paths.back().last_point())
coll.append(ExtrusionLoop(paths)); coll.append(ExtrusionLoop(std::move(paths)));
else else
coll.append(paths); coll.append(std::move(paths));
} }
} }
return coll; return coll;
} }

View file

@ -98,38 +98,6 @@ bool Point::nearest_point(const Points &points, Point* point) const
return true; return true;
} }
/* distance to the closest point of line */
double Point::distance_to(const Line &line) const
{
const double dx = line.b.x() - line.a.x();
const double dy = line.b.y() - line.a.y();
const double l2 = dx*dx + dy*dy; // avoid a sqrt
if (l2 == 0.0) return this->distance_to(line.a); // line.a == line.b case
// Consider the line extending the segment, parameterized as line.a + t (line.b - line.a).
// We find projection of this point onto the line.
// It falls where t = [(this-line.a) . (line.b-line.a)] / |line.b-line.a|^2
const double t = ((this->x() - line.a.x()) * dx + (this->y() - line.a.y()) * dy) / l2;
if (t < 0.0) return this->distance_to(line.a); // beyond the 'a' end of the segment
else if (t > 1.0) return this->distance_to(line.b); // beyond the 'b' end of the segment
Point projection(
line.a.x() + t * dx,
line.a.y() + t * dy
);
return this->distance_to(projection);
}
double Point::perp_distance_to(const Line &line) const
{
if (line.a == line.b) return this->distance_to(line.a);
double n = (double)(line.b.x() - line.a.x()) * (double)(line.a.y() - this->y())
- (double)(line.a.x() - this->x()) * (double)(line.b.y() - line.a.y());
return std::abs(n) / line.length();
}
/* Three points are a counter-clockwise turn if ccw > 0, clockwise if /* Three points are a counter-clockwise turn if ccw > 0, clockwise if
* ccw < 0, and collinear if ccw = 0 because ccw is a determinant that * ccw < 0, and collinear if ccw = 0 because ccw is a determinant that
* gives the signed area of the triangle formed by p1, p2 and this point. * gives the signed area of the triangle formed by p1, p2 and this point.
@ -161,14 +129,14 @@ double Point::ccw_angle(const Point &p1, const Point &p2) const
Point Point::projection_onto(const MultiPoint &poly) const Point Point::projection_onto(const MultiPoint &poly) const
{ {
Point running_projection = poly.first_point(); Point running_projection = poly.first_point();
double running_min = this->distance_to(running_projection); double running_min = (running_projection - *this).cast<double>().norm();
Lines lines = poly.lines(); Lines lines = poly.lines();
for (Lines::const_iterator line = lines.begin(); line != lines.end(); ++line) { for (Lines::const_iterator line = lines.begin(); line != lines.end(); ++line) {
Point point_temp = this->projection_onto(*line); Point point_temp = this->projection_onto(*line);
if (this->distance_to(point_temp) < running_min) { if ((point_temp - *this).cast<double>().norm() < running_min) {
running_projection = point_temp; running_projection = point_temp;
running_min = this->distance_to(running_projection); running_min = (running_projection - *this).cast<double>().norm();
} }
} }
return running_projection; return running_projection;
@ -193,14 +161,10 @@ Point Point::projection_onto(const Line &line) const
/ ( sqr<double>(lx) + sqr<double>(ly) ); / ( sqr<double>(lx) + sqr<double>(ly) );
if (0.0 <= theta && theta <= 1.0) if (0.0 <= theta && theta <= 1.0)
return theta * line.a + (1.0-theta) * line.b; return (theta * line.a.cast<coordf_t>() + (1.0-theta) * line.b.cast<coordf_t>()).cast<coord_t>();
// Else pick closest endpoint. // Else pick closest endpoint.
if (this->distance_to(line.a) < this->distance_to(line.b)) { return ((line.a - *this).cast<double>().squaredNorm() < (line.b - *this).cast<double>().squaredNorm()) ? line.a : line.b;
return line.a;
} else {
return line.b;
}
} }
std::ostream& operator<<(std::ostream &stm, const Pointf &pointf) std::ostream& operator<<(std::ostream &stm, const Pointf &pointf)

View file

@ -35,6 +35,8 @@ typedef std::vector<Pointf3> Pointf3s;
// Vector types with a fixed point coordinate base type. // Vector types with a fixed point coordinate base type.
typedef Eigen::Matrix<coord_t, 2, 1, Eigen::DontAlign> Vec2crd; typedef Eigen::Matrix<coord_t, 2, 1, Eigen::DontAlign> Vec2crd;
typedef Eigen::Matrix<coord_t, 3, 1, Eigen::DontAlign> Vec3crd; typedef Eigen::Matrix<coord_t, 3, 1, Eigen::DontAlign> Vec3crd;
typedef Eigen::Matrix<int64_t, 2, 1, Eigen::DontAlign> Vec2i64;
typedef Eigen::Matrix<int64_t, 3, 1, Eigen::DontAlign> Vec3i64;
// Vector types with a double coordinate base type. // Vector types with a double coordinate base type.
typedef Eigen::Matrix<float, 2, 1, Eigen::DontAlign> Vec2f; typedef Eigen::Matrix<float, 2, 1, Eigen::DontAlign> Vec2f;
@ -47,6 +49,11 @@ typedef Eigen::Transform<double, 2, Eigen::Affine, Eigen::DontAlign> Transform2d
typedef Eigen::Transform<float, 3, Eigen::Affine, Eigen::DontAlign> Transform3f; typedef Eigen::Transform<float, 3, Eigen::Affine, Eigen::DontAlign> Transform3f;
typedef Eigen::Transform<double, 3, Eigen::Affine, Eigen::DontAlign> Transform3d; typedef Eigen::Transform<double, 3, Eigen::Affine, Eigen::DontAlign> Transform3d;
inline int64_t cross2(const Vec2i64 &v1, const Vec2i64 &v2) { return v1.x() * v2.y() - v1.y() * v2.x(); }
inline coord_t cross2(const Vec2crd &v1, const Vec2crd &v2) { return v1.x() * v2.y() - v1.y() * v2.x(); }
inline float cross2(const Vec2f &v1, const Vec2f &v2) { return v1.x() * v2.y() - v1.y() * v2.x(); }
inline double cross2(const Vec2d &v1, const Vec2d &v2) { return v1.x() * v2.y() - v1.y() * v2.x(); }
class Point : public Vec2crd class Point : public Vec2crd
{ {
public: public:
@ -66,7 +73,7 @@ public:
template<typename OtherDerived> template<typename OtherDerived>
Point& operator=(const Eigen::MatrixBase<OtherDerived> &other) Point& operator=(const Eigen::MatrixBase<OtherDerived> &other)
{ {
this->Point::operator=(other); this->Vec2crd::operator=(other);
return *this; return *this;
} }
@ -81,51 +88,33 @@ public:
Point& operator+=(const Point& rhs) { this->x() += rhs.x(); this->y() += rhs.y(); return *this; } Point& operator+=(const Point& rhs) { this->x() += rhs.x(); this->y() += rhs.y(); return *this; }
Point& operator-=(const Point& rhs) { this->x() -= rhs.x(); this->y() -= rhs.y(); return *this; } Point& operator-=(const Point& rhs) { this->x() -= rhs.x(); this->y() -= rhs.y(); return *this; }
Point& operator*=(const coord_t& rhs) { this->x() *= rhs; this->y() *= rhs; return *this; } Point& operator*=(const double &rhs) { this->x() *= rhs; this->y() *= rhs; return *this; }
std::string wkt() const; std::string wkt() const;
std::string dump_perl() const; std::string dump_perl() const;
void scale(double factor) { *this *= factor; }
void translate(double x, double y) { *this += Vector(x, y); }
void translate(const Vector &vector) { *this += vector; }
void rotate(double angle); void rotate(double angle);
void rotate(double angle, const Point &center); void rotate(double angle, const Point &center);
Point rotated(double angle) const { Point res(*this); res.rotate(angle); return res; } Point rotated(double angle) const { Point res(*this); res.rotate(angle); return res; }
Point rotated(double angle, const Point &center) const { Point res(*this); res.rotate(angle, center); return res; } Point rotated(double angle, const Point &center) const { Point res(*this); res.rotate(angle, center); return res; }
bool coincides_with(const Point &rhs) const { return *this == rhs; }
bool coincides_with_epsilon(const Point &point) const; bool coincides_with_epsilon(const Point &point) const;
int nearest_point_index(const Points &points) const; int nearest_point_index(const Points &points) const;
int nearest_point_index(const PointConstPtrs &points) const; int nearest_point_index(const PointConstPtrs &points) const;
int nearest_point_index(const PointPtrs &points) const; int nearest_point_index(const PointPtrs &points) const;
bool nearest_point(const Points &points, Point* point) const; bool nearest_point(const Points &points, Point* point) const;
double distance_to(const Point &point) const { return (point - *this).norm(); }
double distance_to_sq(const Point &point) const { return (point - *this).squaredNorm(); }
double distance_to(const Line &line) const;
double perp_distance_to(const Line &line) const;
double ccw(const Point &p1, const Point &p2) const; double ccw(const Point &p1, const Point &p2) const;
double ccw(const Line &line) const; double ccw(const Line &line) const;
double ccw_angle(const Point &p1, const Point &p2) const; double ccw_angle(const Point &p1, const Point &p2) const;
Point projection_onto(const MultiPoint &poly) const; Point projection_onto(const MultiPoint &poly) const;
Point projection_onto(const Line &line) const; Point projection_onto(const Line &line) const;
Point negative() const { return Point(- *this); }
Vector vector_to(const Point &point) const { return Vector(point - *this); }
}; };
inline Point operator+(const Point& point1, const Point& point2) { return Point(point1.x() + point2.x(), point1.y() + point2.y()); }
inline Point operator-(const Point& point1, const Point& point2) { return Point(point1.x() - point2.x(), point1.y() - point2.y()); }
inline Point operator*(double scalar, const Point& point2) { return Point(scalar * point2.x(), scalar * point2.y()); }
inline int64_t cross(const Point &v1, const Point &v2) { return int64_t(v1.x()) * int64_t(v2.y()) - int64_t(v1.y()) * int64_t(v2.x()); }
inline int64_t dot(const Point &v1, const Point &v2) { return int64_t(v1.x()) * int64_t(v2.x()) + int64_t(v1.y()) * int64_t(v2.y()); }
namespace int128 { namespace int128 {
// Exact orientation predicate,
// Exact orientation predicate, // returns +1: CCW, 0: collinear, -1: CW.
// returns +1: CCW, 0: collinear, -1: CW. int orient(const Point &p1, const Point &p2, const Point &p3);
int orient(const Point &p1, const Point &p2, const Point &p3); // Exact orientation predicate,
// returns +1: CCW, 0: collinear, -1: CW.
// Exact orientation predicate, int cross(const Point &v1, const Slic3r::Point &v2);
// returns +1: CCW, 0: collinear, -1: CW.
int cross(const Point &v1, const Slic3r::Point &v2);
} }
// To be used by std::unordered_map, std::unordered_multimap and friends. // To be used by std::unordered_map, std::unordered_multimap and friends.
@ -204,7 +193,7 @@ public:
const ValueType &value = it->second; const ValueType &value = it->second;
const Point *pt2 = m_point_accessor(value); const Point *pt2 = m_point_accessor(value);
if (pt2 != nullptr) { if (pt2 != nullptr) {
const double d2 = pt.distance_to_sq(*pt2); const double d2 = (pt - *pt2).squaredNorm();
if (d2 < dist_min) { if (d2 < dist_min) {
dist_min = d2; dist_min = d2;
value_min = &value; value_min = &value;
@ -243,7 +232,7 @@ public:
template<typename OtherDerived> template<typename OtherDerived>
Point3& operator=(const Eigen::MatrixBase<OtherDerived> &other) Point3& operator=(const Eigen::MatrixBase<OtherDerived> &other)
{ {
this->Point3::operator=(other); this->Vec3crd::operator=(other);
return *this; return *this;
} }
@ -268,7 +257,6 @@ public:
typedef coordf_t coord_type; typedef coordf_t coord_type;
explicit Pointf() { (*this)(0) = (*this)(1) = 0.; } explicit Pointf() { (*this)(0) = (*this)(1) = 0.; }
// explicit Pointf(double x, double y) { (*this)(0) = x; (*this)(1) = y; }
explicit Pointf(coordf_t x, coordf_t y) { (*this)(0) = x; (*this)(1) = y; } explicit Pointf(coordf_t x, coordf_t y) { (*this)(0) = x; (*this)(1) = y; }
// This constructor allows you to construct Pointf from Eigen expressions // This constructor allows you to construct Pointf from Eigen expressions
template<typename OtherDerived> template<typename OtherDerived>
@ -280,7 +268,7 @@ public:
template<typename OtherDerived> template<typename OtherDerived>
Pointf& operator=(const Eigen::MatrixBase<OtherDerived> &other) Pointf& operator=(const Eigen::MatrixBase<OtherDerived> &other)
{ {
this->Pointf::operator=(other); this->Vec2d::operator=(other);
return *this; return *this;
} }
@ -291,13 +279,8 @@ public:
std::string wkt() const; std::string wkt() const;
std::string dump_perl() const; std::string dump_perl() const;
void scale(double factor) { *this *= factor; }
void translate(double x, double y) { *this += Vec2d(x, y); }
void translate(const Vectorf &vector) { *this += vector; }
void rotate(double angle); void rotate(double angle);
void rotate(double angle, const Pointf &center); void rotate(double angle, const Pointf &center);
Pointf negative() const { return Pointf(- *this); }
Vectorf vector_to(const Pointf &point) const { return point - *this; }
Pointf& operator+=(const Pointf& rhs) { this->x() += rhs.x(); this->y() += rhs.y(); return *this; } Pointf& operator+=(const Pointf& rhs) { this->x() += rhs.x(); this->y() += rhs.y(); return *this; }
Pointf& operator-=(const Pointf& rhs) { this->x() -= rhs.x(); this->y() -= rhs.y(); return *this; } Pointf& operator-=(const Pointf& rhs) { this->x() -= rhs.x(); this->y() -= rhs.y(); return *this; }
Pointf& operator*=(const coordf_t& rhs) { this->x() *= rhs; this->y() *= rhs; return *this; } Pointf& operator*=(const coordf_t& rhs) { this->x() *= rhs; this->y() *= rhs; return *this; }
@ -307,21 +290,6 @@ public:
bool operator< (const Pointf& rhs) const { return this->x() < rhs.x() || (this->x() == rhs.x() && this->y() < rhs.y()); } bool operator< (const Pointf& rhs) const { return this->x() < rhs.x() || (this->x() == rhs.x() && this->y() < rhs.y()); }
}; };
inline Pointf operator+(const Pointf& point1, const Pointf& point2) { return Pointf(point1.x() + point2.x(), point1.y() + point2.y()); }
inline Pointf operator-(const Pointf& point1, const Pointf& point2) { return Pointf(point1.x() - point2.x(), point1.y() - point2.y()); }
inline Pointf operator*(double scalar, const Pointf& point2) { return Pointf(scalar * point2.x(), scalar * point2.y()); }
inline Pointf operator*(const Pointf& point2, double scalar) { return Pointf(scalar * point2.x(), scalar * point2.y()); }
inline coordf_t cross(const Pointf &v1, const Pointf &v2) { return v1.x() * v2.y() - v1.y() * v2.x(); }
inline coordf_t dot(const Pointf &v1, const Pointf &v2) { return v1.x() * v2.x() + v1.y() * v2.y(); }
inline coordf_t dot(const Pointf &v) { return v.x() * v.x() + v.y() * v.y(); }
inline double length(const Vectorf &v) { return sqrt(dot(v)); }
inline double l2(const Vectorf &v) { return dot(v); }
inline Vectorf normalize(const Vectorf& v)
{
coordf_t len = ::sqrt(sqr(v.x()) + sqr(v.y()));
return (len != 0.0) ? 1.0 / len * v : Vectorf(0.0, 0.0);
}
class Pointf3 : public Vec3d class Pointf3 : public Vec3d
{ {
public: public:
@ -340,7 +308,7 @@ public:
template<typename OtherDerived> template<typename OtherDerived>
Pointf3& operator=(const Eigen::MatrixBase<OtherDerived> &other) Pointf3& operator=(const Eigen::MatrixBase<OtherDerived> &other)
{ {
this->Pointf3::operator=(other); this->Vec3d::operator=(other);
return *this; return *this;
} }
@ -351,40 +319,12 @@ public:
const coordf_t& z() const { return (*this)(2); } const coordf_t& z() const { return (*this)(2); }
coordf_t& z() { return (*this)(2); } coordf_t& z() { return (*this)(2); }
void scale(double factor) { *this *= factor; }
void translate(const Vectorf3 &vector) { *this += vector; }
void translate(double x, double y, double z) { *this += Vec3d(x, y, z); }
double distance_to(const Pointf3 &point) const { return (point - *this).norm(); }
Pointf3 negative() const { return Pointf3(- *this); }
Vectorf3 vector_to(const Pointf3 &point) const { return point - *this; }
bool operator==(const Pointf3 &rhs) const { return this->x() == rhs.x() && this->y() == rhs.y() && this->z() == rhs.z(); } bool operator==(const Pointf3 &rhs) const { return this->x() == rhs.x() && this->y() == rhs.y() && this->z() == rhs.z(); }
bool operator!=(const Pointf3 &rhs) const { return ! (*this == rhs); } bool operator!=(const Pointf3 &rhs) const { return ! (*this == rhs); }
Pointf xy() const { return Pointf(this->x(), this->y()); } Pointf xy() const { return Pointf(this->x(), this->y()); }
}; };
inline Pointf3 operator+(const Pointf3& p1, const Pointf3& p2) { return Pointf3(p1.x() + p2.x(), p1.y() + p2.y(), p1.z() + p2.z()); }
inline Pointf3 operator-(const Pointf3& p1, const Pointf3& p2) { return Pointf3(p1.x() - p2.x(), p1.y() - p2.y(), p1.z() - p2.z()); }
inline Pointf3 operator-(const Pointf3& p) { return Pointf3(-p.x(), -p.y(), -p.z()); }
inline Pointf3 operator*(double scalar, const Pointf3& p) { return Pointf3(scalar * p.x(), scalar * p.y(), scalar * p.z()); }
inline Pointf3 operator*(const Pointf3& p, double scalar) { return Pointf3(scalar * p.x(), scalar * p.y(), scalar * p.z()); }
inline Pointf3 cross(const Pointf3& v1, const Pointf3& v2) { return Pointf3(v1.y() * v2.z() - v1.z() * v2.y(), v1.z() * v2.x() - v1.x() * v2.z(), v1.x() * v2.y() - v1.y() * v2.x()); }
inline coordf_t dot(const Pointf3& v1, const Pointf3& v2) { return v1.x() * v2.x() + v1.y() * v2.y() + v1.z() * v2.z(); }
inline coordf_t dot(const Pointf3& v) { return v.x() * v.x() + v.y() * v.y() + v.z() * v.z(); }
inline double length(const Vectorf3 &v) { return sqrt(dot(v)); }
inline double l2(const Vectorf3 &v) { return dot(v); }
inline Pointf3 normalize(const Pointf3& v)
{
coordf_t len = ::sqrt(sqr(v.x()) + sqr(v.y()) + sqr(v.z()));
return (len != 0.0) ? 1.0 / len * v : Pointf3(0.0, 0.0, 0.0);
}
template<typename TO> inline TO convert_to(const Point &src) { return TO(typename TO::coord_type(src.x()), typename TO::coord_type(src.y())); }
template<typename TO> inline TO convert_to(const Pointf &src) { return TO(typename TO::coord_type(src.x()), typename TO::coord_type(src.y())); }
template<typename TO> inline TO convert_to(const Point3 &src) { return TO(typename TO::coord_type(src.x()), typename TO::coord_type(src.y()), typename TO::coord_type(src.z())); }
template<typename TO> inline TO convert_to(const Pointf3 &src) { return TO(typename TO::coord_type(src.x()), typename TO::coord_type(src.y()), typename TO::coord_type(src.z())); }
} // namespace Slic3r } // namespace Slic3r
// start Boost // start Boost

View file

@ -300,24 +300,24 @@ Point Polygon::point_projection(const Point &point) const
for (size_t i = 0; i < this->points.size(); ++ i) { for (size_t i = 0; i < this->points.size(); ++ i) {
const Point &pt0 = this->points[i]; const Point &pt0 = this->points[i];
const Point &pt1 = this->points[(i + 1 == this->points.size()) ? 0 : i + 1]; const Point &pt1 = this->points[(i + 1 == this->points.size()) ? 0 : i + 1];
double d = pt0.distance_to(point); double d = (point - pt0).cast<double>().norm();
if (d < dmin) { if (d < dmin) {
dmin = d; dmin = d;
proj = pt0; proj = pt0;
} }
d = pt1.distance_to(point); d = (point - pt1).cast<double>().norm();
if (d < dmin) { if (d < dmin) {
dmin = d; dmin = d;
proj = pt1; proj = pt1;
} }
Pointf v1(coordf_t(pt1.x() - pt0.x()), coordf_t(pt1.y() - pt0.y())); Pointf v1(coordf_t(pt1.x() - pt0.x()), coordf_t(pt1.y() - pt0.y()));
coordf_t div = dot(v1); coordf_t div = v1.squaredNorm();
if (div > 0.) { if (div > 0.) {
Pointf v2(coordf_t(point.x() - pt0.x()), coordf_t(point.y() - pt0.y())); Pointf v2(coordf_t(point.x() - pt0.x()), coordf_t(point.y() - pt0.y()));
coordf_t t = dot(v1, v2) / div; coordf_t t = v1.dot(v2) / div;
if (t > 0. && t < 1.) { if (t > 0. && t < 1.) {
Point foot(coord_t(floor(coordf_t(pt0.x()) + t * v1.x() + 0.5)), coord_t(floor(coordf_t(pt0.y()) + t * v1.y() + 0.5))); Point foot(coord_t(floor(coordf_t(pt0.x()) + t * v1.x() + 0.5)), coord_t(floor(coordf_t(pt0.y()) + t * v1.y() + 0.5)));
d = foot.distance_to(point); d = (point - foot).cast<double>().norm();
if (d < dmin) { if (d < dmin) {
dmin = d; dmin = d;
proj = foot; proj = foot;

View file

@ -52,92 +52,82 @@ Polyline::lines() const
} }
// removes the given distance from the end of the polyline // removes the given distance from the end of the polyline
void void Polyline::clip_end(double distance)
Polyline::clip_end(double distance)
{ {
while (distance > 0) { while (distance > 0) {
Point last_point = this->last_point(); Vec2d last_point = this->last_point().cast<double>();
this->points.pop_back(); this->points.pop_back();
if (this->points.empty()) break; if (this->points.empty())
break;
double last_segment_length = last_point.distance_to(this->last_point()); Vec2d v = this->last_point().cast<double>() - last_point;
if (last_segment_length <= distance) { double lsqr = v.squaredNorm();
distance -= last_segment_length; if (lsqr > distance * distance) {
continue; this->points.emplace_back((last_point + v * (distance / sqrt(lsqr))).cast<coord_t>());
return;
} }
distance -= sqrt(lsqr);
Line segment(last_point, this->last_point());
this->points.push_back(segment.point_at(distance));
distance = 0;
} }
} }
// removes the given distance from the start of the polyline // removes the given distance from the start of the polyline
void void Polyline::clip_start(double distance)
Polyline::clip_start(double distance)
{ {
this->reverse(); this->reverse();
this->clip_end(distance); this->clip_end(distance);
if (this->points.size() >= 2) this->reverse(); if (this->points.size() >= 2)
this->reverse();
} }
void void Polyline::extend_end(double distance)
Polyline::extend_end(double distance)
{ {
// relocate last point by extending the last segment by the specified length // relocate last point by extending the last segment by the specified length
Line line( Vec2d v = (this->points.back() - *(this->points.end() - 2)).cast<double>().normalized();
this->points.back(), this->points.back() += (v * distance).cast<coord_t>();
*(this->points.end() - 2)
);
this->points.back() = line.point_at(-distance);
} }
void void Polyline::extend_start(double distance)
Polyline::extend_start(double distance)
{ {
// relocate first point by extending the first segment by the specified length // relocate first point by extending the first segment by the specified length
this->points.front() = Line(this->points.front(), this->points[1]).point_at(-distance); Vec2d v = (this->points.front() - this->points[1]).cast<double>().normalized();
this->points.front() += (v * distance).cast<coord_t>();
} }
/* this method returns a collection of points picked on the polygon contour /* this method returns a collection of points picked on the polygon contour
so that they are evenly spaced according to the input distance */ so that they are evenly spaced according to the input distance */
Points Points Polyline::equally_spaced_points(double distance) const
Polyline::equally_spaced_points(double distance) const
{ {
Points points; Points points;
points.push_back(this->first_point()); points.emplace_back(this->first_point());
double len = 0; double len = 0;
for (Points::const_iterator it = this->points.begin() + 1; it != this->points.end(); ++it) { for (Points::const_iterator it = this->points.begin() + 1; it != this->points.end(); ++it) {
double segment_length = it->distance_to(*(it-1)); Vec2d p1 = (it-1)->cast<double>();
Vec2d v = it->cast<double>() - p1;
double segment_length = v.norm();
len += segment_length; len += segment_length;
if (len < distance) continue; if (len < distance)
continue;
if (len == distance) { if (len == distance) {
points.push_back(*it); points.emplace_back(*it);
len = 0; len = 0;
continue; continue;
} }
double take = segment_length - (len - distance); // how much we take of this segment double take = segment_length - (len - distance); // how much we take of this segment
Line segment(*(it-1), *it); points.emplace_back((p1 + v * (take / v.norm())).cast<coord_t>());
points.push_back(segment.point_at(take)); -- it;
--it; len = - take;
len = -take;
} }
return points; return points;
} }
void void Polyline::simplify(double tolerance)
Polyline::simplify(double tolerance)
{ {
this->points = MultiPoint::_douglas_peucker(this->points, tolerance); this->points = MultiPoint::_douglas_peucker(this->points, tolerance);
} }
/* This method simplifies all *lines* contained in the supplied area */ /* This method simplifies all *lines* contained in the supplied area */
template <class T> template <class T>
void void Polyline::simplify_by_visibility(const T &area)
Polyline::simplify_by_visibility(const T &area)
{ {
Points &pp = this->points; Points &pp = this->points;
@ -157,21 +147,20 @@ Polyline::simplify_by_visibility(const T &area)
template void Polyline::simplify_by_visibility<ExPolygon>(const ExPolygon &area); template void Polyline::simplify_by_visibility<ExPolygon>(const ExPolygon &area);
template void Polyline::simplify_by_visibility<ExPolygonCollection>(const ExPolygonCollection &area); template void Polyline::simplify_by_visibility<ExPolygonCollection>(const ExPolygonCollection &area);
void void Polyline::split_at(const Point &point, Polyline* p1, Polyline* p2) const
Polyline::split_at(const Point &point, Polyline* p1, Polyline* p2) const
{ {
if (this->points.empty()) return; if (this->points.empty()) return;
// find the line to split at // find the line to split at
size_t line_idx = 0; size_t line_idx = 0;
Point p = this->first_point(); Point p = this->first_point();
double min = point.distance_to(p); double min = (p - point).cast<double>().norm();
Lines lines = this->lines(); Lines lines = this->lines();
for (Lines::const_iterator line = lines.begin(); line != lines.end(); ++line) { for (Lines::const_iterator line = lines.begin(); line != lines.end(); ++line) {
Point p_tmp = point.projection_onto(*line); Point p_tmp = point.projection_onto(*line);
if (point.distance_to(p_tmp) < min) { if ((p_tmp - point).cast<double>().norm() < min) {
p = p_tmp; p = p_tmp;
min = point.distance_to(p); min = (p - point).cast<double>().norm();
line_idx = line - lines.begin(); line_idx = line - lines.begin();
} }
} }
@ -193,8 +182,7 @@ Polyline::split_at(const Point &point, Polyline* p1, Polyline* p2) const
} }
} }
bool bool Polyline::is_straight() const
Polyline::is_straight() const
{ {
/* Check that each segment's direction is equal to the line connecting /* Check that each segment's direction is equal to the line connecting
first point and last point. (Checking each line against the previous first point and last point. (Checking each line against the previous
@ -208,8 +196,7 @@ Polyline::is_straight() const
return true; return true;
} }
std::string std::string Polyline::wkt() const
Polyline::wkt() const
{ {
std::ostringstream wkt; std::ostringstream wkt;
wkt << "LINESTRING(("; wkt << "LINESTRING((";
@ -254,30 +241,17 @@ bool remove_degenerate(Polylines &polylines)
return modified; return modified;
} }
ThickLines ThickLines ThickPolyline::thicklines() const
ThickPolyline::thicklines() const
{ {
ThickLines lines; ThickLines lines;
if (this->points.size() >= 2) { if (this->points.size() >= 2) {
lines.reserve(this->points.size() - 1); lines.reserve(this->points.size() - 1);
for (size_t i = 0; i < this->points.size()-1; ++i) { for (size_t i = 0; i + 1 < this->points.size(); ++ i)
ThickLine line(this->points[i], this->points[i+1]); lines.emplace_back(this->points[i], this->points[i + 1], this->width[2 * i], this->width[2 * i + 1]);
line.a_width = this->width[2*i];
line.b_width = this->width[2*i+1];
lines.push_back(line);
}
} }
return lines; return lines;
} }
void
ThickPolyline::reverse()
{
Polyline::reverse();
std::reverse(this->width.begin(), this->width.end());
std::swap(this->endpoints.first, this->endpoints.second);
}
Lines3 Polyline3::lines() const Lines3 Polyline3::lines() const
{ {
Lines3 lines; Lines3 lines;

View file

@ -19,6 +19,8 @@ public:
Polyline() {}; Polyline() {};
Polyline(const Polyline &other) : MultiPoint(other.points) {} Polyline(const Polyline &other) : MultiPoint(other.points) {}
Polyline(Polyline &&other) : MultiPoint(std::move(other.points)) {} Polyline(Polyline &&other) : MultiPoint(std::move(other.points)) {}
Polyline(std::initializer_list<Point> list) : MultiPoint(list) {}
explicit Polyline(const Point &p1, const Point &p2) { points.reserve(2); points.emplace_back(p1); points.emplace_back(p2); }
Polyline& operator=(const Polyline &other) { points = other.points; return *this; } Polyline& operator=(const Polyline &other) { points = other.points; return *this; }
Polyline& operator=(Polyline &&other) { points = std::move(other.points); return *this; } Polyline& operator=(Polyline &&other) { points = std::move(other.points); return *this; }
static Polyline new_scale(std::vector<Pointf> points) { static Polyline new_scale(std::vector<Pointf> points) {
@ -129,12 +131,17 @@ inline void polylines_append(Polylines &dst, Polylines &&src)
bool remove_degenerate(Polylines &polylines); bool remove_degenerate(Polylines &polylines);
class ThickPolyline : public Polyline { class ThickPolyline : public Polyline {
public: public:
std::vector<coordf_t> width; ThickPolyline() : endpoints(std::make_pair(false, false)) {}
std::pair<bool,bool> endpoints;
ThickPolyline() : endpoints(std::make_pair(false, false)) {};
ThickLines thicklines() const; ThickLines thicklines() const;
void reverse(); void reverse() {
Polyline::reverse();
std::reverse(this->width.begin(), this->width.end());
std::swap(this->endpoints.first, this->endpoints.second);
}
std::vector<coordf_t> width;
std::pair<bool,bool> endpoints;
}; };
class Polyline3 : public MultiPoint3 class Polyline3 : public MultiPoint3

View file

@ -726,7 +726,7 @@ BoundingBox Print::bounding_box() const
for (const PrintObject *object : this->objects) for (const PrintObject *object : this->objects)
for (Point copy : object->_shifted_copies) { for (Point copy : object->_shifted_copies) {
bb.merge(copy); bb.merge(copy);
copy.translate(object->size.xy()); copy += object->size.xy();
bb.merge(copy); bb.merge(copy);
} }
return bb; return bb;
@ -902,7 +902,7 @@ void Print::_make_skirt()
for (const Point &shift : object->_shifted_copies) { for (const Point &shift : object->_shifted_copies) {
Points copy_points = object_points; Points copy_points = object_points;
for (Point &pt : copy_points) for (Point &pt : copy_points)
pt.translate(shift); pt += shift;
append(points, copy_points); append(points, copy_points);
} }
} }
@ -1052,10 +1052,7 @@ void Print::_make_wipe_tower()
return; return;
// Get wiping matrix to get number of extruders and convert vector<double> to vector<float>: // Get wiping matrix to get number of extruders and convert vector<double> to vector<float>:
#pragma warning(push) std::vector<float> wiping_matrix(cast<float>(this->config.wiping_volumes_matrix.values));
#pragma warning(disable:4244) // disable Visual Studio's warning: conversion from 'double' to 'float', possible loss of data
std::vector<float> wiping_matrix((this->config.wiping_volumes_matrix.values).begin(),(this->config.wiping_volumes_matrix.values).end());
#pragma warning(pop)
// Extract purging volumes for each extruder pair: // Extract purging volumes for each extruder pair:
std::vector<std::vector<float>> wipe_volumes; std::vector<std::vector<float>> wipe_volumes;
const unsigned int number_of_extruders = (unsigned int)(sqrt(wiping_matrix.size())+EPSILON); const unsigned int number_of_extruders = (unsigned int)(sqrt(wiping_matrix.size())+EPSILON);

View file

@ -85,11 +85,8 @@ bool PrintObject::set_copies(const Points &points)
std::vector<Points::size_type> ordered_copies; std::vector<Points::size_type> ordered_copies;
Slic3r::Geometry::chained_path(points, ordered_copies); Slic3r::Geometry::chained_path(points, ordered_copies);
for (size_t point_idx : ordered_copies) { for (size_t point_idx : ordered_copies)
Point copy = points[point_idx]; this->_shifted_copies.push_back(points[point_idx] + this->_copies_shift);
copy.translate(this->_copies_shift);
this->_shifted_copies.push_back(copy);
}
bool invalidated = this->_print->invalidate_step(psSkirt); bool invalidated = this->_print->invalidate_step(psSkirt);
invalidated |= this->_print->invalidate_step(psBrim); invalidated |= this->_print->invalidate_step(psBrim);

View file

@ -506,8 +506,8 @@ public:
for (ExPolygon &island : islands) { for (ExPolygon &island : islands) {
BoundingBox bbox = get_extents(island.contour); BoundingBox bbox = get_extents(island.contour);
auto it_lower = std::lower_bound(m_island_samples.begin(), m_island_samples.end(), bbox.min - Point(1, 1)); auto it_lower = std::lower_bound(m_island_samples.begin(), m_island_samples.end(), Point(bbox.min - Point(1, 1)));
auto it_upper = std::upper_bound(m_island_samples.begin(), m_island_samples.end(), bbox.max + Point(1, 1)); auto it_upper = std::upper_bound(m_island_samples.begin(), m_island_samples.end(), Point(bbox.max + Point(1, 1)));
samples_inside.clear(); samples_inside.clear();
for (auto it = it_lower; it != it_upper; ++ it) for (auto it = it_lower; it != it_upper; ++ it)
if (bbox.contains(*it)) if (bbox.contains(*it))
@ -2059,9 +2059,9 @@ void LoopInterfaceProcessor::generate(MyLayerExtruded &top_contact_layer, const
// Intersection of a ray (p1, p2) with a circle placed at center_last, with radius of circle_distance. // Intersection of a ray (p1, p2) with a circle placed at center_last, with radius of circle_distance.
const Pointf v_seg(coordf_t(p2.x()) - coordf_t(p1.x()), coordf_t(p2.y()) - coordf_t(p1.y())); const Pointf v_seg(coordf_t(p2.x()) - coordf_t(p1.x()), coordf_t(p2.y()) - coordf_t(p1.y()));
const Pointf v_cntr(coordf_t(p1.x() - center_last.x()), coordf_t(p1.y() - center_last.y())); const Pointf v_cntr(coordf_t(p1.x() - center_last.x()), coordf_t(p1.y() - center_last.y()));
coordf_t a = dot(v_seg); coordf_t a = v_seg.squaredNorm();
coordf_t b = 2. * dot(v_seg, v_cntr); coordf_t b = 2. * v_seg.dot(v_cntr);
coordf_t c = dot(v_cntr) - circle_distance * circle_distance; coordf_t c = v_cntr.squaredNorm() - circle_distance * circle_distance;
coordf_t disc = b * b - 4. * a * c; coordf_t disc = b * b - 4. * a * c;
if (disc > 0.) { if (disc > 0.) {
// The circle intersects a ray. Avoid the parts of the segment inside the circle. // The circle intersects a ray. Avoid the parts of the segment inside the circle.
@ -2100,9 +2100,9 @@ void LoopInterfaceProcessor::generate(MyLayerExtruded &top_contact_layer, const
circle_centers.push_back(center_last); circle_centers.push_back(center_last);
} }
external_loops.push_back(std::move(contour)); external_loops.push_back(std::move(contour));
for (Points::const_iterator it_center = circle_centers.begin(); it_center != circle_centers.end(); ++ it_center) { for (const Point &center : circle_centers) {
circles.push_back(circle); circles.push_back(circle);
circles.back().translate(*it_center); circles.back().translate(center);
} }
} }
} }
@ -2392,7 +2392,7 @@ void modulate_extrusion_by_overlapping_layers(
if (end_and_dist2.first == nullptr) { if (end_and_dist2.first == nullptr) {
// New fragment connecting to pt_current was not found. // New fragment connecting to pt_current was not found.
// Verify that the last point found is close to the original end point of the unfragmented path. // Verify that the last point found is close to the original end point of the unfragmented path.
//const double d2 = pt_end.distance_to_sq(pt_current); //const double d2 = (pt_end - pt_current).squaredNorm();
//assert(d2 < coordf_t(search_radius * search_radius)); //assert(d2 < coordf_t(search_radius * search_radius));
// End of the path. // End of the path.
break; break;

View file

@ -130,6 +130,17 @@ inline void append(std::vector<T>& dest, std::vector<T>&& src)
src.shrink_to_fit(); src.shrink_to_fit();
} }
// Casting an std::vector<> from one type to another type without warnings about a loss of accuracy.
template<typename T_TO, typename T_FROM>
std::vector<T_TO> cast(const std::vector<T_FROM> &src)
{
std::vector<T_TO> dst;
dst.reserve(src.size());
for (const T_FROM &a : src)
dst.emplace_back((T_TO)a);
return dst;
}
template <typename T> template <typename T>
inline void remove_nulls(std::vector<T*> &vec) inline void remove_nulls(std::vector<T*> &vec)
{ {

View file

@ -34,11 +34,11 @@ void Bed_2D::repaint()
auto cbb = BoundingBoxf(Pointf(0, 0),Pointf(cw, ch)); auto cbb = BoundingBoxf(Pointf(0, 0),Pointf(cw, ch));
// leave space for origin point // leave space for origin point
cbb.min.translate(4, 0); cbb.min.x() += 4;
cbb.max.translate(-4, -4); cbb.max -= Vec2d(4., 4.);
// leave space for origin label // leave space for origin label
cbb.max.translate(0, -13); cbb.max.y() -= 13;
// read new size // read new size
cw = cbb.size().x(); cw = cbb.size().x();
@ -113,7 +113,7 @@ void Bed_2D::repaint()
dc.DrawLine(wxPoint(origin_px.x(), origin_px.y()), wxPoint(x_end.x(), x_end.y())); dc.DrawLine(wxPoint(origin_px.x(), origin_px.y()), wxPoint(x_end.x(), x_end.y()));
for (auto angle : { -arrow_angle, arrow_angle }){ for (auto angle : { -arrow_angle, arrow_angle }){
auto end = x_end; auto end = x_end;
end.translate(-arrow_len, 0); end.x() -= arrow_len;
end.rotate(angle, x_end); end.rotate(angle, x_end);
dc.DrawLine(wxPoint(x_end.x(), x_end.y()), wxPoint(end.x(), end.y())); dc.DrawLine(wxPoint(x_end.x(), x_end.y()), wxPoint(end.x(), end.y()));
} }
@ -123,7 +123,7 @@ void Bed_2D::repaint()
dc.DrawLine(wxPoint(origin_px.x(), origin_px.y()), wxPoint(y_end.x(), y_end.y())); dc.DrawLine(wxPoint(origin_px.x(), origin_px.y()), wxPoint(y_end.x(), y_end.y()));
for (auto angle : { -arrow_angle, arrow_angle }) { for (auto angle : { -arrow_angle, arrow_angle }) {
auto end = y_end; auto end = y_end;
end.translate(0, +arrow_len); end.y() += arrow_len;
end.rotate(angle, y_end); end.rotate(angle, y_end);
dc.DrawLine(wxPoint(y_end.x(), y_end.y()), wxPoint(end.x(), end.y())); dc.DrawLine(wxPoint(y_end.x(), y_end.y()), wxPoint(end.x(), end.y()));
} }
@ -157,9 +157,7 @@ void Bed_2D::repaint()
// convert G - code coordinates into pixels // convert G - code coordinates into pixels
Point Bed_2D::to_pixels(Pointf point){ Point Bed_2D::to_pixels(Pointf point){
auto p = Pointf(point); auto p = point * m_scale_factor + m_shift;
p.scale(m_scale_factor);
p.translate(m_shift);
return Point(p.x(), GetSize().GetHeight() - p.y()); return Point(p.x(), GetSize().GetHeight() - p.y());
} }
@ -178,10 +176,7 @@ void Bed_2D::mouse_event(wxMouseEvent event){
// convert pixels into G - code coordinates // convert pixels into G - code coordinates
Pointf Bed_2D::to_units(Point point){ Pointf Bed_2D::to_units(Point point){
auto p = Pointf(point.x(), GetSize().GetHeight() - point.y()); return (Pointf(point.x(), GetSize().GetHeight() - point.y()) - m_shift) * (1. / m_scale_factor);
p.translate(m_shift.negative());
p.scale(1 / m_scale_factor);
return p;
} }
void Bed_2D::set_pos(Pointf pos){ void Bed_2D::set_pos(Pointf pos){

View file

@ -929,7 +929,7 @@ static void thick_lines_to_indexed_vertex_array(
bool is_closing = closed && is_last; bool is_closing = closed && is_last;
Vectorf v = Vectorf::new_unscale(line.vector()); Vectorf v = Vectorf::new_unscale(line.vector());
v.scale(inv_len); v *= inv_len;
Pointf a = Pointf::new_unscale(line.a); Pointf a = Pointf::new_unscale(line.a);
Pointf b = Pointf::new_unscale(line.b); Pointf b = Pointf::new_unscale(line.b);
@ -941,16 +941,16 @@ static void thick_lines_to_indexed_vertex_array(
double dist = 0.5 * width; // scaled double dist = 0.5 * width; // scaled
double dx = dist * v.x(); double dx = dist * v.x();
double dy = dist * v.y(); double dy = dist * v.y();
a1.translate(+dy, -dx); a1 += Vectorf(+dy, -dx);
a2.translate(-dy, +dx); a2 += Vectorf(-dy, +dx);
b1.translate(+dy, -dx); b1 += Vectorf(+dy, -dx);
b2.translate(-dy, +dx); b2 += Vectorf(-dy, +dx);
} }
// calculate new XY normals // calculate new XY normals
Vector n = line.normal(); Vector n = line.normal();
Vectorf3 xy_right_normal = Vectorf3::new_unscale(n.x(), n.y(), 0); Vectorf3 xy_right_normal = Vectorf3::new_unscale(n.x(), n.y(), 0);
xy_right_normal.scale(inv_len); xy_right_normal *= inv_len;
int idx_a[4]; int idx_a[4];
int idx_b[4]; int idx_b[4];
@ -994,7 +994,7 @@ static void thick_lines_to_indexed_vertex_array(
} else { } else {
// Continuing a previous segment. // Continuing a previous segment.
// Share left / right vertices if possible. // Share left / right vertices if possible.
double v_dot = dot(v_prev, v); double v_dot = v_prev.dot(v);
bool sharp = v_dot < 0.707; // sin(45 degrees) bool sharp = v_dot < 0.707; // sin(45 degrees)
if (sharp) { if (sharp) {
if (!bottom_z_different) if (!bottom_z_different)
@ -1023,8 +1023,8 @@ static void thick_lines_to_indexed_vertex_array(
Geometry::ray_ray_intersection(b1_prev, v_prev, a1, v, intersection); Geometry::ray_ray_intersection(b1_prev, v_prev, a1, v, intersection);
a1 = intersection; a1 = intersection;
a2 = 2. * a - intersection; a2 = 2. * a - intersection;
assert(length(a1.vector_to(a)) < width); assert((a - a1).norm() < width);
assert(length(a2.vector_to(a)) < width); assert((a - a2).norm() < width);
float *n_left_prev = volume.vertices_and_normals_interleaved.data() + idx_prev[LEFT ] * 6; float *n_left_prev = volume.vertices_and_normals_interleaved.data() + idx_prev[LEFT ] * 6;
float *p_left_prev = n_left_prev + 3; float *p_left_prev = n_left_prev + 3;
float *n_right_prev = volume.vertices_and_normals_interleaved.data() + idx_prev[RIGHT] * 6; float *n_right_prev = volume.vertices_and_normals_interleaved.data() + idx_prev[RIGHT] * 6;
@ -1035,7 +1035,7 @@ static void thick_lines_to_indexed_vertex_array(
p_right_prev[1] = float(a1.y()); p_right_prev[1] = float(a1.y());
xy_right_normal.x() += n_right_prev[0]; xy_right_normal.x() += n_right_prev[0];
xy_right_normal.y() += n_right_prev[1]; xy_right_normal.y() += n_right_prev[1];
xy_right_normal.scale(1. / length(xy_right_normal)); xy_right_normal *= 1. / xy_right_normal.norm();
n_left_prev [0] = float(-xy_right_normal.x()); n_left_prev [0] = float(-xy_right_normal.x());
n_left_prev [1] = float(-xy_right_normal.y()); n_left_prev [1] = float(-xy_right_normal.y());
n_right_prev[0] = float( xy_right_normal.x()); n_right_prev[0] = float( xy_right_normal.x());
@ -1044,7 +1044,7 @@ static void thick_lines_to_indexed_vertex_array(
idx_a[RIGHT] = idx_prev[RIGHT]; idx_a[RIGHT] = idx_prev[RIGHT];
} }
} }
else if (cross(v_prev, v) > 0.) { else if (cross2(v_prev, v) > 0.) {
// Right turn. Fill in the right turn wedge. // Right turn. Fill in the right turn wedge.
volume.push_triangle(idx_prev[RIGHT], idx_a [RIGHT], idx_prev[TOP] ); volume.push_triangle(idx_prev[RIGHT], idx_a [RIGHT], idx_prev[TOP] );
volume.push_triangle(idx_prev[RIGHT], idx_prev[BOTTOM], idx_a [RIGHT] ); volume.push_triangle(idx_prev[RIGHT], idx_prev[BOTTOM], idx_a [RIGHT] );
@ -1172,7 +1172,7 @@ static void thick_lines_to_indexed_vertex_array(const Lines3& lines,
double height = heights[i]; double height = heights[i];
double width = widths[i]; double width = widths[i];
Vectorf3 unit_v = normalize(Vectorf3::new_unscale(line.vector())); Vectorf3 unit_v = Vectorf3::new_unscale(line.vector()).normalized();
Vectorf3 n_top; Vectorf3 n_top;
Vectorf3 n_right; Vectorf3 n_right;
@ -1187,8 +1187,8 @@ static void thick_lines_to_indexed_vertex_array(const Lines3& lines,
else else
{ {
// generic segment // generic segment
n_right = normalize(cross(unit_v, unit_positive_z)); n_right = unit_v.cross(unit_positive_z).normalized();
n_top = normalize(cross(n_right, unit_v)); n_top = n_right.cross(unit_v).normalized();
} }
Vectorf3 rl_displacement = 0.5 * width * n_right; Vectorf3 rl_displacement = 0.5 * width * n_right;
@ -1247,9 +1247,9 @@ static void thick_lines_to_indexed_vertex_array(const Lines3& lines,
{ {
// Continuing a previous segment. // Continuing a previous segment.
// Share left / right vertices if possible. // Share left / right vertices if possible.
double v_dot = dot(unit_v_prev, unit_v); double v_dot = unit_v_prev.dot(unit_v);
bool is_sharp = v_dot < 0.707; // sin(45 degrees) bool is_sharp = v_dot < 0.707; // sin(45 degrees)
bool is_right_turn = dot(n_top_prev, cross(unit_v_prev, unit_v)) > 0.0; bool is_right_turn = n_top_prev.dot(unit_v_prev.cross(unit_v)) > 0.0;
if (is_sharp) if (is_sharp)
{ {
@ -1272,7 +1272,7 @@ static void thick_lines_to_indexed_vertex_array(const Lines3& lines,
// At the crease angle of 45 degrees, the overshot at the corner will be less than (1-1/cos(PI/8)) = 8.2% over an arc. // At the crease angle of 45 degrees, the overshot at the corner will be less than (1-1/cos(PI/8)) = 8.2% over an arc.
// averages normals // averages normals
Vectorf3 average_n_right = normalize(0.5 * (n_right + n_right_prev)); Vectorf3 average_n_right = 0.5 * (n_right + n_right_prev).normalized();
Vectorf3 average_n_left = -average_n_right; Vectorf3 average_n_left = -average_n_right;
Vectorf3 average_rl_displacement = 0.5 * width * average_n_right; Vectorf3 average_rl_displacement = 0.5 * width * average_n_right;

View file

@ -179,7 +179,7 @@ void BedShapePanel::set_shape(ConfigOptionPoints* points)
double avg_dist = 0; double avg_dist = 0;
for (auto pt: polygon.points) for (auto pt: polygon.points)
{ {
double distance = center.distance_to(pt); double distance = (pt - center).cast<double>().norm();
vertex_distances.push_back(distance); vertex_distances.push_back(distance);
avg_dist += distance; avg_dist += distance;
} }

View file

@ -1177,7 +1177,7 @@ void GLCanvas3D::Gizmos::update_hover_state(const GLCanvas3D& canvas, const Poin
// we currently use circular icons for gizmo, so we check the radius // we currently use circular icons for gizmo, so we check the radius
if (it->second->get_state() != GLGizmoBase::On) if (it->second->get_state() != GLGizmoBase::On)
{ {
bool inside = length(Pointf(OverlayOffsetX + half_tex_size, top_y + half_tex_size).vector_to(mouse_pos)) < half_tex_size; bool inside = (mouse_pos - Pointf(OverlayOffsetX + half_tex_size, top_y + half_tex_size)).norm() < half_tex_size;
it->second->set_state(inside ? GLGizmoBase::Hover : GLGizmoBase::Off); it->second->set_state(inside ? GLGizmoBase::Hover : GLGizmoBase::Off);
} }
top_y += (tex_size + OverlayGapY); top_y += (tex_size + OverlayGapY);
@ -1201,7 +1201,7 @@ void GLCanvas3D::Gizmos::update_on_off_state(const GLCanvas3D& canvas, const Poi
float half_tex_size = 0.5f * tex_size; float half_tex_size = 0.5f * tex_size;
// we currently use circular icons for gizmo, so we check the radius // we currently use circular icons for gizmo, so we check the radius
if (length(Pointf(OverlayOffsetX + half_tex_size, top_y + half_tex_size).vector_to(mouse_pos)) < half_tex_size) if ((mouse_pos - Pointf(OverlayOffsetX + half_tex_size, top_y + half_tex_size)).norm() < half_tex_size)
{ {
if ((it->second->get_state() == GLGizmoBase::On)) if ((it->second->get_state() == GLGizmoBase::On))
{ {
@ -1267,7 +1267,7 @@ bool GLCanvas3D::Gizmos::overlay_contains_mouse(const GLCanvas3D& canvas, const
float half_tex_size = 0.5f * tex_size; float half_tex_size = 0.5f * tex_size;
// we currently use circular icons for gizmo, so we check the radius // we currently use circular icons for gizmo, so we check the radius
if (length(Pointf(OverlayOffsetX + half_tex_size, top_y + half_tex_size).vector_to(mouse_pos)) < half_tex_size) if ((mouse_pos - Pointf(OverlayOffsetX + half_tex_size, top_y + half_tex_size)).norm() < half_tex_size)
return true; return true;
top_y += (tex_size + OverlayGapY); top_y += (tex_size + OverlayGapY);
@ -3114,7 +3114,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
m_mouse.drag.start_position_3D = pos3d; m_mouse.drag.start_position_3D = pos3d;
// Remember the shift to to the object center.The object center will later be used // Remember the shift to to the object center.The object center will later be used
// to limit the object placement close to the bed. // to limit the object placement close to the bed.
m_mouse.drag.volume_center_offset = pos3d.vector_to(volume_bbox.center()); m_mouse.drag.volume_center_offset = volume_bbox.center() - pos3d;
} }
} }
else if (evt.RightDown()) else if (evt.RightDown())
@ -3136,7 +3136,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
Pointf3 cur_pos = Linef3(_mouse_to_3d(pos, &z0), _mouse_to_3d(pos, &z1)).intersect_plane(m_mouse.drag.start_position_3D.z()); Pointf3 cur_pos = Linef3(_mouse_to_3d(pos, &z0), _mouse_to_3d(pos, &z1)).intersect_plane(m_mouse.drag.start_position_3D.z());
// Clip the new position, so the object center remains close to the bed. // Clip the new position, so the object center remains close to the bed.
cur_pos.translate(m_mouse.drag.volume_center_offset); cur_pos += m_mouse.drag.volume_center_offset;
Point cur_pos2(scale_(cur_pos.x()), scale_(cur_pos.y())); Point cur_pos2(scale_(cur_pos.x()), scale_(cur_pos.y()));
if (!m_bed.contains(cur_pos2)) if (!m_bed.contains(cur_pos2))
{ {
@ -3144,10 +3144,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
cur_pos.x() = unscale(ip.x()); cur_pos.x() = unscale(ip.x());
cur_pos.y() = unscale(ip.y()); cur_pos.y() = unscale(ip.y());
} }
cur_pos.translate(m_mouse.drag.volume_center_offset.negative()); cur_pos -= m_mouse.drag.volume_center_offset;
// Calculate the translation vector. // Calculate the translation vector.
Vectorf3 vector = m_mouse.drag.start_position_3D.vector_to(cur_pos); Vectorf3 vector = cur_pos - m_mouse.drag.start_position_3D;
// Get the volume being dragged. // Get the volume being dragged.
GLVolume* volume = m_volumes.volumes[m_mouse.drag.move_volume_idx]; GLVolume* volume = m_volumes.volumes[m_mouse.drag.move_volume_idx];
// Get all volumes belonging to the same group, if any. // Get all volumes belonging to the same group, if any.
@ -3169,11 +3169,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
// Apply new temporary volume origin and ignore Z. // Apply new temporary volume origin and ignore Z.
for (GLVolume* v : volumes) for (GLVolume* v : volumes)
{ v->set_origin(v->get_origin() + Vectorf3(vector.x(), vector.y(), 0.0));
Pointf3 origin = v->get_origin();
origin.translate(vector.x(), vector.y(), 0.0);
v->set_origin(origin);
}
m_mouse.drag.start_position_3D = cur_pos; m_mouse.drag.start_position_3D = cur_pos;
m_gizmos.refresh(); m_gizmos.refresh();
@ -3275,9 +3271,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
float z = 0.0f; float z = 0.0f;
const Pointf3& cur_pos = _mouse_to_3d(pos, &z); const Pointf3& cur_pos = _mouse_to_3d(pos, &z);
Pointf3 orig = _mouse_to_3d(m_mouse.drag.start_position_2D, &z); Pointf3 orig = _mouse_to_3d(m_mouse.drag.start_position_2D, &z);
Pointf3 camera_target = m_camera.target; m_camera.target += orig - cur_pos;
camera_target.translate(orig.vector_to(cur_pos).negative());
m_camera.target = camera_target;
m_on_viewport_changed_callback.call(); m_on_viewport_changed_callback.call();
@ -3571,11 +3565,11 @@ float GLCanvas3D::_get_zoom_to_bounding_box_factor(const BoundingBoxf3& bbox) co
{ {
// project vertex on the plane perpendicular to camera forward axis // project vertex on the plane perpendicular to camera forward axis
Pointf3 pos(v.x() - bb_center.x(), v.y() - bb_center.y(), v.z() - bb_center.z()); Pointf3 pos(v.x() - bb_center.x(), v.y() - bb_center.y(), v.z() - bb_center.z());
Pointf3 proj_on_plane = pos - dot(pos, forward) * forward; Pointf3 proj_on_plane = pos - pos.dot(forward) * forward;
// calculates vertex coordinate along camera xy axes // calculates vertex coordinate along camera xy axes
coordf_t x_on_plane = dot(proj_on_plane, right); coordf_t x_on_plane = proj_on_plane.dot(right);
coordf_t y_on_plane = dot(proj_on_plane, up); coordf_t y_on_plane = proj_on_plane.dot(up);
max_x = std::max(max_x, margin_factor * std::abs(x_on_plane)); max_x = std::max(max_x, margin_factor * std::abs(x_on_plane));
max_y = std::max(max_y, margin_factor * std::abs(y_on_plane)); max_y = std::max(max_y, margin_factor * std::abs(y_on_plane));
@ -3653,7 +3647,7 @@ void GLCanvas3D::_camera_tranform() const
::glRotatef(-m_camera.get_theta(), 1.0f, 0.0f, 0.0f); // pitch ::glRotatef(-m_camera.get_theta(), 1.0f, 0.0f, 0.0f); // pitch
::glRotatef(m_camera.phi, 0.0f, 0.0f, 1.0f); // yaw ::glRotatef(m_camera.phi, 0.0f, 0.0f, 1.0f); // yaw
Pointf3 neg_target = m_camera.target.negative(); Pointf3 neg_target = - m_camera.target;
::glTranslatef((GLfloat)neg_target.x(), (GLfloat)neg_target.y(), (GLfloat)neg_target.z()); ::glTranslatef((GLfloat)neg_target.x(), (GLfloat)neg_target.y(), (GLfloat)neg_target.z());
} }

View file

@ -235,13 +235,13 @@ void GLGizmoRotate::on_set_state()
void GLGizmoRotate::on_update(const Pointf& mouse_pos) void GLGizmoRotate::on_update(const Pointf& mouse_pos)
{ {
Vectorf orig_dir(1.0, 0.0); Vectorf orig_dir(1.0, 0.0);
Vectorf new_dir = normalize(mouse_pos - m_center); Vectorf new_dir = (mouse_pos - m_center).normalized();
coordf_t theta = ::acos(clamp(-1.0, 1.0, dot(new_dir, orig_dir))); coordf_t theta = ::acos(clamp(-1.0, 1.0, new_dir.dot(orig_dir)));
if (cross(orig_dir, new_dir) < 0.0) if (cross2(orig_dir, new_dir) < 0.0)
theta = 2.0 * (coordf_t)PI - theta; theta = 2.0 * (coordf_t)PI - theta;
// snap // snap
if (length(m_center.vector_to(mouse_pos)) < 2.0 * (double)m_radius / 3.0) if ((mouse_pos - m_center).norm() < 2.0 * (double)m_radius / 3.0)
{ {
coordf_t step = 2.0 * (coordf_t)PI / (coordf_t)SnapRegionsCount; coordf_t step = 2.0 * (coordf_t)PI / (coordf_t)SnapRegionsCount;
theta = step * (coordf_t)std::round(theta / step); theta = step * (coordf_t)std::round(theta / step);
@ -444,8 +444,8 @@ void GLGizmoScale::on_update(const Pointf& mouse_pos)
{ {
Pointf center(0.5 * (m_grabbers[1].center.x() + m_grabbers[0].center.x()), 0.5 * (m_grabbers[3].center.y() + m_grabbers[0].center.y())); Pointf center(0.5 * (m_grabbers[1].center.x() + m_grabbers[0].center.x()), 0.5 * (m_grabbers[3].center.y() + m_grabbers[0].center.y()));
coordf_t orig_len = length(m_starting_drag_position - center); coordf_t orig_len = (m_starting_drag_position - center).norm();
coordf_t new_len = length(mouse_pos - center); coordf_t new_len = (mouse_pos - center).norm();
coordf_t ratio = (orig_len != 0.0) ? new_len / orig_len : 1.0; coordf_t ratio = (orig_len != 0.0) ? new_len / orig_len : 1.0;
m_scale = m_starting_scale * (float)ratio; m_scale = m_starting_scale * (float)ratio;

View file

@ -894,10 +894,7 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl
const std::vector<double> &init_matrix = (config.option<ConfigOptionFloats>("wiping_volumes_matrix"))->values; const std::vector<double> &init_matrix = (config.option<ConfigOptionFloats>("wiping_volumes_matrix"))->values;
const std::vector<double> &init_extruders = (config.option<ConfigOptionFloats>("wiping_volumes_extruders"))->values; const std::vector<double> &init_extruders = (config.option<ConfigOptionFloats>("wiping_volumes_extruders"))->values;
#pragma warning(push) WipingDialog dlg(parent,cast<float>(init_matrix),cast<float>(init_extruders));
#pragma warning(disable:4244) // disable Visual Studio's warning: conversion from 'double' to 'float', possible loss of data
WipingDialog dlg(parent,std::vector<float>(init_matrix.begin(),init_matrix.end()),std::vector<float>(init_extruders.begin(),init_extruders.end()));
#pragma warning(pop)
if (dlg.ShowModal() == wxID_OK) { if (dlg.ShowModal() == wxID_OK) {
std::vector<float> matrix = dlg.get_matrix(); std::vector<float> matrix = dlg.get_matrix();

View file

@ -261,7 +261,7 @@ std::vector<float> Chart::get_ramming_speed(float sampling) const {
std::vector<std::pair<float,float>> Chart::get_buttons() const { std::vector<std::pair<float,float>> Chart::get_buttons() const {
std::vector<std::pair<float, float>> buttons_out; std::vector<std::pair<float, float>> buttons_out;
for (const auto& button : m_buttons) for (const auto& button : m_buttons)
buttons_out.push_back(std::make_pair(button.get_pos().m_x,button.get_pos().m_y)); buttons_out.push_back(std::make_pair(float(button.get_pos().m_x),float(button.get_pos().m_y)));
return buttons_out; return buttons_out;
} }

View file

@ -74,6 +74,7 @@ extern "C" {
#undef realloc #undef realloc
#undef free #undef free
#undef Zero #undef Zero
#undef Packet
#undef select #undef select
#endif /* _MSC_VER */ #endif /* _MSC_VER */
} }

View file

@ -58,11 +58,7 @@
Clone<Pointf3> origin() const Clone<Pointf3> origin() const
%code%{ RETVAL = THIS->get_origin(); %}; %code%{ RETVAL = THIS->get_origin(); %};
void translate(double x, double y, double z) void translate(double x, double y, double z)
%code%{ %code%{ THIS->set_origin(THIS->get_origin() + Pointf3(x, y, z)); %};
Pointf3 o = THIS->get_origin();
o.translate(x, y, z);
THIS->set_origin(o);
%};
Clone<BoundingBoxf3> bounding_box() const Clone<BoundingBoxf3> bounding_box() const
%code%{ RETVAL = THIS->bounding_box; %}; %code%{ RETVAL = THIS->bounding_box; %};
Clone<BoundingBoxf3> transformed_bounding_box() const; Clone<BoundingBoxf3> transformed_bounding_box() const;

View file

@ -29,7 +29,6 @@
bool parallel_to_line(Line* line) bool parallel_to_line(Line* line)
%code{% RETVAL = THIS->parallel_to(*line); %}; %code{% RETVAL = THIS->parallel_to(*line); %};
Clone<Point> midpoint(); Clone<Point> midpoint();
Clone<Point> point_at(double distance);
Clone<Point> intersection_infinite(Line* other) Clone<Point> intersection_infinite(Line* other)
%code{% %code{%
Point p; Point p;
@ -37,8 +36,8 @@
if (!res) CONFESS("Intersection failed"); if (!res) CONFESS("Intersection failed");
RETVAL = p; RETVAL = p;
%}; %};
Clone<Polyline> as_polyline() Polyline* as_polyline()
%code{% RETVAL = Polyline(*THIS); %}; %code{% RETVAL = new Polyline(THIS->a, THIS->b); %};
Clone<Point> normal(); Clone<Point> normal();
Clone<Point> vector(); Clone<Point> vector();
double ccw(Point* point) double ccw(Point* point)

View file

@ -3,6 +3,7 @@
%{ %{
#include <xsinit.h> #include <xsinit.h>
#include "libslic3r/Point.hpp" #include "libslic3r/Point.hpp"
#include "libslic3r/Line.hpp"
#include "libslic3r/Polygon.hpp" #include "libslic3r/Polygon.hpp"
#include "libslic3r/Polyline.hpp" #include "libslic3r/Polyline.hpp"
%} %}
@ -12,8 +13,10 @@
~Point(); ~Point();
Clone<Point> clone() Clone<Point> clone()
%code{% RETVAL=THIS; %}; %code{% RETVAL=THIS; %};
void scale(double factor); void scale(double factor)
void translate(double x, double y); %code{% *THIS *= factor; %};
void translate(double x, double y)
%code{% *THIS += Point(x, y); %};
SV* arrayref() SV* arrayref()
%code{% RETVAL = to_SV_pureperl(THIS); %}; %code{% RETVAL = to_SV_pureperl(THIS); %};
SV* pp() SV* pp()
@ -30,23 +33,23 @@
Clone<Point> nearest_point(Points points) Clone<Point> nearest_point(Points points)
%code{% Point p; THIS->nearest_point(points, &p); RETVAL = p; %}; %code{% Point p; THIS->nearest_point(points, &p); RETVAL = p; %};
double distance_to(Point* point) double distance_to(Point* point)
%code{% RETVAL = THIS->distance_to(*point); %}; %code{% RETVAL = (*point - *THIS).cast<double>().norm(); %};
double distance_to_line(Line* line) double distance_to_line(Line* line)
%code{% RETVAL = THIS->distance_to(*line); %}; %code{% RETVAL = line->distance_to(*THIS); %};
double perp_distance_to_line(Line* line) double perp_distance_to_line(Line* line)
%code{% RETVAL = THIS->perp_distance_to(*line); %}; %code{% RETVAL = line->perp_distance_to(*THIS); %};
double ccw(Point* p1, Point* p2) double ccw(Point* p1, Point* p2)
%code{% RETVAL = THIS->ccw(*p1, *p2); %}; %code{% RETVAL = THIS->ccw(*p1, *p2); %};
double ccw_angle(Point* p1, Point* p2) double ccw_angle(Point* p1, Point* p2)
%code{% RETVAL = THIS->ccw_angle(*p1, *p2); %}; %code{% RETVAL = THIS->ccw_angle(*p1, *p2); %};
Clone<Point> projection_onto_polygon(Polygon* polygon) Point* projection_onto_polygon(Polygon* polygon)
%code{% RETVAL = new Point(THIS->projection_onto(*polygon)); %}; %code{% RETVAL = new Point(THIS->projection_onto(*polygon)); %};
Clone<Point> projection_onto_polyline(Polyline* polyline) Point* projection_onto_polyline(Polyline* polyline)
%code{% RETVAL = new Point(THIS->projection_onto(*polyline)); %}; %code{% RETVAL = new Point(THIS->projection_onto(*polyline)); %};
Clone<Point> projection_onto_line(Line* line) Point* projection_onto_line(Line* line)
%code{% RETVAL = new Point(THIS->projection_onto(*line)); %}; %code{% RETVAL = new Point(THIS->projection_onto(*line)); %};
Clone<Point> negative() Point* negative()
%code{% RETVAL = new Point(THIS->negative()); %}; %code{% RETVAL = new Point(- *THIS); %};
bool coincides_with_epsilon(Point* point) bool coincides_with_epsilon(Point* point)
%code{% RETVAL = (*THIS) == *point; %}; %code{% RETVAL = (*THIS) == *point; %};
std::string serialize() %code{% char buf[2048]; sprintf(buf, "%ld,%ld", THIS->x(), THIS->y()); RETVAL = buf; %}; std::string serialize() %code{% char buf[2048]; sprintf(buf, "%ld,%ld", THIS->x(), THIS->y()); RETVAL = buf; %};
@ -107,14 +110,16 @@ Point::coincides_with(point_sv)
%code{% THIS->x() = val; %}; %code{% THIS->x() = val; %};
void set_y(double val) void set_y(double val)
%code{% THIS->y() = val; %}; %code{% THIS->y() = val; %};
void translate(double x, double y); void translate(double x, double y)
void scale(double factor); %code{% *THIS += Pointf(x, y); %};
void scale(double factor)
%code{% *THIS *= factor; %};
void rotate(double angle, Pointf* center) void rotate(double angle, Pointf* center)
%code{% THIS->rotate(angle, *center); %}; %code{% THIS->rotate(angle, *center); %};
Clone<Pointf> negative() Pointf* negative()
%code{% RETVAL = THIS->negative(); %}; %code{% RETVAL = new Pointf(- *THIS); %};
Clone<Pointf> vector_to(Pointf* point) Pointf* vector_to(Pointf* point)
%code{% RETVAL = THIS->vector_to(*point); %}; %code{% RETVAL = new Pointf(*point - *THIS); %};
std::string serialize() %code{% char buf[2048]; sprintf(buf, "%lf,%lf", THIS->x(), THIS->y()); RETVAL = buf; %}; std::string serialize() %code{% char buf[2048]; sprintf(buf, "%lf,%lf", THIS->x(), THIS->y()); RETVAL = buf; %};
}; };
@ -135,13 +140,15 @@ Point::coincides_with(point_sv)
%code{% THIS->y() = val; %}; %code{% THIS->y() = val; %};
void set_z(double val) void set_z(double val)
%code{% THIS->z() = val; %}; %code{% THIS->z() = val; %};
void translate(double x, double y, double z); void translate(double x, double y, double z)
void scale(double factor); %code{% *THIS += Pointf3(x, y, z); %};
void scale(double factor)
%code{% *THIS *= factor; %};
double distance_to(Pointf3* point) double distance_to(Pointf3* point)
%code{% RETVAL = THIS->distance_to(*point); %}; %code{% RETVAL = (*point - *THIS).norm(); %};
Clone<Pointf3> negative() Pointf3* negative()
%code{% RETVAL = THIS->negative(); %}; %code{% RETVAL = new Pointf3(- *THIS); %};
Clone<Pointf3> vector_to(Pointf3* point) Pointf3* vector_to(Pointf3* point)
%code{% RETVAL = THIS->vector_to(*point); %}; %code{% RETVAL = new Pointf3(*point - *THIS); %};
std::string serialize() %code{% char buf[2048]; sprintf(buf, "%lf,%lf,%lf", THIS->x(), THIS->y(), THIS->z()); RETVAL = buf; %}; std::string serialize() %code{% char buf[2048]; sprintf(buf, "%lf,%lf,%lf", THIS->x(), THIS->y(), THIS->z()); RETVAL = buf; %};
}; };

View file

@ -176,15 +176,6 @@ _constant()
void set_step_started(PrintStep step) void set_step_started(PrintStep step)
%code%{ THIS->state.set_started(step); %}; %code%{ THIS->state.set_started(step); %};
void clear_filament_stats()
%code%{
THIS->filament_stats.clear();
%};
void set_filament_stats(int extruder_id, float length)
%code%{
THIS->filament_stats.insert(std::pair<size_t,float>(extruder_id, 0));
THIS->filament_stats[extruder_id] += length;
%};
SV* filament_stats() SV* filament_stats()
%code%{ %code%{
HV* hv = newHV(); HV* hv = newHV();

View file

@ -181,7 +181,7 @@ TriangleMesh::slice(z)
std::vector<double> z std::vector<double> z
CODE: CODE:
// convert doubles to floats // convert doubles to floats
std::vector<float> z_f(z.begin(), z.end()); std::vector<float> z_f = cast<float>(z);
std::vector<ExPolygons> layers; std::vector<ExPolygons> layers;
TriangleMeshSlicer mslicer(THIS); TriangleMeshSlicer mslicer(THIS);