mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-15 02:37:51 -06:00
ENH: improve hybrid tree support
1. do not add interface for small overhangs so supports are easier to remove 2. calculate avoidance more accurately using real layer height jira: STUDIO-6285 3. hybrid nodes won't collide with lower layers 4. calculate max move more accurately 5. do not increase radius if next layer has collision jira: STUDIO-2296, STUDIO-7883 6. rewrite plan_layer_heights to prevent support layers overlap. Now the tree support layers are completely independent to object layers. 6. increase collision areas for interface. The top layers may be too close to interface with adaptive layer heights and very small overhang angle Change-Id: I052c3f66e68afb7663e2d70c846dd09ed7086071 (cherry picked from commit aca511caebfdeec270d4fc0ec6bbbadde77cddc9) (cherry picked from commit f2fc996652b3b204b4e554f57afed8519feb0397)
This commit is contained in:
parent
532dcae37a
commit
5054ee8508
5 changed files with 479 additions and 425 deletions
|
@ -845,14 +845,8 @@ void PrintObject::clear_support_layers()
|
||||||
std::shared_ptr<TreeSupportData> PrintObject::alloc_tree_support_preview_cache()
|
std::shared_ptr<TreeSupportData> PrintObject::alloc_tree_support_preview_cache()
|
||||||
{
|
{
|
||||||
if (!m_tree_support_preview_cache) {
|
if (!m_tree_support_preview_cache) {
|
||||||
const coordf_t layer_height = m_config.layer_height.value;
|
|
||||||
const coordf_t xy_distance = m_config.support_object_xy_distance.value;
|
const coordf_t xy_distance = m_config.support_object_xy_distance.value;
|
||||||
const double angle = m_config.tree_support_branch_angle.value * M_PI / 180.;
|
m_tree_support_preview_cache = std::make_shared<TreeSupportData>(*this, xy_distance, g_config_tree_support_collision_resolution);
|
||||||
const coordf_t max_move_distance
|
|
||||||
= (angle < M_PI / 2) ? (coordf_t)(tan(angle) * layer_height) : std::numeric_limits<coordf_t>::max();
|
|
||||||
const coordf_t radius_sample_resolution = g_config_tree_support_collision_resolution;
|
|
||||||
|
|
||||||
m_tree_support_preview_cache = std::make_shared<TreeSupportData>(*this, xy_distance, max_move_distance, radius_sample_resolution);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_tree_support_preview_cache;
|
return m_tree_support_preview_cache;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -28,9 +28,9 @@ struct LayerHeightData
|
||||||
{
|
{
|
||||||
coordf_t print_z = 0;
|
coordf_t print_z = 0;
|
||||||
coordf_t height = 0;
|
coordf_t height = 0;
|
||||||
size_t next_layer_nr = 0;
|
size_t obj_layer_nr = 0;
|
||||||
LayerHeightData() = default;
|
LayerHeightData() = default;
|
||||||
LayerHeightData(coordf_t z, coordf_t h, size_t next_layer) : print_z(z), height(h), next_layer_nr(next_layer) {}
|
LayerHeightData(coordf_t z, coordf_t h, size_t obj_layer) : print_z(z), height(h), obj_layer_nr(obj_layer) {}
|
||||||
coordf_t bottom_z() {
|
coordf_t bottom_z() {
|
||||||
return print_z - height;
|
return print_z - height;
|
||||||
}
|
}
|
||||||
|
@ -202,7 +202,7 @@ public:
|
||||||
* \param radius_sample_resolution Sample size used to round requested node radii.
|
* \param radius_sample_resolution Sample size used to round requested node radii.
|
||||||
* \param collision_resolution
|
* \param collision_resolution
|
||||||
*/
|
*/
|
||||||
TreeSupportData(const PrintObject& object, coordf_t max_move, coordf_t radius_sample_resolution, coordf_t collision_resolution);
|
TreeSupportData(const PrintObject& object, coordf_t radius_sample_resolution, coordf_t collision_resolution);
|
||||||
~TreeSupportData() {
|
~TreeSupportData() {
|
||||||
clear_nodes();
|
clear_nodes();
|
||||||
}
|
}
|
||||||
|
@ -305,11 +305,7 @@ public:
|
||||||
*/
|
*/
|
||||||
coordf_t m_xy_distance;
|
coordf_t m_xy_distance;
|
||||||
|
|
||||||
/*!
|
double branch_scale_factor = 1.0; // tan(45 degrees)
|
||||||
* \brief The maximum distance that the centrepoint of a tree branch may
|
|
||||||
* move in consequtive layers
|
|
||||||
*/
|
|
||||||
coordf_t m_max_move;
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Sample resolution for radius values.
|
* \brief Sample resolution for radius values.
|
||||||
|
@ -328,6 +324,8 @@ public:
|
||||||
// union contours of all layers below
|
// union contours of all layers below
|
||||||
std::vector<ExPolygons> m_layer_outlines_below;
|
std::vector<ExPolygons> m_layer_outlines_below;
|
||||||
|
|
||||||
|
std::vector<double> m_max_move_distances;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Caches for the collision, avoidance and internal model polygons
|
* \brief Caches for the collision, avoidance and internal model polygons
|
||||||
* at given radius and layer indices.
|
* at given radius and layer indices.
|
||||||
|
@ -366,6 +364,10 @@ public:
|
||||||
*/
|
*/
|
||||||
TreeSupport(PrintObject& object, const SlicingParameters &slicing_params);
|
TreeSupport(PrintObject& object, const SlicingParameters &slicing_params);
|
||||||
|
|
||||||
|
void move_bounds_to_contact_nodes(std::vector<TreeSupport3D::SupportElements> &move_bounds,
|
||||||
|
PrintObject &print_object,
|
||||||
|
const TreeSupport3D::TreeSupportSettings &config);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Create the areas that need support.
|
* \brief Create the areas that need support.
|
||||||
*
|
*
|
||||||
|
@ -377,6 +379,19 @@ public:
|
||||||
|
|
||||||
void detect_overhangs(bool check_support_necessity = false);
|
void detect_overhangs(bool check_support_necessity = false);
|
||||||
|
|
||||||
|
SupportNode* create_node(const Point position,
|
||||||
|
const int distance_to_top,
|
||||||
|
const int obj_layer_nr,
|
||||||
|
const int support_roof_layers_below,
|
||||||
|
const bool to_buildplate,
|
||||||
|
SupportNode* parent,
|
||||||
|
coordf_t print_z_,
|
||||||
|
coordf_t height_,
|
||||||
|
coordf_t dist_mm_to_top_ = 0,
|
||||||
|
coordf_t radius_ = 0)
|
||||||
|
{
|
||||||
|
return m_ts_data->create_node(position, distance_to_top, obj_layer_nr, support_roof_layers_below, to_buildplate, parent, print_z_, height_, dist_mm_to_top_, radius_);
|
||||||
|
}
|
||||||
|
|
||||||
int avg_node_per_layer = 0;
|
int avg_node_per_layer = 0;
|
||||||
float nodes_angle = 0;
|
float nodes_angle = 0;
|
||||||
|
@ -419,12 +434,17 @@ private:
|
||||||
std::vector< std::unordered_map<Line, bool, LineHash>> m_mst_line_x_layer_contour_caches;
|
std::vector< std::unordered_map<Line, bool, LineHash>> m_mst_line_x_layer_contour_caches;
|
||||||
|
|
||||||
float DO_NOT_MOVER_UNDER_MM = 0.0;
|
float DO_NOT_MOVER_UNDER_MM = 0.0;
|
||||||
coordf_t MAX_BRANCH_RADIUS = 10.0;
|
coordf_t base_radius = 0.0;
|
||||||
coordf_t MIN_BRANCH_RADIUS = 0.5;
|
const coordf_t MAX_BRANCH_RADIUS = 10.0;
|
||||||
coordf_t MAX_BRANCH_RADIUS_FIRST_LAYER = 12.0;
|
const coordf_t MIN_BRANCH_RADIUS = 0.4;
|
||||||
coordf_t MIN_BRANCH_RADIUS_FIRST_LAYER = 2.0;
|
const coordf_t MAX_BRANCH_RADIUS_FIRST_LAYER = 12.0;
|
||||||
float tree_support_branch_diameter_angle = 5.0;
|
const coordf_t MIN_BRANCH_RADIUS_FIRST_LAYER = 2.0;
|
||||||
coord_t m_min_radius = scale_(1); // in mm
|
const double tree_support_branch_diameter_angle = 5.0;
|
||||||
|
const double diameter_angle_scale_factor = tan(tree_support_branch_diameter_angle*M_PI/180.0);
|
||||||
|
// minimum roof area (1 mm^2), area smaller than this value will not have interface
|
||||||
|
const double minimum_roof_area{SQ(scaled<double>(1.))};
|
||||||
|
float top_z_distance = 0.0;
|
||||||
|
|
||||||
bool is_strong = false;
|
bool is_strong = false;
|
||||||
bool is_slim = false;
|
bool is_slim = false;
|
||||||
bool with_infill = false;
|
bool with_infill = false;
|
||||||
|
@ -492,8 +512,10 @@ private:
|
||||||
coordf_t calc_branch_radius(coordf_t base_radius, size_t layers_to_top, size_t tip_layers, double diameter_angle_scale_factor);
|
coordf_t calc_branch_radius(coordf_t base_radius, size_t layers_to_top, size_t tip_layers, double diameter_angle_scale_factor);
|
||||||
// get unscaled radius(mm) of node based on the distance mm to top
|
// get unscaled radius(mm) of node based on the distance mm to top
|
||||||
coordf_t calc_branch_radius(coordf_t base_radius, coordf_t mm_to_top, double diameter_angle_scale_factor, bool use_min_distance=true);
|
coordf_t calc_branch_radius(coordf_t base_radius, coordf_t mm_to_top, double diameter_angle_scale_factor, bool use_min_distance=true);
|
||||||
coordf_t get_radius(const SupportNode* node, coordf_t base_radius);
|
coordf_t calc_radius(coordf_t mm_to_top);
|
||||||
|
coordf_t get_radius(const SupportNode* node);
|
||||||
ExPolygons get_avoidance(coordf_t radius, size_t obj_layer_nr);
|
ExPolygons get_avoidance(coordf_t radius, size_t obj_layer_nr);
|
||||||
|
// layer's expolygon expanded by radius+m_xy_distance
|
||||||
ExPolygons get_collision(coordf_t radius, size_t layer_nr);
|
ExPolygons get_collision(coordf_t radius, size_t layer_nr);
|
||||||
// get Polygons instead of ExPolygons
|
// get Polygons instead of ExPolygons
|
||||||
Polygons get_collision_polys(coordf_t radius, size_t layer_nr);
|
Polygons get_collision_polys(coordf_t radius, size_t layer_nr);
|
||||||
|
|
|
@ -68,28 +68,28 @@ using namespace std::literals;
|
||||||
static inline void validate_range(const Point &pt)
|
static inline void validate_range(const Point &pt)
|
||||||
{
|
{
|
||||||
static constexpr const int32_t hi = 65536 * 16384;
|
static constexpr const int32_t hi = 65536 * 16384;
|
||||||
if (pt.x() > hi || pt.y() > hi || -pt.x() > hi || -pt.y() > hi)
|
if (pt.x() > hi || pt.y() > hi || -pt.x() > hi || -pt.y() > hi)
|
||||||
throw ClipperLib::clipperException("Coordinate outside allowed range");
|
throw ClipperLib::clipperException("Coordinate outside allowed range");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void validate_range(const Points &points)
|
static inline void validate_range(const Points &points)
|
||||||
{
|
{
|
||||||
for (const Point &p : points)
|
for (const Point &p : points)
|
||||||
validate_range(p);
|
validate_range(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void validate_range(const MultiPoint &mp)
|
static inline void validate_range(const MultiPoint &mp)
|
||||||
{
|
{
|
||||||
validate_range(mp.points);
|
validate_range(mp.points);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void validate_range(const Polygons &polygons)
|
static inline void validate_range(const Polygons &polygons)
|
||||||
{
|
{
|
||||||
for (const Polygon &p : polygons)
|
for (const Polygon &p : polygons)
|
||||||
validate_range(p);
|
validate_range(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void validate_range(const Polylines &polylines)
|
static inline void validate_range(const Polylines &polylines)
|
||||||
{
|
{
|
||||||
for (const Polyline &p : polylines)
|
for (const Polyline &p : polylines)
|
||||||
validate_range(p);
|
validate_range(p);
|
||||||
|
@ -136,7 +136,7 @@ static std::vector<std::pair<TreeSupportSettings, std::vector<size_t>>> group_me
|
||||||
|
|
||||||
size_t largest_printed_mesh_idx = 0;
|
size_t largest_printed_mesh_idx = 0;
|
||||||
|
|
||||||
// Group all meshes that can be processed together. NOTE this is different from mesh-groups! Only one setting object is needed per group,
|
// Group all meshes that can be processed together. NOTE this is different from mesh-groups! Only one setting object is needed per group,
|
||||||
// as different settings in the same group may only occur in the tip, which uses the original settings objects from the meshes.
|
// as different settings in the same group may only occur in the tip, which uses the original settings objects from the meshes.
|
||||||
for (size_t object_id : print_object_ids) {
|
for (size_t object_id : print_object_ids) {
|
||||||
const PrintObject &print_object = *print.get_object(object_id);
|
const PrintObject &print_object = *print.get_object(object_id);
|
||||||
|
@ -228,7 +228,7 @@ static std::vector<std::pair<TreeSupportSettings, std::vector<size_t>>> group_me
|
||||||
|
|
||||||
size_t num_overhang_layers = support_auto ? num_object_layers : std::min(num_object_layers, std::max(size_t(support_enforce_layers), enforcers_layers.size()));
|
size_t num_overhang_layers = support_auto ? num_object_layers : std::min(num_object_layers, std::max(size_t(support_enforce_layers), enforcers_layers.size()));
|
||||||
tbb::parallel_for(tbb::blocked_range<LayerIndex>(1, num_overhang_layers),
|
tbb::parallel_for(tbb::blocked_range<LayerIndex>(1, num_overhang_layers),
|
||||||
[&print_object, &config, &print_config, &enforcers_layers, &blockers_layers,
|
[&print_object, &config, &print_config, &enforcers_layers, &blockers_layers,
|
||||||
support_auto, support_enforce_layers, support_threshold_auto, tan_threshold, enforcer_overhang_offset, num_raft_layers, radius_sample_resolution, &throw_on_cancel, &out]
|
support_auto, support_enforce_layers, support_threshold_auto, tan_threshold, enforcer_overhang_offset, num_raft_layers, radius_sample_resolution, &throw_on_cancel, &out]
|
||||||
(const tbb::blocked_range<LayerIndex> &range) {
|
(const tbb::blocked_range<LayerIndex> &range) {
|
||||||
for (LayerIndex layer_id = range.begin(); layer_id < range.end(); ++ layer_id) {
|
for (LayerIndex layer_id = range.begin(); layer_id < range.end(); ++ layer_id) {
|
||||||
|
@ -263,7 +263,7 @@ static std::vector<std::pair<TreeSupportSettings, std::vector<size_t>>> group_me
|
||||||
overhangs = diff(overhangs, offset_ex(union_(blockers_layers[layer_id]), scale_(radius_sample_resolution)), ApplySafetyOffset::Yes);
|
overhangs = diff(overhangs, offset_ex(union_(blockers_layers[layer_id]), scale_(radius_sample_resolution)), ApplySafetyOffset::Yes);
|
||||||
if (config.bridge_no_support) {
|
if (config.bridge_no_support) {
|
||||||
for (const LayerRegion *layerm : current_layer.regions())
|
for (const LayerRegion *layerm : current_layer.regions())
|
||||||
remove_bridges_from_contacts(print_config, lower_layer, *layerm,
|
remove_bridges_from_contacts(print_config, lower_layer, *layerm,
|
||||||
float(layerm->flow(frExternalPerimeter).scaled_width()), overhangs);
|
float(layerm->flow(frExternalPerimeter).scaled_width()), overhangs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -284,7 +284,7 @@ static std::vector<std::pair<TreeSupportSettings, std::vector<size_t>>> group_me
|
||||||
enforced_overhangs = diff(offset(union_ex(enforced_overhangs), enforcer_overhang_offset),
|
enforced_overhangs = diff(offset(union_ex(enforced_overhangs), enforcer_overhang_offset),
|
||||||
lower_layer.lslices);
|
lower_layer.lslices);
|
||||||
#ifdef TREESUPPORT_DEBUG_SVG
|
#ifdef TREESUPPORT_DEBUG_SVG
|
||||||
// if (! intersecting_edges(enforced_overhangs).empty())
|
// if (! intersecting_edges(enforced_overhangs).empty())
|
||||||
{
|
{
|
||||||
static int irun = 0;
|
static int irun = 0;
|
||||||
SVG::export_expolygons(debug_out_path("treesupport-self-intersections-%d.svg", ++irun),
|
SVG::export_expolygons(debug_out_path("treesupport-self-intersections-%d.svg", ++irun),
|
||||||
|
@ -297,7 +297,7 @@ static std::vector<std::pair<TreeSupportSettings, std::vector<size_t>>> group_me
|
||||||
overhangs = overhangs.empty() ? std::move(enforced_overhangs) : union_(overhangs, enforced_overhangs);
|
overhangs = overhangs.empty() ? std::move(enforced_overhangs) : union_(overhangs, enforced_overhangs);
|
||||||
//check_self_intersections(overhangs, "generate_overhangs - enforcers");
|
//check_self_intersections(overhangs, "generate_overhangs - enforcers");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out[layer_id + num_raft_layers] = std::move(overhangs);
|
out[layer_id + num_raft_layers] = std::move(overhangs);
|
||||||
throw_on_cancel();
|
throw_on_cancel();
|
||||||
}
|
}
|
||||||
|
@ -460,7 +460,7 @@ static std::vector<std::pair<TreeSupportSettings, std::vector<size_t>>> group_me
|
||||||
return true;
|
return true;
|
||||||
if (config.support_rests_on_model && (p.second != LineStatus::TO_BP && p.second != LineStatus::TO_BP_SAFE))
|
if (config.support_rests_on_model && (p.second != LineStatus::TO_BP && p.second != LineStatus::TO_BP_SAFE))
|
||||||
return ! contains(
|
return ! contains(
|
||||||
p.second == LineStatus::TO_MODEL_GRACIOUS || p.second == LineStatus::TO_MODEL_GRACIOUS_SAFE ?
|
p.second == LineStatus::TO_MODEL_GRACIOUS || p.second == LineStatus::TO_MODEL_GRACIOUS_SAFE ?
|
||||||
volumes.getAvoidance(config.getRadius(0), current_layer - 1, p.second == LineStatus::TO_MODEL_GRACIOUS_SAFE ? AvoidanceType::FastSafe : AvoidanceType::Fast, true, min_xy_dist) :
|
volumes.getAvoidance(config.getRadius(0), current_layer - 1, p.second == LineStatus::TO_MODEL_GRACIOUS_SAFE ? AvoidanceType::FastSafe : AvoidanceType::Fast, true, min_xy_dist) :
|
||||||
volumes.getCollision(config.getRadius(0), current_layer - 1, min_xy_dist),
|
volumes.getCollision(config.getRadius(0), current_layer - 1, min_xy_dist),
|
||||||
p.first);
|
p.first);
|
||||||
|
@ -532,7 +532,7 @@ static std::optional<std::pair<Point, size_t>> polyline_sample_next_point_at_dis
|
||||||
// Squared distance of "start_pt" from the ray (p0, p1).
|
// Squared distance of "start_pt" from the ray (p0, p1).
|
||||||
double l2_from_line = xf.squaredNorm();
|
double l2_from_line = xf.squaredNorm();
|
||||||
// Squared distance of an intersection point of a circle with center at the foot point.
|
// Squared distance of an intersection point of a circle with center at the foot point.
|
||||||
if (double l2_intersection = dist2 - l2_from_line;
|
if (double l2_intersection = dist2 - l2_from_line;
|
||||||
l2_intersection > - SCALED_EPSILON) {
|
l2_intersection > - SCALED_EPSILON) {
|
||||||
// The ray (p0, p1) touches or intersects a circle centered at "start_pt" with radius "dist".
|
// The ray (p0, p1) touches or intersects a circle centered at "start_pt" with radius "dist".
|
||||||
// Distance of the circle intersection point from the foot point.
|
// Distance of the circle intersection point from the foot point.
|
||||||
|
@ -627,7 +627,7 @@ static std::optional<std::pair<Point, size_t>> polyline_sample_next_point_at_dis
|
||||||
} else {
|
} else {
|
||||||
if (current_point == next_point->first) {
|
if (current_point == next_point->first) {
|
||||||
// In case a fixpoint is encountered, better aggressively overcompensate so the code does not become stuck here...
|
// In case a fixpoint is encountered, better aggressively overcompensate so the code does not become stuck here...
|
||||||
BOOST_LOG_TRIVIAL(warning) << "Tree Support: Encountered a fixpoint in polyline_sample_next_point_at_distance. This is expected to happen if the distance (currently " << next_distance <<
|
BOOST_LOG_TRIVIAL(warning) << "Tree Support: Encountered a fixpoint in polyline_sample_next_point_at_distance. This is expected to happen if the distance (currently " << next_distance <<
|
||||||
") is smaller than 100";
|
") is smaller than 100";
|
||||||
tree_supports_show_error("Encountered issue while placing tips. Some tips may be missing."sv, true);
|
tree_supports_show_error("Encountered issue while placing tips. Some tips may be missing."sv, true);
|
||||||
if (next_distance > 2 * current_distance)
|
if (next_distance > 2 * current_distance)
|
||||||
|
@ -693,9 +693,9 @@ static std::optional<std::pair<Point, size_t>> polyline_sample_next_point_at_dis
|
||||||
int divisor = static_cast<int>(angles.size());
|
int divisor = static_cast<int>(angles.size());
|
||||||
int index = ((layer_idx % divisor) + divisor) % divisor;
|
int index = ((layer_idx % divisor) + divisor) % divisor;
|
||||||
const AngleRadians fill_angle = angles[index];
|
const AngleRadians fill_angle = angles[index];
|
||||||
Infill roof_computation(pattern, true /* zig_zaggify_infill */, connect_polygons, polygon,
|
Infill roof_computation(pattern, true /* zig_zaggify_infill */, connect_polygons, polygon,
|
||||||
roof ? config.support_roof_line_width : config.support_line_width, support_infill_distance, support_roof_overlap, infill_multiplier,
|
roof ? config.support_roof_line_width : config.support_line_width, support_infill_distance, support_roof_overlap, infill_multiplier,
|
||||||
fill_angle, z, support_shift, config.resolution, wall_line_count, infill_origin,
|
fill_angle, z, support_shift, config.resolution, wall_line_count, infill_origin,
|
||||||
perimeter_gaps, connected_zigzags, use_endpieces, false /* skip_some_zags */, zag_skip_count, pocket_size);
|
perimeter_gaps, connected_zigzags, use_endpieces, false /* skip_some_zags */, zag_skip_count, pocket_size);
|
||||||
Polygons polygons;
|
Polygons polygons;
|
||||||
Polygons lines;
|
Polygons lines;
|
||||||
|
@ -712,7 +712,7 @@ static std::optional<std::pair<Point, size_t>> polyline_sample_next_point_at_dis
|
||||||
|
|
||||||
filler->layer_id = layer_idx;
|
filler->layer_id = layer_idx;
|
||||||
filler->spacing = flow.spacing();
|
filler->spacing = flow.spacing();
|
||||||
filler->angle = roof ?
|
filler->angle = roof ?
|
||||||
//fixme support_layer.interface_id() instead of layer_idx
|
//fixme support_layer.interface_id() instead of layer_idx
|
||||||
(support_params.interface_angle + (layer_idx & 1) ? float(- M_PI / 4.) : float(+ M_PI / 4.)) :
|
(support_params.interface_angle + (layer_idx & 1) ? float(- M_PI / 4.) : float(+ M_PI / 4.)) :
|
||||||
support_params.base_angle;
|
support_params.base_angle;
|
||||||
|
@ -783,7 +783,7 @@ static std::optional<std::pair<Point, size_t>> polyline_sample_next_point_at_dis
|
||||||
result = union_(offset(to_polylines(first), scaled<float>(0.002), jtMiter, 1.2), offset(to_polylines(second), scaled<float>(0.002), jtMiter, 1.2));
|
result = union_(offset(to_polylines(first), scaled<float>(0.002), jtMiter, 1.2), offset(to_polylines(second), scaled<float>(0.002), jtMiter, 1.2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -800,7 +800,7 @@ static std::optional<std::pair<Point, size_t>> polyline_sample_next_point_at_dis
|
||||||
{
|
{
|
||||||
bool do_final_difference = last_step_offset_without_check == 0;
|
bool do_final_difference = last_step_offset_without_check == 0;
|
||||||
Polygons ret = safe_union(me); // ensure sane input
|
Polygons ret = safe_union(me); // ensure sane input
|
||||||
|
|
||||||
// Trim the collision polygons with the region of interest for diff() efficiency.
|
// Trim the collision polygons with the region of interest for diff() efficiency.
|
||||||
Polygons collision_trimmed_buffer;
|
Polygons collision_trimmed_buffer;
|
||||||
auto collision_trimmed = [&collision_trimmed_buffer, &collision, &ret, distance]() -> const Polygons& {
|
auto collision_trimmed = [&collision_trimmed_buffer, &collision, &ret, distance]() -> const Polygons& {
|
||||||
|
@ -882,7 +882,7 @@ public:
|
||||||
// called by sample_overhang_area()
|
// called by sample_overhang_area()
|
||||||
void add_points_along_lines(
|
void add_points_along_lines(
|
||||||
// Insert points (tree tips or top contact interfaces) along these lines.
|
// Insert points (tree tips or top contact interfaces) along these lines.
|
||||||
LineInformations lines,
|
LineInformations lines,
|
||||||
// Start at this layer.
|
// Start at this layer.
|
||||||
LayerIndex insert_layer_idx,
|
LayerIndex insert_layer_idx,
|
||||||
// Insert this number of interface layers.
|
// Insert this number of interface layers.
|
||||||
|
@ -922,7 +922,7 @@ public:
|
||||||
// add all points that would not be valid
|
// add all points that would not be valid
|
||||||
for (const LineInformation &line : points)
|
for (const LineInformation &line : points)
|
||||||
for (const std::pair<Point, LineStatus> &point_data : line)
|
for (const std::pair<Point, LineStatus> &point_data : line)
|
||||||
add_point_as_influence_area(point_data, this_layer_idx,
|
add_point_as_influence_area(point_data, this_layer_idx,
|
||||||
// don't move until
|
// don't move until
|
||||||
roof_tip_layers - dtt_roof_tip,
|
roof_tip_layers - dtt_roof_tip,
|
||||||
// supports roof
|
// supports roof
|
||||||
|
@ -1009,7 +1009,7 @@ private:
|
||||||
// Temps
|
// Temps
|
||||||
coord_t m_base_radius;
|
coord_t m_base_radius;
|
||||||
Polygon m_base_circle;
|
Polygon m_base_circle;
|
||||||
|
|
||||||
// Mutexes, guards
|
// Mutexes, guards
|
||||||
std::mutex m_mutex_movebounds;
|
std::mutex m_mutex_movebounds;
|
||||||
std::vector<std::unordered_set<Point, PointHash>> m_already_inserted;
|
std::vector<std::unordered_set<Point, PointHash>> m_already_inserted;
|
||||||
|
@ -1093,10 +1093,10 @@ void finalize_raft_contact(
|
||||||
// Produce
|
// Produce
|
||||||
// 1) Maximum num_support_roof_layers roof (top interface & contact) layers.
|
// 1) Maximum num_support_roof_layers roof (top interface & contact) layers.
|
||||||
// 2) Tree tips supporting either the roof layers or the object itself.
|
// 2) Tree tips supporting either the roof layers or the object itself.
|
||||||
// num_support_roof_layers should always be respected:
|
// num_support_roof_layers should always be respected:
|
||||||
// If num_support_roof_layers contact layers could not be produced, then the tree tip
|
// If num_support_roof_layers contact layers could not be produced, then the tree tip
|
||||||
// is augmented with SupportElementState::missing_roof_layers
|
// is augmented with SupportElementState::missing_roof_layers
|
||||||
// and the top "missing_roof_layers" of such particular tree tips are supposed to be coverted to
|
// and the top "missing_roof_layers" of such particular tree tips are supposed to be coverted to
|
||||||
// roofs aka interface layers by the tool path generator.
|
// roofs aka interface layers by the tool path generator.
|
||||||
void sample_overhang_area(
|
void sample_overhang_area(
|
||||||
// Area to support
|
// Area to support
|
||||||
|
@ -1108,18 +1108,18 @@ void sample_overhang_area(
|
||||||
const size_t layer_idx,
|
const size_t layer_idx,
|
||||||
// Maximum number of roof (contact, interface) layers between the overhang and tree tips to be generated.
|
// Maximum number of roof (contact, interface) layers between the overhang and tree tips to be generated.
|
||||||
const size_t num_support_roof_layers,
|
const size_t num_support_roof_layers,
|
||||||
//
|
//
|
||||||
const coord_t connect_length,
|
const coord_t connect_length,
|
||||||
// Configuration classes
|
// Configuration classes
|
||||||
const TreeSupportMeshGroupSettings &mesh_group_settings,
|
const TreeSupportMeshGroupSettings& mesh_group_settings,
|
||||||
// Configuration & Output
|
// Configuration & Output
|
||||||
RichInterfacePlacer &interface_placer)
|
RichInterfacePlacer& interface_placer)
|
||||||
{
|
{
|
||||||
// Assumption is that roof will support roof further up to avoid a lot of unnecessary branches. Each layer down it is checked whether the roof area
|
// Assumption is that roof will support roof further up to avoid a lot of unnecessary branches. Each layer down it is checked whether the roof area
|
||||||
// is still large enough to be a roof and aborted as soon as it is not. This part was already reworked a few times, and there could be an argument
|
// is still large enough to be a roof and aborted as soon as it is not. This part was already reworked a few times, and there could be an argument
|
||||||
// made to change it again if there are actual issues encountered regarding supporting roofs.
|
// made to change it again if there are actual issues encountered regarding supporting roofs.
|
||||||
// Main problem is that some patterns change each layer, so just calculating points and checking if they are still valid an layer below is not useful,
|
// Main problem is that some patterns change each layer, so just calculating points and checking if they are still valid an layer below is not useful,
|
||||||
// as the pattern may be different one layer below. Same with calculating which points are now no longer being generated as result from
|
// as the pattern may be different one layer below. Same with calculating which points are now no longer being generated as result from
|
||||||
// a decreasing roof, as there is no guarantee that a line will be above these points. Implementing a separate roof support behavior
|
// a decreasing roof, as there is no guarantee that a line will be above these points. Implementing a separate roof support behavior
|
||||||
// for each pattern harms maintainability as it very well could be >100 LOC
|
// for each pattern harms maintainability as it very well could be >100 LOC
|
||||||
auto generate_roof_lines = [&interface_placer, &mesh_group_settings](const Polygons &area, LayerIndex layer_idx) -> Polylines {
|
auto generate_roof_lines = [&interface_placer, &mesh_group_settings](const Polygons &area, LayerIndex layer_idx) -> Polylines {
|
||||||
|
@ -1186,10 +1186,10 @@ void sample_overhang_area(
|
||||||
|
|
||||||
if (overhang_lines.empty()) {
|
if (overhang_lines.empty()) {
|
||||||
// support_line_width to form a line here as otherwise most will be unsupported. Technically this violates branch distance, but not only is this the only reasonable choice,
|
// support_line_width to form a line here as otherwise most will be unsupported. Technically this violates branch distance, but not only is this the only reasonable choice,
|
||||||
// but it ensures consistant behaviour as some infill patterns generate each line segment as its own polyline part causing a similar line forming behaviour.
|
// but it ensures consistant behaviour as some infill patterns generate each line segment as its own polyline part causing a similar line forming behaviour.
|
||||||
// This is not doen when a roof is above as the roof will support the model and the trees only need to support the roof
|
// This is not doen when a roof is above as the roof will support the model and the trees only need to support the roof
|
||||||
bool supports_roof = dtt_roof > 0;
|
bool supports_roof = dtt_roof > 0;
|
||||||
bool continuous_tips = ! supports_roof && large_horizontal_roof;
|
bool continuous_tips = !supports_roof && large_horizontal_roof;
|
||||||
Polylines polylines = ensure_maximum_distance_polyline(
|
Polylines polylines = ensure_maximum_distance_polyline(
|
||||||
generate_support_infill_lines(overhang_area, interface_placer.support_parameters, supports_roof, layer_idx - layer_generation_dtt,
|
generate_support_infill_lines(overhang_area, interface_placer.support_parameters, supports_roof, layer_idx - layer_generation_dtt,
|
||||||
supports_roof ? mesh_group_settings.support_roof_line_distance : mesh_group_settings.support_tree_branch_distance),
|
supports_roof ? mesh_group_settings.support_roof_line_distance : mesh_group_settings.support_tree_branch_distance),
|
||||||
|
@ -1200,10 +1200,10 @@ void sample_overhang_area(
|
||||||
const size_t min_support_points = std::max(coord_t(1), std::min(coord_t(3), coord_t(total_length(overhang_area) / connect_length)));
|
const size_t min_support_points = std::max(coord_t(1), std::min(coord_t(3), coord_t(total_length(overhang_area) / connect_length)));
|
||||||
if (point_count <= min_support_points) {
|
if (point_count <= min_support_points) {
|
||||||
// add the outer wall (of the overhang) to ensure it is correct supported instead. Try placing the support points in a way that they fully support the outer wall, instead of just the with half of the the support line width.
|
// add the outer wall (of the overhang) to ensure it is correct supported instead. Try placing the support points in a way that they fully support the outer wall, instead of just the with half of the the support line width.
|
||||||
// I assume that even small overhangs are over one line width wide, so lets try to place the support points in a way that the full support area generated from them
|
// I assume that even small overhangs are over one line width wide, so lets try to place the support points in a way that the full support area generated from them
|
||||||
// will support the overhang (if this is not done it may only be half). This WILL NOT be the case when supporting an angle of about < 60<EFBFBD> so there is a fallback,
|
// will support the overhang (if this is not done it may only be half). This WILL NOT be the case when supporting an angle of about < 60 degrees so there is a fallback,
|
||||||
// as some support is better than none.
|
// as some support is better than none.
|
||||||
Polygons reduced_overhang_area = offset(union_ex(overhang_area), - interface_placer.config.support_line_width / 2.2, jtMiter, 1.2);
|
Polygons reduced_overhang_area = offset(union_ex(overhang_area), -interface_placer.config.support_line_width / 2.2, jtMiter, 1.2);
|
||||||
polylines = ensure_maximum_distance_polyline(
|
polylines = ensure_maximum_distance_polyline(
|
||||||
to_polylines(
|
to_polylines(
|
||||||
! reduced_overhang_area.empty() &&
|
! reduced_overhang_area.empty() &&
|
||||||
|
@ -1269,11 +1269,11 @@ static void generate_initial_areas(
|
||||||
|
|
||||||
const coord_t connect_length = (config.support_line_width * 100. / mesh_group_settings.support_tree_top_rate) + std::max(2. * config.min_radius - 1.0 * config.support_line_width, 0.0);
|
const coord_t connect_length = (config.support_line_width * 100. / mesh_group_settings.support_tree_top_rate) + std::max(2. * config.min_radius - 1.0 * config.support_line_width, 0.0);
|
||||||
// As r*r=x*x+y*y (circle equation): If a circle with center at (0,0) the top most point is at (0,r) as in y=r.
|
// As r*r=x*x+y*y (circle equation): If a circle with center at (0,0) the top most point is at (0,r) as in y=r.
|
||||||
// This calculates how far one has to move on the x-axis so that y=r-support_line_width/2.
|
// This calculates how far one has to move on the x-axis so that y=r-support_line_width/2.
|
||||||
// In other words how far does one need to move on the x-axis to be support_line_width/2 away from the circle line.
|
// In other words how far does one need to move on the x-axis to be support_line_width/2 away from the circle line.
|
||||||
// As a circle is round this length is identical for every axis as long as the 90 degrees angle between both remains.
|
// As a circle is round this length is identical for every axis as long as the 90 degrees angle between both remains.
|
||||||
const coord_t circle_length_to_half_linewidth_change = config.min_radius < config.support_line_width ?
|
const coord_t circle_length_to_half_linewidth_change = config.min_radius < config.support_line_width ?
|
||||||
config.min_radius / 2 :
|
config.min_radius / 2 :
|
||||||
scale_(sqrt(sqr(unscale<double>(config.min_radius)) - sqr(unscale<double>(config.min_radius - config.support_line_width / 2))));
|
scale_(sqrt(sqr(unscale<double>(config.min_radius)) - sqr(unscale<double>(config.min_radius - config.support_line_width / 2))));
|
||||||
// Extra support offset to compensate for larger tip radiis. Also outset a bit more when z overwrites xy, because supporting something with a part of a support line is better than not supporting it at all.
|
// Extra support offset to compensate for larger tip radiis. Also outset a bit more when z overwrites xy, because supporting something with a part of a support line is better than not supporting it at all.
|
||||||
//FIXME Vojtech: This is not sufficient for support enforcers to work.
|
//FIXME Vojtech: This is not sufficient for support enforcers to work.
|
||||||
|
@ -1286,14 +1286,16 @@ static void generate_initial_areas(
|
||||||
const size_t num_support_roof_layers = mesh_group_settings.support_roof_layers;
|
const size_t num_support_roof_layers = mesh_group_settings.support_roof_layers;
|
||||||
const bool roof_enabled = num_support_roof_layers > 0;
|
const bool roof_enabled = num_support_roof_layers > 0;
|
||||||
const bool force_tip_to_roof = roof_enabled && (interface_placer.support_parameters.soluble_interface || sqr<double>(config.min_radius) * M_PI > mesh_group_settings.minimum_roof_area);
|
const bool force_tip_to_roof = roof_enabled && (interface_placer.support_parameters.soluble_interface || sqr<double>(config.min_radius) * M_PI > mesh_group_settings.minimum_roof_area);
|
||||||
// cap for how much layer below the overhang a new support point may be added, as other than with regular support every new inserted point
|
// cap for how much layer below the overhang a new support point may be added, as other than with regular support every new inserted point
|
||||||
// may cause extra material and time cost. Could also be an user setting or differently calculated. Idea is that if an overhang
|
// may cause extra material and time cost. Could also be an user setting or differently calculated. Idea is that if an overhang
|
||||||
// does not turn valid in double the amount of layers a slope of support angle would take to travel xy_distance, nothing reasonable will come from it.
|
// does not turn valid in double the amount of layers a slope of support angle would take to travel xy_distance, nothing reasonable will come from it.
|
||||||
// The 2*z_distance_delta is only a catch for when the support angle is very high.
|
// The 2*z_distance_delta is only a catch for when the support angle is very high.
|
||||||
// Used only if not min_xy_dist.
|
// Used only if not min_xy_dist.
|
||||||
coord_t max_overhang_insert_lag = 0;
|
coord_t max_overhang_insert_lag = 0;
|
||||||
if (config.z_distance_top_layers > 0) {
|
if (config.z_distance_top_layers > 0) {
|
||||||
max_overhang_insert_lag = 2 * config.z_distance_top_layers;
|
max_overhang_insert_lag = 2 * config.z_distance_top_layers;
|
||||||
|
|
||||||
|
//FIXME
|
||||||
if (mesh_group_settings.support_angle > EPSILON && mesh_group_settings.support_angle < 0.5 * M_PI - EPSILON) {
|
if (mesh_group_settings.support_angle > EPSILON && mesh_group_settings.support_angle < 0.5 * M_PI - EPSILON) {
|
||||||
//FIXME mesh_group_settings.support_angle does not apply to enforcers and also it does not apply to automatic support angle (by half the external perimeter width).
|
//FIXME mesh_group_settings.support_angle does not apply to enforcers and also it does not apply to automatic support angle (by half the external perimeter width).
|
||||||
//used by max_overhang_insert_lag, only if not min_xy_dist.
|
//used by max_overhang_insert_lag, only if not min_xy_dist.
|
||||||
|
@ -1339,12 +1341,12 @@ static void generate_initial_areas(
|
||||||
relevant_forbidden = offset(union_ex(relevant_forbidden_raw), scaled<float>(0.005), jtMiter, 1.2);
|
relevant_forbidden = offset(union_ex(relevant_forbidden_raw), scaled<float>(0.005), jtMiter, 1.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// every overhang has saved if a roof should be generated for it. This can NOT be done in the for loop as an area may NOT have a roof
|
// every overhang has saved if a roof should be generated for it. This can NOT be done in the for loop as an area may NOT have a roof
|
||||||
// even if it is larger than the minimum_roof_area when it is only larger because of the support horizontal expansion and
|
// even if it is larger than the minimum_roof_area when it is only larger because of the support horizontal expansion and
|
||||||
// it would not have a roof if the overhang is offset by support roof horizontal expansion instead. (At least this is the current behavior of the regular support)
|
// it would not have a roof if the overhang is offset by support roof horizontal expansion instead. (At least this is the current behavior of the regular support)
|
||||||
Polygons overhang_regular;
|
Polygons overhang_regular;
|
||||||
{
|
{
|
||||||
// When support_offset = 0 safe_offset_inc will only be the difference between overhang_raw and relevant_forbidden, that has to be calculated anyway.
|
// When support_offset = 0 safe_offset_inc will only be the difference between overhang_raw and relevant_forbidden, that has to be calculated anyway.
|
||||||
overhang_regular = safe_offset_inc(overhang_raw, mesh_group_settings.support_offset, relevant_forbidden, config.min_radius * 1.75 + config.xy_min_distance, 0, 1);
|
overhang_regular = safe_offset_inc(overhang_raw, mesh_group_settings.support_offset, relevant_forbidden, config.min_radius * 1.75 + config.xy_min_distance, 0, 1);
|
||||||
//check_self_intersections(overhang_regular, "overhang_regular1");
|
//check_self_intersections(overhang_regular, "overhang_regular1");
|
||||||
|
|
||||||
|
@ -1363,7 +1365,7 @@ static void generate_initial_areas(
|
||||||
for (coord_t extra_total_offset_acc = 0; ! remaining_overhang.empty() && extra_total_offset_acc + config.support_line_width / 8 < extra_outset; ) {
|
for (coord_t extra_total_offset_acc = 0; ! remaining_overhang.empty() && extra_total_offset_acc + config.support_line_width / 8 < extra_outset; ) {
|
||||||
const coord_t offset_current_step = std::min(
|
const coord_t offset_current_step = std::min(
|
||||||
extra_total_offset_acc + 2 * config.support_line_width > config.min_radius ?
|
extra_total_offset_acc + 2 * config.support_line_width > config.min_radius ?
|
||||||
config.support_line_width / 8 :
|
config.support_line_width / 8 :
|
||||||
circle_length_to_half_linewidth_change,
|
circle_length_to_half_linewidth_change,
|
||||||
extra_outset - extra_total_offset_acc);
|
extra_outset - extra_total_offset_acc);
|
||||||
extra_total_offset_acc += offset_current_step;
|
extra_total_offset_acc += offset_current_step;
|
||||||
|
@ -1383,10 +1385,10 @@ static void generate_initial_areas(
|
||||||
LineInformations overhang_lines;
|
LineInformations overhang_lines;
|
||||||
{
|
{
|
||||||
//Vojtech: Generate support heads at support_tree_branch_distance spacing by producing a zig-zag infill at support_tree_branch_distance spacing,
|
//Vojtech: Generate support heads at support_tree_branch_distance spacing by producing a zig-zag infill at support_tree_branch_distance spacing,
|
||||||
// which is then resmapled
|
// which is then resmapled
|
||||||
// support_line_width to form a line here as otherwise most will be unsupported. Technically this violates branch distance,
|
// support_line_width to form a line here as otherwise most will be unsupported. Technically this violates branch distance,
|
||||||
// mbut not only is this the only reasonable choice, but it ensures consistent behavior as some infill patterns generate
|
// mbut not only is this the only reasonable choice, but it ensures consistent behavior as some infill patterns generate
|
||||||
// each line segment as its own polyline part causing a similar line forming behavior. Also it is assumed that
|
// each line segment as its own polyline part causing a similar line forming behavior. Also it is assumed that
|
||||||
// the area that is valid a layer below is to small for support roof.
|
// the area that is valid a layer below is to small for support roof.
|
||||||
Polylines polylines = ensure_maximum_distance_polyline(
|
Polylines polylines = ensure_maximum_distance_polyline(
|
||||||
generate_support_infill_lines(remaining_overhang, support_params, false, layer_idx, mesh_group_settings.support_tree_branch_distance),
|
generate_support_infill_lines(remaining_overhang, support_params, false, layer_idx, mesh_group_settings.support_tree_branch_distance),
|
||||||
|
@ -1404,7 +1406,7 @@ static void generate_initial_areas(
|
||||||
}
|
}
|
||||||
for (size_t lag_ctr = 1; lag_ctr <= max_overhang_insert_lag && !overhang_lines.empty() && layer_idx - coord_t(lag_ctr) >= 1; lag_ctr++) {
|
for (size_t lag_ctr = 1; lag_ctr <= max_overhang_insert_lag && !overhang_lines.empty() && layer_idx - coord_t(lag_ctr) >= 1; lag_ctr++) {
|
||||||
// get least restricted avoidance for layer_idx-lag_ctr
|
// get least restricted avoidance for layer_idx-lag_ctr
|
||||||
const Polygons &relevant_forbidden_below = config.support_rests_on_model ?
|
const Polygons &relevant_forbidden_below = config.support_rests_on_model ?
|
||||||
volumes.getCollision(config.getRadius(0), layer_idx - lag_ctr, min_xy_dist) :
|
volumes.getCollision(config.getRadius(0), layer_idx - lag_ctr, min_xy_dist) :
|
||||||
volumes.getAvoidance(config.getRadius(0), layer_idx - lag_ctr, AvoidanceType::Fast, false, min_xy_dist);
|
volumes.getAvoidance(config.getRadius(0), layer_idx - lag_ctr, AvoidanceType::Fast, false, min_xy_dist);
|
||||||
// it is not required to offset the forbidden area here as the points wont change: If points here are not inside the forbidden area neither will they be later when placing these points, as these are the same points.
|
// it is not required to offset the forbidden area here as the points wont change: If points here are not inside the forbidden area neither will they be later when placing these points, as these are the same points.
|
||||||
|
@ -1442,8 +1444,9 @@ static void generate_initial_areas(
|
||||||
// or roof is enabled and these are the thin overhangs at object slopes (not horizontal overhangs).
|
// or roof is enabled and these are the thin overhangs at object slopes (not horizontal overhangs).
|
||||||
if (mesh_group_settings.minimum_support_area > 0)
|
if (mesh_group_settings.minimum_support_area > 0)
|
||||||
remove_small(overhang_regular, mesh_group_settings.minimum_support_area);
|
remove_small(overhang_regular, mesh_group_settings.minimum_support_area);
|
||||||
|
|
||||||
for (ExPolygon &support_part : union_ex(overhang_regular)) {
|
for (ExPolygon &support_part : union_ex(overhang_regular)) {
|
||||||
sample_overhang_area(to_polygons(std::move(support_part)),
|
sample_overhang_area(to_polygons(std::move(support_part)),
|
||||||
false, layer_idx, num_support_roof_layers, connect_length,
|
false, layer_idx, num_support_roof_layers, connect_length,
|
||||||
mesh_group_settings, rich_interface_placer);
|
mesh_group_settings, rich_interface_placer);
|
||||||
throw_on_cancel();
|
throw_on_cancel();
|
||||||
|
@ -1485,7 +1488,7 @@ static unsigned int move_inside(const Polygons &polygons, Point &from, int dista
|
||||||
}
|
}
|
||||||
int64_t dot_prod = ab.dot(ap);
|
int64_t dot_prod = ab.dot(ap);
|
||||||
if (dot_prod <= 0) { // x is projected to before ab
|
if (dot_prod <= 0) { // x is projected to before ab
|
||||||
if (projected_p_beyond_prev_segment) {
|
if (projected_p_beyond_prev_segment) {
|
||||||
// case which looks like: > .
|
// case which looks like: > .
|
||||||
projected_p_beyond_prev_segment = false;
|
projected_p_beyond_prev_segment = false;
|
||||||
Point& x = p1;
|
Point& x = p1;
|
||||||
|
@ -1520,7 +1523,7 @@ static unsigned int move_inside(const Polygons &polygons, Point &from, int dista
|
||||||
p0 = p1;
|
p0 = p1;
|
||||||
p1 = p2;
|
p1 = p2;
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
// x is projected to a point properly on the line segment (not onto a vertex). The case which looks like | .
|
// x is projected to a point properly on the line segment (not onto a vertex). The case which looks like | .
|
||||||
projected_p_beyond_prev_segment = false;
|
projected_p_beyond_prev_segment = false;
|
||||||
Point x = a + (ab.cast<double>() * (double(dot_prod) / double(ab_length2))).cast<coord_t>();
|
Point x = a + (ab.cast<double>() * (double(dot_prod) / double(ab_length2))).cast<coord_t>();
|
||||||
|
@ -1594,7 +1597,7 @@ static Point move_inside_if_outside(const Polygons &polygons, Point from, int di
|
||||||
Polygons &to_bp_data,
|
Polygons &to_bp_data,
|
||||||
Polygons &to_model_data,
|
Polygons &to_model_data,
|
||||||
Polygons &increased,
|
Polygons &increased,
|
||||||
const coord_t overspeed,
|
const coord_t overspeed,
|
||||||
const bool mergelayer)
|
const bool mergelayer)
|
||||||
{
|
{
|
||||||
SupportElementState current_elem{ SupportElementState::propagate_down(parent.state) };
|
SupportElementState current_elem{ SupportElementState::propagate_down(parent.state) };
|
||||||
|
@ -1607,18 +1610,18 @@ static Point move_inside_if_outside(const Polygons &polygons, Point from, int di
|
||||||
if (settings.move) {
|
if (settings.move) {
|
||||||
increased = relevant_offset;
|
increased = relevant_offset;
|
||||||
if (overspeed > 0) {
|
if (overspeed > 0) {
|
||||||
const coord_t safe_movement_distance =
|
const coord_t safe_movement_distance =
|
||||||
(current_elem.use_min_xy_dist ? config.xy_min_distance : config.xy_distance) +
|
(current_elem.use_min_xy_dist ? config.xy_min_distance : config.xy_distance) +
|
||||||
(std::min(config.z_distance_top_layers, config.z_distance_bottom_layers) > 0 ? config.min_feature_size : 0);
|
(std::min(config.z_distance_top_layers, config.z_distance_bottom_layers) > 0 ? config.min_feature_size : 0);
|
||||||
// The difference to ensure that the result not only conforms to wall_restriction, but collision/avoidance is done later.
|
// The difference to ensure that the result not only conforms to wall_restriction, but collision/avoidance is done later.
|
||||||
// The higher last_safe_step_movement_distance comes exactly from the fact that the collision will be subtracted later.
|
// The higher last_safe_step_movement_distance comes exactly from the fact that the collision will be subtracted later.
|
||||||
increased = safe_offset_inc(increased, overspeed, volumes.getWallRestriction(support_element_collision_radius(config, parent.state), layer_idx, parent.state.use_min_xy_dist),
|
increased = safe_offset_inc(increased, overspeed, volumes.getWallRestriction(support_element_collision_radius(config, parent.state), layer_idx, parent.state.use_min_xy_dist),
|
||||||
safe_movement_distance, safe_movement_distance + radius, 1);
|
safe_movement_distance, safe_movement_distance + radius, 1);
|
||||||
}
|
}
|
||||||
if (settings.no_error && settings.move)
|
if (settings.no_error && settings.move)
|
||||||
// as ClipperLib::jtRound has to be used for offsets this simplify is VERY important for performance.
|
// as ClipperLib::jtRound has to be used for offsets this simplify is VERY important for performance.
|
||||||
polygons_simplify(increased, scaled<float>(0.025), polygons_strictly_simple);
|
polygons_simplify(increased, scaled<float>(0.025), polygons_strictly_simple);
|
||||||
} else
|
} else
|
||||||
// if no movement is done the areas keep parent area as no move == offset(0)
|
// if no movement is done the areas keep parent area as no move == offset(0)
|
||||||
increased = parent.influence_area;
|
increased = parent.influence_area;
|
||||||
|
|
||||||
|
@ -1627,7 +1630,7 @@ static Point move_inside_if_outside(const Polygons &polygons, Point from, int di
|
||||||
if (! current_elem.to_buildplate && area(to_bp_data) > _tiny_area_threshold) {
|
if (! current_elem.to_buildplate && area(to_bp_data) > _tiny_area_threshold) {
|
||||||
// mostly happening in the tip, but with merges one should check every time, just to be sure.
|
// mostly happening in the tip, but with merges one should check every time, just to be sure.
|
||||||
current_elem.to_buildplate = true; // sometimes nodes that can reach the buildplate are marked as cant reach, tainting subtrees. This corrects it.
|
current_elem.to_buildplate = true; // sometimes nodes that can reach the buildplate are marked as cant reach, tainting subtrees. This corrects it.
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Corrected taint leading to a wrong to model value on layer " << layer_idx - 1 << " targeting " <<
|
BOOST_LOG_TRIVIAL(debug) << "Corrected taint leading to a wrong to model value on layer " << layer_idx - 1 << " targeting " <<
|
||||||
current_elem.target_height << " with radius " << radius;
|
current_elem.target_height << " with radius " << radius;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1638,7 +1641,7 @@ static Point move_inside_if_outside(const Polygons &polygons, Point from, int di
|
||||||
if (!current_elem.to_model_gracious) {
|
if (!current_elem.to_model_gracious) {
|
||||||
if (mergelayer && area(to_model_data) >= _tiny_area_threshold) {
|
if (mergelayer && area(to_model_data) >= _tiny_area_threshold) {
|
||||||
current_elem.to_model_gracious = true;
|
current_elem.to_model_gracious = true;
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Corrected taint leading to a wrong non gracious value on layer " << layer_idx - 1 << " targeting " <<
|
BOOST_LOG_TRIVIAL(debug) << "Corrected taint leading to a wrong non gracious value on layer " << layer_idx - 1 << " targeting " <<
|
||||||
current_elem.target_height << " with radius " << radius;
|
current_elem.target_height << " with radius " << radius;
|
||||||
} else
|
} else
|
||||||
// Cannot route to gracious areas. Push the tree away from object and route it down anyways.
|
// Cannot route to gracious areas. Push the tree away from object and route it down anyways.
|
||||||
|
@ -1659,8 +1662,8 @@ static Point move_inside_if_outside(const Polygons &polygons, Point from, int di
|
||||||
to_bp_data_2 = diff_clipped(increased, volumes.getAvoidance(next_radius, layer_idx - 1, settings.type, false, settings.use_min_distance));
|
to_bp_data_2 = diff_clipped(increased, volumes.getAvoidance(next_radius, layer_idx - 1, settings.type, false, settings.use_min_distance));
|
||||||
Polygons to_model_data_2;
|
Polygons to_model_data_2;
|
||||||
if (config.support_rests_on_model && !current_elem.to_buildplate)
|
if (config.support_rests_on_model && !current_elem.to_buildplate)
|
||||||
to_model_data_2 = diff_clipped(increased,
|
to_model_data_2 = diff_clipped(increased,
|
||||||
current_elem.to_model_gracious ?
|
current_elem.to_model_gracious ?
|
||||||
volumes.getAvoidance(next_radius, layer_idx - 1, settings.type, true, settings.use_min_distance) :
|
volumes.getAvoidance(next_radius, layer_idx - 1, settings.type, true, settings.use_min_distance) :
|
||||||
volumes.getCollision(next_radius, layer_idx - 1, settings.use_min_distance));
|
volumes.getCollision(next_radius, layer_idx - 1, settings.use_min_distance));
|
||||||
Polygons check_layer_data_2 = current_elem.to_buildplate ? to_bp_data_2 : to_model_data_2;
|
Polygons check_layer_data_2 = current_elem.to_buildplate ? to_bp_data_2 : to_model_data_2;
|
||||||
|
@ -1675,8 +1678,8 @@ static Point move_inside_if_outside(const Polygons &polygons, Point from, int di
|
||||||
while (current_ceil_radius < target_radius && validWithRadius(volumes.getRadiusNextCeil(current_ceil_radius + 1, settings.use_min_distance)))
|
while (current_ceil_radius < target_radius && validWithRadius(volumes.getRadiusNextCeil(current_ceil_radius + 1, settings.use_min_distance)))
|
||||||
current_ceil_radius = volumes.getRadiusNextCeil(current_ceil_radius + 1, settings.use_min_distance);
|
current_ceil_radius = volumes.getRadiusNextCeil(current_ceil_radius + 1, settings.use_min_distance);
|
||||||
size_t resulting_eff_dtt = current_elem.effective_radius_height;
|
size_t resulting_eff_dtt = current_elem.effective_radius_height;
|
||||||
while (resulting_eff_dtt + 1 < current_elem.distance_to_top &&
|
while (resulting_eff_dtt + 1 < current_elem.distance_to_top &&
|
||||||
config.getRadius(resulting_eff_dtt + 1, current_elem.elephant_foot_increases) <= current_ceil_radius &&
|
config.getRadius(resulting_eff_dtt + 1, current_elem.elephant_foot_increases) <= current_ceil_radius &&
|
||||||
config.getRadius(resulting_eff_dtt + 1, current_elem.elephant_foot_increases) <= support_element_radius(config, current_elem))
|
config.getRadius(resulting_eff_dtt + 1, current_elem.elephant_foot_increases) <= support_element_radius(config, current_elem))
|
||||||
++ resulting_eff_dtt;
|
++ resulting_eff_dtt;
|
||||||
current_elem.effective_radius_height = resulting_eff_dtt;
|
current_elem.effective_radius_height = resulting_eff_dtt;
|
||||||
|
@ -1684,7 +1687,7 @@ static Point move_inside_if_outside(const Polygons &polygons, Point from, int di
|
||||||
radius = support_element_collision_radius(config, current_elem);
|
radius = support_element_collision_radius(config, current_elem);
|
||||||
|
|
||||||
const coord_t foot_radius_increase = std::max(config.bp_radius_increase_per_layer - config.branch_radius_increase_per_layer, 0.0);
|
const coord_t foot_radius_increase = std::max(config.bp_radius_increase_per_layer - config.branch_radius_increase_per_layer, 0.0);
|
||||||
// Is nearly all of the time 1, but sometimes an increase of 1 could cause the radius to become bigger than recommendedMinRadius,
|
// Is nearly all of the time 1, but sometimes an increase of 1 could cause the radius to become bigger than recommendedMinRadius,
|
||||||
// which could cause the radius to become bigger than precalculated.
|
// which could cause the radius to become bigger than precalculated.
|
||||||
double planned_foot_increase = std::min(1.0, double(config.recommendedMinRadius(layer_idx - 1) - support_element_radius(config, current_elem)) / foot_radius_increase);
|
double planned_foot_increase = std::min(1.0, double(config.recommendedMinRadius(layer_idx - 1) - support_element_radius(config, current_elem)) / foot_radius_increase);
|
||||||
//FIXME
|
//FIXME
|
||||||
|
@ -1701,14 +1704,14 @@ static Point move_inside_if_outside(const Polygons &polygons, Point from, int di
|
||||||
if (current_elem.to_buildplate)
|
if (current_elem.to_buildplate)
|
||||||
to_bp_data = safe_union(diff_clipped(increased, volumes.getAvoidance(radius, layer_idx - 1, settings.type, false, settings.use_min_distance)));
|
to_bp_data = safe_union(diff_clipped(increased, volumes.getAvoidance(radius, layer_idx - 1, settings.type, false, settings.use_min_distance)));
|
||||||
if (config.support_rests_on_model && (!current_elem.to_buildplate || mergelayer))
|
if (config.support_rests_on_model && (!current_elem.to_buildplate || mergelayer))
|
||||||
to_model_data = safe_union(diff_clipped(increased,
|
to_model_data = safe_union(diff_clipped(increased,
|
||||||
current_elem.to_model_gracious ?
|
current_elem.to_model_gracious ?
|
||||||
volumes.getAvoidance(radius, layer_idx - 1, settings.type, true, settings.use_min_distance) :
|
volumes.getAvoidance(radius, layer_idx - 1, settings.type, true, settings.use_min_distance) :
|
||||||
volumes.getCollision(radius, layer_idx - 1, settings.use_min_distance)
|
volumes.getCollision(radius, layer_idx - 1, settings.use_min_distance)
|
||||||
));
|
));
|
||||||
check_layer_data = current_elem.to_buildplate ? to_bp_data : to_model_data;
|
check_layer_data = current_elem.to_buildplate ? to_bp_data : to_model_data;
|
||||||
if (area(check_layer_data) < _tiny_area_threshold) {
|
if (area(check_layer_data) < _tiny_area_threshold) {
|
||||||
BOOST_LOG_TRIVIAL(error) << "Lost area by doing catch up from " << ceil_radius_before << " to radius " <<
|
BOOST_LOG_TRIVIAL(error) << "Lost area by doing catch up from " << ceil_radius_before << " to radius " <<
|
||||||
volumes.ceilRadius(support_element_collision_radius(config, current_elem), settings.use_min_distance);
|
volumes.ceilRadius(support_element_collision_radius(config, current_elem), settings.use_min_distance);
|
||||||
tree_supports_show_error("Area lost catching up radius. May not cause visible malformation."sv, true);
|
tree_supports_show_error("Area lost catching up radius. May not cause visible malformation."sv, true);
|
||||||
}
|
}
|
||||||
|
@ -1746,7 +1749,7 @@ struct SupportElementMerging {
|
||||||
|
|
||||||
const Eigen::AlignedBox<coord_t, 2>& bbox() const { return bbox_data;}
|
const Eigen::AlignedBox<coord_t, 2>& bbox() const { return bbox_data;}
|
||||||
const Point centroid() const { return (bbox_data.min() + bbox_data.max()) / 2; }
|
const Point centroid() const { return (bbox_data.min() + bbox_data.max()) / 2; }
|
||||||
void set_bbox(const BoundingBox& abbox)
|
void set_bbox(const BoundingBox& abbox)
|
||||||
{ Point eps { coord_t(SCALED_EPSILON), coord_t(SCALED_EPSILON) }; bbox_data = { abbox.min - eps, abbox.max + eps }; }
|
{ Point eps { coord_t(SCALED_EPSILON), coord_t(SCALED_EPSILON) }; bbox_data = { abbox.min - eps, abbox.max + eps }; }
|
||||||
|
|
||||||
// Called by the AABBTree builder to get an index into the vector of source elements.
|
// Called by the AABBTree builder to get an index into the vector of source elements.
|
||||||
|
@ -1778,7 +1781,7 @@ static void increase_areas_one_layer(
|
||||||
// New areas at the layer below layer_idx
|
// New areas at the layer below layer_idx
|
||||||
std::vector<SupportElementMerging> &merging_areas,
|
std::vector<SupportElementMerging> &merging_areas,
|
||||||
// Layer above merging_areas.
|
// Layer above merging_areas.
|
||||||
const LayerIndex layer_idx,
|
const LayerIndex layer_idx,
|
||||||
// Layer elements above merging_areas.
|
// Layer elements above merging_areas.
|
||||||
SupportElements &layer_elements,
|
SupportElements &layer_elements,
|
||||||
// If false, the merging_areas will not be merged for performance reasons.
|
// If false, the merging_areas will not be merged for performance reasons.
|
||||||
|
@ -1794,7 +1797,7 @@ static void increase_areas_one_layer(
|
||||||
assert(merging_area.parents.size() == 1);
|
assert(merging_area.parents.size() == 1);
|
||||||
SupportElement &parent = layer_elements[merging_area.parents.front()];
|
SupportElement &parent = layer_elements[merging_area.parents.front()];
|
||||||
SupportElementState elem = SupportElementState::propagate_down(parent.state);
|
SupportElementState elem = SupportElementState::propagate_down(parent.state);
|
||||||
const Polygons &wall_restriction =
|
const Polygons &wall_restriction =
|
||||||
// Abstract representation of the model outline. If an influence area would move through it, it could teleport through a wall.
|
// Abstract representation of the model outline. If an influence area would move through it, it could teleport through a wall.
|
||||||
volumes.getWallRestriction(support_element_collision_radius(config, parent.state), layer_idx, parent.state.use_min_xy_dist);
|
volumes.getWallRestriction(support_element_collision_radius(config, parent.state), layer_idx, parent.state.use_min_xy_dist);
|
||||||
|
|
||||||
|
@ -1825,10 +1828,10 @@ static void increase_areas_one_layer(
|
||||||
* layer z-1:dddddxxxxxxxxxx
|
* layer z-1:dddddxxxxxxxxxx
|
||||||
* For more detailed visualisation see calculateWallRestrictions
|
* For more detailed visualisation see calculateWallRestrictions
|
||||||
*/
|
*/
|
||||||
const coord_t safe_movement_distance =
|
const coord_t safe_movement_distance =
|
||||||
(elem.use_min_xy_dist ? config.xy_min_distance : config.xy_distance) +
|
(elem.use_min_xy_dist ? config.xy_min_distance : config.xy_distance) +
|
||||||
(std::min(config.z_distance_top_layers, config.z_distance_bottom_layers) > 0 ? config.min_feature_size : 0);
|
(std::min(config.z_distance_top_layers, config.z_distance_bottom_layers) > 0 ? config.min_feature_size : 0);
|
||||||
if (ceiled_parent_radius == volumes.ceilRadius(projected_radius_increased, parent.state.use_min_xy_dist) ||
|
if (ceiled_parent_radius == volumes.ceilRadius(projected_radius_increased, parent.state.use_min_xy_dist) ||
|
||||||
projected_radius_increased < config.increase_radius_until_radius)
|
projected_radius_increased < config.increase_radius_until_radius)
|
||||||
// If it is guaranteed possible to increase the radius, the maximum movement speed can be increased, as it is assumed that the maximum movement speed is the one of the slower moving wall
|
// If it is guaranteed possible to increase the radius, the maximum movement speed can be increased, as it is assumed that the maximum movement speed is the one of the slower moving wall
|
||||||
extra_speed += projected_radius_delta;
|
extra_speed += projected_radius_delta;
|
||||||
|
@ -1837,7 +1840,7 @@ static void increase_areas_one_layer(
|
||||||
// Ensure that the slow movement distance can not become larger than the fast one.
|
// Ensure that the slow movement distance can not become larger than the fast one.
|
||||||
extra_slow_speed += std::min(projected_radius_delta, (config.maximum_move_distance + extra_speed) - (config.maximum_move_distance_slow + extra_slow_speed));
|
extra_slow_speed += std::min(projected_radius_delta, (config.maximum_move_distance + extra_speed) - (config.maximum_move_distance_slow + extra_slow_speed));
|
||||||
|
|
||||||
if (config.layer_start_bp_radius > layer_idx &&
|
if (config.layer_start_bp_radius > layer_idx &&
|
||||||
config.recommendedMinRadius(layer_idx - 1) < config.getRadius(elem.effective_radius_height + 1, elem.elephant_foot_increases)) {
|
config.recommendedMinRadius(layer_idx - 1) < config.getRadius(elem.effective_radius_height + 1, elem.elephant_foot_increases)) {
|
||||||
// can guarantee elephant foot radius increase
|
// can guarantee elephant foot radius increase
|
||||||
if (ceiled_parent_radius == volumes.ceilRadius(config.getRadius(parent.state.effective_radius_height + 1, parent.state.elephant_foot_increases + 1), parent.state.use_min_xy_dist))
|
if (ceiled_parent_radius == volumes.ceilRadius(config.getRadius(parent.state.effective_radius_height + 1, parent.state.elephant_foot_increases + 1), parent.state.use_min_xy_dist))
|
||||||
|
@ -1872,7 +1875,7 @@ static void increase_areas_one_layer(
|
||||||
if (elem.last_area_increase.move && elem.last_area_increase.no_error && elem.can_use_safe_radius && !mergelayer &&
|
if (elem.last_area_increase.move && elem.last_area_increase.no_error && elem.can_use_safe_radius && !mergelayer &&
|
||||||
!avoidance_speed_mismatch && (elem.distance_to_top >= config.tip_layers || parent_moved_slow)) {
|
!avoidance_speed_mismatch && (elem.distance_to_top >= config.tip_layers || parent_moved_slow)) {
|
||||||
// assume that the avoidance type that was best for the parent is best for me. Makes this function about 7% faster.
|
// assume that the avoidance type that was best for the parent is best for me. Makes this function about 7% faster.
|
||||||
insertSetting({ elem.last_area_increase.type, elem.last_area_increase.increase_speed < config.maximum_move_distance ? slow_speed : fast_speed,
|
insertSetting({ elem.last_area_increase.type, elem.last_area_increase.increase_speed < config.maximum_move_distance ? slow_speed : fast_speed,
|
||||||
increase_radius, elem.last_area_increase.no_error, !use_min_radius, elem.last_area_increase.move }, true);
|
increase_radius, elem.last_area_increase.no_error, !use_min_radius, elem.last_area_increase.move }, true);
|
||||||
insertSetting({ elem.last_area_increase.type, elem.last_area_increase.increase_speed < config.maximum_move_distance ? slow_speed : fast_speed,
|
insertSetting({ elem.last_area_increase.type, elem.last_area_increase.increase_speed < config.maximum_move_distance ? slow_speed : fast_speed,
|
||||||
!increase_radius, elem.last_area_increase.no_error, !use_min_radius, elem.last_area_increase.move }, true);
|
!increase_radius, elem.last_area_increase.no_error, !use_min_radius, elem.last_area_increase.move }, true);
|
||||||
|
@ -1892,7 +1895,7 @@ static void increase_areas_one_layer(
|
||||||
insertSetting({ AvoidanceType::Fast, fast_speed, !increase_radius, no_error, !use_min_radius, move }, true);
|
insertSetting({ AvoidanceType::Fast, fast_speed, !increase_radius, no_error, !use_min_radius, move }, true);
|
||||||
} else {
|
} else {
|
||||||
insertSetting({ AvoidanceType::Slow, slow_speed, increase_radius, no_error, !use_min_radius, move }, true);
|
insertSetting({ AvoidanceType::Slow, slow_speed, increase_radius, no_error, !use_min_radius, move }, true);
|
||||||
// while moving fast to be able to increase the radius (b) may seems preferable (over a) this can cause the a sudden skip in movement,
|
// while moving fast to be able to increase the radius (b) may seems preferable (over a) this can cause the a sudden skip in movement,
|
||||||
// which looks similar to a layer shift and can reduce stability.
|
// which looks similar to a layer shift and can reduce stability.
|
||||||
// as such idx have chosen to only use the user setting for radius increases as a friendly recommendation.
|
// as such idx have chosen to only use the user setting for radius increases as a friendly recommendation.
|
||||||
insertSetting({ AvoidanceType::Slow, slow_speed, !increase_radius, no_error, !use_min_radius, move }, true); // a
|
insertSetting({ AvoidanceType::Slow, slow_speed, !increase_radius, no_error, !use_min_radius, move }, true); // a
|
||||||
|
@ -1929,9 +1932,9 @@ static void increase_areas_one_layer(
|
||||||
for (const AreaIncreaseSettings &settings : order) {
|
for (const AreaIncreaseSettings &settings : order) {
|
||||||
if (settings.move) {
|
if (settings.move) {
|
||||||
if (offset_slow.empty() && (settings.increase_speed == slow_speed || ! offset_independant_faster)) {
|
if (offset_slow.empty() && (settings.increase_speed == slow_speed || ! offset_independant_faster)) {
|
||||||
// offsetting in 2 steps makes our offsetted area rounder preventing (rounding) errors created by to pointy areas. At this point one can see that the Polygons class
|
// offsetting in 2 steps makes our offsetted area rounder preventing (rounding) errors created by to pointy areas. At this point one can see that the Polygons class
|
||||||
// was never made for precision in the single digit micron range.
|
// was never made for precision in the single digit micron range.
|
||||||
offset_slow = safe_offset_inc(parent.influence_area, extra_speed + extra_slow_speed + config.maximum_move_distance_slow,
|
offset_slow = safe_offset_inc(parent.influence_area, extra_speed + extra_slow_speed + config.maximum_move_distance_slow,
|
||||||
wall_restriction, safe_movement_distance, offset_independant_faster ? safe_movement_distance + radius : 0, 2);
|
wall_restriction, safe_movement_distance, offset_independant_faster ? safe_movement_distance + radius : 0, 2);
|
||||||
#ifdef TREESUPPORT_DEBUG_SVG
|
#ifdef TREESUPPORT_DEBUG_SVG
|
||||||
SVG::export_expolygons(debug_out_path("treesupport-increase_areas_one_layer-slow-%d-%ld.svg", layer_idx, int(merging_area_idx)),
|
SVG::export_expolygons(debug_out_path("treesupport-increase_areas_one_layer-slow-%d-%ld.svg", layer_idx, int(merging_area_idx)),
|
||||||
|
@ -1941,7 +1944,7 @@ static void increase_areas_one_layer(
|
||||||
}
|
}
|
||||||
if (offset_fast.empty() && settings.increase_speed != slow_speed) {
|
if (offset_fast.empty() && settings.increase_speed != slow_speed) {
|
||||||
if (offset_independant_faster)
|
if (offset_independant_faster)
|
||||||
offset_fast = safe_offset_inc(parent.influence_area, extra_speed + config.maximum_move_distance,
|
offset_fast = safe_offset_inc(parent.influence_area, extra_speed + config.maximum_move_distance,
|
||||||
wall_restriction, safe_movement_distance, offset_independant_faster ? safe_movement_distance + radius : 0, 1);
|
wall_restriction, safe_movement_distance, offset_independant_faster ? safe_movement_distance + radius : 0, 1);
|
||||||
else {
|
else {
|
||||||
const coord_t delta_slow_fast = config.maximum_move_distance - (config.maximum_move_distance_slow + extra_slow_speed);
|
const coord_t delta_slow_fast = config.maximum_move_distance - (config.maximum_move_distance_slow + extra_slow_speed);
|
||||||
|
@ -1956,12 +1959,12 @@ static void increase_areas_one_layer(
|
||||||
}
|
}
|
||||||
std::optional<SupportElementState> result;
|
std::optional<SupportElementState> result;
|
||||||
inc_wo_collision.clear();
|
inc_wo_collision.clear();
|
||||||
if (!settings.no_error) {
|
if (!settings.no_error) {
|
||||||
// ERROR CASE
|
// ERROR CASE
|
||||||
// if the area becomes for whatever reason something that clipper sees as a line, offset would stop working, so ensure that even if it would be a line wrongly, it still actually has an area that can be increased
|
// if the area becomes for whatever reason something that clipper sees as a line, offset would stop working, so ensure that even if it would be a line wrongly, it still actually has an area that can be increased
|
||||||
Polygons lines_offset = offset(to_polylines(parent.influence_area), scaled<float>(0.005), jtMiter, 1.2);
|
Polygons lines_offset = offset(to_polylines(parent.influence_area), scaled<float>(0.005), jtMiter, 1.2);
|
||||||
Polygons base_error_area = union_(parent.influence_area, lines_offset);
|
Polygons base_error_area = union_(parent.influence_area, lines_offset);
|
||||||
result = increase_single_area(volumes, config, settings, layer_idx, parent,
|
result = increase_single_area(volumes, config, settings, layer_idx, parent,
|
||||||
base_error_area, to_bp_data, to_model_data, inc_wo_collision, (config.maximum_move_distance + extra_speed) * 1.5, mergelayer);
|
base_error_area, to_bp_data, to_model_data, inc_wo_collision, (config.maximum_move_distance + extra_speed) * 1.5, mergelayer);
|
||||||
#ifdef TREE_SUPPORT_SHOW_ERRORS
|
#ifdef TREE_SUPPORT_SHOW_ERRORS
|
||||||
BOOST_LOG_TRIVIAL(error)
|
BOOST_LOG_TRIVIAL(error)
|
||||||
|
@ -1970,7 +1973,7 @@ static void increase_areas_one_layer(
|
||||||
#endif // TREE_SUPPORT_SHOW_ERRORS
|
#endif // TREE_SUPPORT_SHOW_ERRORS
|
||||||
<< "Influence area could not be increased! Data about the Influence area: "
|
<< "Influence area could not be increased! Data about the Influence area: "
|
||||||
"Radius: " << radius << " at layer: " << layer_idx - 1 << " NextTarget: " << elem.layer_idx << " Distance to top: " << elem.distance_to_top <<
|
"Radius: " << radius << " at layer: " << layer_idx - 1 << " NextTarget: " << elem.layer_idx << " Distance to top: " << elem.distance_to_top <<
|
||||||
" Elephant foot increases " << elem.elephant_foot_increases << " use_min_xy_dist " << elem.use_min_xy_dist << " to buildplate " << elem.to_buildplate <<
|
" Elephant foot increases " << elem.elephant_foot_increases << " use_min_xy_dist " << elem.use_min_xy_dist << " to buildplate " << elem.to_buildplate <<
|
||||||
" gracious " << elem.to_model_gracious << " safe " << elem.can_use_safe_radius << " until move " << elem.dont_move_until << " \n "
|
" gracious " << elem.to_model_gracious << " safe " << elem.can_use_safe_radius << " until move " << elem.dont_move_until << " \n "
|
||||||
"Parent " << &parent << ": Radius: " << support_element_collision_radius(config, parent.state) << " at layer: " << layer_idx << " NextTarget: " << parent.state.layer_idx <<
|
"Parent " << &parent << ": Radius: " << support_element_collision_radius(config, parent.state) << " at layer: " << layer_idx << " NextTarget: " << parent.state.layer_idx <<
|
||||||
" Distance to top: " << parent.state.distance_to_top << " Elephant foot increases " << parent.state.elephant_foot_increases << " use_min_xy_dist " << parent.state.use_min_xy_dist <<
|
" Distance to top: " << parent.state.distance_to_top << " Elephant foot increases " << parent.state.elephant_foot_increases << " use_min_xy_dist " << parent.state.use_min_xy_dist <<
|
||||||
|
@ -2002,7 +2005,7 @@ static void increase_areas_one_layer(
|
||||||
elem.use_min_xy_dist = false;
|
elem.use_min_xy_dist = false;
|
||||||
if (!settings.no_error)
|
if (!settings.no_error)
|
||||||
#ifdef TREE_SUPPORT_SHOW_ERRORS
|
#ifdef TREE_SUPPORT_SHOW_ERRORS
|
||||||
BOOST_LOG_TRIVIAL(error)
|
BOOST_LOG_TRIVIAL(error)
|
||||||
#else // TREE_SUPPORT_SHOW_ERRORS
|
#else // TREE_SUPPORT_SHOW_ERRORS
|
||||||
BOOST_LOG_TRIVIAL(info)
|
BOOST_LOG_TRIVIAL(info)
|
||||||
#endif // TREE_SUPPORT_SHOW_ERRORS
|
#endif // TREE_SUPPORT_SHOW_ERRORS
|
||||||
|
@ -2029,7 +2032,7 @@ static void increase_areas_one_layer(
|
||||||
merging_area.areas.to_model_areas = std::move(to_model_data);
|
merging_area.areas.to_model_areas = std::move(to_model_data);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If the bottom most point of a branch is set, later functions will assume that the position is valid, and ignore it.
|
// If the bottom most point of a branch is set, later functions will assume that the position is valid, and ignore it.
|
||||||
// But as branches connecting with the model that are to small have to be culled, the bottom most point has to be not set.
|
// But as branches connecting with the model that are to small have to be culled, the bottom most point has to be not set.
|
||||||
// A point can be set on the top most tip layer (maybe more if it should not move for a few layers).
|
// A point can be set on the top most tip layer (maybe more if it should not move for a few layers).
|
||||||
parent.state.result_on_layer_reset();
|
parent.state.result_on_layer_reset();
|
||||||
|
@ -2073,7 +2076,7 @@ static void increase_areas_one_layer(
|
||||||
out.elephant_foot_increases = 0;
|
out.elephant_foot_increases = 0;
|
||||||
if (config.bp_radius_increase_per_layer > 0) {
|
if (config.bp_radius_increase_per_layer > 0) {
|
||||||
coord_t foot_increase_radius = std::abs(std::max(support_element_collision_radius(config, second), support_element_collision_radius(config, first)) - support_element_collision_radius(config, out));
|
coord_t foot_increase_radius = std::abs(std::max(support_element_collision_radius(config, second), support_element_collision_radius(config, first)) - support_element_collision_radius(config, out));
|
||||||
// elephant_foot_increases has to be recalculated, as when a smaller tree with a larger elephant_foot_increases merge with a larger branch
|
// elephant_foot_increases has to be recalculated, as when a smaller tree with a larger elephant_foot_increases merge with a larger branch
|
||||||
// the elephant_foot_increases may have to be lower as otherwise the radius suddenly increases. This results often in a non integer value.
|
// the elephant_foot_increases may have to be lower as otherwise the radius suddenly increases. This results often in a non integer value.
|
||||||
out.elephant_foot_increases = foot_increase_radius / (config.bp_radius_increase_per_layer - config.branch_radius_increase_per_layer);
|
out.elephant_foot_increases = foot_increase_radius / (config.bp_radius_increase_per_layer - config.branch_radius_increase_per_layer);
|
||||||
}
|
}
|
||||||
|
@ -2096,8 +2099,8 @@ static bool merge_influence_areas_two_elements(
|
||||||
{
|
{
|
||||||
// Don't merge gracious with a non gracious area as bad placement could negatively impact reliability of the whole subtree.
|
// Don't merge gracious with a non gracious area as bad placement could negatively impact reliability of the whole subtree.
|
||||||
const bool merging_gracious_and_non_gracious = dst.state.to_model_gracious != src.state.to_model_gracious;
|
const bool merging_gracious_and_non_gracious = dst.state.to_model_gracious != src.state.to_model_gracious;
|
||||||
// Could cause some issues with the increase of one area, as it is assumed that if the smaller is increased
|
// Could cause some issues with the increase of one area, as it is assumed that if the smaller is increased
|
||||||
// by the delta to the larger it is engulfed by it already. But because a different collision
|
// by the delta to the larger it is engulfed by it already. But because a different collision
|
||||||
// may be removed from the in draw_area() generated circles, this assumption could be wrong.
|
// may be removed from the in draw_area() generated circles, this assumption could be wrong.
|
||||||
const bool merging_min_and_regular_xy = dst.state.use_min_xy_dist != src.state.use_min_xy_dist;
|
const bool merging_min_and_regular_xy = dst.state.use_min_xy_dist != src.state.use_min_xy_dist;
|
||||||
|
|
||||||
|
@ -2141,10 +2144,10 @@ static bool merge_influence_areas_two_elements(
|
||||||
if (increased_to_model_radius > config.max_to_model_radius_increase)
|
if (increased_to_model_radius > config.max_to_model_radius_increase)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// if a merge could place a stable branch on unstable ground, would be increasing the radius further
|
// if a merge could place a stable branch on unstable ground, would be increasing the radius further
|
||||||
// than allowed to when merging to model and to_bp trees or would merge to model before it is known
|
// than allowed to when merging to model and to_bp trees or would merge to model before it is known
|
||||||
// they will even been drawn the merge is skipped
|
// they will even been drawn the merge is skipped
|
||||||
if (! dst.state.supports_roof && ! src.state.supports_roof &&
|
if (! dst.state.supports_roof && ! src.state.supports_roof &&
|
||||||
std::max(src.state.distance_to_top, dst.state.distance_to_top) < config.min_dtt_to_model)
|
std::max(src.state.distance_to_top, dst.state.distance_to_top) < config.min_dtt_to_model)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -2155,7 +2158,7 @@ static bool merge_influence_areas_two_elements(
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// the bigger radius is used to verify that the area is still valid after the increase with the delta.
|
// the bigger radius is used to verify that the area is still valid after the increase with the delta.
|
||||||
// If there were a point where the big influence area could be valid with can_use_safe_radius
|
// If there were a point where the big influence area could be valid with can_use_safe_radius
|
||||||
// the element would already be can_use_safe_radius.
|
// the element would already be can_use_safe_radius.
|
||||||
// the smaller radius, which gets increased by delta may reach into the area where use_min_xy_dist is no longer required.
|
// the smaller radius, which gets increased by delta may reach into the area where use_min_xy_dist is no longer required.
|
||||||
const bool use_min_radius = bigger_rad.state.use_min_xy_dist && smaller_rad.state.use_min_xy_dist;
|
const bool use_min_radius = bigger_rad.state.use_min_xy_dist && smaller_rad.state.use_min_xy_dist;
|
||||||
|
@ -2186,7 +2189,7 @@ static bool merge_influence_areas_two_elements(
|
||||||
|
|
||||||
const auto _tiny_area_threshold = tiny_area_threshold();
|
const auto _tiny_area_threshold = tiny_area_threshold();
|
||||||
// dont use empty as a line is not empty, but for this use-case it very well may be (and would be one layer down as union does not keep lines)
|
// dont use empty as a line is not empty, but for this use-case it very well may be (and would be one layer down as union does not keep lines)
|
||||||
// check if the overlap is large enough (Small ares tend to attract rounding errors in clipper).
|
// check if the overlap is large enough (Small ares tend to attract rounding errors in clipper).
|
||||||
if (area(intersect) <= _tiny_area_threshold)
|
if (area(intersect) <= _tiny_area_threshold)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -2208,7 +2211,7 @@ static bool merge_influence_areas_two_elements(
|
||||||
Point new_pos = move_inside_if_outside(intersect, dst.state.next_position);
|
Point new_pos = move_inside_if_outside(intersect, dst.state.next_position);
|
||||||
|
|
||||||
SupportElementState new_state = merge_support_element_states(dst.state, src.state, new_pos, layer_idx - 1, config);
|
SupportElementState new_state = merge_support_element_states(dst.state, src.state, new_pos, layer_idx - 1, config);
|
||||||
new_state.increased_to_model_radius = increased_to_model_radius == 0 ?
|
new_state.increased_to_model_radius = increased_to_model_radius == 0 ?
|
||||||
// increased_to_model_radius was not set yet. Propagate maximum.
|
// increased_to_model_radius was not set yet. Propagate maximum.
|
||||||
std::max(dst.state.increased_to_model_radius, src.state.increased_to_model_radius) :
|
std::max(dst.state.increased_to_model_radius, src.state.increased_to_model_radius) :
|
||||||
increased_to_model_radius;
|
increased_to_model_radius;
|
||||||
|
@ -2296,7 +2299,7 @@ static SupportElementMerging* merge_influence_areas_two_sets(
|
||||||
SupportElementMerging * const dst_begin, SupportElementMerging * dst_end,
|
SupportElementMerging * const dst_begin, SupportElementMerging * dst_end,
|
||||||
SupportElementMerging * src_begin, SupportElementMerging * const src_end)
|
SupportElementMerging * src_begin, SupportElementMerging * const src_end)
|
||||||
{
|
{
|
||||||
// Merging src into dst.
|
// Merging src into dst.
|
||||||
// Areas of src should not overlap with areas of another elements of src.
|
// Areas of src should not overlap with areas of another elements of src.
|
||||||
// Areas of dst should not overlap with areas of another elements of dst.
|
// Areas of dst should not overlap with areas of another elements of dst.
|
||||||
// The memory from dst_begin to src_end is reserved for the merging operation,
|
// The memory from dst_begin to src_end is reserved for the merging operation,
|
||||||
|
@ -2349,8 +2352,8 @@ static SupportElementMerging* merge_influence_areas_two_sets(
|
||||||
* \param layer_idx[in] The current layer.
|
* \param layer_idx[in] The current layer.
|
||||||
*/
|
*/
|
||||||
static void merge_influence_areas(
|
static void merge_influence_areas(
|
||||||
const TreeModelVolumes &volumes,
|
const TreeModelVolumes &volumes,
|
||||||
const TreeSupportSettings &config,
|
const TreeSupportSettings &config,
|
||||||
const LayerIndex layer_idx,
|
const LayerIndex layer_idx,
|
||||||
std::vector<SupportElementMerging> &influence_areas,
|
std::vector<SupportElementMerging> &influence_areas,
|
||||||
std::function<void()> throw_on_cancel)
|
std::function<void()> throw_on_cancel)
|
||||||
|
@ -2538,7 +2541,7 @@ static void create_layer_pathing(const TreeModelVolumes &volumes, const TreeSupp
|
||||||
throw_on_cancel();
|
throw_on_cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) << "Time spent with creating influence areas' subtasks: Increasing areas " << dur_inc.count() / 1000000 <<
|
BOOST_LOG_TRIVIAL(info) << "Time spent with creating influence areas' subtasks: Increasing areas " << dur_inc.count() / 1000000 <<
|
||||||
" ms merging areas: " << (dur_total - dur_inc).count() / 1000000 << " ms";
|
" ms merging areas: " << (dur_total - dur_inc).count() / 1000000 << " ms";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2567,7 +2570,7 @@ static void set_points_on_areas(const SupportElement &elem, SupportElements *lay
|
||||||
// if the value was set somewhere else it it kept. This happens when a branch tries not to move after being unable to create a roof.
|
// if the value was set somewhere else it it kept. This happens when a branch tries not to move after being unable to create a roof.
|
||||||
if (! next_elem.state.result_on_layer_is_set()) {
|
if (! next_elem.state.result_on_layer_is_set()) {
|
||||||
// Move inside has edgecases (see tests) so DONT use Polygons.inside to confirm correct move, Error with distance 0 is <= 1
|
// Move inside has edgecases (see tests) so DONT use Polygons.inside to confirm correct move, Error with distance 0 is <= 1
|
||||||
// it is not required to check if how far this move moved a point as is can be larger than maximum_movement_distance.
|
// it is not required to check if how far this move moved a point as is can be larger than maximum_movement_distance.
|
||||||
// While this seems like a problem it may for example occur after merges.
|
// While this seems like a problem it may for example occur after merges.
|
||||||
next_elem.state.result_on_layer = move_inside_if_outside(next_elem.influence_area, elem.state.result_on_layer);
|
next_elem.state.result_on_layer = move_inside_if_outside(next_elem.influence_area, elem.state.result_on_layer);
|
||||||
// do not call recursive because then amount of layers would be restricted by the stack size
|
// do not call recursive because then amount of layers would be restricted by the stack size
|
||||||
|
@ -2592,9 +2595,9 @@ static void set_to_model_contact_simple(SupportElement &elem)
|
||||||
* \param layer_idx[in] The current layer.
|
* \param layer_idx[in] The current layer.
|
||||||
*/
|
*/
|
||||||
static void set_to_model_contact_to_model_gracious(
|
static void set_to_model_contact_to_model_gracious(
|
||||||
const TreeModelVolumes &volumes,
|
const TreeModelVolumes &volumes,
|
||||||
const TreeSupportSettings &config,
|
const TreeSupportSettings &config,
|
||||||
std::vector<SupportElements> &move_bounds,
|
std::vector<SupportElements> &move_bounds,
|
||||||
SupportElement &first_elem,
|
SupportElement &first_elem,
|
||||||
std::function<void()> throw_on_cancel)
|
std::function<void()> throw_on_cancel)
|
||||||
{
|
{
|
||||||
|
@ -2663,7 +2666,7 @@ static void remove_deleted_elements(std::vector<SupportElements> &move_bounds)
|
||||||
assert(i == layer.size() || i + 1 < layer.size());
|
assert(i == layer.size() || i + 1 < layer.size());
|
||||||
if (i + 1 < int32_t(layer.size())) {
|
if (i + 1 < int32_t(layer.size())) {
|
||||||
element = std::move(layer.back());
|
element = std::move(layer.back());
|
||||||
layer.pop_back();
|
layer.pop_back();
|
||||||
// Mark the current element as deleted.
|
// Mark the current element as deleted.
|
||||||
map_current[i] = -1;
|
map_current[i] = -1;
|
||||||
// Mark the moved element as moved to index i.
|
// Mark the moved element as moved to index i.
|
||||||
|
@ -2692,7 +2695,7 @@ static void create_nodes_from_area(
|
||||||
std::vector<SupportElements> &move_bounds,
|
std::vector<SupportElements> &move_bounds,
|
||||||
std::function<void()> throw_on_cancel)
|
std::function<void()> throw_on_cancel)
|
||||||
{
|
{
|
||||||
// Initialize points on layer 0, with a "random" point in the influence area.
|
// Initialize points on layer 0, with a "random" point in the influence area.
|
||||||
// Point is chosen based on an inaccurate estimate where the branches will split into two, but every point inside the influence area would produce a valid result.
|
// Point is chosen based on an inaccurate estimate where the branches will split into two, but every point inside the influence area would produce a valid result.
|
||||||
{
|
{
|
||||||
SupportElements *layer_above = move_bounds.size() > 1 ? &move_bounds[1] : nullptr;
|
SupportElements *layer_above = move_bounds.size() > 1 ? &move_bounds[1] : nullptr;
|
||||||
|
@ -2912,11 +2915,11 @@ static std::pair<int, int> discretize_circle(const Vec3f ¢er, const Vec3f &n
|
||||||
|
|
||||||
// Returns Z span of the generated mesh.
|
// Returns Z span of the generated mesh.
|
||||||
static std::pair<float, float> extrude_branch(
|
static std::pair<float, float> extrude_branch(
|
||||||
const std::vector<const SupportElement*> &path,
|
const std::vector<const SupportElement*>&path,
|
||||||
const TreeSupportSettings &config,
|
const TreeSupportSettings &config,
|
||||||
const SlicingParameters &slicing_params,
|
const SlicingParameters &slicing_params,
|
||||||
const std::vector<SupportElements> &move_bounds,
|
const std::vector<SupportElements> &move_bounds,
|
||||||
indexed_triangle_set &result)
|
indexed_triangle_set &result)
|
||||||
{
|
{
|
||||||
Vec3d p1, p2, p3;
|
Vec3d p1, p2, p3;
|
||||||
Vec3d v1, v2;
|
Vec3d v1, v2;
|
||||||
|
@ -2925,10 +2928,6 @@ static std::pair<float, float> extrude_branch(
|
||||||
assert(path.size() >= 2);
|
assert(path.size() >= 2);
|
||||||
static constexpr const float eps = 0.015f;
|
static constexpr const float eps = 0.015f;
|
||||||
std::pair<int, int> prev_strip;
|
std::pair<int, int> prev_strip;
|
||||||
|
|
||||||
// char fname[2048];
|
|
||||||
// static int irun = 0;
|
|
||||||
|
|
||||||
float zmin = 0;
|
float zmin = 0;
|
||||||
float zmax = 0;
|
float zmax = 0;
|
||||||
|
|
||||||
|
@ -3074,7 +3073,7 @@ static void organic_smooth_branches_avoid_collisions(
|
||||||
Vec3f position;
|
Vec3f position;
|
||||||
// Previous position, for Laplacian smoothing.
|
// Previous position, for Laplacian smoothing.
|
||||||
Vec3f prev_position;
|
Vec3f prev_position;
|
||||||
//
|
//
|
||||||
Vec3f last_collision;
|
Vec3f last_collision;
|
||||||
double last_collision_depth;
|
double last_collision_depth;
|
||||||
// Minimum Z for which the sphere collision will be evaluated.
|
// Minimum Z for which the sphere collision will be evaluated.
|
||||||
|
@ -3174,7 +3173,7 @@ static void organic_smooth_branches_avoid_collisions(
|
||||||
// Collision detected to be removed.
|
// Collision detected to be removed.
|
||||||
// Nudge the circle center away from the collision.
|
// Nudge the circle center away from the collision.
|
||||||
if (collision_sphere.last_collision_depth > EPSILON)
|
if (collision_sphere.last_collision_depth > EPSILON)
|
||||||
// a little bit of hysteresis to detect end of
|
// a little bit of hysteresis to detect end of
|
||||||
++ num_moved;
|
++ num_moved;
|
||||||
// Shift by maximum 2mm.
|
// Shift by maximum 2mm.
|
||||||
double nudge_dist = std::min(std::max(0., collision_sphere.last_collision_depth + collision_extra_gap), max_nudge_collision_avoidance);
|
double nudge_dist = std::min(std::max(0., collision_sphere.last_collision_depth + collision_extra_gap), max_nudge_collision_avoidance);
|
||||||
|
@ -3379,7 +3378,7 @@ static void generate_support_areas(Print &print, TreeSupport* tree_support, cons
|
||||||
// Generator for model collision, avoidance and internal guide volumes.
|
// Generator for model collision, avoidance and internal guide volumes.
|
||||||
TreeModelVolumes volumes{ print_object, build_volume, config.maximum_move_distance, config.maximum_move_distance_slow, processing.second.front(),
|
TreeModelVolumes volumes{ print_object, build_volume, config.maximum_move_distance, config.maximum_move_distance_slow, processing.second.front(),
|
||||||
#ifdef SLIC3R_TREESUPPORTS_PROGRESS
|
#ifdef SLIC3R_TREESUPPORTS_PROGRESS
|
||||||
m_progress_multiplier, m_progress_offset,
|
m_progress_multiplier, m_progress_offset,
|
||||||
#endif // SLIC3R_TREESUPPORTS_PROGRESS
|
#endif // SLIC3R_TREESUPPORTS_PROGRESS
|
||||||
/* additional_excluded_areas */{} };
|
/* additional_excluded_areas */{} };
|
||||||
|
|
||||||
|
@ -3396,8 +3395,7 @@ static void generate_support_areas(Print &print, TreeSupport* tree_support, cons
|
||||||
for (size_t i = 0; i < print_object.layer_count(); i++) {
|
for (size_t i = 0; i < print_object.layer_count(); i++) {
|
||||||
for (ExPolygon& expoly : print_object.get_layer(i)->loverhangs) {
|
for (ExPolygon& expoly : print_object.get_layer(i)->loverhangs) {
|
||||||
Polygons polys = to_polygons(expoly);
|
Polygons polys = to_polygons(expoly);
|
||||||
if (tree_support->overhang_types[&expoly] == TreeSupport::SharpTail) {
|
if (tree_support->overhang_types[&expoly] == TreeSupport::SharpTail) { polys = offset(polys, scale_(0.2));
|
||||||
polys = offset(to_polygons(expoly), scale_(0.2));
|
|
||||||
}
|
}
|
||||||
append(overhangs[i + num_raft_layers], polys);
|
append(overhangs[i + num_raft_layers], polys);
|
||||||
}
|
}
|
||||||
|
@ -3492,6 +3490,8 @@ static void generate_support_areas(Print &print, TreeSupport* tree_support, cons
|
||||||
bottom_contacts, top_contacts, interface_placer, intermediate_layers, layer_storage,
|
bottom_contacts, top_contacts, interface_placer, intermediate_layers, layer_storage,
|
||||||
throw_on_cancel);
|
throw_on_cancel);
|
||||||
|
|
||||||
|
//tree_support->move_bounds_to_contact_nodes(move_bounds, print_object, config);
|
||||||
|
|
||||||
remove_undefined_layers();
|
remove_undefined_layers();
|
||||||
|
|
||||||
std::tie(interface_layers, base_interface_layers) = generate_interface_layers(print_object.config(), support_params,
|
std::tie(interface_layers, base_interface_layers) = generate_interface_layers(print_object.config(), support_params,
|
||||||
|
|
|
@ -308,7 +308,7 @@ void organic_draw_branches(
|
||||||
SupportGeneratorLayersPtr &intermediate_layers,
|
SupportGeneratorLayersPtr &intermediate_layers,
|
||||||
SupportGeneratorLayerStorage &layer_storage,
|
SupportGeneratorLayerStorage &layer_storage,
|
||||||
|
|
||||||
std::function<void()> throw_on_cancel);
|
std::function<void()> throw_on_cancel);
|
||||||
|
|
||||||
} // namespace TreeSupport3D
|
} // namespace TreeSupport3D
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue