Skip to content
Open
38 changes: 19 additions & 19 deletions include/geometry/Point3Matrix.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ class Point3Matrix
*/
explicit Point3Matrix(const PointMatrix& b)
{
matrix.at(0) = b.matrix.at(0);
matrix.at(1) = b.matrix.at(1);
matrix.at(2) = 0;
matrix.at(3) = b.matrix.at(2);
matrix.at(4) = b.matrix.at(3);
matrix.at(5) = 0;
matrix.at(6) = 0;
matrix.at(7) = 0;
matrix.at(8) = 1;
matrix[0] = b.matrix[0];
matrix[1] = b.matrix[1];
matrix[2] = 0;
matrix[3] = b.matrix[2];
matrix[4] = b.matrix[3];
matrix[5] = 0;
matrix[6] = 0;
matrix[7] = 0;
matrix[8] = 1;
}

Point3Matrix(Point3Matrix&& point3_matrix) = default;
Expand All @@ -48,9 +48,9 @@ class Point3Matrix
const auto x = static_cast<double>(p.x_);
const auto y = static_cast<double>(p.y_);
const auto z = static_cast<double>(p.z_);
return { std::llrint(x * matrix.at(0) + y * matrix.at(1) + z * matrix.at(2)),
std::llrint(x * matrix.at(3) + y * matrix.at(4) + z * matrix.at(5)),
std::llrint(x * matrix.at(6) + y * matrix.at(7) + z * matrix.at(8)) };
return { std::llrint(x * matrix[0] + y * matrix[1] + z * matrix[2]),
std::llrint(x * matrix[3] + y * matrix[4] + z * matrix[5]),
std::llrint(x * matrix[6] + y * matrix[7] + z * matrix[8]) };
}

/*!
Expand All @@ -65,22 +65,22 @@ class Point3Matrix
static Point3Matrix translate(const Point2LL& p)
{
Point3Matrix ret; // uniform matrix
ret.matrix.at(2) = static_cast<double>(p.X);
ret.matrix.at(5) = static_cast<double>(p.Y);
ret.matrix[2] = static_cast<double>(p.X);
ret.matrix[5] = static_cast<double>(p.Y);
return ret;
}

[[nodiscard]] Point3Matrix compose(const Point3Matrix& b) const
{
Point3Matrix ret;
for (int outx = 0; outx < 3; outx++)
for (size_t outx = 0; outx < 3; outx++)
{
for (int outy = 0; outy < 3; outy++)
for (size_t outy = 0; outy < 3; outy++)
{
ret.matrix.at(outy * 3 + outx) = 0;
for (int in = 0; in < 3; in++)
ret.matrix[outy * 3 + outx] = 0;
for (size_t in = 0; in < 3; in++)
{
ret.matrix.at(outy * 3 + outx) += matrix.at(outy * 3 + in) * b.matrix.at(in * 3 + outx);
ret.matrix[outy * 3 + outx] += matrix[outy * 3 + in] * b.matrix[in * 3 + outx];
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion include/progress/Progress.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class Progress
0.1 // FINISH = 6
};

static constexpr std::array<std::string_view, N_PROGRESS_STAGES> names{ "start", "slice", "layerparts", "inset+skin", "support", "export", "process" };
static constexpr std::array<std::string_view, N_PROGRESS_STAGES> names{ "start", "painting", "slice", "layerparts", "inset+skin", "support", "export", "process" };
static std::array<double, N_PROGRESS_STAGES> accumulated_times; //!< Time past before each stage
static double total_timing; //!< An estimate of the total time
static std::optional<LayerIndex> first_skipped_layer; //!< The index of the layer for which we skipped time reporting
Expand Down
121 changes: 53 additions & 68 deletions include/utils/polygonUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -438,22 +438,6 @@ class PolygonUtils
const LocToLineGrid& destination_loc_to_line,
const std::function<int(Point2LL)>& penalty_function = no_penalty_function);

/*!
* Checks whether a given line segment collides with polygons as given in a loc_to_line grid.
*
* If the line segment doesn't intersect with any edge of the polygon, but
* merely touches it, a collision is also reported. For instance, a
* collision is reported when the an endpoint of the line is exactly on the
* polygon, and when the line coincides with an edge.
*
* \param[in] from The start point
* \param[in] to The end point
* \param[in] loc_to_line A SparsePointGridInclusive mapping locations to starting vertices of line segmetns of the \p polygons
* \param[out] collision_result (optional) The polygons segment intersecting with the line segment
* \return whether the line segment collides with the boundary of the polygons
*/
static bool polygonCollidesWithLineSegment(const Point2LL from, const Point2LL to, const LocToLineGrid& loc_to_line, PolygonsPointIndex* collision_result = nullptr);

/*!
* Find the next point (going along the direction of the polygon) with a distance \p dist from the point \p from within the \p poly.
* Returns whether another point could be found within the \p poly which can be found before encountering the point at index \p start_idx.
Expand Down Expand Up @@ -486,65 +470,20 @@ class PolygonUtils
static std::optional<ClosestPointPolygon> getNextParallelIntersection(const ClosestPointPolygon& start, const Point2LL& line_to, const coord_t dist, const bool forward);

/*!
* Checks whether a given line segment collides with a given polygon(s).
* The transformed_startPoint and transformed_endPoint should have the same
* Y coordinate.
*
* If the line segment doesn't intersect with any edge of the polygon, but
* merely touches it, a collision is also reported. For instance, a
* collision is reported when the an endpoint of the line is exactly on the
* polygon, and when the line coincides with an edge.
*
* \param poly The polygon
* \param transformed_startPoint The start point transformed such that it is
* on the same horizontal line as the end point
* \param transformed_endPoint The end point transformed such that it is on
* the same horizontal line as the start point
* \param transformation_matrix The transformation applied to the start and
* end point to be applied to the polygon(s)
* \return whether the line segment collides with the boundary of the
* polygon(s)
*/
static bool
polygonCollidesWithLineSegment(const Polygon& poly, const Point2LL& transformed_startPoint, const Point2LL& transformed_endPoint, PointMatrix transformation_matrix);

/*!
* Checks whether a given line segment collides with a given polygon(s).
*
* If the line segment doesn't intersect with any edge of the polygon, but
* merely touches it, a collision is also reported. For instance, a
* collision is reported when the an endpoint of the line is exactly on the
* polygon, and when the line coincides with an edge.
*
* \param poly The polygon
* \param startPoint The start point
* \param endPoint The end point
* \return whether the line segment collides with the boundary of the
* polygon(s)
*/
static bool polygonCollidesWithLineSegment(const Polygon& poly, const Point2LL& startPoint, const Point2LL& endPoint);

/*!
* Checks whether a given line segment collides with a given polygon(s).
* The transformed_startPoint and transformed_endPoint should have the same
* Y coordinate.
* Checks whether a given line segment collides with polygons as given in a loc_to_line grid.
*
* If the line segment doesn't intersect with any edge of the polygon, but
* merely touches it, a collision is also reported. For instance, a
* collision is reported when the an endpoint of the line is exactly on the
* polygon, and when the line coincides with an edge.
*
* \param poly The polygon
* \param transformed_startPoint The start point transformed such that it is
* on the same horizontal line as the end point
* \param transformed_endPoint The end point transformed such that it is on
* the same horizontal line as the start point
* \param transformation_matrix The transformation applied to the start and
* end point to be applied to the polygon(s)
* \return whether the line segment collides with the boundary of the
* polygon(s)
* \param[in] from The start point
* \param[in] to The end point
* \param[in] loc_to_line A SparsePointGridInclusive mapping locations to starting vertices of line segmetns of the \p polygons
* \param[out] collision_result (optional) The polygons segment intersecting with the line segment
* \return whether the line segment collides with the boundary of the polygons
*/
static bool polygonCollidesWithLineSegment(const Shape& polys, const Point2LL& transformed_startPoint, const Point2LL& transformed_endPoint, PointMatrix transformation_matrix);
static bool polygonCollidesWithLineSegment(const Point2LL& from, const Point2LL& to, const LocToLineGrid& loc_to_line, PolygonsPointIndex* collision_result = nullptr);

/*!
* Checks whether a given line segment collides with a given polygon(s).
Expand Down Expand Up @@ -766,6 +705,52 @@ class PolygonUtils
* @return The parts of the shape that are wider than the given minimum. Note that the returned shape may go beyond the original one.
*/
static Shape getRawWideAreas(const Shape& shape, const coord_t min_width, const coord_t extra_widen = EPSILON);

/*!
* Checks whether a given line segment collides with a given polygon(s).
* The transformed_startPoint and transformed_endPoint should have the same
* Y coordinate.
*
* If the line segment doesn't intersect with any edge of the polygon, but
* merely touches it, a collision is also reported. For instance, a
* collision is reported when the an endpoint of the line is exactly on the
* polygon, and when the line coincides with an edge.
*
* \param poly The polygon
* \param transformed_startPoint The start point transformed such that it is
* on the same horizontal line as the end point
* \param transformed_endPoint The end point transformed such that it is on
* the same horizontal line as the start point
* \param transformation_matrix The transformation applied to the start and
* end point to be applied to the polygon(s)
* \return whether the line segment collides with the boundary of the
* polygon(s)
*/
static bool
polygonCollidesWithLineSegment(const Polygon& poly, const Point2LL& transformed_startPoint, const Point2LL& transformed_endPoint, const PointMatrix& transformation_matrix);

/*!
* Checks whether a given line segment collides with a given polygon(s).
* The transformed_startPoint and transformed_endPoint should have the same
* Y coordinate.
*
* If the line segment doesn't intersect with any edge of the polygon, but
* merely touches it, a collision is also reported. For instance, a
* collision is reported when the an endpoint of the line is exactly on the
* polygon, and when the line coincides with an edge.
*
* \param poly The polygon
* \param transformed_startPoint The start point transformed such that it is
* on the same horizontal line as the end point
* \param transformed_endPoint The end point transformed such that it is on
* the same horizontal line as the start point
* \param transformation_matrix The transformation applied to the start and
* end point to be applied to the polygon(s)
* \return whether the line segment collides with the boundary of the
* polygon(s)
*/
static bool
polygonCollidesWithLineSegment(const Shape& polys, const Point2LL& transformed_startPoint, const Point2LL& transformed_endPoint, const PointMatrix& transformation_matrix);
};

} // namespace cura
Expand Down
6 changes: 6 additions & 0 deletions include/utils/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,12 @@ struct PrecisionedDouble
return (std::abs(value) * std::pow(10.0, precision)) < 1.0;
}

static bool equalGivenPrecision(const PrecisionedDouble& a, const PrecisionedDouble& b)
{
// We expect the 'value's here to be in the hundereds or thousands or so at max, so this implementation should be OK.
return (a.value == b.value) || (std::round(a.value * std::pow(10, a.precision)) == std::round(b.value * std::pow(10, b.precision)));
}

friend inline std::ostream& operator<<(std::ostream& out, const PrecisionedDouble precision_and_input)
{
writeDoubleToStream(precision_and_input.precision, precision_and_input.value, out);
Expand Down
15 changes: 2 additions & 13 deletions src/gcode_export/gcodeExport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1772,19 +1772,8 @@ void GCodeExport::writeSpecificFanCommand(double speed, size_t fan_number)
{
return { (should_scale_zero_to_one ? static_cast<uint8_t>(2) : static_cast<uint8_t>(1)), (should_scale_zero_to_one ? value : value * 255.0) / 100.0 };
};
bool write_value = true;
std::ostringstream new_value;
const auto num_new_val = scale_zero_to_one_optional(speed);
new_value << num_new_val;
const std::string new_value_str = new_value.str();
if (current_fan_speed.has_value())
{
std::ostringstream old_value;
old_value << scale_zero_to_one_optional(current_fan_speed.value());
write_value = new_value_str != old_value.str();
}

if (write_value)
if (! (current_fan_speed.has_value() && PrecisionedDouble::equalGivenPrecision(scale_zero_to_one_optional(current_fan_speed.value()), num_new_val)))
{
if (num_new_val.wouldWriteZero())
{
Expand All @@ -1793,7 +1782,7 @@ void GCodeExport::writeSpecificFanCommand(double speed, size_t fan_number)
}
else
{
*output_stream_ << "M106 S" << new_value_str;
*output_stream_ << "M106 S" << num_new_val;
}

if (fan_number)
Expand Down
40 changes: 20 additions & 20 deletions src/geometry/PointMatrix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ namespace cura
PointMatrix::PointMatrix(double rotation)
{
rotation = rotation / 180 * std::numbers::pi;
matrix.at(0) = std::cos(rotation);
matrix.at(1) = -std::sin(rotation);
matrix.at(2) = -matrix.at(1);
matrix.at(3) = matrix.at(0);
matrix[0] = std::cos(rotation);
matrix[1] = -std::sin(rotation);
matrix[2] = -matrix[1];
matrix[3] = matrix[0];
}

PointMatrix::PointMatrix(const AngleDegrees& rotation)
Expand All @@ -32,45 +32,45 @@ PointMatrix::PointMatrix(const AngleRadians& rotation)

PointMatrix::PointMatrix(const Point2LL& p)
{
matrix.at(0) = static_cast<double>(p.X);
matrix.at(1) = static_cast<double>(p.Y);
double f = std::sqrt((matrix.at(0) * matrix.at(0)) + (matrix.at(1) * matrix.at(1)));
matrix.at(0) /= f;
matrix.at(1) /= f;
matrix.at(2) = -matrix.at(1);
matrix.at(3) = matrix.at(0);
matrix[0] = static_cast<double>(p.X);
matrix[1] = static_cast<double>(p.Y);
double f = std::sqrt((matrix[0] * matrix[0]) + (matrix[1] * matrix[1]));
matrix[0] /= f;
matrix[1] /= f;
matrix[2] = -matrix[1];
matrix[3] = matrix[0];
}

PointMatrix PointMatrix::scale(double s)
{
PointMatrix ret;
ret.matrix.at(0) = s;
ret.matrix.at(3) = s;
ret.matrix[0] = s;
ret.matrix[3] = s;
return ret;
}

Point2LL PointMatrix::apply(const Point2LL& p) const
{
const auto x = static_cast<double>(p.X);
const auto y = static_cast<double>(p.Y);
return { std::llrint(x * matrix.at(0) + y * matrix.at(1)), std::llrint(x * matrix.at(2) + y * matrix.at(3)) };
return { std::llrint(x * matrix[0] + y * matrix[1]), std::llrint(x * matrix[2] + y * matrix[3]) };
}

Point2LL PointMatrix::unapply(const Point2LL& p) const
{
const auto x = static_cast<double>(p.X);
const auto y = static_cast<double>(p.Y);
return { std::llrint(x * matrix.at(0) + y * matrix.at(2)), std::llrint(x * matrix.at(1) + y * matrix.at(3)) };
return { std::llrint(x * matrix[0] + y * matrix[2]), std::llrint(x * matrix[1] + y * matrix[3]) };
}

PointMatrix PointMatrix::inverse() const
{
PointMatrix ret;
double det = matrix.at(0) * matrix.at(3) - matrix.at(1) * matrix.at(2);
ret.matrix.at(0) = matrix.at(3) / det;
ret.matrix.at(1) = -matrix.at(1) / det;
ret.matrix.at(2) = -matrix.at(2) / det;
ret.matrix.at(3) = matrix.at(0) / det;
double det = matrix[0] * matrix[3] - matrix[1] * matrix[2];
ret.matrix[0] = matrix[3] / det;
ret.matrix[1] = -matrix[1] / det;
ret.matrix[2] = -matrix[2] / det;
ret.matrix[3] = matrix[0] / det;
return ret;
}

Expand Down
8 changes: 8 additions & 0 deletions src/geometry/Shape.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "geometry/Polygon.h"
#include "geometry/SingleShape.h"
#include "settings/types/Ratio.h"
#include "utils/AABB.h"
#include "utils/OpenPolylineStitcher.h"
#include "utils/linearAlg2D.h"

Expand Down Expand Up @@ -885,10 +886,17 @@ std::vector<float> Shape::intersectionsWithSegment(const Point2LL& start, const
{
std::vector<float> result;

const AABB lineseg_aabb({ start, end });

for (const Polygon& polygon : getLines())
{
for (auto iterator = polygon.beginSegments(); iterator != polygon.endSegments(); ++iterator)
{
if (! AABB({ (*iterator).start, (*iterator).end }).hit(lineseg_aabb))
{
continue;
}

float t, u;
if (LinearAlg2D::segmentSegmentIntersection(start, end, (*iterator).start, (*iterator).end, t, u))
{
Expand Down
Loading
Loading