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:

enter image description here

so the cursor will be like the circle

Asked By: tahabashar11

||

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 = Axx, and By = Ayy.

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 = Axx, and By = Ayy, 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:

The line at 1°

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!

Answered By: Sylvester Kruin
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.