How to draw a straight using turtle geometry?

Asked

Viewed 702 times

8

I’m trying to supplement my answer to a question about intersections of circles. In this answer, at a given time, I get an equation of the line in through the coefficients a,b,c:

r: a*x + b*y + c = 0

I’d like to represent that straight line on the screen using turtle (turtle), preferably using only turtle geometry:

  • lower/raise the pen
  • turn left/right R degrees
  • walk S steps forward

In this case, my turtle starts from the origin, facing the positive direction of the X axis (facing the X axis+).

It is also appropriate to return to the turtle’s place of origin after a design procedure. After drawing something, staying in a random position is not positive for me.

What I got

Depending on the slope of the straight, I have a different strategy of how to draw it.

Horizontal line

Representing the straight just by (a,b,c), if a == 0, then we have a horizontal line, with y = -c/b.

That way, I need to do the following:

subir caneta
virar 90° para a esquerda     # fico virado para o eixo Y+
andar -c/b
virar 90° para a direita      # volto a ficar voltado para o eixo X+
baixar caneta
desenha a reta                # voltando ao ponto de partida da reta
subir caneta
virar 90° para a direita      # fico virado para o eixo Y-
andar -c/b                    # retorna para a origem
virar 90° para a esquerda     # volto a ficar voltado para o eixo X+

In Python, being t the turtle:

t.penup()
t.left(90)           # fico virado para o eixo Y+
t.forward(-c/b)
t.right(90)          # volto a ficar voltado para o eixo X+
t.pendown()
# desenha a reta e volta a esse mesmo ponto
t.penup()
t.right(90)          # fico virado para o eixo Y-
t.forward(-c/b)      # retorna para a origem
t.left(90)           # volto a ficar voltado para o eixo X+

Upright

Representing the straight just by (a,b,c), if b == 0, then we have a vertical line, with x = -c/a.

That way, I need to do the following:

subir caneta
andar -c/a
virar 90° para a esquerda     # volto a ficar voltado para o eixo Y+
baixar caneta
desenha a reta                # voltando ao ponto de partida da reta
subir caneta
virar 90° para a esquerda     # fico virado para o eixo X-
andar -c/a                    # retorna para a origem
virar 180° para a direita     # volto a ficar voltado para o eixo X+

In Python, being t the turtle:

t.penup()
t.forward(-c/a)
t.left(90)           # volto a ficar voltado para o eixo Y+
t.pendown()
# desenha a reta e volta a esse mesmo ponto
t.penup()
t.left(90)           # fico virado para o eixo X-
t.forward(-c/a)      # retorna para a origem
t.right(180)         # volto a ficar voltado para o eixo X+

Straight line

Representing the straight just by (a,b,c), if a != 0 and b != 0, then we have an inclined line that varies both on the X axis and on the Y axis.

I know she intercepts the X-axis when y = 0, so that point is (-c/a,0). Then I must determine the direction of the straight.

When the line equation is in format y = m*x + k, then m is the tangent of the angle that the line makes with the X axis. This angle is the rotation of how much counterclockwise it is necessary to rotate so that it points in the direction of the line. Then I can get the angle on radians via math.atan(m). Like m = -a/b, then I get the angle via math.atan(-a/b).

I can also calculate the angle without making this explicit division through the math.atan2. When x varies b units, then y needs to vary -a units:

; seja (x0,y0) o ponto inicial da reta e (x1,y1) o ponto da reta obtida deslocando x0 em b unidades
a*x0 + b*y0 + c = 0
a*x1 + b*y1 + c = 0

x1 = x0 + b
; portanto:

a*(x0 + b) + b*y1 + c = 0
a*x0 + a*b + b*y1 + c = 0
a*x0 + a*b + b*y1 + c = a*x0 + b*y0 + c
a*b + b*y1 = b*y0
b*y1 = b*y0 - a*b = b*(y0 - a)
; como b != 0, pois a reta está inclinada:
y1 = y0 - a

; portanto, a inclinação é
(b, -a)

As demonstrated, the direction of the straight line points to (b, -a), call for math.atan2(-a, b) would return the appropriate angle to point in that direction.

After finding the angle in radians, just turn it into degrees and use on the turtle.

In Python, by abstracting radians2degree that turns radians into degrees, would look like this to draw the straight:

inclinacao = radians2degrees(math.atan2(-a, b))
t.penup()
t.forward(-c/a)      # vai ao ponto em que a reta corte o eixo X
t.left(inclinacao)   # inclina na direção da reta
t.pendown()
# desenha a reta e volta a esse mesmo ponto
t.penup()
t.right(inclinacao)  # fico virado para o eixo X+
t.left(180)          # viro para o eixo X-
t.forward(-c/a)      # retorna para a origem
t.right(180)         # volto a ficar voltado para o eixo X+

Specific point of difficulty

Being anywhere on the screen, I can draw a segment of arbitrary size. It is possible to take the screen dimensions in turtle steps through the calls t.window_height() and t.window_length(). I know I can draw occupying the screen (with over) drawing (h**2 + w**2)**0.5 forward, turning 180°, walking twice that distance, then turning 180° again and walking that distance again to return to the origin of the drawing (it is necessary to rotate 180° to return to the original orientation). However, this design method includes a "waste" of off-screen drawing.

The distance (h**2 + w**2)**0.5 is the largest possible between two points of a rectangular window: the distance between the lower-left and upper-right points.

Currently, with a 50-forward and back constant, I draw a small segment, not the whole line:

desenho automatizado da reta obtida a partir da "subtração" da equação de duas circunferências

In this case, I was purposely testing to get the equation of the line from circles whose centers always have y = 0, so the lines are all vertical.

  • 1

    And what is the question? D

  • 1

    @Andersoncarloswoss draw with the turtle something that is "visually" a straight on the screen. When I say "visually a straight line" it is indicating that, in the visual area, the drawn segment goes to the edges. I wanted to draw without exceeding the edges, exceeding at most only rounding error

  • @Jeffersonquesado, my answer helped you?

1 answer

1

If you do not want to exceed the screen limit, the simplest option would be to make a loop in which the turtle walks small steps while not reaching the edge:

w = turtle.window_width()
h = turtle.window_height()
while abs(t.xcor())<w/2 and abs(t.ycor())<h/2:
    t.fd(5)

Another option is to calculate the segment size to reach the screen. For example if y=a*x+b then the value of x at which the turtle reaches the top edge is x_sup=(h/2-b)/a and to the lower edge is x_inf=(-h/2-b)/a. Therefore, the lowest value of x that the turtle can have is min(x_sup,x_inf,-w/2), while the highest value is max(x_sup,x_inf,w/2). Knowing the highest and lowest value of x that the turtle may have, calculate the value of y with y1 = a*x_max+b and y2 = a*x_max+b. At this point, to determine how far your turtle will walk to reach the limit just do d1 = math.sqrt((y1-b)**2+x_max**2) and d2 = math.sqrt((y2-b)**2+x_max**2). End with:

t.forward(d1)
t.left(180)
t.forward(d1+d2)

Here I am assuming that your turtle is already on (x,y)=(0,b) and pointed at the right angle and that you don’t want to use goto

Browser other questions tagged

You are not signed in. Login or sign up in order to post.