Browse Source

grid placement available for elliptical buildplates

Co-authored-by: Casper Lamboo <c.lamboo@ultimaker.com>

CURA-7951
saumya.jain 1 year ago
parent
commit
4096fc864b

+ 1 - 1
cura/Arranging/ArrangeObjectsJob.py

@@ -15,7 +15,7 @@ i18n_catalog = i18nCatalog("cura")
 
 
 class ArrangeObjectsJob(Job):
-    def __init__(self, nodes: List[SceneNode], fixed_nodes: List[SceneNode], min_offset=8,
+    def __init__(self, nodes: List[SceneNode], fixed_nodes: List[SceneNode], min_offset = 8,
                  grid_arrange: bool = False) -> None:
         super().__init__()
         self._nodes = nodes

+ 73 - 17
cura/Arranging/GridArrange.py

@@ -18,10 +18,12 @@ class GridArrange:
 
     _nodes_to_arrange: List["SceneNode"]
     _fixed_nodes: List["SceneNode"]
-    _build_volume_bounding_box = AxisAlignedBox
+    _build_volume: "BuildVolume"
+    _build_volume_bounding_box: AxisAlignedBox
 
     def __init__(self, nodes_to_arrange: List["SceneNode"], build_volume: "BuildVolume", fixed_nodes: List["SceneNode"] = []):
         self._nodes_to_arrange = nodes_to_arrange
+        self._build_volume = build_volume
         self._build_volume_bounding_box = build_volume.getBoundingBox()
         self._fixed_nodes = fixed_nodes
 
@@ -39,7 +41,6 @@ class GridArrange:
         self._initial_leftover_grid_y = math.floor(self._initial_leftover_grid_y)
 
     def arrange(self)-> bool:
-
         grouped_operation, not_fit_count = self.createGroupOperationForArrange()
         grouped_operation.push()
         return not_fit_count == 0
@@ -51,6 +52,11 @@ class GridArrange:
             fixed_nodes_grid_ids = fixed_nodes_grid_ids.union(self.intersectingGridIdxInclusive(node.getBoundingBox()))
 
         build_plate_grid_ids = self.intersectingGridIdxExclusive(self._build_volume_bounding_box)
+
+        # Filter out the corner grid squares if the build plate shape is elliptic
+        if self._build_volume.getShape() == "elliptic":
+            build_plate_grid_ids = set(filter(lambda grid_id: self.checkGridUnderDiscSpace(grid_id[0], grid_id[1]), build_plate_grid_ids))
+
         allowed_grid_idx = build_plate_grid_ids.difference(fixed_nodes_grid_ids)
 
         # Find the sequence in which items are placed
@@ -86,7 +92,6 @@ class GridArrange:
             operation = self.moveNodeOnGrid(node, self._initial_leftover_grid_x, left_over_grid_y)
             grouped_operation.addOperation(operation)
             left_over_grid_y = left_over_grid_y - 1
-
         return grouped_operation, len(leftover_nodes)
 
     def moveNodeOnGrid(self, node: "SceneNode", grid_x: int, grid_y: int) -> "Operation.Operation":
@@ -138,6 +143,35 @@ class GridArrange:
         coord_y = (grid_y - self._build_volume_bounding_box.back) / (self._grid_height + self.offset_y)
         return coord_x, coord_y
 
+    def checkGridUnderDiscSpace(self, grid_x: int, grid_y: int) -> bool:
+        left, back = self.gridSpaceToCoordSpace(grid_x, grid_y)
+        right, front = self.gridSpaceToCoordSpace(grid_x + 1, grid_y + 1)
+        corners = [(left, back), (right, back), (right, front), (left, front)]
+        return all([self.checkPointUnderDiscSpace(x, y) for x, y in corners])
+
+    def checkPointUnderDiscSpace(self, x: float, y: float) -> bool:
+        disc_x, disc_y = self.coordSpaceToDiscSpace(x, y)
+        distance_to_center_squared = disc_x ** 2 + disc_y ** 2
+        return distance_to_center_squared <= 1.0
+
+    def coordSpaceToDiscSpace(self, x: float, y: float) -> Tuple[float, float]:
+        # Transform coordinate system to
+        #
+        #       coord_build_plate_left = -1
+        #       |               coord_build_plate_right = 1
+        #       v     (0,1)     v
+        #       ┌───────┬───────┐  < coord_build_plate_back = -1
+        #       │       │       │
+        #       │       │(0,0)  │
+        # (-1,0)│───────o───────┤(1,0)
+        #       │       │       │
+        #       │       │       │
+        #       └───────┴───────┘  < coord_build_plate_front = +1
+        #             (0,-1)
+        disc_x = ((x - self._build_volume_bounding_box.left) / self._build_volume_bounding_box.width) * 2.0 - 1.0
+        disc_y = ((y - self._build_volume_bounding_box.back) / self._build_volume_bounding_box.depth) * 2.0 - 1.0
+        return disc_x, disc_y
+
     def drawDebugSvg(self):
         with open("Builvolume_test.svg", "w") as f:
             build_volume_bounding_box = self._build_volume_bounding_box
@@ -145,25 +179,39 @@ class GridArrange:
             f.write(
                 f"<svg xmlns='http://www.w3.org/2000/svg' viewBox='{build_volume_bounding_box.left - 100} {build_volume_bounding_box.back - 100} {build_volume_bounding_box.width + 200} {build_volume_bounding_box.depth + 200}'>\n")
 
-            f.write(
-                f"""
-                <rect
-                    x='{build_volume_bounding_box.left}'
-                    y='{build_volume_bounding_box.back}'
-                    width='{build_volume_bounding_box.width}' 
-                    height='{build_volume_bounding_box.depth}' 
-                    fill=\"lightgrey\"
-                />
-                """)
+            ellipse = True
+            if ellipse:
+                f.write(
+                    f"""
+                    <ellipse
+                        cx='{(build_volume_bounding_box.left + build_volume_bounding_box.right) * 0.5}'
+                        cy='{(build_volume_bounding_box.back + build_volume_bounding_box.front) * 0.5}'
+                        rx='{build_volume_bounding_box.width * 0.5}' 
+                        ry='{build_volume_bounding_box.depth * 0.5}' 
+                        fill=\"blue\"
+                    />
+                    """)
+            else:
+                f.write(
+                    f"""
+                    <rect
+                        x='{build_volume_bounding_box.left}'
+                        y='{build_volume_bounding_box.back}'
+                        width='{build_volume_bounding_box.width}' 
+                        height='{build_volume_bounding_box.depth}' 
+                        fill=\"lightgrey\"
+                    />
+                    """)
 
-            for grid_x in range(-10, 10):
-                for grid_y in range(-10, 10):
+            for grid_x in range(0, 100):
+                for grid_y in range(0, 100):
                     # if (grid_x, grid_y) in intersecting_grid_idx:
                     #     fill_color = "red"
                     # elif (grid_x, grid_y) in build_plate_grid_idx:
                     #     fill_color = "green"
                     # else:
                     #     fill_color = "orange"
+
                     coord_grid_x, coord_grid_y = self.gridSpaceToCoordSpace(grid_x, grid_y)
                     f.write(
                         f"""
@@ -172,12 +220,13 @@ class GridArrange:
                             y="{coord_grid_y}"
                             width="{self._grid_width}" 
                             height="{self._grid_height}" 
-                            fill="green"
+                            fill="#ff00ff88"
                             stroke="black"
                         />
                         """)
                     f.write(f"""
                         <text 
+                            font-size="8"
                             x="{coord_grid_x + self._grid_width * 0.5}" 
                             y="{coord_grid_y + self._grid_height * 0.5}"
                         >
@@ -208,4 +257,11 @@ class GridArrange:
                         stroke-width="3"
                     />
                 """)
-            f.write(f"</svg>")
+
+            for x in range(math.floor(self._build_volume_bounding_box.left), math.floor(self._build_volume_bounding_box.right), 50):
+                for y in range(math.floor(self._build_volume_bounding_box.back), math.floor(self._build_volume_bounding_box.front), 50):
+                    color = "green" if self.checkPointUnderDiscSpace(x, y) else "red"
+                    f.write(f"""
+                      <circle cx="{x}" cy="{y}" r="10" fill="{color}" />
+                    """)
+            f.write(f"</svg>")

+ 3 - 0
cura/BuildVolume.py

@@ -203,6 +203,9 @@ class BuildVolume(SceneNode):
         if shape:
             self._shape = shape
 
+    def getShape(self) -> str:
+        return self._shape
+
     def getDiagonalSize(self) -> float:
         """Get the length of the 3D diagonal through the build volume.
 

+ 1 - 1
cura/CuraActions.py

@@ -80,7 +80,7 @@ class CuraActions(QObject):
                 center_y = 0
 
             # Move the object so that it's bottom is on to of the buildplate
-            center_operation = TranslateOperation(current_node, Vector(0, center_y, 0), set_position=True)
+            center_operation = TranslateOperation(current_node, Vector(0, center_y, 0), set_position = True)
             operation.addOperation(center_operation)
         operation.push()
     @pyqtSlot(int)

+ 0 - 16
resources/qml/Actions.qml

@@ -42,8 +42,6 @@ Item
     property alias reloadAll: reloadAllAction
     property alias arrangeAll: arrangeAllAction
     property alias arrangeAllGrid: arrangeAllGridAction
-    property alias arrangeSelection: arrangeSelectionAction
-    property alias arrangeSelectionLock: arrangeSelectionLockAction
     property alias resetAllTranslation: resetAllTranslationAction
     property alias resetAll: resetAllAction
 
@@ -470,20 +468,6 @@ Item
         shortcut: "Shift+Ctrl+R"
     }
 
-    Action
-    {
-        id: arrangeSelectionAction
-        text: catalog.i18nc("@action:inmenu menubar:edit","Arrange Selection")
-        onTriggered: Printer.arrangeSelection(false)
-    }
-
-    Action
-    {
-        id: arrangeSelectionLockAction
-        text: catalog.i18nc("@action:inmenu menubar:edit","Arrange Selection Without Rotation")
-        onTriggered: Printer.arrangeSelection(true)
-    }
-
     Action
     {
         id: resetAllTranslationAction