From 1ba64da3fee97433d6b580aae8fc8e9875143a66 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 17 Aug 2018 14:14:24 +0200 Subject: 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. --- xs/src/libslic3r/BoundingBox.cpp | 14 +- xs/src/libslic3r/BoundingBox.hpp | 8 +- xs/src/libslic3r/BridgeDetector.cpp | 10 +- xs/src/libslic3r/ClipperUtils.cpp | 4 +- xs/src/libslic3r/EdgeGrid.cpp | 12 +- xs/src/libslic3r/ExPolygon.cpp | 89 ++++----- xs/src/libslic3r/ExtrusionEntity.cpp | 2 +- xs/src/libslic3r/ExtrusionEntityCollection.hpp | 11 +- xs/src/libslic3r/Fill/Fill3DHoneycomb.cpp | 2 +- xs/src/libslic3r/Fill/FillGyroid.cpp | 4 +- xs/src/libslic3r/Fill/FillHoneycomb.cpp | 2 +- xs/src/libslic3r/Fill/FillRectilinear.cpp | 2 +- xs/src/libslic3r/Fill/FillRectilinear2.cpp | 8 +- xs/src/libslic3r/Fill/FillRectilinear3.cpp | 54 +++--- xs/src/libslic3r/GCode.cpp | 44 +++-- xs/src/libslic3r/Geometry.cpp | 8 +- xs/src/libslic3r/Line.cpp | 248 ++++++------------------- xs/src/libslic3r/Line.hpp | 86 ++++----- xs/src/libslic3r/Model.cpp | 15 +- xs/src/libslic3r/MotionPlanner.cpp | 10 +- xs/src/libslic3r/MultiPoint.cpp | 20 +- xs/src/libslic3r/MultiPoint.hpp | 9 +- xs/src/libslic3r/PerimeterGenerator.cpp | 154 +++++++-------- xs/src/libslic3r/Point.cpp | 46 +---- xs/src/libslic3r/Point.hpp | 98 ++-------- xs/src/libslic3r/Polygon.cpp | 10 +- xs/src/libslic3r/Polyline.cpp | 108 ++++------- xs/src/libslic3r/Polyline.hpp | 17 +- xs/src/libslic3r/Print.cpp | 9 +- xs/src/libslic3r/PrintObject.cpp | 7 +- xs/src/libslic3r/SupportMaterial.cpp | 16 +- xs/src/libslic3r/libslic3r.h | 11 ++ xs/src/slic3r/GUI/2DBed.cpp | 19 +- xs/src/slic3r/GUI/3DScene.cpp | 34 ++-- xs/src/slic3r/GUI/BedShapeDialog.cpp | 2 +- xs/src/slic3r/GUI/GLCanvas3D.cpp | 32 ++-- xs/src/slic3r/GUI/GLGizmo.cpp | 12 +- xs/src/slic3r/GUI/GUI.cpp | 5 +- xs/src/slic3r/GUI/RammingChart.cpp | 2 +- xs/src/xsinit.h | 1 + xs/xsp/GUI_3DScene.xsp | 6 +- xs/xsp/Line.xsp | 5 +- xs/xsp/Point.xsp | 53 +++--- xs/xsp/Print.xsp | 9 - xs/xsp/TriangleMesh.xsp | 2 +- 45 files changed, 527 insertions(+), 793 deletions(-) diff --git a/xs/src/libslic3r/BoundingBox.cpp b/xs/src/libslic3r/BoundingBox.cpp index 239300fb4..5efc66c2e 100644 --- a/xs/src/libslic3r/BoundingBox.cpp +++ b/xs/src/libslic3r/BoundingBox.cpp @@ -68,8 +68,8 @@ BoundingBox BoundingBox::rotated(double angle, const Point ¢er) const template void BoundingBoxBase::scale(double factor) { - this->min.scale(factor); - this->max.scale(factor); + this->min *= factor; + this->max *= factor; } template void BoundingBoxBase::scale(double factor); template void BoundingBoxBase::scale(double factor); @@ -188,8 +188,9 @@ template double BoundingBox3Base::radius() const; template void BoundingBoxBase::offset(coordf_t delta) { - this->min.translate(-delta, -delta); - this->max.translate(delta, delta); + PointClass v(delta, delta); + this->min -= v; + this->max += v; } template void BoundingBoxBase::offset(coordf_t delta); template void BoundingBoxBase::offset(coordf_t delta); @@ -197,8 +198,9 @@ template void BoundingBoxBase::offset(coordf_t delta); template void BoundingBox3Base::offset(coordf_t delta) { - this->min.translate(-delta, -delta, -delta); - this->max.translate(delta, delta, delta); + PointClass v(delta, delta, delta); + this->min -= v; + this->max += v; } template void BoundingBox3Base::offset(coordf_t delta); diff --git a/xs/src/libslic3r/BoundingBox.hpp b/xs/src/libslic3r/BoundingBox.hpp index 06ef15bab..d4c9fde88 100644 --- a/xs/src/libslic3r/BoundingBox.hpp +++ b/xs/src/libslic3r/BoundingBox.hpp @@ -46,8 +46,8 @@ public: void scale(double factor); PointClass size() 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(const Pointf &pos) { this->translate(pos.x(), pos.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 &v) { this->min += v; this->max += v; } void offset(coordf_t delta); PointClass center() const; bool contains(const PointClass &point) const { @@ -90,8 +90,8 @@ public: void merge(const BoundingBox3Base &bb); PointClass size() 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(const Pointf3 &pos) { this->translate(pos.x(), pos.y(), pos.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 &v) { this->min += v; this->max += v; } void offset(coordf_t delta); PointClass center() const; coordf_t max_size() const; diff --git a/xs/src/libslic3r/BridgeDetector.cpp b/xs/src/libslic3r/BridgeDetector.cpp index dffd043e6..622223a64 100644 --- a/xs/src/libslic3r/BridgeDetector.cpp +++ b/xs/src/libslic3r/BridgeDetector.cpp @@ -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 direction might still benefit from anchors if long enough) double angle_tolerance = PI / 180.0 * 5.0; */ - for (Lines::const_iterator line = unsupported_lines.begin(); line != unsupported_lines.end(); ++line) { - if (!Slic3r::Geometry::directions_parallel(line->direction(), angle)) - unsupported->push_back(*line); - } + for (const Line &line : unsupported_lines) + if (! Slic3r::Geometry::directions_parallel(line.direction(), angle)) { + unsupported->emplace_back(Polyline()); + unsupported->back().points.emplace_back(line.a); + unsupported->back().points.emplace_back(line.b); + } } /* diff --git a/xs/src/libslic3r/ClipperUtils.cpp b/xs/src/libslic3r/ClipperUtils.cpp index b5a18838c..b18132733 100644 --- a/xs/src/libslic3r/ClipperUtils.cpp +++ b/xs/src/libslic3r/ClipperUtils.cpp @@ -634,8 +634,8 @@ _clipper_ln(ClipperLib::ClipType clipType, const Lines &subject, const Polygons // convert Lines to Polylines Polylines polylines; polylines.reserve(subject.size()); - for (Lines::const_iterator line = subject.begin(); line != subject.end(); ++line) - polylines.push_back(*line); + for (const Line &line : subject) + polylines.emplace_back(Polyline(line.a, line.b)); // perform operation polylines = _clipper_pl(clipType, polylines, clip, safety_offset_); diff --git a/xs/src/libslic3r/EdgeGrid.cpp b/xs/src/libslic3r/EdgeGrid.cpp index 78120a471..5a9363f40 100644 --- a/xs/src/libslic3r/EdgeGrid.cpp +++ b/xs/src/libslic3r/EdgeGrid.cpp @@ -767,7 +767,7 @@ void EdgeGrid::Grid::calculate_sdf() const Slic3r::Point &p1 = pts[ipt]; const Slic3r::Point &p2 = pts[(ipt + 1 == pts.size()) ? 0 : ipt + 1]; // Segment vector - const Slic3r::Point v_seg = p1.vector_to(p2); + const Slic3r::Point v_seg = p2 - p1; // 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()); // For each corner of this cell and its 1 ring neighbours: @@ -781,7 +781,7 @@ void EdgeGrid::Grid::calculate_sdf() continue; 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 v_pt = p1.vector_to(pt); + Slic3r::Point v_pt = 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()); if (t_pt < 0) { @@ -790,7 +790,7 @@ void EdgeGrid::Grid::calculate_sdf() if (dabs < d_min) { // Previous point. 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()); if (t2_pt > 0) { // 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. const Slic3r::Point &p1 = pts[ipt]; const Slic3r::Point &p2 = pts[(ipt + 1 == pts.size()) ? 0 : ipt + 1]; - Slic3r::Point v_seg = p1.vector_to(p2); - Slic3r::Point v_pt = p1.vector_to(pt); + Slic3r::Point v_seg = p2 - p1; + Slic3r::Point v_pt = 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()); // l2 of seg @@ -1176,7 +1176,7 @@ bool EdgeGrid::Grid::signed_distance_edges(const Point &pt, coord_t search_radiu if (dabs < d_min) { // Previous point. 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()); if (t2_pt > 0) { // Inside the wedge between the previous and the next segment. diff --git a/xs/src/libslic3r/ExPolygon.cpp b/xs/src/libslic3r/ExPolygon.cpp index 036b037ca..57f56b089 100644 --- a/xs/src/libslic3r/ExPolygon.cpp +++ b/xs/src/libslic3r/ExPolygon.cpp @@ -34,54 +34,43 @@ ExPolygon::operator Polylines() const return to_polylines(*this); } -void -ExPolygon::scale(double factor) +void ExPolygon::scale(double factor) { contour.scale(factor); - for (Polygons::iterator it = holes.begin(); it != holes.end(); ++it) { - (*it).scale(factor); - } + for (Polygon &hole : holes) + hole.scale(factor); } -void -ExPolygon::translate(double x, double y) +void ExPolygon::translate(double x, double y) { contour.translate(x, y); - for (Polygons::iterator it = holes.begin(); it != holes.end(); ++it) { - (*it).translate(x, y); - } + for (Polygon &hole : holes) + hole.translate(x, y); } -void -ExPolygon::rotate(double angle) +void ExPolygon::rotate(double angle) { contour.rotate(angle); - for (Polygons::iterator it = holes.begin(); it != holes.end(); ++it) { - (*it).rotate(angle); - } + for (Polygon &hole : holes) + hole.rotate(angle); } -void -ExPolygon::rotate(double angle, const Point ¢er) +void ExPolygon::rotate(double angle, const Point ¢er) { contour.rotate(angle, center); - for (Polygons::iterator it = holes.begin(); it != holes.end(); ++it) { - (*it).rotate(angle, center); - } + for (Polygon &hole : holes) + hole.rotate(angle, center); } -double -ExPolygon::area() const +double ExPolygon::area() const { double a = this->contour.area(); - for (Polygons::const_iterator it = this->holes.begin(); it != this->holes.end(); ++it) { - a -= -(*it).area(); // holes have negative area - } + for (const Polygon &hole : holes) + a -= - hole.area(); // holes have negative area return a; } -bool -ExPolygon::is_valid() const +bool ExPolygon::is_valid() const { 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) { @@ -90,20 +79,17 @@ ExPolygon::is_valid() const return true; } -bool -ExPolygon::contains(const Line &line) const +bool ExPolygon::contains(const Line &line) const { - return this->contains((Polyline)line); + return this->contains(Polyline(line.a, line.b)); } -bool -ExPolygon::contains(const Polyline &polyline) const +bool ExPolygon::contains(const Polyline &polyline) const { return diff_pl((Polylines)polyline, *this).empty(); } -bool -ExPolygon::contains(const Polylines &polylines) const +bool ExPolygon::contains(const Polylines &polylines) const { #if 0 BoundingBox bbox = get_extents(polylines); @@ -120,8 +106,7 @@ ExPolygon::contains(const Polylines &polylines) const return pl_out.empty(); } -bool -ExPolygon::contains(const Point &point) const +bool ExPolygon::contains(const Point &point) const { if (!this->contour.contains(point)) return false; 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 -bool -ExPolygon::contains_b(const Point &point) const +bool ExPolygon::contains_b(const Point &point) const { 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_back = polyline.points.back(); if (polyline.endpoints.first && !this->has_boundary_point(new_front)) { - Line line(polyline.points.front(), polyline.points[1]); - + Vec2d p1 = polyline.points.front().cast(); + Vec2d p2 = polyline.points[1].cast(); // prevent the line from touching on the other side, otherwise intersection() might return that solution - if (polyline.points.size() == 2) line.b = line.midpoint(); - - line.extend_start(max_width); - (void)this->contour.intersection(line, &new_front); + if (polyline.points.size() == 2) + p2 = (p1 + p2) * 0.5; + // Extend the start of the segment. + p1 -= (p2 - p1).normalized() * max_width; + this->contour.intersection(Line(p1.cast(), p2.cast()), &new_front); } if (polyline.endpoints.second && !this->has_boundary_point(new_back)) { - Line line( - *(polyline.points.end() - 2), - polyline.points.back() - ); - + Vec2d p1 = (polyline.points.end() - 2)->cast(); + Vec2d p2 = polyline.points.back().cast(); // prevent the line from touching on the other side, otherwise intersection() might return that solution - if (polyline.points.size() == 2) line.a = line.midpoint(); - line.extend_end(max_width); - - (void)this->contour.intersection(line, &new_back); + if (polyline.points.size() == 2) + p1 = (p1 + p2) * 0.5; + // Extend the start of the segment. + p2 += (p2 - p1).normalized() * max_width; + this->contour.intersection(Line(p1.cast(), p2.cast()), &new_back); } polyline.points.front() = new_front; polyline.points.back() = new_back; diff --git a/xs/src/libslic3r/ExtrusionEntity.cpp b/xs/src/libslic3r/ExtrusionEntity.cpp index c6f67b169..92f0d3669 100644 --- a/xs/src/libslic3r/ExtrusionEntity.cpp +++ b/xs/src/libslic3r/ExtrusionEntity.cpp @@ -220,7 +220,7 @@ void ExtrusionLoop::split_at(const Point &point, bool prefer_non_overhang) double min_non_overhang = std::numeric_limits::max(); for (ExtrusionPaths::const_iterator path = this->paths.begin(); path != this->paths.end(); ++path) { Point p_tmp = point.projection_onto(path->polyline); - double dist = point.distance_to(p_tmp); + double dist = (p_tmp - point).cast().norm(); if (dist < min) { p = p_tmp; min = dist; diff --git a/xs/src/libslic3r/ExtrusionEntityCollection.hpp b/xs/src/libslic3r/ExtrusionEntityCollection.hpp index 382455fe3..3b34145f8 100644 --- a/xs/src/libslic3r/ExtrusionEntityCollection.hpp +++ b/xs/src/libslic3r/ExtrusionEntityCollection.hpp @@ -50,10 +50,15 @@ public: src.clear(); } } - void append(const ExtrusionPaths &paths) { + void append(const ExtrusionPaths &paths) { this->entities.reserve(this->entities.size() + paths.size()); - for (ExtrusionPaths::const_iterator path = paths.begin(); path != paths.end(); ++path) - this->entities.push_back(path->clone()); + for (const ExtrusionPath &path : paths) + 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 remove(size_t i); diff --git a/xs/src/libslic3r/Fill/Fill3DHoneycomb.cpp b/xs/src/libslic3r/Fill/Fill3DHoneycomb.cpp index 27814b658..5c3697d3e 100644 --- a/xs/src/libslic3r/Fill/Fill3DHoneycomb.cpp +++ b/xs/src/libslic3r/Fill/Fill3DHoneycomb.cpp @@ -187,7 +187,7 @@ void Fill3DHoneycomb::_fill_surface_single( const Point &last_point = pts_end.back(); // TODO: we should also check that both points are on a fill_boundary to avoid // connecting paths on the boundaries of internal regions - if (first_point.distance_to(last_point) <= 1.5 * distance && + if ((last_point - first_point).cast().norm() <= 1.5 * distance && expolygon_off.contains(Line(last_point, first_point))) { // Append the polyline. pts_end.insert(pts_end.end(), it_polyline->points.begin(), it_polyline->points.end()); diff --git a/xs/src/libslic3r/Fill/FillGyroid.cpp b/xs/src/libslic3r/Fill/FillGyroid.cpp index 7e208083b..bbac6f258 100644 --- a/xs/src/libslic3r/Fill/FillGyroid.cpp +++ b/xs/src/libslic3r/Fill/FillGyroid.cpp @@ -49,7 +49,7 @@ static inline Polyline make_wave( point.y() = clamp(0., height, double(point.y())); if (vertical) std::swap(point.x(), point.y()); - polyline.points.emplace_back(convert_to(point * scaleFactor)); + polyline.points.emplace_back((point * scaleFactor).cast()); } 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 // connecting paths on the boundaries of internal regions // TODO: avoid crossing current infill path - if (first_point.distance_to(last_point) <= 5 * distance && + if ((last_point - first_point).cast().norm() <= 5 * distance && expolygon_off.contains(Line(last_point, first_point))) { // Append the polyline. pts_end.insert(pts_end.end(), polyline.points.begin(), polyline.points.end()); diff --git a/xs/src/libslic3r/Fill/FillHoneycomb.cpp b/xs/src/libslic3r/Fill/FillHoneycomb.cpp index c22d5a2d7..ce7ac4a19 100644 --- a/xs/src/libslic3r/Fill/FillHoneycomb.cpp +++ b/xs/src/libslic3r/Fill/FillHoneycomb.cpp @@ -101,7 +101,7 @@ void FillHoneycomb::_fill_surface_single( for (Polylines::iterator it_path = chained.begin(); it_path != chained.end(); ++ it_path) { if (! paths.empty()) { // distance between first point of this path and last point of last path - double distance = paths.back().last_point().distance_to(it_path->first_point()); + double distance = (it_path->first_point() - paths.back().last_point()).cast().norm(); if (distance <= m.hex_width) { paths.back().points.insert(paths.back().points.end(), it_path->points.begin(), it_path->points.end()); continue; diff --git a/xs/src/libslic3r/Fill/FillRectilinear.cpp b/xs/src/libslic3r/Fill/FillRectilinear.cpp index e7f40a21b..5826abdb9 100644 --- a/xs/src/libslic3r/Fill/FillRectilinear.cpp +++ b/xs/src/libslic3r/Fill/FillRectilinear.cpp @@ -103,7 +103,7 @@ void FillRectilinear::_fill_surface_single( const Point &first_point = it_polyline->points.front(); const Point &last_point = pts_end.back(); // Distance in X, Y. - const Vector distance = first_point.vector_to(last_point); + const Vector distance = last_point - first_point; // TODO: we should also check that both points are on a fill_boundary to avoid // connecting paths on the boundaries of internal regions if (this->_can_connect(std::abs(distance.x()), std::abs(distance.y())) && diff --git a/xs/src/libslic3r/Fill/FillRectilinear2.cpp b/xs/src/libslic3r/Fill/FillRectilinear2.cpp index 4416626f6..a9ccdb0fb 100644 --- a/xs/src/libslic3r/Fill/FillRectilinear2.cpp +++ b/xs/src/libslic3r/Fill/FillRectilinear2.cpp @@ -55,14 +55,14 @@ static inline coordf_t segment_length(const Polygon &poly, size_t seg1, const Po coordf_t len = 0; if (seg1 <= seg2) { for (size_t i = seg1; i < seg2; ++ i, pPrev = pThis) - len += pPrev->distance_to(*(pThis = &poly.points[i])); + len += (*pPrev - *(pThis = &poly.points[i])).cast().norm(); } else { for (size_t i = seg1; i < poly.points.size(); ++ i, pPrev = pThis) - len += pPrev->distance_to(*(pThis = &poly.points[i])); + len += (*pPrev - *(pThis = &poly.points[i])).cast().norm(); for (size_t i = 0; i < seg2; ++ i, pPrev = pThis) - len += pPrev->distance_to(*(pThis = &poly.points[i])); + len += (*pPrev - *(pThis = &poly.points[i])).cast().norm(); } - len += pPrev->distance_to(p2); + len += (*pPrev - p2).cast().norm(); return len; } diff --git a/xs/src/libslic3r/Fill/FillRectilinear3.cpp b/xs/src/libslic3r/Fill/FillRectilinear3.cpp index 3c29c95f7..d2ba3d237 100644 --- a/xs/src/libslic3r/Fill/FillRectilinear3.cpp +++ b/xs/src/libslic3r/Fill/FillRectilinear3.cpp @@ -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_end = poly.points[this->iSegment]; // Point, vector of the segment. - const Pointf p1 = convert_to(seg_start); - const Pointf v1 = convert_to(seg_end - seg_start); + const Pointf p1(seg_start.cast()); + const Pointf v1((seg_end - seg_start).cast()); // Point, vector of this hatching line. - const Pointf p2 = convert_to(line->pos); - const Pointf v2 = convert_to(line->dir); + const Pointf p2(line->pos.cast()); + const Pointf v2(line->dir.cast()); // Intersect the two rays. double denom = v1.x() * v2.y() - v2.x() * v1.y(); Point out; @@ -276,13 +276,13 @@ int SegmentIntersection::ordering_along_line(const SegmentIntersection &other) c // other.iSegment succeeds this->iSegment assert(seg_end_a == seg_start_b); // Avoid calling the 128bit x 128bit multiplication below if this->line intersects the common point. - if (cross(this->line->dir, seg_end_b - this->line->pos) == 0) + if (cross2(Vec2i64(this->line->dir.cast()), (seg_end_b - this->line->pos).cast()) == 0) return 0; } else if ((other.iSegment + 1) % poly_a.points.size() == this->iSegment) { // this->iSegment succeeds other.iSegment assert(seg_start_a == seg_end_b); // Avoid calling the 128bit x 128bit multiplication below if this->line intersects the common point. - if (cross(this->line->dir, seg_start_a - this->line->pos) == 0) + if (cross2(Vec2i64(this->line->dir.cast()), (seg_start_a - this->line->pos).cast()) == 0) return 0; } else { // General case. @@ -290,35 +290,35 @@ int SegmentIntersection::ordering_along_line(const SegmentIntersection &other) c } // First test, whether both points of one segment are completely in one half-plane of the other line. - const Point vec_b = seg_end_b - seg_start_b; - int side_start = signum(cross(vec_b, seg_start_a - seg_start_b)); - int side_end = signum(cross(vec_b, seg_end_a - seg_start_b)); + const Vec2i64 vec_b = (seg_end_b - seg_start_b).cast(); + int side_start = signum(cross2(vec_b, (seg_start_a - seg_start_b).cast())); + int side_end = signum(cross2(vec_b, (seg_end_a - seg_start_b).cast())); int side = side_start * side_end; if (side > 0) // This segment is completely inside one half-plane of the other line, therefore the ordering is trivial. - return signum(cross(vec_b, this->line->dir)) * side_start; + return signum(cross2(vec_b, this->line->dir.cast())) * side_start; - const Point vec_a = seg_end_a - seg_start_a; - int side_start2 = signum(cross(vec_a, seg_start_b - seg_start_a)); - int side_end2 = signum(cross(vec_a, seg_end_b - seg_start_a)); + const Vec2i64 vec_a = (seg_end_a - seg_start_a).cast(); + int side_start2 = signum(cross2(vec_a, (seg_start_b - seg_start_a).cast())); + int side_end2 = signum(cross2(vec_a, (seg_end_b - seg_start_a).cast())); int side2 = side_start2 * side_end2; //if (side == 0 && side2 == 0) // The segments share one of their end points. if (side2 > 0) // This segment is completely inside one half-plane of the other line, therefore the ordering is trivial. - return signum(cross(this->line->dir, vec_a)) * side_start2; + return signum(cross2(this->line->dir.cast(), vec_a)) * side_start2; // The two segments intersect and they are not sucessive segments of the same contour. // Ordering of the points depends on the position of the segment intersection (left / right from this->line), // therefore a simple test over the input segment end points is not sufficient. // Find the parameters of intersection of the two segmetns with this->line. - int64_t denom1 = cross(this->line->dir, vec_a); - int64_t denom2 = cross(this->line->dir, vec_b); - Point vx_a = seg_start_a - this->line->pos; - Point vx_b = seg_start_b - this->line->pos; - int64_t t1_times_denom1 = int64_t(vx_a.x()) * int64_t(vec_a.y()) - int64_t(vx_a.y()) * int64_t(vec_a.x()); - int64_t t2_times_denom2 = int64_t(vx_b.x()) * int64_t(vec_b.y()) - int64_t(vx_b.y()) * int64_t(vec_b.x()); + int64_t denom1 = cross2(this->line->dir.cast(), vec_a); + int64_t denom2 = cross2(this->line->dir.cast(), vec_b); + Vec2i64 vx_a = (seg_start_a - this->line->pos).cast(); + Vec2i64 vx_b = (seg_start_b - this->line->pos).cast(); + int64_t t1_times_denom1 = vx_a.x() * vec_a.y() - vx_a.y() * vec_a.x(); + int64_t t2_times_denom2 = vx_b.x() * vec_b.y() - vx_b.y() * vec_b.x(); assert(denom1 != 0); assert(denom2 != 0); return Int128::compare_rationals_filtered(t1_times_denom1, denom1, t2_times_denom2, denom2); @@ -330,7 +330,7 @@ bool SegmentIntersection::operator<(const SegmentIntersection &other) const #ifdef _DEBUG Point p1 = this->pos(); Point p2 = other.pos(); - int64_t d = dot(this->line->dir, p2 - p1); + int64_t d = this->line->dir.cast().dot((p2 - p1).cast()); #endif /* _DEBUG */ int ordering = this->ordering_along_line(other); #ifdef _DEBUG @@ -510,7 +510,7 @@ static bool prepare_infill_hatching_segments( for (size_t i = 1; i < sil.intersections.size(); ++ i) { Point p1 = sil.intersections[i - 1].pos(); Point p2 = sil.intersections[i].pos(); - int64_t d = dot(sil.dir, p2 - p1); + int64_t d = sil.dir.cast().dot((p2 - p1).cast()); assert(d >= - int64_t(SCALED_EPSILON)); } #endif /* _DEBUG */ @@ -672,14 +672,14 @@ static inline coordf_t segment_length(const Polygon &poly, size_t seg1, const Po coordf_t len = 0; if (seg1 <= seg2) { for (size_t i = seg1; i < seg2; ++ i, pPrev = pThis) - len += pPrev->distance_to(*(pThis = &poly.points[i])); + len += (*pPrev - *(pThis = &poly.points[i])).cast().norm(); } else { for (size_t i = seg1; i < poly.points.size(); ++ i, pPrev = pThis) - len += pPrev->distance_to(*(pThis = &poly.points[i])); + len += (*pPrev - *(pThis = &poly.points[i])).cast().norm(); for (size_t i = 0; i < seg2; ++ i, pPrev = pThis) - len += pPrev->distance_to(*(pThis = &poly.points[i])); + len += (*pPrev - *(pThis = &poly.points[i])).cast().norm(); } - len += pPrev->distance_to(p2); + len += (*pPrev - p2).cast().norm(); return len; } @@ -1191,7 +1191,7 @@ static bool fill_hatching_segments_legacy( intrsctn.consumed_vertical_up : seg.intersections[i-1].consumed_vertical_up; if (! consumed) { - coordf_t dist2 = pointLast.distance_to(intrsctn.pos()); + coordf_t dist2 = (intrsctn.pos() - pointLast).cast().norm(); if (dist2 < dist2min) { dist2min = dist2; i_vline = i_vline2; diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index ab9e10ec1..d3441a565 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -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())-> shortest_path(gcodegen.last_pos() + scaled_origin, point + scaled_origin); if (use_external) - result.translate(scaled_origin.negative()); + result.translate(- scaled_origin); 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 Point © : object->_shifted_copies) { islands.emplace_back(expoly.contour); - islands.back().translate(copy); + islands.back().translate(- copy); } //FIXME Mege the islands in parallel. 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()) { const Pointf &extruder_offset = print.config.extruder_offset.get_at(extruder_id); 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)); } 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.y() - pointf.y()) ); - m_last_pos.translate(translate); + m_last_pos += translate; m_wipe.path.translate(translate); m_origin = pointf; } @@ -1678,8 +1678,8 @@ static Points::iterator project_point_to_polygon_and_insert(Polygon &polygon, co j = 0; const Point &p1 = polygon.points[i]; const Point &p2 = polygon.points[j]; - const Slic3r::Point v_seg = p1.vector_to(p2); - const Slic3r::Point v_pt = p1.vector_to(pt); + const Slic3r::Point v_seg = p2 - p1; + 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()); 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) { @@ -1714,7 +1714,7 @@ static Points::iterator project_point_to_polygon_and_insert(Polygon &polygon, co } assert(i_min != size_t(-1)); - if (pt_min.distance_to(polygon.points[i_min]) > eps) { + if ((pt_min - polygon.points[i_min]).cast().norm() > eps) { // Insert a new point on the segment i_min, i_min+1. return polygon.points.insert(polygon.points.begin() + (i_min + 1), pt_min); } @@ -1726,8 +1726,8 @@ std::vector polygon_parameter_by_length(const Polygon &polygon) // Parametrize the polygon by its length. std::vector lengths(polygon.points.size()+1, 0.); 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.back() = lengths[lengths.size()-2] + float(polygon.points.front().distance_to(polygon.points.back())); + lengths[i] = lengths[i-1] + (polygon.points[i] - polygon.points[i-1]).cast().norm(); + lengths.back() = lengths[lengths.size()-2] + (polygon.points.front() - polygon.points.back()).cast().norm(); return lengths; } @@ -1775,8 +1775,8 @@ std::vector polygon_angles_at_vertices(const Polygon &polygon, const std: const Point &p0 = polygon.points[idx_prev]; const Point &p1 = polygon.points[idx_curr]; const Point &p2 = polygon.points[idx_next]; - const Point v1 = p0.vector_to(p1); - const Point v2 = p1.vector_to(p2); + const Point v1 = p1 - p0; + 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 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))); @@ -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 // 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 - Line first_segment( - paths.front().polyline.points[0], - paths.front().polyline.points[1] - ); - double distance = std::min( - scale_(EXTRUDER_CONFIG(nozzle_diameter)), - first_segment.length() - ); - Point point = first_segment.point_at(distance); - point.rotate(angle, first_segment.a); - + Vec2d p1 = paths.front().polyline.points.front().cast(); + Vec2d p2 = paths.front().polyline.points[1].cast(); + Vec2d v = p2 - p1; + double nd = scale_(EXTRUDER_CONFIG(nozzle_diameter)); + double l2 = v.squaredNorm(); + // Shift by no more than a nozzle diameter. + //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(); + pt.rotate(angle, paths.front().polyline.points.front()); // 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; diff --git a/xs/src/libslic3r/Geometry.cpp b/xs/src/libslic3r/Geometry.cpp index ee58815ab..eb206ce62 100644 --- a/xs/src/libslic3r/Geometry.cpp +++ b/xs/src/libslic3r/Geometry.cpp @@ -1042,12 +1042,12 @@ MedialAxis::validate_edge(const VD::edge_type* edge) calculate the distance to that endpoint instead. */ coordf_t w0 = cell_r->contains_segment() - ? line.a.distance_to(segment_r)*2 - : line.a.distance_to(this->retrieve_endpoint(cell_r))*2; + ? segment_r.distance_to(line.a)*2 + : (this->retrieve_endpoint(cell_r) - line.a).cast().norm()*2; coordf_t w1 = cell_l->contains_segment() - ? line.b.distance_to(segment_l)*2 - : line.b.distance_to(this->retrieve_endpoint(cell_l))*2; + ? segment_l.distance_to(line.b)*2 + : (this->retrieve_endpoint(cell_l) - line.b).cast().norm()*2; if (cell_l->contains_segment() && cell_r->contains_segment()) { // calculate the relative angle between the two boundary segments diff --git a/xs/src/libslic3r/Line.cpp b/xs/src/libslic3r/Line.cpp index 383845a0d..cd1a0dbe1 100644 --- a/xs/src/libslic3r/Line.cpp +++ b/xs/src/libslic3r/Line.cpp @@ -7,8 +7,7 @@ namespace Slic3r { -std::string -Line::wkt() const +std::string Line::wkt() const { std::ostringstream ss; ss << "LINESTRING(" << this->a.x() << " " << this->a.y() << "," @@ -16,124 +15,58 @@ Line::wkt() const return ss.str(); } -Line::operator Lines() const +bool Line::intersection_infinite(const Line &other, Point* point) const { - Lines lines; - lines.push_back(*this); - return lines; -} - -Line::operator Polyline() const -{ - 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 ¢er) -{ - 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) + Vec2d a1 = this->a.cast(); + Vec2d a2 = other.a.cast(); + Vec2d v12 = (other.a - this->a).cast(); + Vec2d v1 = (this->b - this->a).cast(); + Vec2d v2 = (other.b - other.a).cast(); + double denom = cross2(v1, v2); + if (std::fabs(denom) < EPSILON) return false; - - double t1 = (x.x() * d2.y() - x.y() * d2.x())/cross; - point->x() = this->a.x() + d1.x() * t1; - point->y() = this->a.y() + d1.y() * t1; + double t1 = cross2(v12, v2) / denom; + *point = (a1 + t1 * v1).cast(); return true; } -bool -Line::coincides_with(const Line &line) const -{ - return this->a == line.a && this->b == line.b; -} - -double -Line::distance_to(const Point &point) const +/* distance to the closest point of line */ +double Line::distance_to(const Point &point) const { - return point.distance_to(*this); + const Line &line = *this; + const Vec2d v = (line.b - line.a).cast(); + const Vec2d va = (point - line.a).cast(); + 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().norm(); // beyond the 'b' end of the segment + return (t * v - va).norm(); } -double -Line::atan2_() const +double Line::perp_distance_to(const Point &point) const { - return atan2(this->b.y() - this->a.y(), this->b.x() - this->a.x()); + const Line &line = *this; + const Vec2d v = (line.b - line.a).cast(); + const Vec2d va = (point - line.a).cast(); + if (line.a == line.b) + return va.norm(); + return std::abs(cross2(v, va)) / v.norm(); } -double -Line::orientation() const +double Line::orientation() const { double angle = this->atan2_(); if (angle < 0) angle = 2*PI + angle; return angle; } -double -Line::direction() const +double Line::direction() const { double atan2 = this->atan2_(); return (fabs(atan2 - PI) < EPSILON) ? 0 @@ -141,105 +74,42 @@ Line::direction() const : atan2; } -bool -Line::parallel_to(double angle) const { - return Slic3r::Geometry::directions_parallel(this->direction(), angle); -} - -bool -Line::parallel_to(const Line &line) const { - return this->parallel_to(line.direction()); -} - -Vector -Line::vector() const +bool Line::parallel_to(double angle) const { - return Vector(this->b.x() - this->a.x(), this->b.y() - this->a.y()); -} - -Vector -Line::normal() const -{ - return Vector((this->b.y() - this->a.y()), -(this->b.x() - this->a.x())); -} - -void -Line::extend_end(double distance) -{ - // relocate last point by extending the segment by the specified length - Line line = *this; - line.reverse(); - this->b = line.point_at(-distance); -} - -void -Line::extend_start(double distance) -{ - // relocate first point by extending the first segment by the specified length - this->a = this->point_at(-distance); + return Slic3r::Geometry::directions_parallel(this->direction(), angle); } -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) - { +bool Line::intersection(const Line &l2, Point *intersection) const +{ + const Line &l1 = *this; + const Vec2d v1 = (l1.b - l1.a).cast(); + const Vec2d v2 = (l2.b - l2.a).cast(); + const Vec2d v12 = (l1.a - l2.a).cast(); + double denom = cross2(v1, v2); + double nume_a = cross2(v2, v12); + double nume_b = cross2(v1, v12); + if (fabs(denom) < EPSILON) +#if 0 + // Lines are collinear. Return true if they are coincident (overlappign). + return ! (fabs(nume_a) < EPSILON && fabs(nume_b) < EPSILON); +#else + return false; +#endif + double t1 = nume_a / denom; + double t2 = nume_b / denom; + if (t1 >= 0 && t1 <= 1.0f && t2 >= 0 && t2 <= 1.0f) { // Get the intersection point. - intersection->x() = this->a.x() + ua*(this->b.x() - this->a.x()); - intersection->y() = this->a.y() + ua*(this->b.y() - this->a.y()); + (*intersection) = (l1.a.cast() + t1 * v1).cast(); return true; } - 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 { - Vec3d v = this->b - this->a; + auto v = (this->b - this->a).cast(); double t = (z - this->a.z()) / v.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); -} - } diff --git a/xs/src/libslic3r/Line.hpp b/xs/src/libslic3r/Line.hpp index 4826017ab..a38810f71 100644 --- a/xs/src/libslic3r/Line.hpp +++ b/xs/src/libslic3r/Line.hpp @@ -18,77 +18,77 @@ typedef std::vector ThickLines; class Line { public: - Point a; - Point b; - Line() {}; - 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; - operator Lines() const; - operator Polyline() const; - void scale(double factor); - void translate(double x, double y); - void rotate(double angle, const Point ¢er); - void reverse(); - double length() const; - Point midpoint() const; - void point_at(double distance, Point* point) const; - Point point_at(double distance) const; - bool intersection_infinite(const Line &other, Point* point) const; - bool coincides_with(const Line &line) const; + explicit operator Lines() const { Lines lines; lines.emplace_back(*this); return lines; } + void scale(double factor) { this->a *= factor; this->b *= factor; } + void translate(double x, double y) { Vector v(x, y); this->a += v; this->b += v; } + void rotate(double angle, const Point ¢er) { this->a.rotate(angle, center); this->b.rotate(angle, center); } + void reverse() { std::swap(this->a, this->b); } + double length() const { return (b - a).cast().norm(); } + Point midpoint() const { return (this->a + this->b) / 2; } + bool intersection_infinite(const Line &other, Point* point) const; + bool coincides_with(const Line &line) const { return this->a == line.a && this->b == line.b; } double distance_to(const Point &point) const; - bool parallel_to(double angle) const; - bool parallel_to(const Line &line) const; - double atan2_() const; + double perp_distance_to(const Point &point) const; + bool parallel_to(double angle) 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 direction() const; - Vector vector() const; - Vector normal() const; - void extend_end(double distance); - void extend_start(double distance); - bool intersection(const Line& line, Point* intersection) const; - double ccw(const Point& point) const; + Vector vector() const { return this->b - this->a; } + Vector normal() const { return Vector((this->b.y() - this->a.y()), -(this->b.x() - this->a.x())); } + bool intersection(const Line& line, Point* intersection) const; + double ccw(const Point& point) const { return point.ccw(*this); } + + Point a; + Point b; }; class ThickLine : public Line { - 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) {}; +public: + ThickLine() : a_width(0), b_width(0) {} + ThickLine(Point a, Point b) : Line(a, b), a_width(0), b_width(0) {} + ThickLine(Point a, Point b, double wa, double wb) : Line(a, b), a_width(wa), b_width(wb) {} + + coordf_t a_width, b_width; }; class Line3 { public: - Point3 a; - Point3 b; - Line3() {} Line3(const Point3& _a, const Point3& _b) : a(_a), b(_b) {} - double length() const; - Vector3 vector() const; + double length() const { return (this->a - this->b).cast().norm(); } + Vector3 vector() const { return this->b - this->a; } + + Point3 a; + Point3 b; }; class Linef { - public: +public: + Linef() {} + explicit Linef(Pointf _a, Pointf _b): a(_a), b(_b) {} + Pointf a; Pointf b; - Linef() {}; - explicit Linef(Pointf _a, Pointf _b): a(_a), b(_b) {}; }; 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 b; - Linef3() {}; - explicit Linef3(Pointf3 _a, Pointf3 _b): a(_a), b(_b) {}; - Pointf3 intersect_plane(double z) const; - void scale(double factor); }; } // namespace Slic3r diff --git a/xs/src/libslic3r/Model.cpp b/xs/src/libslic3r/Model.cpp index a04ab7317..e22f87f65 100644 --- a/xs/src/libslic3r/Model.cpp +++ b/xs/src/libslic3r/Model.cpp @@ -256,12 +256,10 @@ void Model::center_instances_around_point(const Pointf &point) for (size_t i = 0; i < o->instances.size(); ++ i) bb.merge(o->instance_bounding_box(i, false)); - Sizef3 size = bb.size(); - coordf_t shift_x = -bb.min.x() + point.x() - size.x()/2; - coordf_t shift_y = -bb.min.y() + point.y() - size.y()/2; + Pointf shift = point - 0.5 * bb.size().xy() - bb.min.xy(); for (ModelObject *o : this->objects) { for (ModelInstance *i : o->instances) - i->offset.translate(shift_x, shift_y); + i->offset += shift; 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 Pointf &pos : positions) { ModelInstance *instance = o->add_instance(*i); - instance->offset.translate(pos); + instance->offset += pos; } } o->invalidate_bounding_box(); @@ -1075,16 +1073,15 @@ void ModelObject::center_around_origin() vector.y() -= size.y()/2; this->translate(vector); - this->origin_translation.translate(vector); + this->origin_translation += vector; if (!this->instances.empty()) { for (ModelInstance *i : this->instances) { // apply rotation and scaling to vector as well before translating instance, // in order to leave final position unaltered - Vectorf v = vector.negative().xy(); + Vectorf v = - vector.xy(); v.rotate(i->rotation); - v.scale(i->scaling_factor); - i->offset.translate(v); + i->offset += v * i->scaling_factor; } this->invalidate_bounding_box(); } diff --git a/xs/src/libslic3r/MotionPlanner.cpp b/xs/src/libslic3r/MotionPlanner.cpp index e8605d68c..ff3475ed8 100644 --- a/xs/src/libslic3r/MotionPlanner.cpp +++ b/xs/src/libslic3r/MotionPlanner.cpp @@ -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 (m_islands.empty()) - return Line(from, to); + return Polyline(from, to); // Are both points in the same island? 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? // If so, we avoid generating the visibility environment. 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. island_idx = idx; break; @@ -90,7 +90,7 @@ Polyline MotionPlanner::shortest_path(const Point &from, const Point &to) if (env.m_env.expolygons.empty()) { // if this environment is empty (probably because it's too small), perform straight move // and avoid running the algorithms on empty dataset - return Line(from, to); + return Polyline(from, to); } // Now check whether points are inside the environment. @@ -224,7 +224,7 @@ const MotionPlannerGraph& MotionPlanner::init_graph(int island_idx) else v1_idx = i_v1->second; // 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().norm()); } } } @@ -238,7 +238,7 @@ static inline size_t nearest_waypoint_index(const Point &start_point, const Poin size_t idx = size_t(-1); double dmin = std::numeric_limits::infinity(); for (const Point &p : middle_points) { - double d = start_point.distance_to(p) + p.distance_to(end_point); + double d = (p - start_point).cast().norm() + (end_point - p).cast().norm(); if (d < dmin) { idx = &p - middle_points.data(); dmin = d; diff --git a/xs/src/libslic3r/MultiPoint.cpp b/xs/src/libslic3r/MultiPoint.cpp index 403761a5e..b9fc70967 100644 --- a/xs/src/libslic3r/MultiPoint.cpp +++ b/xs/src/libslic3r/MultiPoint.cpp @@ -11,18 +11,20 @@ MultiPoint::operator Points() const void MultiPoint::scale(double factor) { for (Point &pt : points) - pt.scale(factor); + pt *= factor; } void MultiPoint::translate(double x, double y) { + Vector v(x, y); 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) @@ -79,7 +81,7 @@ MultiPoint::find_point(const Point &point) const bool 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().norm(); return dist < SCALED_EPSILON; } @@ -137,10 +139,10 @@ bool MultiPoint::first_intersection(const Line& line, Point* intersection) const if (l.intersection(line, &ip)) { if (! found) { found = true; - dmin = ip.distance_to(line.a); + dmin = (line.a - ip).cast().norm(); *intersection = ip; } else { - double d = ip.distance_to(line.a); + double d = (line.a - ip).cast().norm(); if (d < dmin) { dmin = d; *intersection = ip; @@ -176,7 +178,7 @@ MultiPoint::_douglas_peucker(const Points &points, const double tolerance) Line full(points.front(), points.back()); for (Points::const_iterator it = points.begin() + 1; it != points.end(); ++it) { // we use shortest distance, not perpendicular distance - double d = it->distance_to(full); + double d = full.distance_to(*it); if (d > dmax) { index = it - points.begin(); dmax = d; @@ -215,7 +217,7 @@ void MultiPoint3::translate(double x, double y) void MultiPoint3::translate(const Point& vector) { - translate(vector.x(), vector.y()); + this->translate(vector.x(), vector.y()); } double MultiPoint3::length() const diff --git a/xs/src/libslic3r/MultiPoint.hpp b/xs/src/libslic3r/MultiPoint.hpp index 0970e9a67..e8e275c65 100644 --- a/xs/src/libslic3r/MultiPoint.hpp +++ b/xs/src/libslic3r/MultiPoint.hpp @@ -18,10 +18,11 @@ public: Points points; operator Points() const; - MultiPoint() {}; + MultiPoint() {} MultiPoint(const MultiPoint &other) : points(other.points) {} MultiPoint(MultiPoint &&other) : points(std::move(other.points)) {} - explicit MultiPoint(const Points &_points): points(_points) {} + MultiPoint(std::initializer_list list) : points(list) {} + explicit MultiPoint(const Points &_points) : points(_points) {} MultiPoint& operator=(const MultiPoint &other) { points = other.points; return *this; } MultiPoint& operator=(MultiPoint &&other) { points = std::move(other.points); return *this; } void scale(double factor); @@ -43,9 +44,9 @@ public: int idx = -1; if (! this->points.empty()) { idx = 0; - double dist_min = this->points.front().distance_to(point); + double dist_min = (point - this->points.front()).cast().norm(); 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().norm(); if (d < dist_min) { dist_min = d; idx = i; diff --git a/xs/src/libslic3r/PerimeterGenerator.cpp b/xs/src/libslic3r/PerimeterGenerator.cpp index b6ed33f79..8e7b33cc8 100644 --- a/xs/src/libslic3r/PerimeterGenerator.cpp +++ b/xs/src/libslic3r/PerimeterGenerator.cpp @@ -366,99 +366,103 @@ ExtrusionEntityCollection PerimeterGenerator::_traverse_loops( 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 - // 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 - const double tolerance = scale_(0.05); + ExtrusionPaths paths; + ExtrusionPath path(role); + ThickLines lines = thick_polyline.thicklines(); - ExtrusionEntityCollection coll; - for (const ThickPolyline &p : polylines) { - ExtrusionPaths paths; - ExtrusionPath path(role); - ThickLines lines = p.thicklines(); + for (int i = 0; i < (int)lines.size(); ++i) { + const ThickLine& line = lines[i]; - for (int i = 0; i < (int)lines.size(); ++i) { - const ThickLine& line = lines[i]; - - const coordf_t line_len = line.length(); - if (line_len < SCALED_EPSILON) continue; - - double thickness_delta = fabs(line.a_width - line.b_width); - if (thickness_delta > tolerance) { - const unsigned short segments = ceil(thickness_delta / tolerance); - const coordf_t seg_len = line_len / segments; - Points pp; - std::vector width; - { - pp.push_back(line.a); - 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); + const coordf_t line_len = line.length(); + if (line_len < SCALED_EPSILON) continue; + + double thickness_delta = fabs(line.a_width - line.b_width); + if (thickness_delta > tolerance) { + const unsigned short segments = ceil(thickness_delta / tolerance); + const coordf_t seg_len = line_len / segments; + Points pp; + std::vector width; + { + pp.push_back(line.a); + width.push_back(line.a_width); + for (size_t j = 1; j < segments; ++j) { + pp.push_back((line.a.cast() + (line.b - line.a).cast().normalized() * (j * seg_len)).cast()); - assert(pp.size() == segments + 1); - assert(width.size() == segments*2); - } - - // delete this line and insert new ones - lines.erase(lines.begin() + i); - 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); + 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); - -- i; - continue; + assert(pp.size() == segments + 1); + assert(width.size() == segments*2); + } + + // delete this line and insert new ones + lines.erase(lines.begin() + i); + 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); } - const double w = fmax(line.a_width, line.b_width); - if (path.polyline.points.empty()) { - path.polyline.append(line.a); + -- 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); - // 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); - } else { - // we need to initialize a new line - paths.emplace_back(std::move(path)); - path = ExtrusionPath(role); - -- i; - } + // 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. if (! paths.empty()) { if (paths.front().first_point() == paths.back().last_point()) - coll.append(ExtrusionLoop(paths)); + coll.append(ExtrusionLoop(std::move(paths))); else - coll.append(paths); + coll.append(std::move(paths)); } } - return coll; } diff --git a/xs/src/libslic3r/Point.cpp b/xs/src/libslic3r/Point.cpp index da5520e26..670643a2c 100644 --- a/xs/src/libslic3r/Point.cpp +++ b/xs/src/libslic3r/Point.cpp @@ -98,38 +98,6 @@ bool Point::nearest_point(const Points &points, Point* point) const 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 * 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. @@ -161,14 +129,14 @@ double Point::ccw_angle(const Point &p1, const Point &p2) const Point Point::projection_onto(const MultiPoint &poly) const { Point running_projection = poly.first_point(); - double running_min = this->distance_to(running_projection); + double running_min = (running_projection - *this).cast().norm(); Lines lines = poly.lines(); for (Lines::const_iterator line = lines.begin(); line != lines.end(); ++line) { Point point_temp = this->projection_onto(*line); - if (this->distance_to(point_temp) < running_min) { + if ((point_temp - *this).cast().norm() < running_min) { running_projection = point_temp; - running_min = this->distance_to(running_projection); + running_min = (running_projection - *this).cast().norm(); } } return running_projection; @@ -193,14 +161,10 @@ Point Point::projection_onto(const Line &line) const / ( sqr(lx) + sqr(ly) ); if (0.0 <= theta && theta <= 1.0) - return theta * line.a + (1.0-theta) * line.b; + return (theta * line.a.cast() + (1.0-theta) * line.b.cast()).cast(); // Else pick closest endpoint. - if (this->distance_to(line.a) < this->distance_to(line.b)) { - return line.a; - } else { - return line.b; - } + return ((line.a - *this).cast().squaredNorm() < (line.b - *this).cast().squaredNorm()) ? line.a : line.b; } std::ostream& operator<<(std::ostream &stm, const Pointf &pointf) diff --git a/xs/src/libslic3r/Point.hpp b/xs/src/libslic3r/Point.hpp index 1de8c22bc..affe1e80e 100644 --- a/xs/src/libslic3r/Point.hpp +++ b/xs/src/libslic3r/Point.hpp @@ -35,6 +35,8 @@ typedef std::vector Pointf3s; // Vector types with a fixed point coordinate base type. typedef Eigen::Matrix Vec2crd; typedef Eigen::Matrix Vec3crd; +typedef Eigen::Matrix Vec2i64; +typedef Eigen::Matrix Vec3i64; // Vector types with a double coordinate base type. typedef Eigen::Matrix Vec2f; @@ -47,6 +49,11 @@ typedef Eigen::Transform Transform2d typedef Eigen::Transform Transform3f; typedef Eigen::Transform 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 { public: @@ -66,7 +73,7 @@ public: template Point& operator=(const Eigen::MatrixBase &other) { - this->Point::operator=(other); + this->Vec2crd::operator=(other); 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 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 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, const Point ¢er); Point rotated(double angle) const { Point res(*this); res.rotate(angle); return res; } Point rotated(double angle, const Point ¢er) 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; int nearest_point_index(const Points &points) const; int nearest_point_index(const PointConstPtrs &points) const; int nearest_point_index(const PointPtrs &points) 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 Line &line) const; double ccw_angle(const Point &p1, const Point &p2) const; Point projection_onto(const MultiPoint &poly) 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 { - -// Exact orientation predicate, -// returns +1: CCW, 0: collinear, -1: CW. -int orient(const Point &p1, const Point &p2, const Point &p3); - -// Exact orientation predicate, -// returns +1: CCW, 0: collinear, -1: CW. -int cross(const Point &v1, const Slic3r::Point &v2); + // Exact orientation predicate, + // returns +1: CCW, 0: collinear, -1: CW. + int orient(const Point &p1, const Point &p2, const Point &p3); + // Exact orientation predicate, + // 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. @@ -204,7 +193,7 @@ public: const ValueType &value = it->second; const Point *pt2 = m_point_accessor(value); if (pt2 != nullptr) { - const double d2 = pt.distance_to_sq(*pt2); + const double d2 = (pt - *pt2).squaredNorm(); if (d2 < dist_min) { dist_min = d2; value_min = &value; @@ -243,7 +232,7 @@ public: template Point3& operator=(const Eigen::MatrixBase &other) { - this->Point3::operator=(other); + this->Vec3crd::operator=(other); return *this; } @@ -268,7 +257,6 @@ public: typedef coordf_t coord_type; 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; } // This constructor allows you to construct Pointf from Eigen expressions template @@ -280,7 +268,7 @@ public: template Pointf& operator=(const Eigen::MatrixBase &other) { - this->Pointf::operator=(other); + this->Vec2d::operator=(other); return *this; } @@ -291,13 +279,8 @@ public: std::string wkt() 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, const Pointf ¢er); - 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 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()); } }; -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 { public: @@ -340,7 +308,7 @@ public: template Pointf3& operator=(const Eigen::MatrixBase &other) { - this->Pointf3::operator=(other); + this->Vec3d::operator=(other); return *this; } @@ -351,40 +319,12 @@ public: const coordf_t& z() const { 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 == rhs); } 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 inline TO convert_to(const Point &src) { return TO(typename TO::coord_type(src.x()), typename TO::coord_type(src.y())); } -template inline TO convert_to(const Pointf &src) { return TO(typename TO::coord_type(src.x()), typename TO::coord_type(src.y())); } -template 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 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 // start Boost diff --git a/xs/src/libslic3r/Polygon.cpp b/xs/src/libslic3r/Polygon.cpp index dfa8f7d8e..83aea58d9 100644 --- a/xs/src/libslic3r/Polygon.cpp +++ b/xs/src/libslic3r/Polygon.cpp @@ -300,24 +300,24 @@ Point Polygon::point_projection(const Point &point) const for (size_t i = 0; i < this->points.size(); ++ i) { const Point &pt0 = this->points[i]; const Point &pt1 = this->points[(i + 1 == this->points.size()) ? 0 : i + 1]; - double d = pt0.distance_to(point); + double d = (point - pt0).cast().norm(); if (d < dmin) { dmin = d; proj = pt0; } - d = pt1.distance_to(point); + d = (point - pt1).cast().norm(); if (d < dmin) { dmin = d; proj = pt1; } 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.) { 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.) { 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().norm(); if (d < dmin) { dmin = d; proj = foot; diff --git a/xs/src/libslic3r/Polyline.cpp b/xs/src/libslic3r/Polyline.cpp index d183f4dda..16275c346 100644 --- a/xs/src/libslic3r/Polyline.cpp +++ b/xs/src/libslic3r/Polyline.cpp @@ -52,92 +52,82 @@ Polyline::lines() const } // removes the given distance from the end of the polyline -void -Polyline::clip_end(double distance) +void Polyline::clip_end(double distance) { while (distance > 0) { - Point last_point = this->last_point(); + Vec2d last_point = this->last_point().cast(); this->points.pop_back(); - if (this->points.empty()) break; - - double last_segment_length = last_point.distance_to(this->last_point()); - if (last_segment_length <= distance) { - distance -= last_segment_length; - continue; + if (this->points.empty()) + break; + Vec2d v = this->last_point().cast() - last_point; + double lsqr = v.squaredNorm(); + if (lsqr > distance * distance) { + this->points.emplace_back((last_point + v * (distance / sqrt(lsqr))).cast()); + return; } - - Line segment(last_point, this->last_point()); - this->points.push_back(segment.point_at(distance)); - distance = 0; + distance -= sqrt(lsqr); } } // removes the given distance from the start of the polyline -void -Polyline::clip_start(double distance) +void Polyline::clip_start(double distance) { this->reverse(); this->clip_end(distance); - if (this->points.size() >= 2) this->reverse(); + if (this->points.size() >= 2) + this->reverse(); } -void -Polyline::extend_end(double distance) +void Polyline::extend_end(double distance) { // relocate last point by extending the last segment by the specified length - Line line( - this->points.back(), - *(this->points.end() - 2) - ); - this->points.back() = line.point_at(-distance); + Vec2d v = (this->points.back() - *(this->points.end() - 2)).cast().normalized(); + this->points.back() += (v * distance).cast(); } -void -Polyline::extend_start(double distance) +void Polyline::extend_start(double distance) { // 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().normalized(); + this->points.front() += (v * distance).cast(); } /* this method returns a collection of points picked on the polygon contour so that they are evenly spaced according to the input distance */ -Points -Polyline::equally_spaced_points(double distance) const +Points Polyline::equally_spaced_points(double distance) const { Points points; - points.push_back(this->first_point()); + points.emplace_back(this->first_point()); double len = 0; 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(); + Vec2d v = it->cast() - p1; + double segment_length = v.norm(); len += segment_length; - if (len < distance) continue; - + if (len < distance) + continue; if (len == distance) { - points.push_back(*it); + points.emplace_back(*it); len = 0; continue; } - double take = segment_length - (len - distance); // how much we take of this segment - Line segment(*(it-1), *it); - points.push_back(segment.point_at(take)); - --it; - len = -take; + points.emplace_back((p1 + v * (take / v.norm())).cast()); + -- it; + len = - take; } return points; } -void -Polyline::simplify(double tolerance) +void Polyline::simplify(double tolerance) { this->points = MultiPoint::_douglas_peucker(this->points, tolerance); } /* This method simplifies all *lines* contained in the supplied area */ template -void -Polyline::simplify_by_visibility(const T &area) +void Polyline::simplify_by_visibility(const T &area) { Points &pp = this->points; @@ -157,21 +147,20 @@ Polyline::simplify_by_visibility(const T &area) template void Polyline::simplify_by_visibility(const ExPolygon &area); template void Polyline::simplify_by_visibility(const ExPolygonCollection &area); -void -Polyline::split_at(const Point &point, Polyline* p1, Polyline* p2) const +void Polyline::split_at(const Point &point, Polyline* p1, Polyline* p2) const { if (this->points.empty()) return; // find the line to split at size_t line_idx = 0; Point p = this->first_point(); - double min = point.distance_to(p); + double min = (p - point).cast().norm(); Lines lines = this->lines(); for (Lines::const_iterator line = lines.begin(); line != lines.end(); ++line) { Point p_tmp = point.projection_onto(*line); - if (point.distance_to(p_tmp) < min) { + if ((p_tmp - point).cast().norm() < min) { p = p_tmp; - min = point.distance_to(p); + min = (p - point).cast().norm(); line_idx = line - lines.begin(); } } @@ -193,8 +182,7 @@ Polyline::split_at(const Point &point, Polyline* p1, Polyline* p2) const } } -bool -Polyline::is_straight() const +bool Polyline::is_straight() const { /* Check that each segment's direction is equal to the line connecting first point and last point. (Checking each line against the previous @@ -208,8 +196,7 @@ Polyline::is_straight() const return true; } -std::string -Polyline::wkt() const +std::string Polyline::wkt() const { std::ostringstream wkt; wkt << "LINESTRING(("; @@ -254,30 +241,17 @@ bool remove_degenerate(Polylines &polylines) return modified; } -ThickLines -ThickPolyline::thicklines() const +ThickLines ThickPolyline::thicklines() const { ThickLines lines; if (this->points.size() >= 2) { lines.reserve(this->points.size() - 1); - for (size_t i = 0; i < this->points.size()-1; ++i) { - ThickLine line(this->points[i], this->points[i+1]); - line.a_width = this->width[2*i]; - line.b_width = this->width[2*i+1]; - lines.push_back(line); - } + for (size_t i = 0; i + 1 < this->points.size(); ++ i) + lines.emplace_back(this->points[i], this->points[i + 1], this->width[2 * i], this->width[2 * i + 1]); } 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 lines; diff --git a/xs/src/libslic3r/Polyline.hpp b/xs/src/libslic3r/Polyline.hpp index 46877faf9..9d6cf91ee 100644 --- a/xs/src/libslic3r/Polyline.hpp +++ b/xs/src/libslic3r/Polyline.hpp @@ -19,6 +19,8 @@ public: Polyline() {}; Polyline(const Polyline &other) : MultiPoint(other.points) {} Polyline(Polyline &&other) : MultiPoint(std::move(other.points)) {} + Polyline(std::initializer_list 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=(Polyline &&other) { points = std::move(other.points); return *this; } static Polyline new_scale(std::vector points) { @@ -129,12 +131,17 @@ inline void polylines_append(Polylines &dst, Polylines &&src) bool remove_degenerate(Polylines &polylines); class ThickPolyline : public Polyline { - public: - std::vector width; - std::pair endpoints; - ThickPolyline() : endpoints(std::make_pair(false, false)) {}; +public: + ThickPolyline() : endpoints(std::make_pair(false, false)) {} 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 width; + std::pair endpoints; }; class Polyline3 : public MultiPoint3 diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index f60fb1b62..353d8ace5 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -726,7 +726,7 @@ BoundingBox Print::bounding_box() const for (const PrintObject *object : this->objects) for (Point copy : object->_shifted_copies) { bb.merge(copy); - copy.translate(object->size.xy()); + copy += object->size.xy(); bb.merge(copy); } return bb; @@ -902,7 +902,7 @@ void Print::_make_skirt() for (const Point &shift : object->_shifted_copies) { Points copy_points = object_points; for (Point &pt : copy_points) - pt.translate(shift); + pt += shift; append(points, copy_points); } } @@ -1052,10 +1052,7 @@ void Print::_make_wipe_tower() return; // Get wiping matrix to get number of extruders and convert vector to vector: -#pragma warning(push) -#pragma warning(disable:4244) // disable Visual Studio's warning: conversion from 'double' to 'float', possible loss of data - std::vector wiping_matrix((this->config.wiping_volumes_matrix.values).begin(),(this->config.wiping_volumes_matrix.values).end()); -#pragma warning(pop) + std::vector wiping_matrix(cast(this->config.wiping_volumes_matrix.values)); // Extract purging volumes for each extruder pair: std::vector> wipe_volumes; const unsigned int number_of_extruders = (unsigned int)(sqrt(wiping_matrix.size())+EPSILON); diff --git a/xs/src/libslic3r/PrintObject.cpp b/xs/src/libslic3r/PrintObject.cpp index b060816a1..a8404c0ed 100644 --- a/xs/src/libslic3r/PrintObject.cpp +++ b/xs/src/libslic3r/PrintObject.cpp @@ -85,11 +85,8 @@ bool PrintObject::set_copies(const Points &points) std::vector ordered_copies; Slic3r::Geometry::chained_path(points, ordered_copies); - for (size_t point_idx : ordered_copies) { - Point copy = points[point_idx]; - copy.translate(this->_copies_shift); - this->_shifted_copies.push_back(copy); - } + for (size_t point_idx : ordered_copies) + this->_shifted_copies.push_back(points[point_idx] + this->_copies_shift); bool invalidated = this->_print->invalidate_step(psSkirt); invalidated |= this->_print->invalidate_step(psBrim); diff --git a/xs/src/libslic3r/SupportMaterial.cpp b/xs/src/libslic3r/SupportMaterial.cpp index 3fcefcff0..cf272eaa7 100644 --- a/xs/src/libslic3r/SupportMaterial.cpp +++ b/xs/src/libslic3r/SupportMaterial.cpp @@ -506,8 +506,8 @@ public: for (ExPolygon &island : islands) { 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_upper = std::upper_bound(m_island_samples.begin(), m_island_samples.end(), bbox.max + 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(), Point(bbox.max + Point(1, 1))); samples_inside.clear(); for (auto it = it_lower; it != it_upper; ++ 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. 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())); - coordf_t a = dot(v_seg); - coordf_t b = 2. * dot(v_seg, v_cntr); - coordf_t c = dot(v_cntr) - circle_distance * circle_distance; + coordf_t a = v_seg.squaredNorm(); + coordf_t b = 2. * v_seg.dot(v_cntr); + coordf_t c = v_cntr.squaredNorm() - circle_distance * circle_distance; coordf_t disc = b * b - 4. * a * c; if (disc > 0.) { // 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); } 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 ¢er : circle_centers) { 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) { // 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. - //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)); // End of the path. break; diff --git a/xs/src/libslic3r/libslic3r.h b/xs/src/libslic3r/libslic3r.h index 77006cebe..e6ebc14e5 100644 --- a/xs/src/libslic3r/libslic3r.h +++ b/xs/src/libslic3r/libslic3r.h @@ -130,6 +130,17 @@ inline void append(std::vector& dest, std::vector&& src) src.shrink_to_fit(); } +// Casting an std::vector<> from one type to another type without warnings about a loss of accuracy. +template +std::vector cast(const std::vector &src) +{ + std::vector dst; + dst.reserve(src.size()); + for (const T_FROM &a : src) + dst.emplace_back((T_TO)a); + return dst; +} + template inline void remove_nulls(std::vector &vec) { diff --git a/xs/src/slic3r/GUI/2DBed.cpp b/xs/src/slic3r/GUI/2DBed.cpp index 585205923..03791bdb2 100644 --- a/xs/src/slic3r/GUI/2DBed.cpp +++ b/xs/src/slic3r/GUI/2DBed.cpp @@ -34,11 +34,11 @@ void Bed_2D::repaint() auto cbb = BoundingBoxf(Pointf(0, 0),Pointf(cw, ch)); // leave space for origin point - cbb.min.translate(4, 0); - cbb.max.translate(-4, -4); + cbb.min.x() += 4; + cbb.max -= Vec2d(4., 4.); // leave space for origin label - cbb.max.translate(0, -13); + cbb.max.y() -= 13; // read new size 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())); for (auto angle : { -arrow_angle, arrow_angle }){ auto end = x_end; - end.translate(-arrow_len, 0); + end.x() -= arrow_len; end.rotate(angle, x_end); 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())); for (auto angle : { -arrow_angle, arrow_angle }) { auto end = y_end; - end.translate(0, +arrow_len); + end.y() += arrow_len; end.rotate(angle, y_end); 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 Point Bed_2D::to_pixels(Pointf point){ - auto p = Pointf(point); - p.scale(m_scale_factor); - p.translate(m_shift); + auto p = point * m_scale_factor + m_shift; 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 Pointf Bed_2D::to_units(Point point){ - auto p = Pointf(point.x(), GetSize().GetHeight() - point.y()); - p.translate(m_shift.negative()); - p.scale(1 / m_scale_factor); - return p; + return (Pointf(point.x(), GetSize().GetHeight() - point.y()) - m_shift) * (1. / m_scale_factor); } void Bed_2D::set_pos(Pointf pos){ diff --git a/xs/src/slic3r/GUI/3DScene.cpp b/xs/src/slic3r/GUI/3DScene.cpp index 0c446806c..68e11e378 100644 --- a/xs/src/slic3r/GUI/3DScene.cpp +++ b/xs/src/slic3r/GUI/3DScene.cpp @@ -929,7 +929,7 @@ static void thick_lines_to_indexed_vertex_array( bool is_closing = closed && is_last; Vectorf v = Vectorf::new_unscale(line.vector()); - v.scale(inv_len); + v *= inv_len; Pointf a = Pointf::new_unscale(line.a); 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 dx = dist * v.x(); double dy = dist * v.y(); - a1.translate(+dy, -dx); - a2.translate(-dy, +dx); - b1.translate(+dy, -dx); - b2.translate(-dy, +dx); + a1 += Vectorf(+dy, -dx); + a2 += Vectorf(-dy, +dx); + b1 += Vectorf(+dy, -dx); + b2 += Vectorf(-dy, +dx); } // calculate new XY normals Vector n = line.normal(); 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_b[4]; @@ -994,7 +994,7 @@ static void thick_lines_to_indexed_vertex_array( } else { // Continuing a previous segment. // 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) if (sharp) { 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); a1 = intersection; a2 = 2. * a - intersection; - assert(length(a1.vector_to(a)) < width); - assert(length(a2.vector_to(a)) < width); + assert((a - a1).norm() < width); + assert((a - a2).norm() < width); float *n_left_prev = volume.vertices_and_normals_interleaved.data() + idx_prev[LEFT ] * 6; float *p_left_prev = n_left_prev + 3; 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()); xy_right_normal.x() += n_right_prev[0]; 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 [1] = float(-xy_right_normal.y()); 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]; } } - else if (cross(v_prev, v) > 0.) { + else if (cross2(v_prev, v) > 0.) { // 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_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 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_right; @@ -1187,8 +1187,8 @@ static void thick_lines_to_indexed_vertex_array(const Lines3& lines, else { // generic segment - n_right = normalize(cross(unit_v, unit_positive_z)); - n_top = normalize(cross(n_right, unit_v)); + n_right = unit_v.cross(unit_positive_z).normalized(); + n_top = n_right.cross(unit_v).normalized(); } 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. // 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_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) { @@ -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. // 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_rl_displacement = 0.5 * width * average_n_right; diff --git a/xs/src/slic3r/GUI/BedShapeDialog.cpp b/xs/src/slic3r/GUI/BedShapeDialog.cpp index 170724956..0cdc1df43 100644 --- a/xs/src/slic3r/GUI/BedShapeDialog.cpp +++ b/xs/src/slic3r/GUI/BedShapeDialog.cpp @@ -179,7 +179,7 @@ void BedShapePanel::set_shape(ConfigOptionPoints* points) double avg_dist = 0; for (auto pt: polygon.points) { - double distance = center.distance_to(pt); + double distance = (pt - center).cast().norm(); vertex_distances.push_back(distance); avg_dist += distance; } diff --git a/xs/src/slic3r/GUI/GLCanvas3D.cpp b/xs/src/slic3r/GUI/GLCanvas3D.cpp index a9a76d2da..91a8ea890 100644 --- a/xs/src/slic3r/GUI/GLCanvas3D.cpp +++ b/xs/src/slic3r/GUI/GLCanvas3D.cpp @@ -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 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); } 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; // 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)) { @@ -1267,7 +1267,7 @@ bool GLCanvas3D::Gizmos::overlay_contains_mouse(const GLCanvas3D& canvas, const float half_tex_size = 0.5f * tex_size; // 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; top_y += (tex_size + OverlayGapY); @@ -3114,7 +3114,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_mouse.drag.start_position_3D = pos3d; // Remember the shift to to the object center.The object center will later be used // 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()) @@ -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()); // 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())); if (!m_bed.contains(cur_pos2)) { @@ -3144,10 +3144,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) cur_pos.x() = unscale(ip.x()); 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. - 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. GLVolume* volume = m_volumes.volumes[m_mouse.drag.move_volume_idx]; // 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. for (GLVolume* v : volumes) - { - Pointf3 origin = v->get_origin(); - origin.translate(vector.x(), vector.y(), 0.0); - v->set_origin(origin); - } + v->set_origin(v->get_origin() + Vectorf3(vector.x(), vector.y(), 0.0)); m_mouse.drag.start_position_3D = cur_pos; m_gizmos.refresh(); @@ -3275,9 +3271,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) float z = 0.0f; const Pointf3& cur_pos = _mouse_to_3d(pos, &z); Pointf3 orig = _mouse_to_3d(m_mouse.drag.start_position_2D, &z); - Pointf3 camera_target = m_camera.target; - camera_target.translate(orig.vector_to(cur_pos).negative()); - m_camera.target = camera_target; + m_camera.target += orig - cur_pos; 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 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 - coordf_t x_on_plane = dot(proj_on_plane, right); - coordf_t y_on_plane = dot(proj_on_plane, up); + coordf_t x_on_plane = proj_on_plane.dot(right); + coordf_t y_on_plane = proj_on_plane.dot(up); 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)); @@ -3653,7 +3647,7 @@ void GLCanvas3D::_camera_tranform() const ::glRotatef(-m_camera.get_theta(), 1.0f, 0.0f, 0.0f); // pitch ::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()); } diff --git a/xs/src/slic3r/GUI/GLGizmo.cpp b/xs/src/slic3r/GUI/GLGizmo.cpp index d31965b74..c52230c61 100644 --- a/xs/src/slic3r/GUI/GLGizmo.cpp +++ b/xs/src/slic3r/GUI/GLGizmo.cpp @@ -235,13 +235,13 @@ void GLGizmoRotate::on_set_state() void GLGizmoRotate::on_update(const Pointf& mouse_pos) { Vectorf orig_dir(1.0, 0.0); - Vectorf new_dir = normalize(mouse_pos - m_center); - coordf_t theta = ::acos(clamp(-1.0, 1.0, dot(new_dir, orig_dir))); - if (cross(orig_dir, new_dir) < 0.0) + Vectorf new_dir = (mouse_pos - m_center).normalized(); + coordf_t theta = ::acos(clamp(-1.0, 1.0, new_dir.dot(orig_dir))); + if (cross2(orig_dir, new_dir) < 0.0) theta = 2.0 * (coordf_t)PI - theta; // 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; 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())); - coordf_t orig_len = length(m_starting_drag_position - center); - coordf_t new_len = length(mouse_pos - center); + coordf_t orig_len = (m_starting_drag_position - center).norm(); + coordf_t new_len = (mouse_pos - center).norm(); coordf_t ratio = (orig_len != 0.0) ? new_len / orig_len : 1.0; m_scale = m_starting_scale * (float)ratio; diff --git a/xs/src/slic3r/GUI/GUI.cpp b/xs/src/slic3r/GUI/GUI.cpp index d1f5a8650..19656fb5e 100644 --- a/xs/src/slic3r/GUI/GUI.cpp +++ b/xs/src/slic3r/GUI/GUI.cpp @@ -894,10 +894,7 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl const std::vector &init_matrix = (config.option("wiping_volumes_matrix"))->values; const std::vector &init_extruders = (config.option("wiping_volumes_extruders"))->values; -#pragma warning(push) -#pragma warning(disable:4244) // disable Visual Studio's warning: conversion from 'double' to 'float', possible loss of data - WipingDialog dlg(parent,std::vector(init_matrix.begin(),init_matrix.end()),std::vector(init_extruders.begin(),init_extruders.end())); -#pragma warning(pop) + WipingDialog dlg(parent,cast(init_matrix),cast(init_extruders)); if (dlg.ShowModal() == wxID_OK) { std::vector matrix = dlg.get_matrix(); diff --git a/xs/src/slic3r/GUI/RammingChart.cpp b/xs/src/slic3r/GUI/RammingChart.cpp index 2603a5eab..8954ff93b 100644 --- a/xs/src/slic3r/GUI/RammingChart.cpp +++ b/xs/src/slic3r/GUI/RammingChart.cpp @@ -261,7 +261,7 @@ std::vector Chart::get_ramming_speed(float sampling) const { std::vector> Chart::get_buttons() const { std::vector> buttons_out; 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; } diff --git a/xs/src/xsinit.h b/xs/src/xsinit.h index f6080660c..02a8d9e80 100644 --- a/xs/src/xsinit.h +++ b/xs/src/xsinit.h @@ -74,6 +74,7 @@ extern "C" { #undef realloc #undef free #undef Zero + #undef Packet #undef select #endif /* _MSC_VER */ } diff --git a/xs/xsp/GUI_3DScene.xsp b/xs/xsp/GUI_3DScene.xsp index 38c85c328..e4194f87e 100644 --- a/xs/xsp/GUI_3DScene.xsp +++ b/xs/xsp/GUI_3DScene.xsp @@ -58,11 +58,7 @@ Clone origin() const %code%{ RETVAL = THIS->get_origin(); %}; void translate(double x, double y, double z) - %code%{ - Pointf3 o = THIS->get_origin(); - o.translate(x, y, z); - THIS->set_origin(o); - %}; + %code%{ THIS->set_origin(THIS->get_origin() + Pointf3(x, y, z)); %}; Clone bounding_box() const %code%{ RETVAL = THIS->bounding_box; %}; Clone transformed_bounding_box() const; diff --git a/xs/xsp/Line.xsp b/xs/xsp/Line.xsp index 92429e57a..ccbe97458 100644 --- a/xs/xsp/Line.xsp +++ b/xs/xsp/Line.xsp @@ -29,7 +29,6 @@ bool parallel_to_line(Line* line) %code{% RETVAL = THIS->parallel_to(*line); %}; Clone midpoint(); - Clone point_at(double distance); Clone intersection_infinite(Line* other) %code{% Point p; @@ -37,8 +36,8 @@ if (!res) CONFESS("Intersection failed"); RETVAL = p; %}; - Clone as_polyline() - %code{% RETVAL = Polyline(*THIS); %}; + Polyline* as_polyline() + %code{% RETVAL = new Polyline(THIS->a, THIS->b); %}; Clone normal(); Clone vector(); double ccw(Point* point) diff --git a/xs/xsp/Point.xsp b/xs/xsp/Point.xsp index df4df60b7..1d569c4f3 100644 --- a/xs/xsp/Point.xsp +++ b/xs/xsp/Point.xsp @@ -3,6 +3,7 @@ %{ #include #include "libslic3r/Point.hpp" +#include "libslic3r/Line.hpp" #include "libslic3r/Polygon.hpp" #include "libslic3r/Polyline.hpp" %} @@ -12,8 +13,10 @@ ~Point(); Clone clone() %code{% RETVAL=THIS; %}; - void scale(double factor); - void translate(double x, double y); + void scale(double factor) + %code{% *THIS *= factor; %}; + void translate(double x, double y) + %code{% *THIS += Point(x, y); %}; SV* arrayref() %code{% RETVAL = to_SV_pureperl(THIS); %}; SV* pp() @@ -30,23 +33,23 @@ Clone nearest_point(Points points) %code{% Point p; THIS->nearest_point(points, &p); RETVAL = p; %}; double distance_to(Point* point) - %code{% RETVAL = THIS->distance_to(*point); %}; + %code{% RETVAL = (*point - *THIS).cast().norm(); %}; 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) - %code{% RETVAL = THIS->perp_distance_to(*line); %}; + %code{% RETVAL = line->perp_distance_to(*THIS); %}; double ccw(Point* p1, Point* p2) %code{% RETVAL = THIS->ccw(*p1, *p2); %}; double ccw_angle(Point* p1, Point* p2) %code{% RETVAL = THIS->ccw_angle(*p1, *p2); %}; - Clone projection_onto_polygon(Polygon* polygon) + Point* projection_onto_polygon(Polygon* polygon) %code{% RETVAL = new Point(THIS->projection_onto(*polygon)); %}; - Clone projection_onto_polyline(Polyline* polyline) + Point* projection_onto_polyline(Polyline* polyline) %code{% RETVAL = new Point(THIS->projection_onto(*polyline)); %}; - Clone projection_onto_line(Line* line) + Point* projection_onto_line(Line* line) %code{% RETVAL = new Point(THIS->projection_onto(*line)); %}; - Clone negative() - %code{% RETVAL = new Point(THIS->negative()); %}; + Point* negative() + %code{% RETVAL = new Point(- *THIS); %}; bool coincides_with_epsilon(Point* point) %code{% RETVAL = (*THIS) == *point; %}; 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; %}; void set_y(double val) %code{% THIS->y() = val; %}; - void translate(double x, double y); - void scale(double factor); + void translate(double x, double y) + %code{% *THIS += Pointf(x, y); %}; + void scale(double factor) + %code{% *THIS *= factor; %}; void rotate(double angle, Pointf* center) %code{% THIS->rotate(angle, *center); %}; - Clone negative() - %code{% RETVAL = THIS->negative(); %}; - Clone vector_to(Pointf* point) - %code{% RETVAL = THIS->vector_to(*point); %}; + Pointf* negative() + %code{% RETVAL = new Pointf(- *THIS); %}; + Pointf* vector_to(Pointf* point) + %code{% RETVAL = new Pointf(*point - *THIS); %}; 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; %}; void set_z(double val) %code{% THIS->z() = val; %}; - void translate(double x, double y, double z); - void scale(double factor); + void translate(double x, double y, double z) + %code{% *THIS += Pointf3(x, y, z); %}; + void scale(double factor) + %code{% *THIS *= factor; %}; double distance_to(Pointf3* point) - %code{% RETVAL = THIS->distance_to(*point); %}; - Clone negative() - %code{% RETVAL = THIS->negative(); %}; - Clone vector_to(Pointf3* point) - %code{% RETVAL = THIS->vector_to(*point); %}; + %code{% RETVAL = (*point - *THIS).norm(); %}; + Pointf3* negative() + %code{% RETVAL = new Pointf3(- *THIS); %}; + Pointf3* vector_to(Pointf3* 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; %}; }; diff --git a/xs/xsp/Print.xsp b/xs/xsp/Print.xsp index 717064916..a6fb4f1b2 100644 --- a/xs/xsp/Print.xsp +++ b/xs/xsp/Print.xsp @@ -176,15 +176,6 @@ _constant() void set_step_started(PrintStep 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(extruder_id, 0)); - THIS->filament_stats[extruder_id] += length; - %}; SV* filament_stats() %code%{ HV* hv = newHV(); diff --git a/xs/xsp/TriangleMesh.xsp b/xs/xsp/TriangleMesh.xsp index d4578303b..1691066a5 100644 --- a/xs/xsp/TriangleMesh.xsp +++ b/xs/xsp/TriangleMesh.xsp @@ -181,7 +181,7 @@ TriangleMesh::slice(z) std::vector z CODE: // convert doubles to floats - std::vector z_f(z.begin(), z.end()); + std::vector z_f = cast(z); std::vector layers; TriangleMeshSlicer mslicer(THIS); -- cgit v1.2.3