How to statically print string as canvas on terminal - Python - python

I'm learning and experimenting with the graphics stuff. In this little project, I'm trying to output the graphic result just by printing to the terminal without using other libraries. I have chosen to use python seems more straightforward to implement, and I can focus on understanding the maths. I will move back to C# or C++ later.
What I have implemented:
I have used a list to store all canvas values (two different symbols the ██ for the dots and ░░ for the background).
And I have created a function that creates a dot on the canvas. By taking x and y to calculate the position in the list and change the symbol.
Then I create a function that can draw a line by creating dots on the canvas.
Lastly, I have to use the projection matrix and rotation matrix to create a rotation cube on the canvas.
I have (kind of)successfully output the cube on the terminal and python shell. The shape is still a little bit weird, but I will work on that.
My question:
But when I want to print out like an animation, the output jiggles; sometimes, there are a few lines of delay. I have searched online and seen others creating ASCII graphic engines. Their production is at a fixed rate and fixed position. How can I print out the screen statically? Is there a way I don't need to implement other game engines or graphic libraries to complete the task?
Or do I need to create my window using API and output the result?
PS: I have used os.system('cls') to clear it each time, but it's too slow and is far from the high frame rate ASCII engine I've seen, and the delay still appears, which makes the canvas jiggles a bit.
Output Result:
https://www.youtube.com/watch?v=ZDe2IXKNpYk
Output code:
I just simple get all the values that plug into the list and print the canvas out
while 1:
createCanvas()
createAngleMatrix(angle)
setCube()
angle += 0.05
printCanvas(canvas)
time.sleep(0.05)
Thank you for your time reading or answering my question.
Updates:
I have found some different methods to stabilize the canvas. I have used os.system('cls'), but it's too slow and flickers. And I have tried using the '\r' in print by printing from the start of the line, but my canvas string contains a '\n' new line, so it doesn't work. Then I find the '\033[1A' and '\x1b[2K'which can clear line by line. But because the canvas is a brick of SCKII text, every time it deletes all and reprints again, it will flicker like crazy similar to using the os.system('cls'). But the update speed is very fast. Currently, the splashing effect caused by reprinting all over each time is the problem. Are there any other methods that can static print out the canvas?
The canvas at the end will be a string something like this:
['+++++++\n++++++\n++++++\n+++++++\n']
Update2:
As I have mentioned, I have used the remove line method, and I have created some tests for the rendering time. The coloring (I used the color escape code to color the text) has slowed down the render time, creating flickering. I have run some more tests, and the render time for the coloring will be about 4.5 to 6 seconds, and the black and white will only need 3 to 4.4 seconds for 100 frames. Is there any way I can improve this or other ways to output the canvas?
output result:
No color: https://youtu.be/q7ujCopm0bo
Color : https://youtu.be/cPvuxrcaWy4
Source code:
https://gist.github.com/KPLAYING77/417591578d01bd07e40ff846ec878773
I expected to output the canvas at a fixed rate in any size of the canvas and any size of the window.

Related

Is there a way to draw in the "background" using turtle?

Is there a way to have an image be created/drawn entirely without the actual Window that usually pops up when starting a turtle script showing up? The reason for this question is that while doing more research into another problem I posted here:
How to properly interact with turtle canvas/screen sizing?
I found that resizing the screen using maximize on the window actually altered what was capture when using .getcanvas() to be saved.
This wouldn't be a problem if I weren't attempting to create large images, larger than my monitors certainly. (around 15000 x 15000 pixels).
Thus I am wondering if there is a way to have the entire drawing process be done in the background. Without a window popping up at all. This way (I would hope at least) my images aren't becoming distorted or incorrectly sized due to buggy window interactions. As an example when I try to create an image this big, even with turtle.tracer(False) set it still flashes for a small amount of time (as the images are large and take time to complete) and while it is 'open' I cannot switch to it, it does not appear on my screen, it only appears on the task bar, which I can hover over and like with other applications 'preview' it without clicking on it, and it does not show there. However the image will be created and saved. But the dimensions are entirely wrong based on the code I used.
For a minimally repeatable example please look to the hyperlink to my related question. The code and subsequent image of that post is directly related to this question. But as the questions are different in nature I decided to create this post asking it.
Any feedback would be greatly appreciated as I cannot find any information in the documentation on how this might be done if it is possible at all. If anyone knows any good resources to directly contact regarding Turtle then that information would be welcomed as well.
I'm not sure if this will help to much but if you set the turtles speed to 0 then there will be no animation and the turtle will draw the picture instantly.
The code would look something like: turtle.speed(0)

Creating a "Fill" command in tk inter

I am pretty new to Python and coding in general. I have been working on a program that is similar in nature to ms paint. So far, I've added the capabilities to create multi-colored rectangles, lines, ovals, and really any polygon.
I've been using the tkinter GUI. I've been wanting to add a fill command, but I'm kind of stuck as to how to start it. My idea for how it would work would be that it would check the color of the pixel the user is currently hovering over, then check up, down, left, and right for the same color in pixels. If it found that, it would change the color of those pixels (I guess by creating a really small rectangle object?). This would theoretically be able to fill an area. But, I really can't find anything on how to access the color of a pixel in tkinter.
I know the location is event.x and event.y for a specific event, but I can't find anything about pixel color. I don't really have any code written for it yet because I am unsure that tkinter can even access the color of a pixel and not just object colors.
Unfortunately, this isn't possible. I did some searching around, and found several other similar questions, but the general idea is that Tkinter does not support such a feature. It makes sense, considering that Tkinter is a GUI library.
I saw a suggestion somewhere, where an idea was proposed to create 1x1 rectangles using the Tkinter Canvas to basically mimic pixels. However, this method eventually leads into performance issues and lagging, so it's not really recommended either.
You may want to try exploring some other libraries to work together with Tkinter. You can keep the Tkinter GUI, but use an image manipulation library or something similar which integrates well with Tkinter, for the actual pixel drawing.

Drawing graphics for LCDs

Im not sure if this is the correct place to ask this but as its more programming related than electronics I am posting here.
I have recently purchased a small LCD to experiment with. Its just one colour. Im using python to control it over serial.
My question is when it comes to the actual drawing. This whole area is completely new to me so I don't know if I am thinking the right way / going down the right path.
I want to be able to draw things on the LCD such as progress bars, animations (such as volume meters etc) and other simple - non text - based things. Just anything really.
In my mind the way I imagine doing this is by using python to draw a complete image of what I want on the LCD. Using PIL / Pillow for example and constantly redrawing and resending to the LCD.
So in the case of the progress bar, everything that's static is the same but then the progress bar rectangle for example would have its width altered each redraw.
I dont know if this it the correct way or if there are better ways or even if there are specific tools / modules for this kind of thing.

Fastest way of removing matplotlib artists from canvas embedded with wxpython

I have a python program where I have several matplotlib canvases embedded into a wxpython application. One of the canvases has many crosses in it. When the user right-click in this canvas the closest cross should be removed together with everything belonging to this cross (they are linked through an unique id-tag, and there might be things in every canvas that should be removed). I want the removing (or actually the replotting) to be as fast as possible. The program is quite large so I use several threads etc.
The easiest thing to implement this is to use wx.CallAfter(canvas.draw) for each canvas. However, there is a delay between the rightclick and the refresh of every canvas so I believe that canvas.draw() is too slow.
I saw two other functions for fast redrawing: the matplotlib functions blit() and draw_artist(). As far as I understand, blit() refreshes changed pixels inside some area (I used the axes bbox). I managed to get it to work with blit() in the sense that the program ran without crashing...but not updating what you see on the screen.
Did not manage to get draw_artist() to work when removing a pixel (tried using first line.remove(), then draw_artist(line) but the line was ofcourse already dead so draw_artist did not work).
Note: I called blit() and draw_artist() with wx.CallAfter()!
The feeling I have is that blit() is the best solution, but I did not manage to get it to update to the "screen-level". So my question is: what is the fastest and most resource-saving way of removing artists from matplotlib.canvases (embedded into wxPython) without redrawing more than you need to, but still let the change propagate to the screen?

Force repaint of wxPython Window, wxmpl plot

I'm having problems getting my wxPython window to refresh. It's currently plotting a graph using wxmpl which can be zoomed, panned, etc. On occasion the user may plot a large amount of data and zoom in on a small portion, which can cause it to 'freeze up'. By that I mean the plot itself is not updated, and the axis labels are drawn on top of each other. It is modifying the plot, just not displaying the updated info correctly. If you resize the window the plot is redrawn correctly.
I've spend an inordinate amount of time digging through source code and documentation for wx, wxmpl, and matplotlib... The best solution I've come up with is resizing the window to force a repaint (thus displaying the updated plot correctly).
# All of these fail - displays the same, incorrect plot
# (view is a wxmpl.PlotPanel object, which inherits from wx.Window among other things)
view.Refresh()
view.Update()
view.draw()
# This works, but is clearly less than ideal
view.SetSize((view.GetSize().width, view.GetSize().height+1))
view.SetSize((view.GetSize().width, view.GetSize().height-1))
There's got to be a better way - what I really want to know is what wx.Window.SetSize does to redraw the window, and just call that instead. Or, is there another method that I missed somewhere?
The panel.Layout() command is a great option because it is exactly the same method that is called when you resize your window. I also had trouble with the refresh and update methods. Layout seems to work when those two fail.
If you can't place it anywhere else, you could try
wx.Yield()
instead of Refresh or Update.
I would also try Show(False) and then Show(True) on the PlotPanel.
In a computational expensive application, where you are expecting something to be calculated for over 0.1 sec and probably have some user input it is not recommended usually to make those intense drawing in the GUI thread.
Not aware of your specific situation, but general approach if that you move all time consuming tasks (be it computation, image adjustment (e.g. scaling)) to the non GUI thread. Just a normal Python thread is fine, and once you have an long part complete, you refresh your GUI. During computation of course it would be a user friendly to display some sort of "waiting" sign. Also disable other controls, so bored user will not be able to change anything midway to your computation.
I was stuck with that issue since my early days with Java and later with Python, mostly in connection to network operations (which NEVER should be in GUI thread).
In case it is image adjusment (or graphics generation), which takes much time, background thread can prepare image in wxMemoryDC and then wxDC::Blit it to the window of your choice. I am not aware if this can be done with your component wxmpl.PlotPanel, so you will have to research this.

Categories