How to make lines around the origin(will be cursor) in tkinter
Question:
What I am planning to do is make 360 lines that every one of it points to a different angle and it all will be around the cursor
so line 1 will be in angle 1 and line 2 in angle 2
and I want it to be around the cursor
def redraw(event):
cv.delete("all")
length = 100
xorigin = event.x - 250
yorigin = event.y - 250
newx = (xorigin - 500)*numpy.cos(45 * numpy.pi / 360)
newy = (xorigin - 250)*numpy.sin(45 * numpy.pi / 360)
cv.create_line(xorigin+250,yorigin+250,newx,newy, fill="red")
I’ve tried to make it one line for testing but the line is not from the angle i want + the origin(cursor) kinda broken
so basically what I am trying to do:
so the cursor will be like the circle
Answers:
I’ve found the solution! I’ll go through and explain the code (and the math), but if you want to skip all that, a working example will be at the bottom.
numpy.cos
and numpy.sin
use radians, not degrees
This causes some confusion: you want degrees, but you’re getting incorrect values, because these functions calculate radians. Well, to use a radians function to calculate degrees, you need to multiply your degrees argument by /180. Hence, calling the sin()
and cos()
functions with degrees will look like this:
# Calculate the cosine of 45° like this: cos (45 * ( / 180))°
degrees = 45
numpy.cos(degrees*(numpy.pi/180))
# Calculate the sine of 45° like this: sin (45 * ( / 180))°
degrees = 45
numpy.sin(degrees*(numpy.pi/180))
Getting line coords from mouse position
Let’s think of your line as a right triangle, where point A is the location of the mouse, point B is the other end of the line, angle a is the angle of the line relative to the x-axis, side h is the line you want to draw, and h itself represents the length of the line:
B
|
|
|
| h
y |
|
|
|_ a°
|_|______
x A
You have the (x, y)
coordinates for A already: xorigin
and yorigin
. The (x, y)
coordinates for B are simply the lengths of each leg of the triangle subtracted from A‘s coordinates.
In other words, Bx = Ax – x, and By = Ay – y.
But how do we get x and y? Well, we know that cos a° = x / h, so we can solve for x, and get x = h * cos a°. Doing the same thing for sin and y, we get y = h * sin a°.
Applying these formulas in Python
Alright, let’s convert these formulas into valid Python! In the wonderful imaginary world of computers, a right triangle can have an angle measure of any size, so we don’t need to worry about giving an angle measure that’s too big.
To keep things simple, we’re going to create our own sin()
and cos()
functions that automatically convert the degrees to radians:
def cos(degrees):
return numpy.cos(degrees*(numpy.pi/180))
def sin(degrees):
return numpy.sin(degrees*(numpy.pi/180))
Here, we apply the formulas Bx = Ax – x, and By = Ay – y, replacing x and y with h * cos a° and h * sin a°, respectively:
newx = xorigin - (length * cos(d))
newy = yorigin - (length * sin(d))
Where d
is any number of degrees starting at leg x and rotating clockwise.
Putting it all together
Now for a demonstration program. You mentioned in your question that you wanted to create a full circle of lines: well, this program does just that. It loops through all the degrees and draws a line at each angle measure, starting at 1° and continuing through to 360°.
Remember, the degrees start at the left half of the x-axis, so a line with an angle measure of 1° will look like this:
import numpy, tkinter
root = tkinter.Tk()
canvas = tkinter.Canvas(root)
canvas.pack(expand=True, fill="both")
def cos(degrees):
return numpy.cos(degrees*(numpy.pi/180))
def sin(degrees):
return numpy.sin(degrees*(numpy.pi/180))
def redraw(event):
canvas.delete("all")
length = 100
xorigin = event.x
yorigin = event.y
# Loop through all the degrees of the circle, drawing a line for each one
for d in range(0, 360):
newx = xorigin - (length * cos(d))
newy = yorigin - (length * sin(d))
canvas.create_line(xorigin, yorigin, newx, newy, fill="red")
canvas.bind("<Motion>", redraw)
root.mainloop()
Hope this helps, and let me know if you have any questions about this answer!
What I am planning to do is make 360 lines that every one of it points to a different angle and it all will be around the cursor
so line 1 will be in angle 1 and line 2 in angle 2
and I want it to be around the cursor
def redraw(event):
cv.delete("all")
length = 100
xorigin = event.x - 250
yorigin = event.y - 250
newx = (xorigin - 500)*numpy.cos(45 * numpy.pi / 360)
newy = (xorigin - 250)*numpy.sin(45 * numpy.pi / 360)
cv.create_line(xorigin+250,yorigin+250,newx,newy, fill="red")
I’ve tried to make it one line for testing but the line is not from the angle i want + the origin(cursor) kinda broken
so basically what I am trying to do:
so the cursor will be like the circle
I’ve found the solution! I’ll go through and explain the code (and the math), but if you want to skip all that, a working example will be at the bottom.
numpy.cos
and numpy.sin
use radians, not degrees
This causes some confusion: you want degrees, but you’re getting incorrect values, because these functions calculate radians. Well, to use a radians function to calculate degrees, you need to multiply your degrees argument by /180. Hence, calling the sin()
and cos()
functions with degrees will look like this:
# Calculate the cosine of 45° like this: cos (45 * ( / 180))°
degrees = 45
numpy.cos(degrees*(numpy.pi/180))
# Calculate the sine of 45° like this: sin (45 * ( / 180))°
degrees = 45
numpy.sin(degrees*(numpy.pi/180))
Getting line coords from mouse position
Let’s think of your line as a right triangle, where point A is the location of the mouse, point B is the other end of the line, angle a is the angle of the line relative to the x-axis, side h is the line you want to draw, and h itself represents the length of the line:
B
|
|
|
| h
y |
|
|
|_ a°
|_|______
x A
You have the (x, y)
coordinates for A already: xorigin
and yorigin
. The (x, y)
coordinates for B are simply the lengths of each leg of the triangle subtracted from A‘s coordinates.
In other words, Bx = Ax – x, and By = Ay – y.
But how do we get x and y? Well, we know that cos a° = x / h, so we can solve for x, and get x = h * cos a°. Doing the same thing for sin and y, we get y = h * sin a°.
Applying these formulas in Python
Alright, let’s convert these formulas into valid Python! In the wonderful imaginary world of computers, a right triangle can have an angle measure of any size, so we don’t need to worry about giving an angle measure that’s too big.
To keep things simple, we’re going to create our own sin()
and cos()
functions that automatically convert the degrees to radians:
def cos(degrees):
return numpy.cos(degrees*(numpy.pi/180))
def sin(degrees):
return numpy.sin(degrees*(numpy.pi/180))
Here, we apply the formulas Bx = Ax – x, and By = Ay – y, replacing x and y with h * cos a° and h * sin a°, respectively:
newx = xorigin - (length * cos(d))
newy = yorigin - (length * sin(d))
Where d
is any number of degrees starting at leg x and rotating clockwise.
Putting it all together
Now for a demonstration program. You mentioned in your question that you wanted to create a full circle of lines: well, this program does just that. It loops through all the degrees and draws a line at each angle measure, starting at 1° and continuing through to 360°.
Remember, the degrees start at the left half of the x-axis, so a line with an angle measure of 1° will look like this:
import numpy, tkinter
root = tkinter.Tk()
canvas = tkinter.Canvas(root)
canvas.pack(expand=True, fill="both")
def cos(degrees):
return numpy.cos(degrees*(numpy.pi/180))
def sin(degrees):
return numpy.sin(degrees*(numpy.pi/180))
def redraw(event):
canvas.delete("all")
length = 100
xorigin = event.x
yorigin = event.y
# Loop through all the degrees of the circle, drawing a line for each one
for d in range(0, 360):
newx = xorigin - (length * cos(d))
newy = yorigin - (length * sin(d))
canvas.create_line(xorigin, yorigin, newx, newy, fill="red")
canvas.bind("<Motion>", redraw)
root.mainloop()
Hope this helps, and let me know if you have any questions about this answer!