1

Something like this image here:

enter image description here

How does one make half an oval or a semi circle without the flat part? so basically just the curved part.

This is what I have came up with. this code prints the half of a oval that I need but I only need the curved part.

import turtle
half = turtle.Turtle()
half.penup()
half.goto(-115,95)
half.setheading(-90)
half.pendown()
half.circle(100, 180) 
half.left(90)
half.forward(200)
starball
  • 20,030
  • 7
  • 43
  • 238
  • 1
    just remove the last two lines, or call `penup` before you call `left(90)` – Alexander Jan 13 '23 at 03:10
  • You can probably adapt something in [How do you draw an ellipse/oval in turtle graphics?](https://stackoverflow.com/questions/29465666/how-do-you-draw-an-ellipse-oval-in-turtle-graphics) – ggorlen Jan 13 '23 at 06:50

1 Answers1

1

This is how you can draw a rotated oval with a start and a end degree point and a offset position on turtle, it's a bit slow but accurate.

This is the mathematical explanation of the equation for a rotated ellipse.

from numpy import arctan2
from math import sin, cos, radians, degrees
import turtle

# function that return 2 y from a given x, scale and rotation [ellipse function]
#https://rohankjoshi.medium.com/the-equation-for-a-rotated-ellipse-5888731da76
def get_y_ellipse(ellipse_size, x, alpha):
    a, b = ellipse_size[0] / 2, ellipse_size[1] / 2
    delta_sqrt = ((b**4-2*a**2*b**2+a**4)*sin(2*alpha)**2*x**2-4*a**4*x**2*cos(alpha)**2*sin(alpha)**2-4*a**2*b**2*x**2*cos(alpha)**2+4*a**4*b**2*cos(alpha)**2-4*a**2*b**2*x**2*sin(alpha)**4-4*b**4*x**2*sin(alpha)**2*cos(alpha)**2+4*a**2*b**4*sin(alpha)**2)**(1/2)
    y1 = ((-b**2 + a**2)*sin(2*alpha)*x + delta_sqrt) / (2*a**2*cos(alpha)**2+2*b**2*sin(alpha)**2)
    y2 = ((-b**2 + a**2)*sin(2*alpha)*x - delta_sqrt) / (2*a**2*cos(alpha)**2+2*b**2*sin(alpha)**2)
    return y1, y2

# angle between 2 point on a 2d plane
def angle_to(p1, p2, rotation):
    return (degrees(arctan2(p2[1] - p1[1], p2[0] - p1[0])) + rotation) % 360

window = turtle.Screen()

#############################################
# oval settings #############################
center_position = (0,0)
rotation = 0
ellipse_size = (100, 50)

draw_from_angle = 180
draw_to_angle = 360
#############################################
#############################################

#optimal min and max x axis
min_x = -int(ellipse_size[0]/2)
max_x = int(ellipse_size[0]/2)

trl = turtle.Turtle()
trl.penup()

# keep track of the first point to close the ellipse
first_point = None

# the ellipse function return a +- result, this for cycle draws the positive side the second one draws the negative one
for x in range(min_x, max_x):
    #get the y from the function of x
    y1, y2 = get_y_ellipse(ellipse_size, x, radians(rotation))
    # check if value is not a complex number
    if type(y1) in (int, float):
        trl.goto(center_position[0]+x, center_position[1]+y1)
        # if the angle of the new_position from the center is not between the from_angle and the to_angle list the pen
        if draw_from_angle < angle_to(center_position, (center_position[0]+x, center_position[1]+y1), rotation) < draw_to_angle:
            trl.pendown()
            if first_point == None:
                first_point = (center_position[0]+x, center_position[1]+y1)
                print(first_point)
        else:
            trl.penup()

# elaborate a range of xs from right to left side of the screen
for x in range(max_x, min_x, -1):
    y1, y2 = get_y_ellipse(ellipse_size, x, radians(rotation))
    if type(y2) in (int, float):
        trl.goto(center_position[0]+x, center_position[1]+y2)
        if draw_from_angle < angle_to(center_position, (center_position[0]+x, center_position[1]+y2), rotation) < draw_to_angle:
            trl.pendown()
        else:
            trl.penup()

# close the ellipse
if first_point != None:
    trl.goto(first_point[0], first_point[1])

window.mainloop()

Hope thats help.

marick
  • 109
  • 6