passagemath-plot 10.6.31rc3__cp314-cp314-macosx_13_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of passagemath-plot might be problematic. Click here for more details.
- passagemath_plot-10.6.31rc3.dist-info/METADATA +172 -0
- passagemath_plot-10.6.31rc3.dist-info/RECORD +82 -0
- passagemath_plot-10.6.31rc3.dist-info/WHEEL +6 -0
- passagemath_plot-10.6.31rc3.dist-info/top_level.txt +2 -0
- passagemath_plot.dylibs/libgfortran.5.dylib +0 -0
- passagemath_plot.dylibs/libgsl.28.dylib +0 -0
- passagemath_plot.dylibs/libopenblasp-r0.3.29.dylib +0 -0
- passagemath_plot.dylibs/libquadmath.0.dylib +0 -0
- sage/all__sagemath_plot.py +15 -0
- sage/ext_data/threejs/animation.css +195 -0
- sage/ext_data/threejs/animation.html +85 -0
- sage/ext_data/threejs/animation.js +273 -0
- sage/ext_data/threejs/fat_lines.js +48 -0
- sage/ext_data/threejs/threejs-version.txt +1 -0
- sage/ext_data/threejs/threejs_template.html +597 -0
- sage/interfaces/all__sagemath_plot.py +1 -0
- sage/interfaces/gnuplot.py +196 -0
- sage/interfaces/jmoldata.py +208 -0
- sage/interfaces/povray.py +56 -0
- sage/plot/all.py +42 -0
- sage/plot/animate.py +1796 -0
- sage/plot/arc.py +504 -0
- sage/plot/arrow.py +671 -0
- sage/plot/bar_chart.py +205 -0
- sage/plot/bezier_path.py +400 -0
- sage/plot/circle.py +435 -0
- sage/plot/colors.py +1606 -0
- sage/plot/complex_plot.cpython-314-darwin.so +0 -0
- sage/plot/complex_plot.pyx +1446 -0
- sage/plot/contour_plot.py +1792 -0
- sage/plot/density_plot.py +318 -0
- sage/plot/disk.py +373 -0
- sage/plot/ellipse.py +375 -0
- sage/plot/graphics.py +3580 -0
- sage/plot/histogram.py +354 -0
- sage/plot/hyperbolic_arc.py +404 -0
- sage/plot/hyperbolic_polygon.py +416 -0
- sage/plot/hyperbolic_regular_polygon.py +296 -0
- sage/plot/line.py +626 -0
- sage/plot/matrix_plot.py +629 -0
- sage/plot/misc.py +509 -0
- sage/plot/multigraphics.py +1294 -0
- sage/plot/plot.py +4183 -0
- sage/plot/plot3d/all.py +23 -0
- sage/plot/plot3d/base.cpython-314-darwin.so +0 -0
- sage/plot/plot3d/base.pxd +12 -0
- sage/plot/plot3d/base.pyx +3378 -0
- sage/plot/plot3d/implicit_plot3d.py +659 -0
- sage/plot/plot3d/implicit_surface.cpython-314-darwin.so +0 -0
- sage/plot/plot3d/implicit_surface.pyx +1453 -0
- sage/plot/plot3d/index_face_set.cpython-314-darwin.so +0 -0
- sage/plot/plot3d/index_face_set.pxd +32 -0
- sage/plot/plot3d/index_face_set.pyx +1873 -0
- sage/plot/plot3d/introduction.py +131 -0
- sage/plot/plot3d/list_plot3d.py +649 -0
- sage/plot/plot3d/parametric_plot3d.py +1130 -0
- sage/plot/plot3d/parametric_surface.cpython-314-darwin.so +0 -0
- sage/plot/plot3d/parametric_surface.pxd +12 -0
- sage/plot/plot3d/parametric_surface.pyx +893 -0
- sage/plot/plot3d/platonic.py +601 -0
- sage/plot/plot3d/plot3d.py +1442 -0
- sage/plot/plot3d/plot_field3d.py +162 -0
- sage/plot/plot3d/point_c.pxi +148 -0
- sage/plot/plot3d/revolution_plot3d.py +309 -0
- sage/plot/plot3d/shapes.cpython-314-darwin.so +0 -0
- sage/plot/plot3d/shapes.pxd +22 -0
- sage/plot/plot3d/shapes.pyx +1382 -0
- sage/plot/plot3d/shapes2.py +1512 -0
- sage/plot/plot3d/tachyon.py +1779 -0
- sage/plot/plot3d/texture.py +453 -0
- sage/plot/plot3d/transform.cpython-314-darwin.so +0 -0
- sage/plot/plot3d/transform.pxd +21 -0
- sage/plot/plot3d/transform.pyx +268 -0
- sage/plot/plot3d/tri_plot.py +589 -0
- sage/plot/plot_field.py +362 -0
- sage/plot/point.py +624 -0
- sage/plot/polygon.py +562 -0
- sage/plot/primitive.py +249 -0
- sage/plot/scatter_plot.py +199 -0
- sage/plot/step.py +85 -0
- sage/plot/streamline_plot.py +328 -0
- sage/plot/text.py +432 -0
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-plot
|
|
2
|
+
"""
|
|
3
|
+
Transformations
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
# ***************************************************************************
|
|
7
|
+
# Copyright (C) 2007 Robert Bradshaw <robertwb@math.washington.edu>
|
|
8
|
+
#
|
|
9
|
+
# This program is free software: you can redistribute it and/or modify
|
|
10
|
+
# it under the terms of the GNU General Public License as published by
|
|
11
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
12
|
+
# (at your option) any later version.
|
|
13
|
+
# https://www.gnu.org/licenses/
|
|
14
|
+
# ***************************************************************************
|
|
15
|
+
|
|
16
|
+
from libc.math cimport sin, cos, sqrt
|
|
17
|
+
|
|
18
|
+
include "point_c.pxi"
|
|
19
|
+
|
|
20
|
+
from sage.rings.real_double import RDF
|
|
21
|
+
|
|
22
|
+
from sage.matrix.constructor import matrix
|
|
23
|
+
from sage.modules.free_module_element import vector
|
|
24
|
+
|
|
25
|
+
pi = RDF.pi()
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
cdef class Transformation:
|
|
29
|
+
def __init__(self, scale=(1,1,1),
|
|
30
|
+
rot=None,
|
|
31
|
+
trans=[0,0,0],
|
|
32
|
+
m=None):
|
|
33
|
+
|
|
34
|
+
if scale is None:
|
|
35
|
+
scale = (1,1,1)
|
|
36
|
+
if trans is None:
|
|
37
|
+
trans = [0,0,0]
|
|
38
|
+
|
|
39
|
+
# TODO: determine for sure if x3d does scale or rotation first
|
|
40
|
+
if m is not None:
|
|
41
|
+
self.matrix = m
|
|
42
|
+
|
|
43
|
+
else:
|
|
44
|
+
m = matrix(RDF, 3, 3,
|
|
45
|
+
[scale[0], 0, 0, 0, scale[1], 0, 0, 0, scale[2]])
|
|
46
|
+
|
|
47
|
+
if rot is not None:
|
|
48
|
+
# rotate about v by theta
|
|
49
|
+
vx, vy, vz, theta = rot
|
|
50
|
+
m *= rotate_arbitrary((vx, vy, vz), theta)
|
|
51
|
+
|
|
52
|
+
self.matrix = m.augment(matrix(RDF, 3, 1, list(trans))) \
|
|
53
|
+
.stack(matrix(RDF, 1, 4, [0,0,0,1]))
|
|
54
|
+
|
|
55
|
+
# this raw data is used for optimized transformations
|
|
56
|
+
m_data = self.matrix.list()
|
|
57
|
+
cdef int i
|
|
58
|
+
for i in range(12):
|
|
59
|
+
self._matrix_data[i] = m_data[i]
|
|
60
|
+
|
|
61
|
+
def get_matrix(self):
|
|
62
|
+
return self.matrix.__copy__()
|
|
63
|
+
|
|
64
|
+
def is_skew(self, eps=1e-5):
|
|
65
|
+
dx, dy, dz = self.matrix[0:3, 0:3].columns()
|
|
66
|
+
return abs(dx.dot_product(dy)) + abs(dx.dot_product(dz)) + abs(dy.dot_product(dz)) > eps
|
|
67
|
+
|
|
68
|
+
def is_uniform(self, eps=1e-5):
|
|
69
|
+
cols = self.matrix[0:3, 0:3].columns()
|
|
70
|
+
lens = [col.dot_product(col) for col in cols]
|
|
71
|
+
return abs(lens[0] - lens[1]) + abs(lens[0] - lens[2]) < eps
|
|
72
|
+
|
|
73
|
+
def is_uniform_on(self, basis, eps=1e-5):
|
|
74
|
+
basis = [vector(RDF, self.transform_vector(b)) for b in basis]
|
|
75
|
+
a = basis.pop()
|
|
76
|
+
len_a = a.dot_product(a)
|
|
77
|
+
return max([abs(len_a - b.dot_product(b)) for b in basis]) < eps
|
|
78
|
+
|
|
79
|
+
cpdef transform_point(self, x):
|
|
80
|
+
cdef point_c res, P
|
|
81
|
+
P.x, P.y, P.z = x
|
|
82
|
+
point_c_transform(&res, self._matrix_data, P)
|
|
83
|
+
return res.x, res.y, res.z
|
|
84
|
+
|
|
85
|
+
cpdef transform_vector(self, v):
|
|
86
|
+
cdef point_c res, P
|
|
87
|
+
P.x, P.y, P.z = v
|
|
88
|
+
point_c_stretch(&res, self._matrix_data, P)
|
|
89
|
+
return res.x, res.y, res.z
|
|
90
|
+
|
|
91
|
+
cpdef transform_bounding_box(self, box):
|
|
92
|
+
cdef point_c lower, upper, res, temp
|
|
93
|
+
cdef point_c bounds[2]
|
|
94
|
+
bounds[0].x, bounds[0].y, bounds[0].z = box[0]
|
|
95
|
+
bounds[1].x, bounds[1].y, bounds[1].z = box[1]
|
|
96
|
+
point_c_transform(&lower, self._matrix_data, bounds[0])
|
|
97
|
+
point_c_transform(&upper, self._matrix_data, bounds[0])
|
|
98
|
+
cdef int i
|
|
99
|
+
for i in range(1, 8):
|
|
100
|
+
temp.x = bounds[ i & 1 ].x
|
|
101
|
+
temp.y = bounds[(i & 2) >> 1].y
|
|
102
|
+
temp.z = bounds[(i & 4) >> 2].z
|
|
103
|
+
point_c_transform(&res, self._matrix_data, temp)
|
|
104
|
+
point_c_lower_bound(&lower, lower, res)
|
|
105
|
+
point_c_upper_bound(&upper, upper, res)
|
|
106
|
+
return (lower.x, lower.y, lower.z), (upper.x, upper.y, upper.z)
|
|
107
|
+
|
|
108
|
+
cdef void transform_point_c(self, point_c* res, point_c P) noexcept:
|
|
109
|
+
point_c_transform(res, self._matrix_data, P)
|
|
110
|
+
|
|
111
|
+
cdef void transform_vector_c(self, point_c* res, point_c P) noexcept:
|
|
112
|
+
point_c_stretch(res, self._matrix_data, P)
|
|
113
|
+
|
|
114
|
+
def __mul__(Transformation self, Transformation other):
|
|
115
|
+
return Transformation(m = self.matrix * other.matrix)
|
|
116
|
+
|
|
117
|
+
def __invert__(Transformation self):
|
|
118
|
+
return Transformation(m=~self.matrix)
|
|
119
|
+
|
|
120
|
+
def __call__(self, p):
|
|
121
|
+
return self.transform_point(p)
|
|
122
|
+
|
|
123
|
+
def max_scale(self):
|
|
124
|
+
if self._svd is None:
|
|
125
|
+
self._svd = self.matrix[0:3, 0:3].SVD()
|
|
126
|
+
return self._svd[1][0,0]
|
|
127
|
+
|
|
128
|
+
def avg_scale(self):
|
|
129
|
+
if self._svd is None:
|
|
130
|
+
self._svd = self.matrix[0:3, 0:3].SVD()
|
|
131
|
+
return (self._svd[1][0,0] * self._svd[1][1,1] * self._svd[1][2,2]) ** (1/3.0)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def rotate_arbitrary(v, double theta):
|
|
135
|
+
"""
|
|
136
|
+
Return a matrix that rotates the coordinate space about
|
|
137
|
+
the axis v by the angle ``theta``.
|
|
138
|
+
|
|
139
|
+
INPUT:
|
|
140
|
+
|
|
141
|
+
- ``theta`` -- real number, the angle
|
|
142
|
+
|
|
143
|
+
EXAMPLES::
|
|
144
|
+
|
|
145
|
+
sage: from sage.plot.plot3d.transform import rotate_arbitrary
|
|
146
|
+
|
|
147
|
+
Try rotating about the axes::
|
|
148
|
+
|
|
149
|
+
sage: rotate_arbitrary((1,0,0), 1)
|
|
150
|
+
[ 1.0 0.0 0.0]
|
|
151
|
+
[ 0.0 0.5403023058681398 0.8414709848078965]
|
|
152
|
+
[ 0.0 -0.8414709848078965 0.5403023058681398]
|
|
153
|
+
sage: rotate_arbitrary((0,1,0), 1)
|
|
154
|
+
[ 0.5403023058681398 0.0 -0.8414709848078965]
|
|
155
|
+
[ 0.0 1.0 0.0]
|
|
156
|
+
[ 0.8414709848078965 0.0 0.5403023058681398]
|
|
157
|
+
sage: rotate_arbitrary((0,0,1), 1)
|
|
158
|
+
[ 0.5403023058681398 0.8414709848078965 0.0]
|
|
159
|
+
[-0.8414709848078965 0.5403023058681398 0.0]
|
|
160
|
+
[ 0.0 0.0 1.0]
|
|
161
|
+
|
|
162
|
+
These next two should be the same (up to floating-point errors)::
|
|
163
|
+
|
|
164
|
+
sage: rotate_arbitrary((1,1,1), 1) # rel tol 1e-15
|
|
165
|
+
[ 0.6935348705787598 0.6390560643047186 -0.33259093488347846]
|
|
166
|
+
[-0.33259093488347846 0.6935348705787598 0.6390560643047186]
|
|
167
|
+
[ 0.6390560643047186 -0.3325909348834784 0.6935348705787598]
|
|
168
|
+
sage: rotate_arbitrary((1,1,1), -1)^(-1) # rel tol 1e-15
|
|
169
|
+
[ 0.6935348705787598 0.6390560643047186 -0.33259093488347846]
|
|
170
|
+
[-0.33259093488347846 0.6935348705787598 0.6390560643047186]
|
|
171
|
+
[ 0.6390560643047185 -0.33259093488347835 0.6935348705787598]
|
|
172
|
+
|
|
173
|
+
Make sure it does the right thing...::
|
|
174
|
+
|
|
175
|
+
sage: rotate_arbitrary((1,2,3), -1).det()
|
|
176
|
+
1.0000000000000002
|
|
177
|
+
sage: rotate_arbitrary((1,1,1), 2*pi/3) * vector(RDF, (1,2,3)) # rel tol 2e-15 # needs sage.symbolic
|
|
178
|
+
(1.9999999999999996, 2.9999999999999996, 0.9999999999999999)
|
|
179
|
+
sage: rotate_arbitrary((1,2,3), 5) * vector(RDF, (1,2,3)) # rel tol 2e-15
|
|
180
|
+
(1.0000000000000002, 2.0, 3.000000000000001)
|
|
181
|
+
sage: rotate_arbitrary((1,1,1), pi/7)^7 # rel tol 2e-15 # needs sage.symbolic
|
|
182
|
+
[-0.33333333333333337 0.6666666666666671 0.6666666666666665]
|
|
183
|
+
[ 0.6666666666666665 -0.33333333333333337 0.6666666666666671]
|
|
184
|
+
[ 0.6666666666666671 0.6666666666666667 -0.33333333333333326]
|
|
185
|
+
|
|
186
|
+
AUTHORS:
|
|
187
|
+
|
|
188
|
+
- Robert Bradshaw
|
|
189
|
+
|
|
190
|
+
ALGORITHM:
|
|
191
|
+
|
|
192
|
+
There is a formula. Where did it come from? Lets take
|
|
193
|
+
a quick jaunt into Sage's calculus package...
|
|
194
|
+
|
|
195
|
+
Setup some variables::
|
|
196
|
+
|
|
197
|
+
sage: vx,vy,vz,theta = var('x y z theta') # needs sage.symbolic
|
|
198
|
+
|
|
199
|
+
Symbolic rotation matrices about X and Y axis::
|
|
200
|
+
|
|
201
|
+
sage: def rotX(theta): return matrix(SR, 3, 3, [1, 0, 0, 0, cos(theta), -sin(theta), 0, sin(theta), cos(theta)])
|
|
202
|
+
sage: def rotZ(theta): return matrix(SR, 3, 3, [cos(theta), -sin(theta), 0, sin(theta), cos(theta), 0, 0, 0, 1])
|
|
203
|
+
|
|
204
|
+
Normalizing `y` so that `|v|=1`. Perhaps there is a better
|
|
205
|
+
way to tell Maxima that `x^2+y^2+z^2=1` which would make for
|
|
206
|
+
a much cleaner calculation::
|
|
207
|
+
|
|
208
|
+
sage: vy = sqrt(1-vx^2-vz^2) # needs sage.symbolic
|
|
209
|
+
|
|
210
|
+
Now we rotate about the `x`-axis so `v` is in the `xy`-plane::
|
|
211
|
+
|
|
212
|
+
sage: t = arctan(vy/vz)+pi/2 # needs sage.symbolic
|
|
213
|
+
sage: m = rotX(t) # needs sage.symbolic
|
|
214
|
+
sage: new_y = vy*cos(t) - vz*sin(t) # needs sage.symbolic
|
|
215
|
+
|
|
216
|
+
And rotate about the `z` axis so `v` lies on the `x` axis::
|
|
217
|
+
|
|
218
|
+
sage: s = arctan(vx/new_y) + pi/2 # needs sage.symbolic
|
|
219
|
+
sage: m = rotZ(s) * m # needs sage.symbolic
|
|
220
|
+
|
|
221
|
+
Rotating about `v` in our old system is the same as rotating
|
|
222
|
+
about the `x`-axis in the new::
|
|
223
|
+
|
|
224
|
+
sage: m = rotX(theta) * m # needs sage.symbolic
|
|
225
|
+
|
|
226
|
+
Do some simplifying here to avoid blow-up::
|
|
227
|
+
|
|
228
|
+
sage: m = m.simplify_rational() # needs sage.symbolic
|
|
229
|
+
|
|
230
|
+
Now go back to the original coordinate system::
|
|
231
|
+
|
|
232
|
+
sage: m = rotZ(-s) * m # needs sage.symbolic
|
|
233
|
+
sage: m = rotX(-t) * m # needs sage.symbolic
|
|
234
|
+
|
|
235
|
+
And simplify every single entry (which is more effective that simplify
|
|
236
|
+
the whole matrix like above)::
|
|
237
|
+
|
|
238
|
+
sage: m.parent()([x.simplify_full() for x in m._list()]) # random # long time, needs sage.symbolic
|
|
239
|
+
[ -(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]
|
|
240
|
+
[ -(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)]
|
|
241
|
+
[ -((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)]
|
|
242
|
+
|
|
243
|
+
Re-expressing some entries in terms of y and resolving the absolute
|
|
244
|
+
values introduced by eliminating y, we get the desired result.
|
|
245
|
+
"""
|
|
246
|
+
cdef double x,y,z, len_v
|
|
247
|
+
x,y,z = v
|
|
248
|
+
len_v = sqrt(x*x+y*y+z*z)
|
|
249
|
+
# normalize for an easier formula
|
|
250
|
+
x /= len_v
|
|
251
|
+
y /= len_v
|
|
252
|
+
z /= len_v
|
|
253
|
+
cdef double cos_t = cos(theta), sin_t = sin(theta)
|
|
254
|
+
|
|
255
|
+
entries = [
|
|
256
|
+
(1 - cos_t)*x*x + cos_t,
|
|
257
|
+
sin_t*z - (cos_t - 1)*x*y,
|
|
258
|
+
-sin_t*y + (1 - cos_t)*x*z,
|
|
259
|
+
|
|
260
|
+
-sin_t*z + (1 - cos_t)*x*y,
|
|
261
|
+
(1 - cos_t)*y*y + cos_t,
|
|
262
|
+
sin_t*x - (cos_t - 1)*z*y,
|
|
263
|
+
|
|
264
|
+
sin_t*y - (cos_t - 1)*x*z,
|
|
265
|
+
-(cos_t - 1)*z*y - sin_t*x,
|
|
266
|
+
(1 - cos_t)*z*z + cos_t ]
|
|
267
|
+
|
|
268
|
+
return matrix(RDF, 3, 3, entries)
|