Skip to content

Commit

Permalink
Fix crash when using tangent on angles with PI/2 value
Browse files Browse the repository at this point in the history
std::tan with a value of PI/2 works but return a huge number, which will
crash subsequent processings. A function has been added to process a
"safe tangent" calculation that return a big but not huge number.

CURA-11804
  • Loading branch information
wawanbreton committed Jul 2, 2024
1 parent 4f6207a commit 8ba57ad
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 7 deletions.
13 changes: 13 additions & 0 deletions include/settings/types/Angle.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,19 @@ inline AngleRadians::AngleRadians(const AngleDegrees& value)
{
}

/*!
* \brief Safe call to "std::tan" which limits the higher angle value to something slightly less that π/2 so that when
* the given angle is higher that this value, the returned value is not a huge number
* \param angle The input angle, which should be [0, π/2]
* \return The tangent value of the angle, limited
* \note This method exists as a convenience because this is a common case in the engine, as we have many settings that
* are angles setup on [0, π/2] and which translate to a distance
*/
inline double boundedTan(const AngleRadians& angle)
{
return std::tan(std::min(static_cast<double>(angle), std::numbers::pi / 2.0 - 0.001));
}

} // namespace cura

#endif // ANGLE_H
14 changes: 7 additions & 7 deletions src/support.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -471,11 +471,11 @@ Shape AreaSupport::join(const SliceDataStorage& storage, const Shape& supportLay
coord_t conical_support_offset;
if (conical_support_angle > 0)
{ // outward ==> wider base than overhang
conical_support_offset = -(tan(conical_support_angle) - 0.01) * layer_thickness;
conical_support_offset = -boundedTan(conical_support_angle) * layer_thickness;
}
else
{ // inward ==> smaller base than overhang
conical_support_offset = (tan(-conical_support_angle) - 0.01) * layer_thickness;
conical_support_offset = boundedTan(-conical_support_angle) * layer_thickness;
}
const bool conical_support = infill_settings.get<bool>("support_conical_enabled") && conical_support_angle != 0;
if (conical_support)
Expand Down Expand Up @@ -888,7 +888,7 @@ Shape AreaSupport::generateVaryingXYDisallowedArea(const SliceMeshStorage& stora
const auto support_distance = z_delta_poly.support_distance;
const auto delta_z = z_delta_poly.delta_z;
const auto layer_delta = z_delta_poly.layer_delta;
const auto xy_distance_natural = support_distance * std::tan(overhang_angle);
const auto xy_distance_natural = support_distance * boundedTan(overhang_angle);

for (auto [current_poly_idx, current_poly] : layer_current | ranges::views::enumerate)
{
Expand Down Expand Up @@ -1244,11 +1244,11 @@ void AreaSupport::generateSupportAreasForMesh(
coord_t conical_support_offset;
if (conical_support_angle > 0)
{ // outward ==> wider base than overhang
conical_support_offset = -(tan(conical_support_angle) - 0.01) * layer_thickness;
conical_support_offset = -boundedTan(conical_support_angle) * layer_thickness;
}
else
{ // inward ==> smaller base than overhang
conical_support_offset = (tan(-conical_support_angle) - 0.01) * layer_thickness;
conical_support_offset = boundedTan(-conical_support_angle) * layer_thickness;
}
const bool conical_support = infill_settings.get<bool>("support_conical_enabled") && conical_support_angle != 0;
for (LayerIndex layer_idx = 1; layer_idx < storage.support.supportLayers.size(); layer_idx++)
Expand Down Expand Up @@ -1447,7 +1447,7 @@ std::pair<Shape, Shape> AreaSupport::computeBasicAndFullOverhang(const SliceData

const coord_t layer_height = mesh.settings.get<coord_t>("layer_height");
const AngleRadians support_angle = mesh.settings.get<AngleRadians>("support_angle");
const double tan_angle = tan(support_angle) - 0.01; // The X/Y component of the support angle. 0.01 to make 90 degrees work too.
const double tan_angle = boundedTan(support_angle); // The X/Y component of the support angle
// overhang areas protruding less then `max_dist_from_lower_layer` don't need support
const coord_t max_dist_from_lower_layer = tan_angle * layer_height; // Maximum horizontal distance that can be bridged.

Expand Down Expand Up @@ -1576,7 +1576,7 @@ void AreaSupport::handleTowers(
}
else
{
const double tan_tower_roof_angle = tan(tower_roof_angle);
const double tan_tower_roof_angle = boundedTan(tower_roof_angle);
tower_roof_expansion_distance = layer_thickness / tan_tower_roof_angle;
}

Expand Down

0 comments on commit 8ba57ad

Please sign in to comment.