Get the current coordinates of an item on a Canvas widget given its item handle? - python

From reading the docs (http://effbot.org/tkinterbook/canvas.htm#reference), there doesn't appear to me to be a way to do this. Just wanted to make sure I hadn't made a mistake. (I.e. one would have to internally store the coordinates of various items in a program if one wanted to do boundary checking, for example. [e.g. Check, before moving an oval, that it will not bump into a wall, represented by a line on the current canvas, the coordinate information of which is also stored.])

Use the coords method:
coords = the_canvas.coords(item_id)

Related

updating chosen elements in Pygame

I am working on animation of Fourier Transform in python, pygame. I want the result to look more or less as following:
https://www.youtube.com/watch?v=ACvXAjZE9jQ
I need to update the screen in order to constantly draw arms, or links in their new positions. However, updating the screen erases the graph drawn by the arms. I am drawing it by putting small dots in time intervals.
Would anyone have any suggestion how to deal with this dilemma or propose another solution?
My first idea was to add all the points coordinates to the list and draw them all together at every update, but the operation quickly becomes too inefficient and the animation keeps slowing dowm.
My first idea was to add all the points coordinates to the list and draw them all together at every update
This is the usual approach. However, I suggest converting the coordinates to int before adding them to the list, and only adding coordinate tuples that are not already in the list. This means that a new position must be compared with the last position before it is added. With this approach, the list should not become so long that the application slows down significantly. e.g.:
def appendPoint(point_list, x, y):
new_point = round(x), round(y)
if not point_list or point_list[-1] != new_point:
point_list.append(new_point)

How can I make a rectangle in pygame be able to check for other rectangles around it?

As part of my current pygame project (I am very new to pygame), I have created multiple rectangles that move at random around the screen. As one of the features of this game, I want to make it so if one rectangle is close enough to another one, it moves towards it. Another feature I want to add is that rectangles cannot collide with each other, but I don't want to just do the regular
if rectangle1.colliderect(rectangle2):
rectange.x -= 10 # That is, it's previous position
because it will make the animations look odd.
The main way I can see to solve these problems is to use some sort of function that could check if a rectangle.x - 30 is another rectangle (or something similar), but I am unaware of one that exists.
I have attempted to look through google, but I haven't found anything as all the posts are different problems that aren't quite the same.
Thank you for any responses!
Use inflate to create a rectangle that is larger than the original one and surrounds it. Use this rectangle to find other rectangles in range:
test_rect = rect1.inflate(dist, dist)
if test_rect.colliderect(rect2):
# [...]

Dividing canvas to regions, then attracting nearby items to the nearest region?

I'm creating GUI using python tkinter to visualize Road Scenarios (the main vehicle & close by vehicles). I draw in the canvas lines to give road top view (as the Picture below).
The user can insert a rectangle (vehicle) then move it freely on the canvas.
What I want is: after the user moves the rectangle to where ever he wants, the y coordination of the rectangle will relocate to the nearest lane, to have a nice looking png at the end.
My thought about it:
Divide the canvas to regions (each Region represent a lane)
Create a function which knows when the rectangle finished moving, then modify the y coordination of it to the nearest Region (lane).
Not sure how to apply this in Code though. Any useful canvas functions or another approach are much appreciated.
The approach I mentioned at the question worked for me.
A list identifing the y-axis sides of each Region was created.
After creating the items needed, they all share a common Tag.
Choose which part of the items you want to consider the original Point (which will be used later as the item's current location). Canvas.bboc(CURRENT) can be sufficient to do that.
Detect when does the item enter a Region, by comparing if the item's current Location is within the boundaries of a Region.
Use Canvas.coords() or Cancas.move() methods to move the items at the middle of the regoin they have entered.

Modify polygons so that they don't overlap and area stays the same

I have a set of polygons and they can overlap with each other, like this:
I want to modify them in such a way that they don't overlap and the resulting surface area stays the same. Something like this:
It is okay if the shape or the position changes. The main thing is that they should not overlap with each other and the area should not change much (I know the area changed a little in the second image but I drew it manually thus let's just assume that the areas did not change).
I am trying to do it programmatically with the help of Python. Basically I stored polygons in a PostGIS database and with the help of a script I want to retrieve them and modify them.
I am very new to GIS and thus this seems like a difficult task.
What is the correct way of doing it? Is there an algorithm that solves this kind of problems?
Take a look at ST_buffer and try passing a signed float as the second argument (degrees to reduce radius by)
SELECT buffer(the_geom,-0.01) as geom
Be careful with negative buffers as you could run into issues if the buffer size exceeds the radius, see here.
Here is what I did:
Iterated over all the polygons and found overlapping polygons. Then, I moved the polygon in different directions and found the best moving direction by calculating the minimum resulting overlapping area. Then I simply moved the polygon in that best direction until there is no overlapping area.

How to clear Tkinter Canvas?

When I draw a shape using:
canvas.create_rectangle(10, 10, 50, 50, color="green")
Does Tkinter keep track of the fact that it was created?
In a simple game I'm making, my code has one Frame create a bunch of rectangles, and then draw a big black rectangle to clear the screen, and then draw another set of updated rectangles, and so on.
Am I creating thousands of rectangle objects in memory?
I know you can assign the code above to a variable, but if I don't do that and just draw directly to the canvas, does it stay in memory, or does it just draw the pixels, like in the HTML5 canvas?
Every canvas item is an object that Tkinter keeps track of. If you are clearing the screen by just drawing a black rectangle, then you effectively have created a memory leak -- eventually your program will crash due to the millions of items that have been drawn.
To clear a canvas, use the delete method. Give it the special parameter "all" to delete all items on the canvas (the string "all"" is a special tag that represents all items on the canvas):
canvas.delete("all")
If you want to delete only certain items on the canvas (such as foreground objects, while leaving the background objects on the display) you can assign tags to each item. Then, instead of "all", you could supply the name of a tag.
If you're creating a game, you probably don't need to delete and recreate items. For example, if you have an object that is moving across the screen, you can use the move or coords method to move the item.
Items drawn to the canvas are persistent. create_rectangle returns an item id that you need to keep track of. If you don't remove old items your program will eventually slow down.
From Fredrik Lundh's An Introduction to Tkinter:
Note that items added to the canvas are kept until you remove them. If
you want to change the drawing, you can either use methods like
coords, itemconfig, and move to modify the items, or use delete to
remove them.
Yes, I believe you are creating thousands of objects. If you're looking for an easy way to delete a bunch of them at once, use canvas tags described here. This lets you perform the same operation (such as deletion) on a large number of objects.

Categories