0

I am generating a 3d renderer in python, that when given a list of 3D lines, it converts them to 2D and draws them on the screen with turtle graphics.

This is an example for a set of 3D lines:


#
import math
import turtle
import random
import time
def rotatex(list,rot):
  x=list[0]
  y=list[1]
  z=list[2]
  newx = x;
  newy = y*math.cos(rot) - z*math.sin(rot);
  newz = y*math.sin(rot) + z*math.cos(rot);
  return [newx,newy,newz]
def rotatey(list,rot):
  x=list[0]
  y=list[1]
  z=list[2]
  newx = x*math.cos(rot) + z*math.sin(rot);
  newy = y;
  newz = z*math.cos(rot) - x*math.sin(rot);  
  return [newx,newy,newz]
def rotatez(list,rot):
  x=list[0]
  y=list[1]
  z=list[2]
  newx = x*math.cos(rot) - y*math.sin(rot);
  newy = x*math.sin(rot) + y*math.cos(rot);
  newz = z;  
  return [newx,newy,newz]
def project(p):
  camera=[0,-50,-300]
  return [((p[0]-camera[0])/camera[2])*100,((p[1]-camera[1])/camera[2])*100]
def render(p1,p2):
  turtle.penup()
  turtle.goto(p1[0],p1[1])
  turtle.pendown()
  turtle.goto(p2[0],p2[1])
  turtle.penup()
def degreestoradians(degrees):
  return degrees*0.175
def createpolygonlines(sidelength,sides,center):
  polygonlines=[]
  temp=[]
  apothem=(sidelength/2)/math.tan(360/(sides*2))
  turtle.goto(center[0],center[1])
  turtle.penup()
  turtle.setheading(270)
  turtle.forward(apothem)
  turtle.setheading(0)
  turtle.forward(sidelength/2)
  turtle.setheading(180)
  180*(sides-2)/sides
  for i in range(0,sides):
    temp.append(list(turtle.pos()))
    turtle.forward(sidelength)
    turtle.left(90)
    temp.append(list(turtle.pos()))
    polygonlines.append(temp)
    temp=[]
  print(polygonlines)
  return polygonlines
pointsgenerated=createpolygonlines(100,4,[0,0])
for i in pointsgenerated:
  i[0].append(0)
  i[1].append(0)
print(pointsgenerated)
turtle.clear()
points=pointsgenerated
renderbuffer=[]
rotx=degreestoradians(20)
roty=degreestoradians(20)
rotz=degreestoradians(20)
for i in range(0,len(points)):
  points[i][0]=rotatex(points[i][0],rotx)
  points[i][0]=rotatey(points[i][0],roty)
  points[i][0]=rotatez(points[i][0],rotz)
  points[i][1]=rotatex(points[i][1],rotx)
  points[i][1]=rotatey(points[i][1],roty)
  points[i][1]=rotatez(points[i][1],rotz)
for i in points:
  print(i)
print("Now let's flatten it")
for i in range(0,len(points)):
  renderbuffer.append([project(points[i][0]),project(points[i][1])]);
print(renderbuffer)
for i in range(0,len(renderbuffer)):
  render(renderbuffer[i][0],renderbuffer[i][1])
turtle.update()

Above set of lines draws the 12 lines needed to make a cube, each row contains two points needed to draw a line (startpoint & endpoint).

I would like a formula that would generate a set of lines for a regular polygon (2D is needed, I'll explain why later) with information like the center and side length.

I tried coming up with an equation, but the algebra isn't coming out right, please tell me what equation I should be using!

Anonymous
  • 13
  • 2

1 Answers1

0

Checkout the render_polygon function which can generate regular polygons given side length, centre and number of sides:

import turtle
import math
def render(p1,p2):
  turtle.penup()
  turtle.goto(p1[0],p1[1])
  turtle.pendown()
  turtle.goto(p2[0],p2[1])
  turtle.penup()

def render_polygon(centre,side_length, number_of_sides):
  n=number_of_sides
  xcentre=centre[0]
  ycentre=centre[1]
  pi=math.pi
  r=side_length/math.sqrt(2*(1-math.cos(2*pi/n)))
  xstart=r+xcentre
  ystart=0+ycentre
  xprev=xstart
  yprev=ystart
  for i in range(1,n):
      x=r*math.cos(2*pi*i/n)+xcentre
      y=r*math.sin(2*pi*i/n)+ycentre
      render([xprev,yprev],[x,y])
      xprev=x
      yprev=y
  render([xprev,yprev],[xstart,ystart])
win=turtle.Screen()
win.setup(width=300,height=300)
turtle.shape("circle")
#turtle.hideturtle()
render_polygon([0,0],50,4)
render_polygon([50/math.sqrt(2),-50/math.sqrt(2)],50,4)
render_polygon([50/math.sqrt(2),50/math.sqrt(2)],50,4)
render_polygon([-50/math.sqrt(2),-50/math.sqrt(2)],50,4)
render_polygon([-50/math.sqrt(2),50/math.sqrt(2)],50,4)
render_polygon([20,20],30,3)
render_polygon([60,-30],40,9)
render_polygon([-40,-30],50,6)
render_polygon([-40,50],5,60)
William
  • 464
  • 2
  • 16
  • 1
    Thanks a lot! I would have upvoted you, but I don't have 15 rep yet! Thanks so much for the help! I will use this in my code! – Anonymous Jan 28 '22 at 01:03