feat: Add Z Anti-Aliasing (ZAA) contouring support

Port Z Anti-Aliasing from BambuStudio-ZAA (https://github.com/adob/BambuStudio-ZAA)
to OrcaSlicer. ZAA eliminates stair-stepping on curved and sloped top surfaces
by raycasting each extrusion point against the original 3D mesh and micro-adjusting
Z height to follow the actual surface geometry.

Key changes:
- Add ContourZ.cpp raycasting algorithm (~330 lines)
- Extend geometry with 3D support (Point3, Line3, Polyline3, MultiPoint3)
- Template arc fitting for 2D/3D compatibility
- Change ExtrusionPath::polyline from Polyline to Polyline3
- Add 5 ZAA config options (zaa_enabled, zaa_min_z, etc.)
- Add posContouring pipeline step in PrintObject
- Update GCode writer for 3D coordinate output
- Add ZAA settings UI in Print Settings > Quality
- Add docs/ZAA.md with usage and implementation details

ZAA is opt-in and disabled by default. When disabled, the slicing pipeline
is unchanged.
This commit is contained in:
Matthias Nott
2026-02-09 20:38:46 +01:00
parent cae1567726
commit 963f8d86b7
57 changed files with 1817 additions and 204 deletions

View File

@@ -251,6 +251,7 @@ bool remove_degenerate(Polylines &polylines);
// Returns index of a segment of a polyline and foot point of pt on polyline.
std::pair<int, Point> foot_pt(const Points &polyline, const Point &pt);
std::pair<int, Point3> foot_pt(const Points3 &polyline, const Point3 &pt);
class ThickPolyline : public Polyline {
public:
@@ -290,7 +291,68 @@ inline ThickPolylines to_thick_polylines(Polylines&& polylines, const coordf_t w
class Polyline3 : public MultiPoint3
{
public:
Polyline3() {}
explicit Polyline3(const Points3 &points) { this->points = points; }
explicit Polyline3(const Polyline &poly, coord_t z = 0) {
this->points.reserve(poly.points.size());
for (const Point &pt : poly.points) {
this->points.emplace_back(pt.x(), pt.y(), z);
}
}
virtual Lines3 lines() const;
// Convert to 2D Polyline by dropping Z coordinates
Polyline to_polyline() const;
// Clip the end of the polyline by a distance
void clip_end(double distance);
// Simplify polyline using Douglas-Peucker algorithm
void simplify(double tolerance);
// Simplify by arc fitting (for ZAA arc fitting support)
void simplify_by_fitting_arc(double tolerance);
// Reverse the polyline
using MultiPoint3::reverse;
// Split polyline at given index
bool split_at_index(const size_t index, Polyline3 *p1, Polyline3 *p2) const;
// Split polyline at a given point (2D)
void split_at(Point &point, Polyline3* p1, Polyline3* p2) const;
// Split polyline at a given point (3D)
void split_at(Point3 &point, Polyline3* p1, Polyline3* p2) const;
// Split polyline at a given length
bool split_at_length(const double length, Polyline3 *p1, Polyline3 *p2) const;
// Append a single point
void append(const Point3& point);
// Append another Polyline3
void append(const Polyline3& src);
// Append before (prepend)
void append_before(const Point3& point);
// Arc fitting support - fitting_result stores arc path data
// This is populated by simplify_by_fitting_arc()
// Uses the global PathFittingData from ArcFitter.hpp
std::vector<PathFittingData> fitting_result;
private:
// Helper methods for split_at_index
bool split_fitting_result_before_index(size_t index, Point3 &new_endpoint, std::vector<PathFittingData> &result) const {
// Simplified stub - full implementation would handle arc fitting data
return false;
}
bool split_fitting_result_after_index(size_t index, Point3 &new_startpoint, std::vector<PathFittingData> &result) const {
// Simplified stub - full implementation would handle arc fitting data
return false;
}
};
typedef std::vector<Polyline3> Polylines3;