Displaying CadQuery data in a QT5 window in Python - python

I wrote a python program using the PyQt5 libraries. This program I can make into an executable with pyinstaller.
I would like to add the functionality to show a 3D cad image based on user inputs. The CadQuery package has a nice intuitive approach and I would like to use it.
From the OCC.Display.qtDisplay I take my viewer. The problem is that the viewer does not accept the workplanes generated by CadQuery. I prefer not to export to files, but directly port the results from the cad generator to the viewer. Does anyone have any suggestions or experiences?
The following (partial) code works to display an AIS shape:
import OCC.Display.qtDisplay as qtDisplay
import cadquery as cq
self.canvas = qtDisplay.qtViewer3d(self)
self.horizontalLayout.addWidget(self.canvas)
a_box = BRepPrimAPI_MakeBox(10., 20., 30.).Shape()
self.ais_box = self.canvas._display.DisplayShape(a_box)[0]
self.canvas._display.FitAll()
but adding the following code (including the example bottle) does not:
self.makebottle()
self.canvas._display.DisplayShape(self.result.solids())
self.canvas._display.FitAll()
def makebottle(self):
(L,w,t) = (20.0, 6.0, 3.0)
s = cq.Workplane("XY")
# Draw half the profile of the bottle and extrude it
p = (s.center(-L/2.0, 0).vLine(w/2.0)
.threePointArc((L/2.0, w/2.0 + t),(L, w/2.0)).vLine(-w/2.0)
.mirrorX().extrude(30.0,True))
#make the neck
p = p.faces(">Z").workplane(centerOption="CenterOfMass").circle(3.0).extrude(2.0,True)
#make a shell
self.result = p.faces(">Z").shell(0.3)
Should I try to convert the workplanes? or use another package to make this work.

Related

Rendering in blender dont take rotation updates of camera and light directions

I'm trying to render a cube (default blender scene) with a camera facing it. I have added a spotlight at the same location as the camera. Spotlight direction also faces towards the cube.
When I render, location changes take effect for both camera and spotlight but, rotations don't. scene context update is deprecated now. I have seen other update answers, but they don't seem to help.
I have done some workarounds and they seem to work, but this is not the correct way.
If I render the same set of commands twice (in a loop), I get the correct render.
If I run the script from the blender's python console (only once), I get the correct render. But If the same code is run as a script inside the blender, render is again wrong.
import pdb
import numpy as np
import bpy
def look_at(obj_camera, point):
loc_camera = obj_camera.matrix_world.to_translation()
direction = point - loc_camera
rot_quat = direction.to_track_quat('-Z', 'Y')
obj_camera.rotation_euler = rot_quat.to_euler()
data_path='some folder'
locs=np.array([ 0.00000000e+00, -1.00000000e+01, 3.00000011e-06]) #Assume, (I have big array where camera and spotlight needs to be placed, and then made to look towards cube)
obj_camera = bpy.data.objects["Camera"]
obj_other = bpy.data.objects["Cube"]
bpy.data.lights['Light'].type='SPOT'
obj_light=bpy.data.objects['Light']
loc=locs
i=0
##### if I run following lines two times, correct render is obtained.
obj_camera.location = loc
obj_light.location= obj_camera.location
look_at(obj_light, obj_other.matrix_world.to_translation())
look_at(obj_camera, obj_other.matrix_world.to_translation())
bpy.context.scene.render.filepath = data_path+'image_{}.png'.format(i)
bpy.ops.render.render(write_still = True)
You might need to call bpy.context.view_layer.update() (bpy.context.scene.update() with older versions than blender 2.8) after changing the camera orientation by obj_camera.rotation_euler = rot_quat.to_euler() and make sure that the layers that are going to be rendered are active when calling update() (see here https://blender.stackexchange.com/questions/104958/object-locations-not-updating-before-render-python).
(A bit late ;-) but this was one of the rare questions I found for a related issue.)

How do I make a 800x800 console window with python

I've recently been making a simple text based game in python 3.9 and I want to make it so when you run the .exe it will open a console window that is 800x800 or whatever ratio I want to put in. Could anyone help me do this please!
The only option that i can think of its to run tour program in PowerShell, this one can resize it self with something like this
$pshost = get-host
$pswindow = $pshost.ui.rawui
$newsize = $pswindow.buffersize
$newsize.height = 3000
$newsize.width = 150
$pswindow.buffersize = $newsize
$newsize = $pswindow.windowsize
$newsize.height = 50
$newsize.width = 150
$pswindow.windowsize = $newsize
I get this code from here
You can call this commands inside python with OS module.
I couldnt test the code cause #teamLinux.

Exporting animated Bokeh plots as GIF

I've been looking into using the Bokeh library to create animated data visualisations for some small projects I am working on. I feel that the gif format would be the best file format to export these visualisations in. It is widely used and they should be easy to share.
Is it possible (and advisable) to export bokeh animated plots in the gif format?
If so, will I need to make use of any additional tools to do this?
If not, is there a different file format that would be better suited to this?
I found this thread about potential options for creating gifs in Python, but I'm not sure if any of them are relevant to the Bokeh library. Programmatically generate video or animated GIF in Python?
Any help would be much appreciated. Many thanks.
Bokeh plot has a SaveTool which allows you to save the plot canvas manually in PNG format but this would be a lot of work for you to do. Alternatively you could automate this process by implementing Bokeh server app with update() function that updates the data_source property of your plot e.g. each second and saves a screenshot using export_png() function. Then you could use those images to build an animation e.g. using the Python lib you mentioned above.
This is an example script to run with bokeh serve --show app.py:
The content of app.py:
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure, curdoc
from datetime import datetime
from bokeh.io import export_png
import random
source = ColumnDataSource(dict(time = [datetime.now()], value = [random.randint(5, 10)]))
plot = figure(plot_width = 1200, x_axis_type = 'datetime', tools = 'pan,box_select,crosshair,reset,save,wheel_zoom')
plot.line(x = 'time', y = 'value', line_color = 'black', source = source)
counter = 0
def update():
global counter
new_source_data = dict(time = [datetime.now()], value = [random.randint(5, 10)])
source.stream(new_source_data)
counter = counter + 1
export_png(plot, filename = "plot_" + str(counter) + ".png")
curdoc().add_root(plot)
curdoc().add_periodic_callback(update, 1000)
To make this script work you need to have phantomjs installed on your system. So first you need to install nodejs and npm, then install phantomjs like this:
sudo npm install -g phantomjs-prebuilt
If you are using Mac then another option is to use QuickTime Player screen recording to make a movie and then convert it into an animated gif using FFMPEG like explained in this post

Buffer function for python 3+

I'm trying to open a vtk window using vtk_show, but my Ipython console crashes every time i do this, apparently this is because Ipython can't display an external window, which is exactly what vtk_show does. I searched on google for a solution, but it's written for python2 (i'm using python 3.6.3). Here's the solution i found:
import vtk
from IPython.display import Image
def vtk_show(renderer, width=400, height=300):
"""
Takes vtkRenderer instance and returns an IPython Image with the
rendering.
"""
renderWindow = vtk.vtkRenderWindow()
renderWindow.SetOffScreenRendering(1)
renderWindow.AddRenderer(renderer)
renderWindow.SetSize(width, height)
renderWindow.Render()
windowToImageFilter = vtk.vtkWindowToImageFilter()
windowToImageFilter.SetInput(renderWindow)
windowToImageFilter.Update()
writer = vtk.vtkPNGWriter()
writer.SetWriteToMemory(1)
writer.SetInputConnection(windowToImageFilter.GetOutputPort())
writer.Write()
data = str(buffer(writer.GetResult()))
return Image(data)
I'm getting an error while trying to use the buffer built-in function of python2, but as this function doesn't exist on python3+ i'm stuck.. If anyone could help me with this i would be very appreciated. Thanks in advance!
At least these two points must be modified on your code to have the same behavior with Python 3:
The buffer(...) built-in function in Python 2 has been replaced by memoryview(...) in Python 3: What is Python buffer type for?. Replace the buffer call by memoryview
the str(...) built-in function has to replaced by a bytes(...) call to get a bytes object: https://docs.python.org/2/howto/pyporting.html#text-versus-binary-data
So the data = ... line should read:
data = bytes(memoryview(writer.GetResult()))
To clarify, I believe this example was an adaptation of a very informative blog example showing how to extract surfaces from medical images using VTK's marching cubes algorithm. The accompanying Jupyter notebook was intended for Python 2.7, and as mentioned for it to be used in Python 3.6+, the data=... portion needs to be changed.
import vtk
from IPython.display import Image
def vtk_show(renderer, width=400, height=300):
"""
Takes vtkRenderer instance and returns an IPython Image with the
rendering.
"""
renderWindow = vtk.vtkRenderWindow()
renderWindow.SetOffScreenRendering(1)
renderWindow.AddRenderer(renderer)
renderWindow.SetSize(width, height)
renderWindow.Render()
windowToImageFilter = vtk.vtkWindowToImageFilter()
windowToImageFilter.SetInput(renderWindow)
windowToImageFilter.Update()
writer = vtk.vtkPNGWriter()
writer.SetWriteToMemory(1)
writer.SetInputConnection(windowToImageFilter.GetOutputPort())
writer.Write()
data = memoryview(writer.GetResults()).tobytes()
return Image(data)
Credit for the solution definitely goes to #MafiaSkafia and #jcgiret, but I wanted to post a full and final solution.

Are there any toolkit libraries for curses with Python bindings?

I'm writing a text-based hex viewer for fun and usefulness(I intend to add syntax highlighting for many different filetypes), and am wondering if there are any curses toolkits I could use.
I will probably write something myself anyway as to familiarize myself with the way gui toolkits work, but it would be nice to know of useful libraries for future reference for myself and others.
Urwid is the best library to work with curses and python that I know.
Altenatively, you might find also interesting snack (newt-based library).
For more information, please have a look at this question.
npyscreen
Npyscreen is a Python widget library and application framework for programming terminal or console applications. It is built on top of ncurses, which is part of the standard library.
The focus of this library is to provide a rapid way to develop console applications. In general, adding a control to the screen requires only one line of code.
This framework should be powerful enough to create everything from quick, simple programs to complex, multi-screen applications.
#!/usr/bin/env python
# encoding: utf-8
import npyscreen
class TestApp(npyscreen.NPSApp):
def main(self):
# These lines create the form and populate it with widgets.
# A fairly complex screen in only 8 or so lines of code - a line for each control.
F = npyscreen.Form(name = "Welcome to Npyscreen",)
t = F.add(npyscreen.TitleText, name = "Text:",)
fn = F.add(npyscreen.TitleFilename, name = "Filename:")
fn2 = F.add(npyscreen.TitleFilenameCombo, name="Filename2:")
dt = F.add(npyscreen.TitleDateCombo, name = "Date:")
s = F.add(npyscreen.TitleSlider, out_of=12, name = "Slider")
ml = F.add(npyscreen.MultiLineEdit,
value = """try typing here!\nMutiline text, press ^R to reformat.\n""",
max_height=5, rely=9)
ms = F.add(npyscreen.TitleSelectOne, max_height=4, value = [1,], name="Pick One",
values = ["Option1","Option2","Option3"], scroll_exit=True)
ms2= F.add(npyscreen.TitleMultiSelect, max_height =-2, value = [1,], name="Pick Several",
values = ["Option1","Option2","Option3"], scroll_exit=True)
# This lets the user interact with the Form.
F.edit()
print(ms.get_selected_objects())
if __name__ == "__main__":
App = TestApp()
App.run()
On GitHub there is a free to use, study, modify and re-distribute High Level GUI library, at "https://github.com/rigordo959/tsWxGTUI_PyVx_Repository".
It is implemented in Python 2x & 3x using the "curses" Low Level GUI package.
Your application programs can be programmed using a character-mode subset of the pixel-mode "wxPython" High Level GUI API. It supports displays with keyboard and mouse input and various terminal emulators including the color xterms (8-color with 64-color pairs and 16-color with 256-color pairs) and non-color vt100/vt220.

Categories

Resources