Merge branch '5.10' into CURA-12428_Changelog510

This commit is contained in:
Erwan MATHIEU 2025-03-10 16:00:56 +01:00 committed by GitHub
commit bc8ee22681
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 59 additions and 47 deletions

View File

@ -40,7 +40,7 @@ class ArrangeObjectsJob(Job):
found_solution_for_all = False
try:
found_solution_for_all = arranger.arrange()
found_solution_for_all = arranger.arrange(only_if_full_success = True)
except: # If the thread crashes, the message should still close
Logger.logException("e",
"Unable to arrange the objects on the buildplate. The arrange algorithm has crashed.")

View File

@ -16,12 +16,16 @@ class Arranger:
"""
raise NotImplementedError
def arrange(self, add_new_nodes_in_scene: bool = False) -> bool:
def arrange(self, add_new_nodes_in_scene: bool = False, only_if_full_success: bool = False) -> bool:
"""
Find placement for a set of scene nodes, and move them by using a single grouped operation.
:param add_new_nodes_in_scene: Whether to create new scene nodes before applying the transformations and rotations
:return: found_solution_for_all: Whether the algorithm found a place on the buildplate for all the objects
"""
grouped_operation, not_fit_count = self.createGroupOperationForArrange(add_new_nodes_in_scene)
grouped_operation.push()
return not_fit_count == 0
full_success = not_fit_count == 0
if full_success or not only_if_full_success:
grouped_operation.push()
return full_success

View File

@ -54,22 +54,6 @@ class Nest2DArrange(Arranger):
machine_depth = self._build_volume.getDepth() - (edge_disallowed_size * 2)
build_plate_bounding_box = Box(int(machine_width * self._factor), int(machine_depth * self._factor))
if self._fixed_nodes is None:
self._fixed_nodes = []
# Add all the items we want to arrange
node_items = []
for node in self._nodes_to_arrange:
hull_polygon = node.callDecoration("getConvexHull")
if not hull_polygon or hull_polygon.getPoints is None:
Logger.log("w", "Object {} cannot be arranged because it has no convex hull.".format(node.getName()))
continue
converted_points = []
for point in hull_polygon.getPoints():
converted_points.append(Point(int(point[0] * self._factor), int(point[1] * self._factor)))
item = Item(converted_points)
node_items.append(item)
# Use a tiny margin for the build_plate_polygon (the nesting doesn't like overlapping disallowed areas)
half_machine_width = 0.5 * machine_width - 1
half_machine_depth = 0.5 * machine_depth - 1
@ -80,40 +64,66 @@ class Nest2DArrange(Arranger):
[half_machine_width, half_machine_depth]
], numpy.float32))
disallowed_areas = self._build_volume.getDisallowedAreas()
for area in disallowed_areas:
converted_points = []
def _convert_points(points):
if points is not None and len(points) > 2: # numpy array has to be explicitly checked against None
converted_points = []
for point in points:
converted_points.append(Point(int(point[0] * self._factor), int(point[1] * self._factor)))
return [converted_points]
else:
return []
polygons_nodes_to_arrange = []
for node in self._nodes_to_arrange:
hull_polygon = node.callDecoration("getConvexHull")
if not hull_polygon or hull_polygon.getPoints is None:
Logger.log("w", "Object {} cannot be arranged because it has no convex hull.".format(node.getName()))
continue
polygons_nodes_to_arrange += _convert_points(hull_polygon.getPoints())
polygons_disallowed_areas = []
for area in self._build_volume.getDisallowedAreas():
# Clip the disallowed areas so that they don't overlap the bounding box (The arranger chokes otherwise)
clipped_area = area.intersectionConvexHulls(build_plate_polygon)
if clipped_area.getPoints() is not None and len(
clipped_area.getPoints()) > 2: # numpy array has to be explicitly checked against None
for point in clipped_area.getPoints():
converted_points.append(Point(int(point[0] * self._factor), int(point[1] * self._factor)))
polygons_disallowed_areas += _convert_points(clipped_area.getPoints())
disallowed_area = Item(converted_points)
polygons_fixed_nodes = []
if self._fixed_nodes is None:
self._fixed_nodes = []
for node in self._fixed_nodes:
hull_polygon = node.callDecoration("getConvexHull")
if hull_polygon is not None:
polygons_fixed_nodes += _convert_points(hull_polygon.getPoints())
strategies = [NfpConfig.Alignment.CENTER,
NfpConfig.Alignment.BOTTOM_LEFT,
NfpConfig.Alignment.BOTTOM_RIGHT,
NfpConfig.Alignment.TOP_LEFT,
NfpConfig.Alignment.TOP_RIGHT]
found_solution_for_all = False
while not found_solution_for_all and len(strategies) > 0:
# Add all the items we want to arrange
node_items = []
for polygon in polygons_nodes_to_arrange:
node_items.append(Item(polygon))
for polygon in polygons_disallowed_areas:
disallowed_area = Item(polygon)
disallowed_area.markAsDisallowedAreaInBin(0)
node_items.append(disallowed_area)
for node in self._fixed_nodes:
converted_points = []
hull_polygon = node.callDecoration("getConvexHull")
if hull_polygon is not None and hull_polygon.getPoints() is not None and len(
hull_polygon.getPoints()) > 2: # numpy array has to be explicitly checked against None
for point in hull_polygon.getPoints():
converted_points.append(Point(int(point[0] * self._factor), int(point[1] * self._factor)))
item = Item(converted_points)
for polygon in polygons_fixed_nodes:
item = Item(polygon)
item.markAsFixedInBin(0)
node_items.append(item)
strategies = [NfpConfig.Alignment.CENTER] * 3 + [NfpConfig.Alignment.BOTTOM_LEFT] * 3
found_solution_for_all = False
while not found_solution_for_all and len(strategies) > 0:
config = NfpConfig()
config.accuracy = 1.0
config.alignment = NfpConfig.Alignment.CENTER
config.alignment = NfpConfig.Alignment.DONT_ALIGN
config.starting_point = strategies[0]
strategies = strategies[1:]

View File

@ -84,6 +84,7 @@ class MultiplyObjectsJob(Job):
arranger = Nest2DArrange(nodes, Application.getInstance().getBuildVolume(), fixed_nodes, factor=1000)
group_operation, not_fit_count = arranger.createGroupOperationForArrange(add_new_nodes_in_scene=True)
found_solution_for_all = not_fit_count == 0
if nodes_to_add_without_arrange:
for nested_node in nodes_to_add_without_arrange:

View File

@ -92,10 +92,10 @@
"cool_min_temperature": { "value": "material_print_temperature-15" },
"default_material_print_temperature": { "maximum_value_warning": 320 },
"extra_infill_lines_to_support_skins": { "value": "'walls_and_lines'" },
"flooring_layer_count": { "value": "1" },
"flooring_layer_count": { "value": 0 },
"gradual_flow_enabled": { "value": false },
"hole_xy_offset": { "value": 0.075 },
"infill_material_flow": { "value": "1.1*material_flow" },
"infill_material_flow": { "value": "material_flow" },
"infill_overlap": { "value": 10 },
"infill_pattern": { "value": "'zigzag' if infill_sparse_density > 80 else 'grid'" },
"infill_sparse_density": { "value": 15 },
@ -374,7 +374,7 @@
"speed_travel":
{
"maximum_value": 500,
"value": 500
"value": 400
},
"speed_travel_layer_0":
{
@ -427,7 +427,6 @@
"support_tree_bp_diameter": { "value": 15 },
"support_tree_tip_diameter": { "value": 1.0 },
"support_tree_top_rate": { "value": 20 },
"support_wall_count": { "value": 2 },
"support_xy_distance_overhang": { "value": "machine_nozzle_size" },
"support_z_distance": { "value": "0.4*material_shrinkage_percentage_z/100.0" },
"top_bottom_thickness": { "value": "round(4*layer_height, 2)" },

View File

@ -397,8 +397,6 @@
"z_seam_corner": { "value": "'z_seam_corner_inner'" },
"z_seam_position": { "value": "'backleft'" },
"z_seam_type": { "value": "'sharpest_corner'" },
"z_seam_x": { "value": 150 },
"z_seam_y": { "value": 180 },
"zig_zaggify_infill": { "value": true }
}
}