Transformations¶
-
class
sage.plot.plot3d.transform.
Transformation
¶ Bases:
object
-
avg_scale
()¶
-
get_matrix
()¶
-
is_skew
(eps=1e-05)¶
-
is_uniform
(eps=1e-05)¶
-
is_uniform_on
(basis, eps=1e-05)¶
-
max_scale
()¶
-
transform_bounding_box
(box)¶
-
transform_point
(x)¶
-
transform_vector
(v)¶
-
-
sage.plot.plot3d.transform.
rotate_arbitrary
(v, theta)¶ Return a matrix that rotates the coordinate space about the axis v by the angle
theta
.INPUT:
theta
- real number, the angle
EXAMPLES:
sage: from sage.plot.plot3d.transform import rotate_arbitrary
Try rotating about the axes:
sage: rotate_arbitrary((1,0,0), 1) [ 1.0 0.0 0.0] [ 0.0 0.5403023058681398 0.8414709848078965] [ 0.0 -0.8414709848078965 0.5403023058681398] sage: rotate_arbitrary((0,1,0), 1) [ 0.5403023058681398 0.0 -0.8414709848078965] [ 0.0 1.0 0.0] [ 0.8414709848078965 0.0 0.5403023058681398] sage: rotate_arbitrary((0,0,1), 1) [ 0.5403023058681398 0.8414709848078965 0.0] [-0.8414709848078965 0.5403023058681398 0.0] [ 0.0 0.0 1.0]
These next two should be the same (up to floating-point errors):
sage: rotate_arbitrary((1,1,1), 1) # rel tol 1e-15 [ 0.6935348705787598 0.6390560643047186 -0.33259093488347846] [-0.33259093488347846 0.6935348705787598 0.6390560643047186] [ 0.6390560643047186 -0.3325909348834784 0.6935348705787598] sage: rotate_arbitrary((1,1,1), -1)^(-1) # rel tol 1e-15 [ 0.6935348705787598 0.6390560643047186 -0.33259093488347846] [-0.33259093488347846 0.6935348705787598 0.6390560643047186] [ 0.6390560643047185 -0.33259093488347835 0.6935348705787598]
Make sure it does the right thing…:
sage: rotate_arbitrary((1,2,3), -1).det() 1.0000000000000002 sage: rotate_arbitrary((1,1,1), 2*pi/3) * vector(RDF, (1,2,3)) # rel tol 2e-15 (1.9999999999999996, 2.9999999999999996, 0.9999999999999999) sage: rotate_arbitrary((1,2,3), 5) * vector(RDF, (1,2,3)) # rel tol 2e-15 (1.0000000000000002, 2.0, 3.000000000000001) sage: rotate_arbitrary((1,1,1), pi/7)^7 # rel tol 2e-15 [-0.33333333333333337 0.6666666666666671 0.6666666666666665] [ 0.6666666666666665 -0.33333333333333337 0.6666666666666671] [ 0.6666666666666671 0.6666666666666667 -0.33333333333333326]
AUTHORS:
Robert Bradshaw
ALGORITHM:
There is a formula. Where did it come from? Lets take a quick jaunt into Sage’s calculus package…
Setup some variables:
sage: vx,vy,vz,theta = var('x y z theta')
Symbolic rotation matrices about X and Y axis:
sage: def rotX(theta): return matrix(SR, 3, 3, [1, 0, 0, 0, cos(theta), -sin(theta), 0, sin(theta), cos(theta)]) sage: def rotZ(theta): return matrix(SR, 3, 3, [cos(theta), -sin(theta), 0, sin(theta), cos(theta), 0, 0, 0, 1])
Normalizing $y$ so that $|v|=1$. Perhaps there is a better way to tell Maxima that $x^2+y^2+z^2=1$ which would make for a much cleaner calculation:
sage: vy = sqrt(1-vx^2-vz^2)
Now we rotate about the $x$-axis so $v$ is in the $xy$-plane:
sage: t = arctan(vy/vz)+pi/2 sage: m = rotX(t) sage: new_y = vy*cos(t) - vz*sin(t)
And rotate about the $z$ axis so $v$ lies on the $x$ axis:
sage: s = arctan(vx/new_y) + pi/2 sage: m = rotZ(s) * m
Rotating about $v$ in our old system is the same as rotating about the $x$-axis in the new:
sage: m = rotX(theta) * m
Do some simplifying here to avoid blow-up:
sage: m = m.simplify_rational()
Now go back to the original coordinate system:
sage: m = rotZ(-s) * m sage: m = rotX(-t) * m
And simplify every single entry (which is more effective that simplify the whole matrix like above):
sage: m.parent()([x.simplify_full() for x in m._list()]) # long time; random [ -(cos(theta) - 1)*x^2 + cos(theta) -(cos(theta) - 1)*sqrt(-x^2 - z^2 + 1)*x + sin(theta)*abs(z) -((cos(theta) - 1)*x*z^2 + sqrt(-x^2 - z^2 + 1)*sin(theta)*abs(z))/z] [ -(cos(theta) - 1)*sqrt(-x^2 - z^2 + 1)*x - sin(theta)*abs(z) (cos(theta) - 1)*x^2 + (cos(theta) - 1)*z^2 + 1 -((cos(theta) - 1)*sqrt(-x^2 - z^2 + 1)*z*abs(z) - x*z*sin(theta))/abs(z)] [ -((cos(theta) - 1)*x*z^2 - sqrt(-x^2 - z^2 + 1)*sin(theta)*abs(z))/z -((cos(theta) - 1)*sqrt(-x^2 - z^2 + 1)*z*abs(z) + x*z*sin(theta))/abs(z) -(cos(theta) - 1)*z^2 + cos(theta)]
Re-expressing some entries in terms of y and resolving the absolute values introduced by eliminating y, we get the desired result.