I'm trying to complement my answer to a circumference intersection question . In this answer, at a given moment, I get an equation of the line through the coefficients a,b,c
:
r: a*x + b*y + c = 0
I would like to represent this line on the screen using tortoise ( turtle
) preferably using only turtle geometry :
- download / upload 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 X + axis).
It is also appropriate to return to the place of origin of the turtle after a drawing procedure. After drawing something, staying in a random position is not positive.
What I have
Depending on the slope of the line, I have a different strategy of how to draw it.
Horizontal line
Representing the line only by (a,b,c)
, if a == 0
, then we have a horizontal line, with y = -c/b
.
So, 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+
Vertical line
Representing the line only by (a,b,c)
, if b == 0
, then we have a vertical line, with x = -c/a
.
So, 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+
Slope line
Representing the line only by (a,b,c)
, if a != 0
and b != 0
, then we have a sloped line that varies on both the X-axis and the Y-axis.
I know that it intercepts the X axis when y = 0
, so that point is (-c/a,0)
. Then I must determine the direction of the line.
When the equation of the line is in the y = m*x + k
format, 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 pointing toward the straight. So I can get the angle in radians via math.atan(m)
. As m = -a/b
, then I get the angle via math.atan(-a/b)
.
I can also compute the angle without making this explicit split through math.atan2
. When x
varies% with% units, then b
needs to vary y
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 shown, the direction of the line points to -a
, calling (b, -a)
would return the appropriate angle to point in that direction.
After finding the angle in radians, only turn to degrees and use the turtle.
In Python, abstracting% with% transforming radians into degrees, would look like this to draw the line:
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. You can pick up the screen dimensions in tortoise steps by calling math.atan2(-a, b)
and radians2degree
. I know that I can draw by occupying the screen (with surplus) drawing t.window_height()
forward, turning 180 °, walking 2 times that distance, then turning 180 ° again and walking that distance again to return to the origin of the drawing (it is necessary rotate 180 ° to return to the original orientation). However, this drawing method includes a "waste" of off-screen drawing.
The distance
t.window_length()
is the largest possible between two points of a rectangular window: the distance between the left-upper and the lower-right.
Currently, with a constant of 50 back and forth, I draw a small segment, not the entire straight:
In this case, I was purposely testing to get the equation of the line from circles whose centers always have (h**2 + w**2)**0.5
, so the lines are all vertical.