Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
684c316
Hackathon '25: Slice/Print-ID label: Determine axis/ranges of project…
rburema Jul 16, 2025
96e4390
Apply clang-format
rburema Jul 16, 2025
3d63cf5
Hackathon '25: Slice/Print-ID label: Apply label-extents to model/gco…
rburema Jul 17, 2025
7eb5fdb
Apply clang-format
rburema Jul 17, 2025
8890a04
Label points didn't include the one _just_ before the label.
rburema Jul 18, 2025
1febbdd
Fix int-vector * integer multiplication. (Not sure if the floating-po…
rburema Jul 18, 2025
0e7f289
Print-ID/Slice-ID: Pass UV coords through to gcode (not yet mapped to…
rburema Jul 18, 2025
b7c9201
Slice-ID/Print-ID: Should now use the actual label-UV, instead of dat…
rburema Jul 18, 2025
5ed6cf0
Slice-ID/Print-ID: (errrr ... fix recreating the image each time and …
rburema Jul 18, 2025
4750542
Slice-ID/Print-ID: Prints a timestamp on the painted area.
rburema Jul 18, 2025
410fc23
Apply clang-format
rburema Jul 18, 2025
0a0b434
Slice-ID: Clean up a little.
rburema Jul 18, 2025
e6c2b89
Slice-ID/Print-ID: Squashed commit of the following:
rburema Jul 19, 2025
e2520a9
Apply clang-format
rburema Jul 19, 2025
6098408
Fix Capitalizaton for *nix (Mac and Linux) builds.
rburema Jul 19, 2025
d5bce75
Slide-ID/Print-ID: Fix little code and spelling stuff (and hopefully …
rburema Jul 19, 2025
6acf96b
Small readability adjustments.
rburema Jul 21, 2025
5f1f08d
Rewrite 'sliced UV coords' to use _line_ grid instead of _point_ grid.
rburema Jul 21, 2025
37d47e8
Going to need the Segments outside of the lne-grid as well.
rburema Jul 21, 2025
05b7f99
State of Slice-ID/Print-ID at the end of the Hackathon '25.
rburema Jul 21, 2025
96efb64
Apply clang-format
rburema Jul 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ set(engine_SRCS # Except main.cpp.
src/utils/ExtrusionLine.cpp
src/utils/ExtrusionSegment.cpp
src/utils/gettime.cpp
src/utils/IdFieldInfo.cpp
src/utils/LabelMaker.cpp
src/utils/linearAlg2D.cpp
src/utils/ListPolyIt.cpp
src/utils/Matrix4x3D.cpp
Expand Down
5 changes: 5 additions & 0 deletions include/ExtruderPlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

namespace cura
{
class Image;
class LayerPlanBuffer;
class LayerPlan;
/*!
Expand Down Expand Up @@ -124,6 +125,10 @@ class ExtruderPlan
*/
void applyBackPressureCompensation(const Ratio back_pressure_compensation);

/*!
*/
void applyIdLabel(const Image& slice_id_texture, const coord_t current_z);

/*!
* Gets the mesh being printed first on this plan
*/
Expand Down
3 changes: 2 additions & 1 deletion include/FffGcodeWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ namespace cura
{

class AngleDegrees;
class Image;
class Shape;
class SkinPart;
class SliceDataStorage;
Expand Down Expand Up @@ -229,7 +230,7 @@ class FffGcodeWriter : public NoCopy
* \param total_layers The total number of layers.
* \return The layer plans
*/
ProcessLayerResult processLayer(const SliceDataStorage& storage, LayerIndex layer_nr, const size_t total_layers) const;
ProcessLayerResult processLayer(const SliceDataStorage& storage, LayerIndex layer_nr, const size_t total_layers, const std::optional<Image>& slice_id_texture) const;

/*!
* This function checks whether prime blob should happen for any extruder on the first layer.
Expand Down
5 changes: 5 additions & 0 deletions include/LayerPlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -835,6 +835,10 @@ class LayerPlan : public NoCopy
*/
void applyGradualFlow();

/*!
*/
void applyIdLabel(const Image& slice_id_texture);

/*!
* Gets the mesh being printed first on this layer
*/
Expand Down Expand Up @@ -917,6 +921,7 @@ class LayerPlan : public NoCopy
const coord_t path_z_offset,
double extrusion_mm3_per_mm,
PrintFeatureType feature,
const std::optional<std::string_view>& inline_comment = std::nullopt,
bool update_extrusion_offset = false);

/*!
Expand Down
23 changes: 21 additions & 2 deletions include/SlicedUVCoordinates.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
#define SLICEDUVCOORDINATES_H

#include <optional>
#include <unordered_map>
#include <utility>

#include "geometry/Point2LL.h"
#include "utils/Point2F.h"
#include "utils/SparsePointGridInclusive.h"
#include "utils/SparseLineGrid.h"

namespace cura
{
Expand All @@ -23,17 +25,34 @@ class SlicedUVCoordinates

std::optional<Point2F> getClosestUVCoordinates(const Point2LL& position) const;

/*! /!\ WARNINGS /!\
* - Currently assumes straight spans in UV-space will be over at most 2 faces, but this isn't _universally_ true.
* - Currently returns the UV-coords of the _entire_ segment from and to are part of,
* even if from and to repressent some points other than begin and end (though it should handle reversed).
*/
std::optional<std::pair<Point2F, Point2F>> getUVCoordsLineSegment(const Point2LL& from, const Point2LL& to) const;

private:
struct Segment
{
Point2LL start, end;
Point2F uv_start, uv_end;
};
struct SegmentLocator
{
public:
std::pair<Point2LL, Point2LL> operator()(Segment* const& seg)
{
return { seg->start, seg->end };
}
};

static constexpr coord_t cell_size{ 1000 };
static constexpr coord_t search_radius{ 1000 };
SparsePointGridInclusive<Point2F> located_uv_coordinates_;

std::vector<Segment> segments_;
SparseLineGrid<Segment*, SegmentLocator> located_uv_coords_segs_;
std::unordered_multimap<Point2LL, Segment*> segs_by_point_;
};

} // namespace cura
Expand Down
25 changes: 25 additions & 0 deletions include/TextureDataMapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
#include <map>
#include <string>

#include <fmt/format.h>

#include "utils/Point2F.h"

namespace cura
{

Expand All @@ -32,5 +36,26 @@ enum class TextureArea
Avoid = 2, // Area is to be avoided
};

using Texel = std::pair<TextureArea, Point2F>;

} // namespace cura

namespace fmt
{
template<>
struct formatter<cura::TextureBitField>
{
constexpr auto parse(format_parse_context& ctx)
{
return ctx.end();
}

template<typename FormatContext>
auto format(const cura::TextureBitField& tbf, FormatContext& ctx) const
{
return format_to(ctx.out(), "[{} -- {}]", tbf.bit_range_start_index, tbf.bit_range_end_index);
}
};
} // namespace fmt

#endif // MESH_H
2 changes: 2 additions & 0 deletions include/TextureDataProvider.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ class TextureDataProvider

std::optional<TextureArea> getAreaPreference(const Point2LL& position, const std::string& feature) const;

bool getTexelsForSpan(const Point2LL& a, const Point2LL& b, const std::string& feature, std::vector<Texel>& res) const;

private:
std::shared_ptr<SlicedUVCoordinates> uv_coordinates_;
std::shared_ptr<Image> texture_;
Expand Down
18 changes: 16 additions & 2 deletions include/gcodeExport.h
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,13 @@ class GCodeExport : public NoCopy
* \param feature the feature that's currently printing
* \param update_extrusion_offset whether to update the extrusion offset to match the current flow rate
*/
void writeExtrusion(const Point2LL& p, const Velocity& speed, double extrusion_mm3_per_mm, PrintFeatureType feature, bool update_extrusion_offset = false);
void writeExtrusion(
const Point2LL& p,
const Velocity& speed,
double extrusion_mm3_per_mm,
PrintFeatureType feature,
const std::optional<std::string_view>& inline_comment = std::nullopt,
bool update_extrusion_offset = false);

/*!
* Go to a X/Y location with the z-hopped Z value
Expand All @@ -396,7 +402,13 @@ class GCodeExport : public NoCopy
* \param feature the feature that's currently printing
* \param update_extrusion_offset whether to update the extrusion offset to match the current flow rate
*/
void writeExtrusion(const Point3LL& p, const Velocity& speed, double extrusion_mm3_per_mm, PrintFeatureType feature, bool update_extrusion_offset = false);
void writeExtrusion(
const Point3LL& p,
const Velocity& speed,
double extrusion_mm3_per_mm,
PrintFeatureType feature,
const std::optional<std::string_view>& inline_comment = std::nullopt,
bool update_extrusion_offset = false);

/*!
* Initialize the extruder trains.
Expand Down Expand Up @@ -471,6 +483,7 @@ class GCodeExport : public NoCopy
const Velocity& speed,
const double extrusion_mm3_per_mm,
const PrintFeatureType& feature,
const std::optional<std::string_view>& inline_comment = std::nullopt,
const bool update_extrusion_offset = false);

/*!
Expand All @@ -490,6 +503,7 @@ class GCodeExport : public NoCopy
const coord_t z,
const double e,
const PrintFeatureType& feature,
const std::optional<std::string_view>& inline_comment = std::nullopt,
const std::optional<RetractionAmounts>& retraction_amounts = std::nullopt);

/*!
Expand Down
9 changes: 8 additions & 1 deletion include/geometry/Point3LL.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,19 @@ class Point3LL
Point3LL operator*(const Point3LL& p) const; //!< Element-wise multiplication. For dot product, use .dot()!
Point3LL operator/(const Point3LL& p) const;

template<utils::numeric T>
template<utils::floating_point T>
Point3LL operator*(const T& i) const
{
return { std::llround(static_cast<T>(x_) * i), std::llround(static_cast<T>(y_) * i), std::llround(static_cast<T>(z_) * i) };
}

template<utils::integral T>
Point3LL operator*(const T& i) const
{
const coord_t ii = static_cast<coord_t>(i);
return { x_ * ii, y_ * ii, z_ * ii };
}

template<utils::numeric T>
Point3LL operator/(const T& i) const
{
Expand Down
4 changes: 4 additions & 0 deletions include/mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "TextureDataMapping.h"
#include "settings/Settings.h"
#include "utils/AABB3D.h"
#include "utils/IDFieldInfo.h"
#include "utils/Matrix4x3D.h"
#include "utils/Point2F.h"

Expand Down Expand Up @@ -100,6 +101,8 @@ class Image
return getPixel(static_cast<size_t>(uv_coordinates.x_ * width_), static_cast<size_t>(uv_coordinates.y_ * height_));
}

void visitSpanPerPixel(const Point2F& a, const Point2F& b, const std::function<void(const int32_t, const Point2F&)>& func) const;

private:
std::vector<uint8_t> data_; // The raw pixels, data
size_t width_{ 0 }; // The image width
Expand All @@ -115,6 +118,7 @@ See MeshFace for the specifics of how/when faces are connected.
*/
class Mesh
{
private:
//! The vertex_hash_map stores a index reference of each vertex for the hash of that location. Allows for quick retrieval of points with the same location.
std::unordered_map<uint32_t, std::vector<uint32_t>> vertex_hash_map_;
AABB3D aabb_;
Expand Down
3 changes: 3 additions & 0 deletions include/pathPlanning/GCodePath.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "geometry/Point2LL.h"
#include "settings/types/Ratio.h"
#include "sliceDataStorage.h"
#include "utils/Point2F.h"

namespace cura
{
Expand Down Expand Up @@ -46,6 +47,8 @@ struct GCodePath
bool perform_z_hop{ false }; //!< Whether to perform a z_hop in this path, which is assumed to be a travel path.
bool perform_prime{ false }; //!< Whether this path is preceded by a prime (blob)
std::vector<Point3LL> points{}; //!< The points constituting this path. The Z coordinate is an offset relative to the actual layer height, added to the global z_offset.
std::optional<std::vector<Point2F>> idlabel_uv_per_point
= std::nullopt; //!< If this path is part of an ID-label, contains for each path-point an UV-point into the label-texture.
bool done{ false }; //!< Path is finished, no more moves should be added, and a new path should be started instead of any appending done to this one.
double fan_speed{ GCodePathConfig::FAN_SPEED_DEFAULT }; //!< fan speed override for this path, value should be within range 0-100 (inclusive) and ignored otherwise
TimeMaterialEstimates estimates{}; //!< Naive time and material estimates
Expand Down
6 changes: 6 additions & 0 deletions include/sliceDataStorage.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "settings/types/LayerIndex.h"
#include "utils/AABB.h"
#include "utils/AABB3D.h"
#include "utils/IDFieldInfo.h"
#include "utils/NoCopy.h"

namespace cura
Expand Down Expand Up @@ -307,6 +308,7 @@ class SliceMeshStorage
Settings& settings;
std::vector<SliceLayer> layers;
std::string mesh_name;
std::optional<IdFieldInfo> id_field_info;

LayerIndex layer_nr_max_filled_layer; //!< the layer number of the uppermost layer with content (modified while infill meshes are processed)

Expand Down Expand Up @@ -337,6 +339,10 @@ class SliceMeshStorage
*/
SliceMeshStorage(Mesh* mesh, const size_t slice_layer_count);

/*!
*/
void setIdFieldInfo(const std::vector<Point3LL>& label_pt_cloud);

/*!
* \param extruder_nr The extruder for which to check
* \return whether a particular extruder is used by this mesh
Expand Down
4 changes: 4 additions & 0 deletions include/slicer.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ class SlicerLayer
*/
void makePolygons(const Mesh* mesh);

/*!
*/
void clearSegments();

protected:
/*!
* Connect the segments into loops which correctly form polygons (don't perform stitching here)
Expand Down
8 changes: 8 additions & 0 deletions include/utils/AABB3D.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ struct AABB3D
*/
AABB flatten() const;

/*!
* Whether or not this represents an actual box in 'real' space, not a _negative_ volume.
* Note that the volume might still be empty (== 0.0), which can happen if it represents a(n axis aligned) plane, a line, or a point.
*
* \return Whether or not the space the box envelops is at least 0.
*/
bool exists() const;

/*!
* Check whether this aabb overlaps with another.
*
Expand Down
39 changes: 39 additions & 0 deletions include/utils/IDFieldInfo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (c) 2025 UltiMaker
// CuraEngine is released under the terms of the AGPLv3 or higher

#ifndef ID_FIELD_INFO_H
#define ID_FIELD_INFO_H

#include <optional>

#include "geometry/Point3LL.h"
#include "utils/AABB.h"
#include "utils/Point2F.h"
#include "utils/Point3D.h"

namespace cura
{
const double CLOSE_1D = std::nextafter(1.0, 0.0);
const float CLOSE_1F = std::nextafter(1.0f, 0.0f);
// NOTE: nextafter isn't constexpr yet in c++20, replace with constexpr when we do C++23

struct IdFieldInfo
{
typedef std::pair<double, double> span_t;

Point3D primary_axis_;
span_t primary_span_;

Point3D secondary_axis_;
span_t secondary_span_;

Point3D normal_;

public:
static std::optional<IdFieldInfo> fromPointCloud(const std::vector<Point3LL>& points);

Point2F worldPointToLabelUv(const Point3LL& pt) const;
};
} // namespace cura

#endif // ID_FIELD_INFO_H
16 changes: 16 additions & 0 deletions include/utils/LabelMaker.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright (c) 2025 UltiMaker
// CuraEngine is released under the terms of the AGPLv3 or higher

#ifndef LABEL_MAKER_H
#define LABEL_MAKER_H

#include <cstdint>
#include <string_view>
#include <vector>

namespace cura
{
void paintStringToBuffer(const std::string_view& str, const size_t buffer_width, const size_t buffer_height, std::vector<uint8_t>& buffer);
}

#endif // LABEL_MAKER_H
Loading