diff --git a/src/Movement/Kinematics/HangprinterKinematics.cpp b/src/Movement/Kinematics/HangprinterKinematics.cpp index 4c8e9efc58..f10ddab9ca 100644 --- a/src/Movement/Kinematics/HangprinterKinematics.cpp +++ b/src/Movement/Kinematics/HangprinterKinematics.cpp @@ -99,6 +99,7 @@ void HangprinterKinematics::Init() noexcept constexpr float DefaultTorqueConstants[HANGPRINTER_AXES] = { 0.0F }; ARRAY_INIT(anchors, DefaultAnchors); + anchorMode = HangprinterAnchorMode::LastOnTop; printRadius = DefaultPrintRadius; spoolBuildupFactor = DefaultSpoolBuildupFactor; ARRAY_INIT(spoolRadii, DefaultSpoolRadii); @@ -419,25 +420,51 @@ static bool isSameSide(float const v0[3], float const v1[3], float const v2[3], return dot0*dot1 > 0.0F; } -// For each triangle side in a pseudo-pyramid, check if the point is inside the pyramid (Except for the base) -// Also check that any point below the line between two exterior anchors (all anchors are exterior except for the last one) -// is in the "inside part" all the way down to min_Z, however low it may be. -// To further limit the movements in the X and Y axes one can simply set a smaller print radius. -bool HangprinterKinematics::IsReachable(float axesCoords[MaxAxes], AxesBitmap axes) const noexcept /*override*/ +bool HangprinterKinematics::IsInsidePyramidSides(float const coords[3]) const noexcept { - float const coords[3] = {axesCoords[X_AXIS], axesCoords[Y_AXIS], axesCoords[Z_AXIS]}; bool reachable = true; // Check all the planes defined by triangle sides in the pyramid for (size_t i = 0; reachable && i < HANGPRINTER_AXES - 1; ++i) { reachable = reachable && isSameSide(anchors[i], anchors[(i+1) % (HANGPRINTER_AXES - 1)], anchors[HANGPRINTER_AXES - 1], anchors[(i+2) % (HANGPRINTER_AXES - 1)], coords); } + return reachable; +} + +bool HangprinterKinematics::IsInsidePrismSides(float const coords[3], unsigned const discount_last) const noexcept +{ + bool reachable = true; // For each side of the base, check the plane formed by side and another point bellow them in z. - for (size_t i = 0; reachable && i < HANGPRINTER_AXES - 1; ++i) { + for (size_t i = 0; reachable && i < HANGPRINTER_AXES - discount_last; ++i) { float const lower_point[3] = {anchors[i][0], anchors[i][1], anchors[i][2] - 1}; reachable = reachable && isSameSide(anchors[i], anchors[(i+1) % (HANGPRINTER_AXES - 1)], lower_point, anchors[(i+2) % (HANGPRINTER_AXES - 1)], coords); } + return reachable; +} + +// For each triangle side in a pseudo-pyramid, check if the point is inside the pyramid (Except for the base) +// Also check that any point below the line between two exterior anchors (all anchors are exterior except for the last one) +// is in the "inside part" all the way down to min_Z, however low it may be. +// To further limit the movements in the X and Y axes one can simply set a smaller print radius. +bool HangprinterKinematics::IsReachable(float axesCoords[MaxAxes], AxesBitmap axes) const noexcept /*override*/ +{ + float const coords[3] = {axesCoords[X_AXIS], axesCoords[Y_AXIS], axesCoords[Z_AXIS]}; + bool reachable = true; + + switch (anchorMode) { + case HangprinterAnchorMode::None: + return true; + + // This reaches a pyramid on top of the lower prism if the bed is below the lower anchors + case HangprinterAnchorMode::LastOnTop: + default: + reachable = reachable && IsInsidePyramidSides(coords); + reachable = reachable && IsInsidePrismSides(coords, 1); + + case HangprinterAnchorMode::AllOnTop: + reachable = reachable && IsInsidePrismSides(coords, 0); + }; return reachable; } diff --git a/src/Movement/Kinematics/HangprinterKinematics.h b/src/Movement/Kinematics/HangprinterKinematics.h index 8280e73217..3db608e857 100644 --- a/src/Movement/Kinematics/HangprinterKinematics.h +++ b/src/Movement/Kinematics/HangprinterKinematics.h @@ -12,6 +12,13 @@ #if SUPPORT_HANGPRINTER +// Different modes can be configured for different tradeoffs in terms of printing volumes and speeds +enum class HangprinterAnchorMode { + None, // All is reacheable in None anchor mode as printing volume + LastOnTop, // (Default) Rsults in a pyramid plus a prism below if the lower anchors are above the printing bed + AllOnTop, // Result in a prism (speeds get limited, specially going down in Z) +}; + class HangprinterKinematics : public RoundBedKinematics { public: @@ -55,6 +62,9 @@ class HangprinterKinematics : public RoundBedKinematics protected: DECLARE_OBJECT_MODEL_WITH_ARRAYS + bool IsInsidePyramidSides(float const coords[3]) const noexcept; + bool IsInsidePrismSides(float const coords[3], unsigned const discount_last) const noexcept; + private: // Basic facts about movement system static constexpr size_t HANGPRINTER_AXES = 4; @@ -71,6 +81,7 @@ class HangprinterKinematics : public RoundBedKinematics void PrintParameters(const StringRef& reply) const noexcept; // Print all the parameters for debugging // The real defaults are in the cpp file + HangprinterAnchorMode anchorMode = HangprinterAnchorMode::LastOnTop; float printRadius = 0.0F; float anchors[HANGPRINTER_AXES][3] = {{ 0.0, 0.0, 0.0}, { 0.0, 0.0, 0.0},