Browse Source

CURA-4425 scale image to full size; still has a bug that it is shifted vertically; still need to clean code

Jack Ha 7 years ago
parent
commit
7856d61b5a
2 changed files with 67 additions and 17 deletions
  1. 0 1
      cura/Scene/CuraSceneNode.py
  2. 67 16
      cura/Snapshot.py

+ 0 - 1
cura/Scene/CuraSceneNode.py

@@ -1,7 +1,6 @@
 from typing import List
 
 from UM.Application import Application
-from UM.Logger import Logger
 from UM.Scene.SceneNode import SceneNode
 from copy import deepcopy
 from cura.Settings.ExtrudersModel import ExtrudersModel

+ 67 - 16
cura/Snapshot.py

@@ -1,13 +1,17 @@
 # Copyright (c) 2018 Ultimaker B.V.
 # Cura is released under the terms of the LGPLv3 or higher.
+import numpy
+
 from PyQt5 import QtCore
 
 from cura.PreviewPass import PreviewPass
+from cura.Scene import ConvexHullNode
 
 from UM.Application import Application
 from UM.Math.AxisAlignedBox import AxisAlignedBox
 from UM.Math.Matrix import Matrix
 from UM.Math.Vector import Vector
+from UM.Mesh.MeshData import transformVertices
 from UM.Scene.Camera import Camera
 from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
 
@@ -25,18 +29,33 @@ class Snapshot:
 
         # determine zoom and look at
         bbox = None
+        hulls = None
         for node in DepthFirstIterator(root):
+            if type(node) == ConvexHullNode:
+                print(node)
             if node.callDecoration("isSliceable") and node.getMeshData() and node.isVisible():
                 if bbox is None:
                     bbox = node.getBoundingBox()
                 else:
                     bbox = bbox + node.getBoundingBox()
+                convex_hull = node.getMeshData().getConvexHullTransformedVertices(node.getWorldTransformation())
+                if hulls is None:
+                    hulls = convex_hull
+                else:
+                    hulls = numpy.concatenate((hulls, convex_hull), axis = 0)
+
         if bbox is None:
             bbox = AxisAlignedBox()
 
         look_at = bbox.center
         size = max(bbox.width, bbox.height, bbox.depth * 0.5)
 
+        # Somehow the aspect ratio is also influenced in reverse by the screen width/height
+        # So you have to set it to render_width/render_height to get 1
+        projection_matrix = Matrix()
+        projection_matrix.setPerspective(30, render_width / render_height, 1, 500)
+        camera.setProjectionMatrix(projection_matrix)
+
         looking_from_offset = Vector(1, 1, 2)
         if size > 0:
             # determine the watch distance depending on the size
@@ -46,28 +65,60 @@ class Snapshot:
         camera.setPosition(look_at + looking_from_offset)
         camera.lookAt(look_at)
 
-        # Somehow the aspect ratio is also influenced in reverse by the screen width/height
-        # So you have to set it to render_width/render_height to get 1
-        projection_matrix = Matrix()
-        projection_matrix.setPerspective(30, render_width / render_height, 1, 500)
-
-        camera.setProjectionMatrix(projection_matrix)
+        # we need this for the projection calculation
+        hulls4 = numpy.ones((hulls.shape[0], 4))
+        hulls4[:, :-1] = hulls
+        #position = Vector(10, 10, 10)
+        # projected_position = camera.project(position)
 
         preview_pass.setCamera(camera)
         preview_pass.setSize(render_width, render_height)  # texture size
         preview_pass.render()
         pixel_output = preview_pass.getOutput()
 
-        # It's a bit annoying that window size has to be taken into account
-        if pixel_output.width() >= pixel_output.height():
-            # Scale it to the correct height
-            image = pixel_output.scaledToHeight(height, QtCore.Qt.SmoothTransformation)
-            # Then chop of the width
-            cropped_image = image.copy(image.width() // 2 - width // 2, 0, width, height)
+        print("Calculating image coordinates...")
+        view = camera.getWorldTransformation().getInverse()
+        min_x, max_x, min_y, max_y = render_width, 0, render_height, 0
+        for hull_coords in hulls4:
+            projected_position = view.getData().dot(hull_coords)
+            projected_position2 = projection_matrix.getData().dot(projected_position)
+            #xx, yy = camera.project(Vector(data = hull_coords))
+            # xx, yy range from -1 to 1
+            xx = projected_position2[0] / projected_position2[2] / 2.0
+            yy = projected_position2[1] / projected_position2[2] / 2.0
+            # x, y 0..render_width/height
+            x = int(render_width / 2 + xx * render_width / 2)
+            y = int(render_height / 2 + yy * render_height / 2)
+            min_x = min(x, min_x)
+            max_x = max(x, max_x)
+            min_y = min(y, min_y)
+            max_y = max(y, max_y)
+        print(min_x, max_x, min_y, max_y)
+
+        # print("looping all pixels in python...")
+        # min_x_, max_x_, min_y_, max_y_ = render_width, 0, render_height, 0
+        # for y in range(int(render_height)):
+        #     for x in range(int(render_width)):
+        #         color = pixel_output.pixelColor(x, y)
+        #         if color.alpha() > 0:
+        #             min_x_ = min(x, min_x_)
+        #             max_x_ = max(x, max_x_)
+        #             min_y_ = min(y, min_y_)
+        #             max_y_ = max(y, max_y_)
+        # print(min_x_, max_x_, min_y_, max_y_)
+
+        # make it a square
+        if max_x - min_x >= max_y - min_y:
+            # make y bigger
+            min_y, max_y = int((max_y + min_y) / 2 - (max_x - min_x) / 2), int((max_y + min_y) / 2 + (max_x - min_x) / 2)
         else:
-            # Scale it to the correct width
-            image = pixel_output.scaledToWidth(width, QtCore.Qt.SmoothTransformation)
-            # Then chop of the height
-            cropped_image = image.copy(0, image.height() // 2 - height // 2, width, height)
+            # make x bigger
+            min_x, max_x = int((max_x + min_x) / 2 - (max_y - min_y) / 2), int((max_x + min_x) / 2 + (max_y - min_y) / 2)
+        copy_pixel_output = pixel_output.copy(min_x, min_y, max_x - min_x, max_y - min_y)
+
+        # Scale it to the correct height
+        image = copy_pixel_output.scaledToHeight(height, QtCore.Qt.SmoothTransformation)
+        # Then chop of the width
+        cropped_image = image.copy(image.width() // 2 - width // 2, 0, width, height)
 
         return cropped_image