# THE FOLLOWING CODE FALLS UNDER THE LICENCE BELOW:
#
# Copyright (c) 2015, authors of Vispy
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of Vispy Development Team nor the names of its
# contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import numpy as np
[docs]def translate(M, x, y=None, z=None):
"""
translate produces a translation by (x, y, z) .
Parameters
----------
x, y, z
Specify the x, y, and z coordinates of a translation vector.
"""
if y is None: y = x
if z is None: z = x
T = [[ 1, 0, 0, x],
[ 0, 1, 0, y],
[ 0, 0, 1, z],
[ 0, 0, 0, 1]]
T = np.array(T, dtype=np.float32).T
M[...] = np.dot(M,T)
[docs]def translate2(x, y=None, z=None):
"""
translate produces a translation by (x, y, z) .
Parameters
----------
x, y, z
Specify the x, y, and z coordinates of a translation vector.
"""
if y is None: y = x
if z is None: z = x
T = [[ 1, 0, 0, x],
[ 0, 1, 0, y],
[ 0, 0, 1, z],
[ 0, 0, 0, 1]]
T = np.array(T, dtype=np.float32).T
return T
[docs]def scale(M, x, y=None, z=None):
"""
scale produces a non uniform scaling along the x, y, and z axes. The three
parameters indicate the desired scale factor along each of the three axes.
Parameters
----------
x, y, z
Specify scale factors along the x, y, and z axes, respectively.
"""
if y is None: y = x
if z is None: z = x
S = [[ x, 0, 0, 0],
[ 0, y, 0, 0],
[ 0, 0, z, 0],
[ 0, 0, 0, 1]]
S = np.array(S,dtype=np.float32).T
M[...] = np.dot(M,S)
[docs]def xrotate(M,theta):
t = np.pi*theta/180
cosT = np.cos( t )
sinT = np.sin( t )
R = np.array(
[[ 1.0, 0.0, 0.0, 0.0 ],
[ 0.0, cosT,-sinT, 0.0 ],
[ 0.0, sinT, cosT, 0.0 ],
[ 0.0, 0.0, 0.0, 1.0 ]], dtype=np.float32)
M[...] = np.dot(M,R)
[docs]def yrotate(M,theta):
t = np.pi*theta/180
cosT = np.cos( t )
sinT = np.sin( t )
R = np.array(
[[ cosT, 0.0, sinT, 0.0 ],
[ 0.0, 1.0, 0.0, 0.0 ],
[-sinT, 0.0, cosT, 0.0 ],
[ 0.0, 0.0, 0.0, 1.0 ]], dtype=np.float32)
M[...] = np.dot(M,R)
[docs]def zrotate(M,theta):
t = np.pi*theta/180
cosT = np.cos( t )
sinT = np.sin( t )
R = np.array(
[[ cosT,-sinT, 0.0, 0.0 ],
[ sinT, cosT, 0.0, 0.0 ],
[ 0.0, 0.0, 1.0, 0.0 ],
[ 0.0, 0.0, 0.0, 1.0 ]], dtype=np.float32)
M[...] = np.dot(M,R)
[docs]def rotate(M, angle, x, y, z, point=None):
"""
rotate produces a rotation of angle degrees around the vector (x, y, z).
Parameters
----------
M
Current transformation as a numpy array
angle
Specifies the angle of rotation, in degrees.
x, y, z
Specify the x, y, and z coordinates of a vector, respectively.
"""
angle = np.pi*angle/180
c,s = np.cos(angle), np.sin(angle)
n = np.sqrt(x*x+y*y+z*z)
x /= n
y /= n
z /= n
cx,cy,cz = (1-c)*x, (1-c)*y, (1-c)*z
R = np.array([[ cx*x + c , cy*x - z*s, cz*x + y*s, 0],
[ cx*y + z*s, cy*y + c , cz*y - x*s, 0],
[ cx*z - y*s, cy*z + x*s, cz*z + c, 0],
[ 0, 0, 0, 1]]).T
M[...] = np.dot(M,R)
[docs]def ortho( left, right, bottom, top, znear, zfar ):
assert( right != left )
assert( bottom != top )
assert( znear != zfar )
M = np.zeros((4,4), dtype=np.float32)
M[0,0] = +2.0/(right-left)
M[3,0] = -(right+left)/float(right-left)
M[1,1] = +2.0/(top-bottom)
M[3,1] = -(top+bottom)/float(top-bottom)
M[2,2] = -2.0/(zfar-znear)
M[3,2] = -(zfar+znear)/float(zfar-znear)
M[3,3] = 1.0
return M
[docs]def frustum( left, right, bottom, top, znear, zfar ):
assert( right != left )
assert( bottom != top )
assert( znear != zfar )
M = np.zeros((4,4), dtype=np.float32)
M[0,0] = +2.0*znear/(right-left)
M[2,0] = (right+left)/(right-left)
M[1,1] = +2.0*znear/(top-bottom)
M[3,1] = (top+bottom)/(top-bottom)
M[2,2] = -(zfar+znear)/(zfar-znear)
M[3,2] = -2.0*znear*zfar/(zfar-znear)
M[2,3] = -1.0
return M
[docs]def perspective(fovy, aspect, znear, zfar):
assert( znear != zfar )
h = np.tan(fovy / 360.0 * np.pi) * znear
w = h * aspect
return frustum( -w, w, -h, h, znear, zfar )
# THE FOLLOWING CODE FALLS UNDER THE LICENCE BELOW:
#
# Copyright (c) 2006-2017, Christoph Gohlke
# Copyright (c) 2006-2017, The Regents of the University of California
# Produced at the Laboratory for Fluorescence Dynamics
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the copyright holders nor the names of any
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
[docs]def quaternion_matrix(quaternion):
"""Return homogeneous rotation matrix from quaternion.
>>> M = quaternion_matrix([0.99810947, 0.06146124, 0, 0])
>>> numpy.allclose(M, rotation_matrix(0.123, [1, 0, 0]))
True
>>> M = quaternion_matrix([1, 0, 0, 0])
>>> numpy.allclose(M, numpy.identity(4))
True
>>> M = quaternion_matrix([0, 1, 0, 0])
>>> numpy.allclose(M, numpy.diag([1, -1, -1, 1]))
True
"""
q = np.array(quaternion, dtype=np.float64, copy=True)
n = np.dot(q, q)
if n < 1e-6:
return np.identity(4)
q *= np.sqrt(2.0 / n)
q = np.outer(q, q)
return np.array([
[(1.0-q[2, 2]-q[3, 3]), ( q[1, 2]-q[3, 0]),( q[1, 3]+q[2, 0]), 0.0],
[( q[1, 2]+q[3, 0]), (1.0-q[1, 1]-q[3, 3]),( q[2, 3]-q[1, 0]), 0.0],
[( q[1, 3]-q[2, 0]), ( q[2, 3]+q[1, 0]),( 1.0-q[1, 1]-q[2, 2]), 0.0],
[ 0.0, 0.0, 0.0, 1.0]])