import math from scipy.spatial import ConvexHull from pyray.shapes.oned.circle import * from pyray.axes import * from pyray.shapes.twod.plane import * from pyray.shapes.twod.functional import * def paraboloid_circles_rotatingplane(basepath='.\\', scale=200, shift=np.array([1000,1000,0])): im_ind = 0 for i in (np.concatenate((np.arange(0.5,1,0.01), np.arange(1,3,0.05),np.arange(3,10,0.6)),axis=0) + 1e-4): #Controls the rotation of the plane. r2 = general_rotation(np.array([.3, .3, .3]), np.pi/i) r1 = np.eye(4) orthogonal_vec = np.dot(r2, np.array([0,1,0])) orthogonal_vec = orthogonal_vec/sum(orthogonal_vec**2) # Should be unnecessary since rotation doesn't change magnitude. for j in range(4,5): # Controls the rotation of the paraboloid. r = rotation(3, 2*np.pi*j/30.0) r1[:3,:3] = r im = Image.new("RGB", (2048, 2048), "black") draw = ImageDraw.Draw(im, 'RGBA') translate = np.array([0,0,1.5]) rotated_xz_plane(draw, r, r2, scale, shift, translate) render_scene_4d_axis(draw, r1, 4) for z in np.arange(0.001, 3.5, 0.01): #generalized_circle(draw, np.array([0,0,z]), np.array([0,0,1]), np.sqrt(z), r, rgba = (255,20,147,50)) #generalized_arc(draw, r, np.array([0,0,z]), np.array([0,0,1]), np.array([np.sqrt(z),0,z]), np.sqrt(z), 0.5, (255,20,147,50)) #generalized_arc(draw, r, np.array([0,0,z]), np.array([0,0,1]), np.array([-np.sqrt(z),0,z]), np.sqrt(z), 0.5, (255,20,147,10)) pt1 = np.dot(r, np.array([-np.sqrt(z),0,z])) theta = np.pi * 2.0 / 180.0 rot = general_rotation(np.dot(r,np.array([0,0,1])),theta) for j in range(0,180): pt2 = np.dot(rot, pt1) pt2Orig = np.dot(np.transpose(r),pt2) if sum(pt2Orig * orthogonal_vec) - 1.5*orthogonal_vec[2] > 0: draw.line((pt1[0]*scale + shift[0], pt1[1]*scale+shift[1], pt2[0]*scale+shift[0], pt2[1]*scale+shift[1]),\ fill=(255,20,147,100), width=5) else: draw.line((pt1[0]*scale + shift[0], pt1[1]*scale+shift[1], pt2[0]*scale+shift[0], pt2[1]*scale+shift[1]),\ fill=(255,20,147,40), width=5) pt1 = pt2 three_d_parabola(draw, r, r2) im.save(basepath + 'im' + str(im_ind) + '.png') im_ind = im_ind + 1 def paraboloid_circles(basepath='.\\', scale=200, shift=np.array([1000,1000,0])): r2=general_rotation(np.array([0,0,1]),np.pi/2) orthogonal_vec = np.dot(r2, np.array([0,1,0])) r = rotation(3, 2*np.pi*4/30.0) r1 = np.eye(4) r1[:3,:3] = r im = Image.new("RGB", (2048, 2048), "black") draw = ImageDraw.Draw(im, 'RGBA') translate = np.array([0,1.5,0]) #rotated_xz_plane(draw, r, r2, scale, shift, translate=translate) render_scene_4d_axis(draw, r1, 4) for z in np.arange(0.001, 3.5, 0.01): generalized_arc(draw, r, np.array([0,0,z]), np.array([0,0,1]), np.array([np.sqrt(z),0,z]), np.sqrt(z), 0.5, (255,20,147,50)) generalized_arc(draw, r, np.array([0,0,z]), np.array([0,0,1]), np.array([-np.sqrt(z),0,z]), np.sqrt(z), 0.5, (255,20,147,10)) three_d_parabola(draw, r, r2) im.save(basepath + 'im' + str(0) + '.png') def paraboloid_dirty(im_ind=0, scale=200, shift=np.array([1000,1000,0]), opacity=60, basepath='.\\'): #i=1 #r2 = general_rotation(np.array([.3, .3, .3]), np.pi/i) r1 = np.eye(4) rot = general_rotation(np.array([0,0,1]), np.pi/20.0 * (8 + im_ind/3.0)) j=4 #r = rotation(3, 2 * np.pi* j /30.0) r=np.eye(3) rr = general_rotation(np.array([0,1,0]), np.pi/20.0 * (im_ind/7.0)) r = np.dot(r,rr) r = np.dot(r, rot) r1[:3,:3] = r im = Image.new("RGB", (2048, 2048), "black") draw = ImageDraw.Draw(im, 'RGBA') #translate = np.array([0, 0, 1.5]) render_scene_4d_axis(draw, r1, 4, scale, shift) for z in np.arange(0.001, 3.5, 0.02): if z<=1: prcnt1=0.0; point1 = np.array([np.sqrt(z),0,z]) prcnt2=1.0; point2 = np.array([-np.sqrt(z),0,z]) else: angle=2*np.arccos(1/np.sqrt(z)) prcnt1=-angle/2/np.pi; point1 = np.array([1,np.sqrt(z-1),z]) prcnt2=-1+prcnt1; point2 = np.array([-np.sqrt(z-1),1,z]) generalized_arc(draw, r, center=np.array([0,0,z]), vec=np.array([0,0,1]), point=point1, radius=np.sqrt(z), prcnt=prcnt1, rgba=(255,20,147,50)) generalized_arc(draw, r, np.array([0,0,z]), np.array([0,0,1]), point2, np.sqrt(z), prcnt2, (255,20,147,10)) ## Highlight axes xax1=np.array([-100.0,0,0.0]);xax1=np.dot(r,xax1)*scale+shift xax2=np.array([100.0,0,0.0]);xax2=np.dot(r,xax2)*scale+shift draw.line((xax1[0], xax1[1], xax2[0], xax2[1]), fill=(235,255,0), width=4) xax1=np.array([0.0,-100,0.0]);xax1=np.dot(r,xax1)*scale+shift xax2=np.array([0.0,100,0.0]);xax2=np.dot(r,xax2)*scale+shift draw.line((xax1[0], xax1[1], xax2[0], xax2[1]), fill=(235,255,0), width=4) xzgradients(draw, r, 1.0) # draws the arrows correponding to gradients. ## Draw the plane. pt1 = np.array([1.0,-1.2,0]); pt2 = np.array([1.0,1.2,0]) z = 1.2**2+1 pt3 = np.array([1.0,-1.2,z]); pt4 = np.array([1.0,1.2,z]) pt1 = np.dot(r,pt1)*scale+shift; pt2 = np.dot(r,pt2)*scale+shift pt3 = np.dot(r,pt3)*scale+shift; pt4 = np.dot(r,pt4)*scale+shift draw.polygon([(pt1[0], pt1[1]), (pt2[0], pt2[1]), (pt4[0], pt4[1]), (pt3[0], pt3[1])],\ (0,102,255,150)) pt = np.array([1.0,0,1.0]);pt=np.dot(r,pt)*scale+shift pt_z = np.array([0.0,0,1.0]); pt_z=np.dot(r,pt_z)*scale+shift draw.line((pt[0], pt[1], pt_z[0], pt_z[1]), fill=(255,0,120), width=4) pt_y = np.array([1.0,0,0.0]); pt_y=np.dot(r,pt_y)*scale+shift #draw.line((pt[0], pt[1], pt_y[0], pt_y[1]), fill=(255,0,120), width=4) draw.ellipse((pt[0]-10, pt[1]-10, pt[0]+10, pt[1]+10), fill = (0,255,0)) pt = shift draw.ellipse((pt[0]-10, pt[1]-10, pt[0]+10, pt[1]+10), fill = (255,255,0)) im.save(basepath + 'im' + str(im_ind) + '.png') def xzgradients(draw, r, y): for x in [-1.2,-0.7,-0.4,0.0,0.4,0.7,1.2]: z = x*x + y*y #draw_points(draw, r, y, x) #arrowV1(draw,r,np.array([y,x,z]), np.array([2.5*y,2.5*x,z]), (204,102,255)) arrowV1(draw,r,np.array([y,x,z]), np.array([2.5*y,2.5*x,z]), (255,20,147)) #arrowV1(draw,r,np.array([y,x,z]), np.array([y+1.0,x,z]), (0,102,255)) arrowV1(draw,r,np.array([y,x,z]), np.array([y-1.0,x,z]), (0,102,255)) def paraboloidTangent(draw, r, x1, y1, d = 1.0, rgba = (120,80,200,150), scale = 200, shift = np.array([1000,1000,0])): ''' Draws a tangent plane to a paraboloid: x^2+y^2 = z at point given by coordinates (x1, y1) ''' x2 = x1-d y2 = y1+d pt1 = np.dot(r, np.array([x2, y2, z_plane(x2, y2, x1, y1)])) * scale + shift[:3] x2 = x1+d y2 = y1+d pt2 = np.dot(r, np.array([x2, y2, z_plane(x2, y2, x1, y1)])) * scale + shift[:3] x2 = x1+d y2 = y1-d pt3 = np.dot(r, np.array([x2, y2, z_plane(x2, y2, x1, y1)])) * scale + shift[:3] x2 = x1-d y2 = y1-d pt4 = np.dot(r, np.array([x2, y2, z_plane(x2, y2, x1, y1)])) * scale + shift[:3] draw.polygon([(pt1[0], pt1[1]), (pt2[0], pt2[1]), (pt3[0], pt3[1]), (pt4[0], pt4[1])], rgba) def paraboloid(x, y, coeff=0.1, intercept=0.1): ''' ''' return coeff*(x**2 + y**2) - intercept def paraboloid_intersection(draw, r, x1, y1, coeff, intercept, shift=np.array([1000.0, 1000.0, 0.0]), scale=200.0, rgba=(250,250,20), start_line=-12, extend=1.7, width=10): ''' Draws the intersection arc of two paraboloids. args: extend: The amount by which the arc is to extend from its starting point. This parameter was tuned by hit and trial. ''' def parametrized_pt(t, x1, y1, coeff, intercept): ''' See 180225 ''' x = t y = (x1**2 + y1**2 - 2*t*x1)/(2*y1) z = coeff*(x**2+y**2) - intercept return np.array([x, y, z]) t = start_line pt1 = np.dot(r, parametrized_pt(t, x1, y1, coeff, intercept)) * scale + shift[:3] #for i in range(1, int_line): while t <= abs(start_line)*extend: t += 1/10.0 pt2 = np.dot(r, parametrized_pt(t, x1, y1, coeff, intercept)) * scale + shift[:3] draw.line((pt1[0], pt1[1], pt2[0], pt2[1]), fill=rgba, width=width) pt1 = pt2 def draw_paraboloids(scale=12.5, basedir=".\\"): ''' Draws a pair of flapping paraboloids. args: scale: How big should the paraboloids be relative to the image. basedir:The directory where the images are to be saved. In the main pyray repo, basedir is ..\\images\\RotatingCube\\ ''' sep = 8 base_coeff = 0.01 start_line = -12 r1 = np.eye(4) for j in range(21,22): r = rotation(3, np.pi/30*j) r1[:3,:3] = r for i1 in range(20): i = 2.5*np.sin(i1*np.pi/10.0) im = Image.new("RGB", (2048, 2048), (1, 1, 1)) draw = ImageDraw.Draw(im, 'RGBA') render_scene_4d_axis(draw, r1, 4) fn = lambda x, y : paraboloid(x, y, coeff=i*base_coeff, intercept=i) cfn = lambda x, y : 0.0 #drawFunctionalXYGrid(draw, r, scale=50, fn=cfn, extent=15) drawXYGrid(draw, r, meshLen=1.0) drawFunctionalXYGrid(draw, r, scale=scale, fn=fn, extent=20, rgba2=(0,255,0,75), saperatingPlane=np.array([-1,-1,sep])) shift1 = np.dot(r, np.array([sep,sep,0]))*scale + np.array([1000.0, 1000.0, 0]) drawFunctionalXYGrid(draw, r, scale=scale, fn=fn, shift=shift1, rgba=(202,200,20,150), extent=20, rgba2=(202,200,20,75), saperatingPlane=np.array([1,1,sep])) draw_circle_x_y(draw, r, center=np.array([0,0]), radius=np.sqrt(1/base_coeff), scale=scale) draw_circle_x_y(draw, r, center=np.array([0,0]), radius=np.sqrt(1/base_coeff), scale=scale, shift=shift1) paraboloid_intersection(draw, r, sep, sep, i*base_coeff, i, scale=scale, start_line=start_line) im.save(basedir + "im" + str(i1) + ".png") def draw_paraboloidsV2(scale=20.0, ind=0): sep = 8 base_coeff = 0.02 start_line = -12.0 r1 = np.eye(4) j = 21 r = rotation(3, np.pi/30*j) r1[:3,:3] = r shift = np.array([1000.0, 1000.0, 0.0]) for i1 in range(2,3): pt_orig = -9.0*np.array([np.cos(np.pi*6.0/15.0), np.sin(np.pi*6.0/15.0), 0]) for ind in range(15): #i = 2.5*np.sin(i1*np.pi/10.0) i = 2.0 c = i*base_coeff im = Image.new("RGB", (2048, 2048), (1, 1, 1)) draw = ImageDraw.Draw(im, 'RGBA') fn = lambda x, y : paraboloid(x, y, coeff=i*base_coeff, intercept=i) cfn = lambda x, y : 0.0 drawFunctionalXYGrid(draw, r, scale=scale, fn=fn, extent=30, rgba2=(0,255,0,40), saperatingPlane=np.array([-1,-1,sep])) shift1 = np.dot(r, np.array([sep,sep,0.0]))*scale + np.array([1000.0, 1000.0, 0.0]) drawFunctionalXYGrid(draw, r, scale=scale, fn=fn, shift=shift1, rgba=(202,200,20,150), extent=30, rgba2=(202,200,20,40), saperatingPlane=np.array([1,1,sep])) draw_circle_x_y(draw, r, center=np.array([0,0]), radius=np.sqrt(1/base_coeff), scale=scale) draw_circle_x_y(draw, r, center=np.array([0,0]), radius=np.sqrt(1/base_coeff), scale=scale, shift=shift1) paraboloid_intersection(draw, r, sep, sep, i*base_coeff, i, scale=scale, start_line=start_line) render_scene_4d_axis(draw, r1, 4) #pt_orig = 10.0*np.array([np.cos(np.pi*ind/15.0), np.sin(np.pi*ind/15.0), 0]) pt = pt_orig z1 = i*base_coeff*(pt[0]**2 + pt[1]**2) - i z2 = i*base_coeff*((pt[0] - sep)**2 + (pt[1] - sep)**2) - i pt1 = np.array([pt[0],pt[1],z1]) pt1 = np.dot(r, pt1)*scale+shift pt2 = np.array([pt[0],pt[1],z2]) pt2 = np.dot(r, pt2)*scale+shift pt = np.dot(r, pt)*scale+shift draw.ellipse((pt[0]-5, pt[1]-5, pt[0]+5, pt[1]+5), fill = (255,0,120)) draw.ellipse((pt1[0]-5, pt1[1]-5, pt1[0]+5, pt1[1]+5), fill = (0,255,0)) draw.ellipse((pt2[0]-5, pt2[1]-5, pt2[0]+5, pt2[1]+5), fill = (202,200,20)) draw.line((pt[0], pt[1], pt2[0], pt2[1]), fill="white", width=3) [x0, y0] = [0, 0] [x1, y1] = pt_orig[:2] [a1, b1, d1] = [2*c*(x1-x0), 2*c*(y1-y0), c*(x1-x0)**2 + c*(y1-y0)**2 - i -2*c*(x1-x0)*x1 - 2*c*(y1-y0)*y1] [x0_1, y0_1] = [sep, sep] [a2, b2, d2] = [2*c*(x1-x0_1), 2*c*(y1-y0_1), c*(x1-x0_1)**2 + c*(y1-y0_1)**2 \ - i -2*c*(x1-x0_1)*x1 - 2*c*(y1-y0_1)*y1] [line_pt1, line_pt2] = plane_intersection(draw, r, plane1=[a1, b1, d1], plane2=[a2, b2, d2], x_start=pt_orig[0]-7, x_end=pt_orig[0]+7, scale=scale, shift=shift) generalizedParaboloidTangent(draw, r, pt_orig[0], pt_orig[1], d=10.0, x0=0, y0=0, c=c, i=i , scale=scale, shift=shift, line_pt1=line_pt1, line_pt2=line_pt2, rgba=(153,255,102,150)) generalizedParaboloidTangent(draw, r, pt_orig[0], pt_orig[1], d=10.0, x0=sep, y0=sep, c=c, i=i , scale=scale, shift=shift, line_pt1=line_pt1, line_pt2=line_pt2, rgba=(255,204,102,150)) mat = np.array([[a1, b1],[a2, b2]]) rhs = np.array([-d1, -d2]) pt_orig = np.linalg.solve(mat, rhs) pt_orig = np.append(pt_orig, 0) pt = np.dot(r, pt_orig)*scale+shift draw.line((pt[0], pt[1], line_pt1[0], line_pt1[1])) draw.line((pt[0], pt[1], line_pt2[0], line_pt2[1])) drawXYGrid(draw, r, meshLen=1.0) im.save("Images\\RotatingCube\\im" + str(ind) + ".png") def three_d_parabola(draw, r, r2, scale = 200, shift = np.array([1000,1000,0])): ''' Draws a curve described by the intersection of a plane with the paraboloid x^2+y^2 = z params: r: The rotation matrix the whole scene is rotated by r2: The rotation matrix that the inetersecting plane is to be rotated by ''' # Assume you start with the x-z plane orthogonal_vec = np.array([0,1,0]) orthogonal_vec = np.dot(r2, orthogonal_vec) b = 1.5 [thetax, thetay, thetaz] = orthogonal_vec c1 = -thetax/thetaz/2 c2 = -thetay/thetaz/2 c3 = np.sqrt(b + c1**2 + c2**2) x_min = max((c1 - abs(c3)),-np.sqrt(3.5)) x_max = min((c1 + abs(c3)),np.sqrt(3.5)) y = c2 + np.sqrt(c3*c3 - (x_min-c1)*(x_min-c1)) pt1 = np.dot(r, [x_min, y, (x_min**2+y**2)]) * scale + shift[:3] for x in np.arange(x_min, x_max, 0.01): y = c2 + np.sqrt(c3*c3 - (x-c1)*(x-c1)) pt2 = np.dot(r, [x, y, (x**2 + y**2)]) * scale + shift[:3] if x**2 + y**2 < 3.5: draw.line((pt1[0], pt1[1], pt2[0], pt2[1]), fill = (204,102,255), width=5) pt1 = pt2 y = c2 + np.sqrt(c3*c3 - (x_min-c1)*(x_min-c1)) pt1 = np.dot(r, [x_min, y, (x_min**2+y**2)]) * scale + shift[:3] for x in np.arange(x_min, x_max, 0.01): y = c2 - np.sqrt(c3*c3 - (x-c1)*(x-c1)) pt2 = np.dot(r, [x, y, (x**2 + y**2)]) * scale + shift[:3] if x**2 + y**2 < 3.5: draw.line((pt1[0], pt1[1], pt2[0], pt2[1]), fill = (204,102,255), width=5) pt1 = pt2 def plane_intersection(draw, r, plane1=[0,0,0], plane2=[0,0,0], x_start=0, x_end=0, scale=200, shift=np.array([1000,1000,0])): [a1,b1,d1] = plane1 [a2,b2,d2] = plane2 x = x_start y = ((d2-d1) + (a2-a1)*x)/(b1-b2) z = a1*x+b1*y+d1 pt1 = np.dot(r, np.array([x, y, z])) * scale + shift[:3] init_pt = pt1 while x <= x_end: x += 1/10.0 y = ((d2-d1) + (a2-a1)*x)/(b1-b2) z = a1*x+b1*y+d1 pt2 = np.dot(r, np.array([x, y, z])) * scale + shift[:3] #draw.line((pt1[0], pt1[1], pt2[0], pt2[1]), fill = "white", width=3) pt1 = pt2 fin_pt = pt1 return [init_pt, fin_pt] def paraboloidTangentV2(draw, r, x1, y1, c=1.0, d = 1.0, rgba = (120,80,200,150), scale = 200, shift = np.array([1000,1000,0]), line_pt1=None, line_pt2=None): ''' Draws a tangent plane to a paraboloid: x^2+y^2 = z at point given by coordinates (x1, y1) ''' x2 = x1-d y2 = y1+d pt1 = np.dot(r, np.array([x2, y2, c*z_plane(x2, y2, x1, y1)])) * scale + shift[:3] x2 = x1+d y2 = y1+d pt2 = np.dot(r, np.array([x2, y2, c*z_plane(x2, y2, x1, y1)])) * scale + shift[:3] x2 = x1+d y2 = y1-d pt3 = np.dot(r, np.array([x2, y2, c*z_plane(x2, y2, x1, y1)])) * scale + shift[:3] x2 = x1-d y2 = y1-d pt4 = np.dot(r, np.array([x2, y2, c*z_plane(x2, y2, x1, y1)])) * scale + shift[:3] #draw.polygon([(pt1[0], pt1[1]), (pt2[0], pt2[1]), (pt3[0], pt3[1]), (pt4[0], pt4[1])], rgba) sqr1 = [[pt1[0], pt1[1]], [pt2[0], pt2[1]], [pt3[0],pt3[1]], [pt4[0], pt4[1]]] if line_pt1 is not None: sqr1.append([line_pt1[0], line_pt1[1]]) if line_pt2 is not None: sqr1.append([line_pt2[0], line_pt2[1]]) hull = ConvexHull([i[:2] for i in sqr1]).vertices poly = [(sqr1[i][0], sqr1[i][1]) for i in hull] draw.polygon(poly, rgba) def z_plane(x, y, x1, y1): ''' Returns the z-coordinate of a point on a plane that is tangent to the paraboloid z = x^2 + y^2 ''' return 2*x1*x + 2*y1*y - (x1**2 + y1**2) def generalizedParaboloidTangent(draw, r, x1, y1, d=1.0, x0=0.0, y0=0.0, rgba=(120,80,200,150), c=1.0, i=0.0, scale=200, shift=np.array([1000,1000,0]), line_pt1=None, line_pt2=None, p=1.0): ''' Draws a tangent plane to a paraboloid: x^2+y^2 = z at point given by coordinates (x1, y1) ''' x2 = x1-d y2 = y1+d pt1 = np.dot(r, np.array([x2, y2, z_plane_generalized(x2, y2, x1, y1, x0, y0, c, i)]))*scale + shift[:3] x2 = x1+d y2 = y1+d pt2 = np.dot(r, np.array([x2, y2, z_plane_generalized(x2, y2, x1, y1, x0, y0, c, i)]))*scale + shift[:3] x2 = x1+d y2 = y1-d pt3 = np.dot(r, np.array([x2, y2, z_plane_generalized(x2, y2, x1, y1, x0, y0, c, i)]))*scale + shift[:3] x2 = x1-d y2 = y1-d pt4 = np.dot(r, np.array([x2, y2, z_plane_generalized(x2, y2, x1, y1, x0, y0, c, i)]))*scale + shift[:3] #draw.polygon([(pt1[0], pt1[1]), (pt2[0], pt2[1]), (pt3[0], pt3[1]), (pt4[0], pt4[1])], rgba) sqr1 = [[pt1[0], pt1[1]], [pt2[0], pt2[1]], [pt3[0],pt3[1]], [pt4[0], pt4[1]]] if line_pt1 is not None: sqr1.append([line_pt1[0], line_pt1[1]]) if line_pt2 is not None: sqr1.append([line_pt2[0], line_pt2[1]]) try: hull = ConvexHull([i[:2] for i in sqr1]).vertices except: hull = range(4) orig_pt = np.dot(r, np.array([x1,y1,z_plane_generalized(x1, y1, x1, y1, x0, y0, c, i)]))*scale+shift[:3] poly = [(sqr1[i][0]*p+orig_pt[0]*(1-p), sqr1[i][1]*p+orig_pt[1]*(1-p)) for i in hull] draw.polygon(poly, rgba) def z_plane_generalized(x, y, x1, y1, x0, y0, c=1.0, i=0.0): d = c*(x1-x0)**2 + c*(y1-y0)**2 - i -2*c*(x1-x0)*x1 - 2*c*(y1-y0)*y1 return 2*c*(x1-x0)*x + 2*c*(y1-y0)*y + d