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

This commit is contained in:
Jack Ha 2018-02-01 17:31:43 +01:00
parent c432646908
commit 7856d61b5a
2 changed files with 67 additions and 17 deletions

View file

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

View file

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