In [ ]:
import plotly.offline as py
import plotly.graph_objs as go
py.init_notebook_mode(connected=True)
import numpy as np
import ipywidgets as widgets
import json
In [ ]:
def mesh2D(xlim, ylim, n=5): #Set up Meshgrid
if isinstance(n, int):
x = np.linspace(xlim[0],xlim[1],n)
y = np.linspace(ylim[0],ylim[1],n)
elif isinstance(n, list):
x = np.linspace(xlim[0],xlim[1],n[0])
y = np.linspace(ylim[0],ylim[1],n[1])
else:
raise Exception("Invalid Parameter")
return np.meshgrid(x, y, sparse=True)
In [ ]:
def addOpacity(string, intensity="0.5"):
strList = list(string)
strList.pop()
string = "".join(strList) + "," + intensity +")"
return string
In [ ]:
class Line:
def __init__(self, pointList):
self.x = []
self.y = []
self.z = []
for i in range(len(pointList)):
self.x.append(pointList[i][0])
self.y.append(pointList[i][1])
self.z.append(pointList[i][2])
def gObject(self, color="rgb(210,64,0)"):
lineObject = go.Scatter3d(mode="lines",
x=self.x,
y=self.y,
z=self.z,
line=dict(color=(color),
width=7)
)
return lineObject
In [ ]:
class Sphere:
def __init__(self, radius=5, center=[0, 0, 0]):
self.radius = radius
self.center = center
meshSize = 20
theta = np.linspace(0,2*np.pi,meshSize)
phi = np.linspace(0,np.pi,meshSize)
self.x = radius*np.outer(np.cos(theta),np.sin(phi)) + center[0]
self.y = radius*np.outer(np.sin(theta),np.sin(phi)) + center[1]
self.z = radius*np.outer(np.ones(meshSize),np.cos(phi)) + center[2]
def gObject(self, color=[[0.0, "rgb(0,62,116)"], [1.0, "rgb(255,255,255)"]]):
sphere = go.Surface(x=self.x.tolist(),
y=self.y.tolist(),
z=self.z.tolist(),
showscale=False,
opacity=0.7,
colorscale=color
)
return sphere
In [ ]:
class Point:
def __init__(self, position):
self.position = np.array(position)
def gObject(self, color="rgb(0,62,116)"):
point = go.Scatter3d(mode="markers",
x=[self.position[0]],
y=[self.position[1]],
z=[self.position[2]],
marker=dict(color=color,
size=7
)
)
return point
Orange: "rgb(210,64,0)"
Dark Green: "rgb(2,137,59)"
Imperial Blue: "rgb(0,62,116)"
Pool Blue: "rgb(2,161,205)"
In [ ]:
theta1 = np.pi/2
t = np.linspace(0, theta1, 10)
initialPosition = np.matrix([[2], [2], [2]])
In [ ]:
def roXaxis(theta):
M = np.matrix([[1, 0, 0],
[0, np.cos(theta), -np.sin(theta)],
[0, np.sin(theta), np.cos(theta)]
])
return M
def roYaxis(theta):
M = np.matrix([[np.cos(theta), 0, np.sin(theta)],
[0, 1, 0],
[-np.sin(theta), 0, np.cos(theta)]
])
return M
def roZaxis(theta):
M = np.matrix([[np.cos(theta), -np.sin(theta), 0],
[np.sin(theta), np.cos(theta), 0],
[0, 0 ,1]
])
return M
In [ ]:
def computeFrames(rotation, theta, point, frames):
vecPoint = np.matrix([[point[0]],
[point[1]],
[point[2]]
])
t = np.linspace(0, theta, frames)
lineList = [point]
output = []
for i in t:
newPoint = rotation(i)*vecPoint
ptList = np.reshape(newPoint,(1,3)).tolist()[0]
lineList.append(ptList)
output.append([Point(ptList).gObject(), Line(lineList).gObject("rgb(210,64,0)")])
return [output, ptList]
In [ ]:
def computeCompositeFrames(rotation1, rotation2, theta, point, frames, color1="rgb(210,64,0)", color2="rgb(210,64,0)"):
vecPoint = np.matrix([[point[0]],
[point[1]],
[point[2]]
])
t = np.linspace(0, theta, frames)
lineList = [point]
output = []
for i in t:
newPoint = rotation1(i)*vecPoint
ptList = np.reshape(newPoint,(1,3)).tolist()[0]
lineList.append(ptList)
output.append([Point(ptList).gObject(),
Line(lineList).gObject(color1),
Line([[0., 0., 0.], [0., 0., 0.]]).gObject()
])
lineList1 = [ptList]
for j in t[1:]:
newPoint2 = rotation2(j)*newPoint
ptList = np.reshape(newPoint2,(1,3)).tolist()[0]
lineList1.append(ptList)
output.append([Point(ptList).gObject(),
Line(lineList1).gObject(color2),
Line(lineList).gObject(addOpacity(color1, "0.7"))
])
return output
In [ ]:
data = []
for i in range(8):
line = Line([[0., 0., 0.], [0., 0., 0.]]) #Add dummy lines for transformations
data.append(line.gObject("rgb(0,0,0)"))
radius = 2*np.sqrt(3)
sphere = Sphere(radius)
data.append(sphere.gObject())
initialPoint = [2., 2., 2.]
data.append(Point(initialPoint).gObject("rgb(0,0,0)"))
for i in range(3):
uvec = [0., 0., 0.]
uvec[i] = 1
line = Line([[0., 0., 0.], uvec])
data.append(line.gObject("rgb(0,0,0)"))
frames = []
frameSize = 20
frameList1 = computeCompositeFrames(roYaxis,roZaxis,
np.pi/2,
initialPoint,
frameSize,
"rgb(255,0,0)",
"rgb(0,0,255)"
)
frameList2 = computeCompositeFrames(roZaxis,roYaxis,
np.pi/2,
initialPoint,
frameSize,
"rgb(0,0,255)",
"rgb(255,0,0)"
)
for i in range(len(frameList1)):
frames.append(dict(data=[frameList1[i][0],
frameList1[i][1],
frameList1[i][2],
frameList2[i][0],
frameList2[i][1],
frameList2[i][2]
],
name="frame %i" %i
)
)
In [ ]:
steps=[]
for i in range(0,frameSize,1):
step = dict(label='R1',
method='animate',
args=[["frame %i" %i],
dict(mode="immediate",
transition=dict(duration=300
),
frame=dict(duration=300,
redraw=False
)
)
]
)
steps.append(step)
for i in range(0,frameSize-1,1):
step = dict(label='R2',
method='animate',
args=[["frame %i" %(i + frameSize)],
dict(mode="immediate",
transition=dict(duration=300
),
frame=dict(duration=300,
redraw=False
)
)
]
)
steps.append(step)
sliders= [dict(
active=0,
pad={'t':2*frameSize},
steps=steps
)]
layout=dict(width=1000, height=500,
title='Non-Communativeness of 3D Rotations',
hovermode='closest',
updatemenus=[dict(x=-0.05,
y=0.15,
yanchor="top",
xanchor="right",
showactive=False,
type="buttons",
pad={"t": 87, "r": 10},
buttons=[dict(method="animate",
args=[None,
dict(fromcurrent=True,
transition=dict(duration=50,
easing="quadratic-in-out"
),
frame=dict(duration=50,
redraw=False
)
)
],
label="Play"
),
dict(method="animate",
args=[[None],
dict(mode="immediate",
transition=dict(duration=0
),
frame=dict(duration=0,
redraw=False
)
)
],
label="Pause"
)
]
)
],
showlegend=False,#This can be used to isolate individual trace
sliders=sliders)
figure = dict(data=data, frames=frames, layout=layout)
py.plot(figure)
In [ ]:
# import json
# with open("data_3d.json", 'w') as test_file:
# json.dump(figure, test_file, ensure_ascii=False)