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.

Files changed (82) hide show
  1. passagemath_plot-10.6.31rc3.dist-info/METADATA +172 -0
  2. passagemath_plot-10.6.31rc3.dist-info/RECORD +82 -0
  3. passagemath_plot-10.6.31rc3.dist-info/WHEEL +6 -0
  4. passagemath_plot-10.6.31rc3.dist-info/top_level.txt +2 -0
  5. passagemath_plot.dylibs/libgfortran.5.dylib +0 -0
  6. passagemath_plot.dylibs/libgsl.28.dylib +0 -0
  7. passagemath_plot.dylibs/libopenblasp-r0.3.29.dylib +0 -0
  8. passagemath_plot.dylibs/libquadmath.0.dylib +0 -0
  9. sage/all__sagemath_plot.py +15 -0
  10. sage/ext_data/threejs/animation.css +195 -0
  11. sage/ext_data/threejs/animation.html +85 -0
  12. sage/ext_data/threejs/animation.js +273 -0
  13. sage/ext_data/threejs/fat_lines.js +48 -0
  14. sage/ext_data/threejs/threejs-version.txt +1 -0
  15. sage/ext_data/threejs/threejs_template.html +597 -0
  16. sage/interfaces/all__sagemath_plot.py +1 -0
  17. sage/interfaces/gnuplot.py +196 -0
  18. sage/interfaces/jmoldata.py +208 -0
  19. sage/interfaces/povray.py +56 -0
  20. sage/plot/all.py +42 -0
  21. sage/plot/animate.py +1796 -0
  22. sage/plot/arc.py +504 -0
  23. sage/plot/arrow.py +671 -0
  24. sage/plot/bar_chart.py +205 -0
  25. sage/plot/bezier_path.py +400 -0
  26. sage/plot/circle.py +435 -0
  27. sage/plot/colors.py +1606 -0
  28. sage/plot/complex_plot.cpython-314-darwin.so +0 -0
  29. sage/plot/complex_plot.pyx +1446 -0
  30. sage/plot/contour_plot.py +1792 -0
  31. sage/plot/density_plot.py +318 -0
  32. sage/plot/disk.py +373 -0
  33. sage/plot/ellipse.py +375 -0
  34. sage/plot/graphics.py +3580 -0
  35. sage/plot/histogram.py +354 -0
  36. sage/plot/hyperbolic_arc.py +404 -0
  37. sage/plot/hyperbolic_polygon.py +416 -0
  38. sage/plot/hyperbolic_regular_polygon.py +296 -0
  39. sage/plot/line.py +626 -0
  40. sage/plot/matrix_plot.py +629 -0
  41. sage/plot/misc.py +509 -0
  42. sage/plot/multigraphics.py +1294 -0
  43. sage/plot/plot.py +4183 -0
  44. sage/plot/plot3d/all.py +23 -0
  45. sage/plot/plot3d/base.cpython-314-darwin.so +0 -0
  46. sage/plot/plot3d/base.pxd +12 -0
  47. sage/plot/plot3d/base.pyx +3378 -0
  48. sage/plot/plot3d/implicit_plot3d.py +659 -0
  49. sage/plot/plot3d/implicit_surface.cpython-314-darwin.so +0 -0
  50. sage/plot/plot3d/implicit_surface.pyx +1453 -0
  51. sage/plot/plot3d/index_face_set.cpython-314-darwin.so +0 -0
  52. sage/plot/plot3d/index_face_set.pxd +32 -0
  53. sage/plot/plot3d/index_face_set.pyx +1873 -0
  54. sage/plot/plot3d/introduction.py +131 -0
  55. sage/plot/plot3d/list_plot3d.py +649 -0
  56. sage/plot/plot3d/parametric_plot3d.py +1130 -0
  57. sage/plot/plot3d/parametric_surface.cpython-314-darwin.so +0 -0
  58. sage/plot/plot3d/parametric_surface.pxd +12 -0
  59. sage/plot/plot3d/parametric_surface.pyx +893 -0
  60. sage/plot/plot3d/platonic.py +601 -0
  61. sage/plot/plot3d/plot3d.py +1442 -0
  62. sage/plot/plot3d/plot_field3d.py +162 -0
  63. sage/plot/plot3d/point_c.pxi +148 -0
  64. sage/plot/plot3d/revolution_plot3d.py +309 -0
  65. sage/plot/plot3d/shapes.cpython-314-darwin.so +0 -0
  66. sage/plot/plot3d/shapes.pxd +22 -0
  67. sage/plot/plot3d/shapes.pyx +1382 -0
  68. sage/plot/plot3d/shapes2.py +1512 -0
  69. sage/plot/plot3d/tachyon.py +1779 -0
  70. sage/plot/plot3d/texture.py +453 -0
  71. sage/plot/plot3d/transform.cpython-314-darwin.so +0 -0
  72. sage/plot/plot3d/transform.pxd +21 -0
  73. sage/plot/plot3d/transform.pyx +268 -0
  74. sage/plot/plot3d/tri_plot.py +589 -0
  75. sage/plot/plot_field.py +362 -0
  76. sage/plot/point.py +624 -0
  77. sage/plot/polygon.py +562 -0
  78. sage/plot/primitive.py +249 -0
  79. sage/plot/scatter_plot.py +199 -0
  80. sage/plot/step.py +85 -0
  81. sage/plot/streamline_plot.py +328 -0
  82. sage/plot/text.py +432 -0
@@ -0,0 +1,589 @@
1
+ # sage_setup: distribution = sagemath-plot
2
+ r"""
3
+ Adaptive refinement code for 3d surface plotting
4
+
5
+ AUTHOR:
6
+
7
+ - Tom Boothby -- Algorithm design, code
8
+ - Joshua Kantor -- Algorithm design
9
+ - Marshall Hampton -- Docstrings and doctests
10
+
11
+ .. TODO::
12
+
13
+ - Parametrizations (cylindrical, spherical)
14
+ - Massive optimization
15
+ """
16
+
17
+ ###########################################################################
18
+ # Copyright (C) 2007 Tom Boothby <boothby@u.washington.edu>
19
+ # 2007 Joshua Kantor <jkantor@math.washington.edu>
20
+ #
21
+ # Distributed under the terms of the GNU General Public License (GPL)
22
+ # http://www.gnu.org/licenses/
23
+ ###########################################################################
24
+
25
+ from sage.plot.colors import hue
26
+ from math import sqrt
27
+ import random
28
+
29
+
30
+ class Triangle:
31
+ """
32
+ A graphical triangle class.
33
+ """
34
+ def __init__(self, a, b, c, color=0):
35
+ """
36
+ a, b, c : triples (x,y,z) representing corners on a triangle in 3-space.
37
+
38
+ TESTS::
39
+
40
+ sage: from sage.plot.plot3d.tri_plot import Triangle
41
+ sage: tri = Triangle([0,0,0],[-1,2,3],[0,2,0])
42
+ sage: tri._a
43
+ [0, 0, 0]
44
+ sage: tri.__init__([0,0,1],[-1,2,3],[0,2,0])
45
+ sage: tri._a
46
+ [0, 0, 1]
47
+ """
48
+ self._a = a
49
+ self._b = b
50
+ self._c = c
51
+ self._color = color
52
+
53
+ def str(self):
54
+ """
55
+ Return a string representation of an instance of the Triangle
56
+ class of the form
57
+
58
+ a b c color
59
+
60
+ where a, b, and c are corner coordinates and color is the color.
61
+
62
+ TESTS::
63
+
64
+ sage: from sage.plot.plot3d.tri_plot import Triangle
65
+ sage: tri = Triangle([0,0,0],[-1,2,3],[0,2,0])
66
+ sage: print(tri.str())
67
+ [0, 0, 0] [-1, 2, 3] [0, 2, 0] 0
68
+ """
69
+ return f"{self._a} {self._b} {self._c} {self._color}"
70
+
71
+ def set_color(self, color):
72
+ """
73
+ This method will reset the color of the triangle.
74
+
75
+ TESTS::
76
+
77
+ sage: from sage.plot.plot3d.tri_plot import Triangle
78
+ sage: tri = Triangle([0,0,0],[-1,2,3],[0,2,1])
79
+ sage: tri._color
80
+ 0
81
+ sage: tri.set_color(1)
82
+ sage: tri._color
83
+ 1
84
+ """
85
+ self._color = color
86
+
87
+ def get_vertices(self):
88
+ """
89
+ Return a tuple of vertex coordinates of the triangle.
90
+
91
+ TESTS::
92
+
93
+ sage: from sage.plot.plot3d.tri_plot import Triangle
94
+ sage: tri = Triangle([0,0,0],[-1,2,3],[0,2,1])
95
+ sage: tri.get_vertices()
96
+ ([0, 0, 0], [-1, 2, 3], [0, 2, 1])
97
+ """
98
+ return (self._a, self._b, self._c)
99
+
100
+
101
+ class SmoothTriangle(Triangle):
102
+ """
103
+ A class for smoothed triangles.
104
+ """
105
+ def __init__(self, a, b, c, da, db, dc, color=0):
106
+ """
107
+ a, b, c : triples (x,y,z) representing corners on a triangle in 3-space
108
+ da, db, dc : triples (dx,dy,dz) representing the normal vector at each point a,b,c
109
+
110
+ TESTS::
111
+
112
+ sage: from sage.plot.plot3d.tri_plot import SmoothTriangle
113
+ sage: t = SmoothTriangle([1,2,3],[2,3,4],[0,0,0],[0,0,1],[0,1,0],[1,0,0])
114
+ sage: t._a
115
+ [1, 2, 3]
116
+ """
117
+ self._a = a
118
+ self._b = b
119
+ self._c = c
120
+ self._da = da
121
+ self._db = db
122
+ self._dc = dc
123
+ self._color = color
124
+
125
+ def str(self):
126
+ """
127
+ Return a string representation of the SmoothTriangle of the form.
128
+
129
+ a b c color da db dc
130
+
131
+ where a, b, and c are the triangle corner coordinates,
132
+ da, db, dc are normals at each corner, and color is the color.
133
+
134
+ TESTS::
135
+
136
+ sage: from sage.plot.plot3d.tri_plot import SmoothTriangle
137
+ sage: t = SmoothTriangle([1,2,3],[2,3,4],[0,0,0],[0,0,1],[0,1,0],[1,0,0])
138
+ sage: print(t.str())
139
+ [1, 2, 3] [2, 3, 4] [0, 0, 0] 0 [0, 0, 1] [0, 1, 0] [1, 0, 0]
140
+ """
141
+ return "{} {} {} {} {} {} {}".format(self._a, self._b, self._c, self._color, self._da, self._db, self._dc)
142
+
143
+ def get_normals(self):
144
+ """
145
+ Return the normals to vertices a, b, and c.
146
+
147
+ TESTS::
148
+
149
+ sage: from sage.plot.plot3d.tri_plot import SmoothTriangle
150
+ sage: t = SmoothTriangle([1,2,3],[2,3,4],[0,0,0],[0,0,1],[0,1,0],[2,0,0])
151
+ sage: t.get_normals()
152
+ ([0, 0, 1], [0, 1, 0], [2, 0, 0])
153
+ """
154
+ return (self._da, self._db, self._dc)
155
+
156
+
157
+ class TriangleFactory:
158
+ def triangle(self, a, b, c, color=None):
159
+ """
160
+ Parameters:
161
+ a, b, c : triples (x,y,z) representing corners on a triangle in 3-space
162
+
163
+ Returns:
164
+ a Triangle object with the specified coordinates
165
+
166
+ TESTS::
167
+
168
+ sage: from sage.plot.plot3d.tri_plot import TriangleFactory
169
+ sage: factory = TriangleFactory()
170
+ sage: tri = factory.triangle([0,0,0],[0,0,1],[1,1,0])
171
+ sage: tri.get_vertices()
172
+ ([0, 0, 0], [0, 0, 1], [1, 1, 0])
173
+ """
174
+ if color is None:
175
+ return Triangle(a,b,c)
176
+ else:
177
+ return Triangle(a,b,c,color)
178
+
179
+ def smooth_triangle(self, a, b, c, da, db, dc, color=None):
180
+ """
181
+ Parameters:
182
+
183
+ - a, b, c : triples (x,y,z) representing corners on a triangle in 3-space
184
+ - da, db, dc : triples (dx,dy,dz) representing the normal vector at each point a,b,c
185
+
186
+ Returns:
187
+ a SmoothTriangle object with the specified coordinates and normals
188
+
189
+ TESTS::
190
+
191
+ sage: from sage.plot.plot3d.tri_plot import TriangleFactory
192
+ sage: factory = TriangleFactory()
193
+ sage: sm_tri = factory.smooth_triangle([0,0,0],[0,0,1],[1,1,0],[0,0,1],[0,2,0],[1,0,0])
194
+ sage: sm_tri.get_normals()
195
+ ([0, 0, 1], [0, 2, 0], [1, 0, 0])
196
+ """
197
+ if color is None:
198
+ return SmoothTriangle(a,b,c,da,db,dc)
199
+ else:
200
+ return SmoothTriangle(a,b,c,da,db,dc,color)
201
+
202
+ def get_colors(self, list):
203
+ """
204
+ Parameters:
205
+ list: an iterable collection of values which can be cast into colors
206
+ -- typically an RGB triple, or an RGBA 4-tuple
207
+
208
+ Returns:
209
+ a list of single parameters which can be passed into the set_color
210
+ method of the Triangle or SmoothTriangle objects generated by this
211
+ factory.
212
+
213
+ TESTS::
214
+
215
+ sage: from sage.plot.plot3d.tri_plot import TriangleFactory
216
+ sage: factory = TriangleFactory()
217
+ sage: factory.get_colors([1,2,3])
218
+ [1, 2, 3]
219
+ """
220
+ return list
221
+
222
+
223
+ class TrianglePlot:
224
+ """
225
+ Recursively plot a function of two variables by building squares of 4 triangles, checking at
226
+ every stage whether or not each square should be split into four more squares. This way,
227
+ more planar areas get fewer triangles, and areas with higher curvature get more triangles.
228
+ """
229
+
230
+ def str(self):
231
+ """
232
+ Return a string listing the objects in the instance of the TrianglePlot class.
233
+
234
+ TESTS::
235
+
236
+ sage: from sage.plot.plot3d.tri_plot import TrianglePlot, TriangleFactory
237
+ sage: tf = TriangleFactory()
238
+ sage: t = TrianglePlot(tf, lambda x,y: x^3+y*x-1, (-1, 3), (-2, 100), max_depth = 4)
239
+ sage: len(t.str())
240
+ 68980
241
+ """
242
+ return "".join(o.str() for o in self._objects)
243
+
244
+ def __init__(self, triangle_factory, f, min_x__max_x, min_y__max_y, g=None,
245
+ min_depth=4, max_depth=8, num_colors=None, max_bend=.3):
246
+ """
247
+
248
+ TESTS::
249
+
250
+ sage: from sage.plot.plot3d.tri_plot import TrianglePlot, TriangleFactory
251
+ sage: tf = TriangleFactory()
252
+ sage: t = TrianglePlot(tf, lambda x,y: x^2+y^2, (0, 1), (0, 1))
253
+ sage: t._f(1,1)
254
+ 2
255
+ """
256
+ (min_x, max_x) = min_x__max_x
257
+ (min_y, max_y) = min_y__max_y
258
+ self._triangle_factory = triangle_factory
259
+ self._f = f
260
+ self._g = g
261
+ self._min_depth = min_depth
262
+ self._max_depth = max_depth
263
+ self._max_bend = max_bend
264
+ self._objects = []
265
+ if min(max_x - min_x, max_y - min_y) == 0:
266
+ raise ValueError('plot rectangle is really a line; make sure min_x != max_x and min_y != max_y')
267
+ self._num_colors = num_colors
268
+ if g is None:
269
+ def fcn(x, y):
270
+ return [self._f(x,y)]
271
+ else:
272
+ def fcn(x, y):
273
+ return [self._f(x,y), self._g(x,y)]
274
+
275
+ self._fcn = fcn
276
+
277
+ # generate the necessary data to kick-start the recursion
278
+ mid_x = (min_x + max_x)/2
279
+ mid_y = (min_y + max_y)/2
280
+ sw_z = fcn(min_x,min_y)
281
+ nw_z = fcn(min_x,max_y)
282
+ se_z = fcn(max_x,min_y)
283
+ ne_z = fcn(max_x,max_y)
284
+ mid_z = fcn(mid_x,mid_y)
285
+
286
+ self._min = min(sw_z[0], nw_z[0], se_z[0], ne_z[0], mid_z[0])
287
+ self._max = max(sw_z[0], nw_z[0], se_z[0], ne_z[0], mid_z[0])
288
+
289
+ # jump in and start building blocks
290
+ outer = self.plot_block(min_x, mid_x, max_x, min_y, mid_y, max_y, sw_z, nw_z, se_z, ne_z, mid_z, 0)
291
+
292
+ # build the boundary triangles
293
+ self.triangulate(outer.left, outer.left_c)
294
+ self.triangulate(outer.top, outer.top_c)
295
+ self.triangulate(outer.right, outer.right_c)
296
+ self.triangulate(outer.bottom, outer.bottom_c)
297
+
298
+ zrange = self._max - self._min
299
+ if num_colors is not None and zrange != 0:
300
+ colors = triangle_factory.get_colors([hue(float(i/num_colors)) for i in range(num_colors)])
301
+
302
+ for o in self._objects:
303
+ vertices = o.get_vertices()
304
+ avg_z = (vertices[0][2] + vertices[1][2] + vertices[2][2])/3
305
+ o.set_color(colors[int(num_colors * (avg_z - self._min) / zrange)])
306
+
307
+ def plot_block(self, min_x, mid_x, max_x, min_y, mid_y, max_y, sw_z, nw_z, se_z, ne_z, mid_z, depth):
308
+ """
309
+ Recursive triangulation function for plotting.
310
+
311
+ First six inputs are scalars, next 5 are 2-dimensional lists, and the depth argument
312
+ keeps track of the depth of recursion.
313
+
314
+ TESTS::
315
+
316
+ sage: from sage.plot.plot3d.tri_plot import TrianglePlot, TriangleFactory
317
+ sage: tf = TriangleFactory()
318
+ sage: t = TrianglePlot(tf, lambda x,y: x^2 + y^2, (-1,1), (-1, 1), max_depth=3)
319
+ sage: q = t.plot_block(0,.5,1,0,.5,1,[0,1],[0,1],[0,1],[0,1],[0,1],2)
320
+ sage: q.left
321
+ [[(0, 0, 0)], [(0, 0.500000000000000, 0.250000000000000)], [(0, 1, 0)]]
322
+ """
323
+
324
+ if depth < self._max_depth:
325
+ # recursion is still an option -- step in one last level if we're within tolerance
326
+ # and just keep going if we're not.
327
+ # assumption: it's cheap to build triangles, so we might as well use all the data
328
+ # we calculate
329
+
330
+ # big square boundary midpoints
331
+ mid_w_z = self._fcn(min_x, mid_y)
332
+ mid_n_z = self._fcn(mid_x, max_y)
333
+ mid_e_z = self._fcn(max_x, mid_y)
334
+ mid_s_z = self._fcn(mid_x, min_y)
335
+
336
+ next_depth = depth+1
337
+ if depth < self._min_depth:
338
+ # midpoints locations of sub_squares
339
+ qtr1_x = (min_x + mid_x)/2
340
+ qtr1_y = (min_y + mid_y)/2
341
+ qtr3_x = (mid_x + max_x)/2
342
+ qtr3_y = (mid_y + max_y)/2
343
+
344
+ sw_depth = next_depth
345
+ nw_depth = next_depth
346
+ se_depth = next_depth
347
+ ne_depth = next_depth
348
+ else:
349
+ # compute the midpoint-to-corner vectors
350
+ sw_v = (min_x - mid_x, min_y - mid_y, sw_z[0] - mid_z[0])
351
+ nw_v = (min_x - mid_x, max_y - mid_y, nw_z[0] - mid_z[0])
352
+ se_v = (max_x - mid_x, min_y - mid_y, se_z[0] - mid_z[0])
353
+ ne_v = (max_x - mid_x, max_y - mid_y, ne_z[0] - mid_z[0])
354
+
355
+ # compute triangle normal unit vectors by taking the cross-products
356
+ # of the midpoint-to-corner vectors. always go around clockwise
357
+ # so we're guaranteed to have a positive value near 1 when neighboring
358
+ # triangles are parallel
359
+ # However -- crossunit doesn't really return a unit vector. It returns
360
+ # the length of the vector to avoid numerical instability when the
361
+ # length is nearly zero -- rather than divide by nearly zero, we multiply
362
+ # the other side of the inequality by nearly zero -- in general, this
363
+ # should work a bit better because of the density of floating-point
364
+ # numbers near zero.
365
+ norm_w = crossunit(sw_v, nw_v)
366
+ norm_n = crossunit(nw_v, ne_v)
367
+ norm_e = crossunit(ne_v, se_v)
368
+ norm_s = crossunit(se_v, sw_v)
369
+
370
+ # compute the dot products of the triangle unit norms
371
+ e_sw = norm_w[0]*norm_s[0] + norm_w[1]*norm_s[1] + norm_w[2]*norm_s[2]
372
+ e_nw = norm_w[0]*norm_n[0] + norm_w[1]*norm_n[1] + norm_w[2]*norm_n[2]
373
+ e_se = norm_e[0]*norm_s[0] + norm_e[1]*norm_s[1] + norm_e[2]*norm_s[2]
374
+ e_ne = norm_e[0]*norm_n[0] + norm_e[1]*norm_n[1] + norm_e[2]*norm_n[2]
375
+
376
+ if e_sw < self._max_bend*norm_s[3]*norm_w[3]:
377
+ sw_depth = next_depth
378
+ else:
379
+ sw_depth = self._max_depth
380
+ if e_nw < self._max_bend*norm_n[3]*norm_w[3]:
381
+ nw_depth = next_depth
382
+ else:
383
+ nw_depth = self._max_depth
384
+ if e_se < self._max_bend*norm_s[3]*norm_e[3]:
385
+ se_depth = next_depth
386
+ else:
387
+ se_depth = self._max_depth
388
+ if e_ne < self._max_bend*norm_n[3]*norm_e[3]:
389
+ ne_depth = next_depth
390
+ else:
391
+ ne_depth = self._max_depth
392
+
393
+ qtr1_x = min_x + (.325 + random.random()/4)*(mid_x-min_x)
394
+ qtr3_x = mid_x + (.325 + random.random()/4)*(max_x-mid_x)
395
+ qtr1_y = min_y + (.325 + random.random()/4)*(mid_y-min_y)
396
+ qtr3_y = mid_y + (.325 + random.random()/4)*(max_y-mid_y)
397
+
398
+ # function evaluated at the midpoints (possibly random)
399
+ mid_sw_z = self._fcn(qtr1_x,qtr1_y)
400
+ mid_nw_z = self._fcn(qtr1_x,qtr3_y)
401
+ mid_se_z = self._fcn(qtr3_x,qtr1_y)
402
+ mid_ne_z = self._fcn(qtr3_x,qtr3_y)
403
+
404
+ self.extrema([mid_w_z[0], mid_n_z[0], mid_e_z[0], mid_s_z[0], mid_sw_z[0], mid_se_z[0], mid_nw_z[0], mid_sw_z[0]])
405
+
406
+ # recurse into the sub-squares
407
+ sw = self.plot_block(min_x, qtr1_x, mid_x, min_y, qtr1_y, mid_y, sw_z, mid_w_z, mid_s_z, mid_z, mid_sw_z, sw_depth)
408
+ nw = self.plot_block(min_x, qtr1_x, mid_x, mid_y, qtr3_y, max_y, mid_w_z, nw_z, mid_z, mid_n_z, mid_nw_z, nw_depth)
409
+ se = self.plot_block(mid_x, qtr3_x, max_x, min_y, qtr1_y, mid_y, mid_s_z, mid_z, se_z, mid_e_z, mid_se_z, se_depth)
410
+ ne = self.plot_block(mid_x, qtr3_x, max_x, mid_y, qtr3_y, max_y, mid_z, mid_n_z, mid_e_z, ne_z, mid_ne_z, ne_depth)
411
+
412
+ # join the sub-squares
413
+ self.interface(1, sw.right, sw.right_c, se.left, se.left_c)
414
+ self.interface(1, nw.right, nw.right_c, ne.left, ne.left_c)
415
+ self.interface(0, sw.top, sw.top_c, nw.bottom, nw.bottom_c)
416
+ self.interface(0, se.top, se.top_c, ne.bottom, ne.bottom_c)
417
+
418
+ # get the boundary information about the subsquares
419
+ left = sw.left + nw.left[1:]
420
+ left_c = sw.left_c + nw.left_c
421
+ right = se.right + ne.right[1:]
422
+ right_c = se.right_c + ne.right_c
423
+ top = nw.top + ne.top[1:]
424
+ top_c = nw.top_c + ne.top_c
425
+ bottom = sw.bottom + se.bottom[1:]
426
+ bottom_c = sw.bottom_c + se.bottom_c
427
+
428
+ else:
429
+ # just build the square we're in
430
+ if self._g is None:
431
+ sw = [(min_x, min_y, sw_z[0])]
432
+ nw = [(min_x, max_y, nw_z[0])]
433
+ se = [(max_x, min_y, se_z[0])]
434
+ ne = [(max_x, max_y, ne_z[0])]
435
+ c = [[(mid_x, mid_y, mid_z[0])]]
436
+ else:
437
+ sw = [(min_x, min_y, sw_z[0]), sw_z[1]]
438
+ nw = [(min_x, max_y, nw_z[0]), nw_z[1]]
439
+ se = [(max_x, min_y, se_z[0]), se_z[1]]
440
+ ne = [(max_x, max_y, ne_z[0]), ne_z[1]]
441
+ c = [[(mid_x, mid_y, mid_z[0]), mid_z[1]]]
442
+
443
+ left = [sw, nw]
444
+ left_c = c
445
+ top = [nw, ne]
446
+ top_c = c
447
+ right = [se, ne]
448
+ right_c = c
449
+ bottom = [sw, se]
450
+ bottom_c = c
451
+
452
+ return PlotBlock(left, left_c, top, top_c, right, right_c, bottom, bottom_c)
453
+
454
+ def interface(self, n, p, p_c, q, q_c):
455
+ """
456
+ Take a pair of lists of points, and compares the (n)th coordinate, and
457
+ "zips" the lists together into one. The "centers", supplied in p_c and
458
+ q_c are matched up such that the lists describe triangles whose sides
459
+ are "perfectly" aligned. This algorithm assumes that p and q start and
460
+ end at the same point, and are sorted smallest to largest.
461
+
462
+ TESTS::
463
+
464
+ sage: from sage.plot.plot3d.tri_plot import TrianglePlot, TriangleFactory
465
+ sage: tf = TriangleFactory()
466
+ sage: t = TrianglePlot(tf, lambda x,y: x^2 - y*x, (0, -2), (0, 2), max_depth=3)
467
+ sage: t.interface(1, [[(-1/4, 0, 1/16)], [(-1/4, 1/4, 1/8)]], [[(-1/8, 1/8, 1/32)]], [[(-1/4, 0, 1/16)], [(-1/4, 1/4, 1/8)]], [[(-3/8, 1/8, 3/16)]])
468
+ sage: t._objects[-1].get_vertices()
469
+ ((-1/4, 0, 1/16), (-1/4, 1/4, 1/8), (-3/8, 1/8, 3/16))
470
+ """
471
+ m = [p[0]] # a sorted union of p and q
472
+ mpc = [p_c[0]] # centers from p_c corresponding to m
473
+ mqc = [q_c[0]] # centers from q_c corresponding to m
474
+
475
+ i = 1
476
+ j = 1
477
+
478
+ while i < len(p_c) or j < len(q_c):
479
+ if p[i][0][n] == q[j][0][n]:
480
+ m.append(p[i])
481
+ mpc.append(p_c[i])
482
+ mqc.append(q_c[j])
483
+ i += 1
484
+ j += 1
485
+ elif p[i][0][n] < q[j][0][n]:
486
+ m.append(p[i])
487
+ mpc.append(p_c[i])
488
+ mqc.append(mqc[-1])
489
+ i += 1
490
+ else:
491
+ m.append(q[j])
492
+ mpc.append(mpc[-1])
493
+ mqc.append(q_c[j])
494
+ j += 1
495
+
496
+ m.append(p[-1])
497
+
498
+ self.triangulate(m, mpc)
499
+ self.triangulate(m, mqc)
500
+
501
+ def triangulate(self, p, c):
502
+ """
503
+ Pass in a list of edge points (p) and center points (c).
504
+ Triangles will be rendered between consecutive edge points and the
505
+ center point with the same index number as the earlier edge point.
506
+
507
+ TESTS::
508
+
509
+ sage: from sage.plot.plot3d.tri_plot import TrianglePlot, TriangleFactory
510
+ sage: tf = TriangleFactory()
511
+ sage: t = TrianglePlot(tf, lambda x,y: x^2 - y*x, (0, -2), (0, 2))
512
+ sage: t.triangulate([[[1,0,0],[0,0,1]],[[0,1,1],[1,1,1]]],[[[0,3,1]]])
513
+ sage: t._objects[-1].get_vertices()
514
+ ([1, 0, 0], [0, 1, 1], [0, 3, 1])
515
+ """
516
+
517
+ if self._g is None:
518
+ for i in range(0,len(p)-1):
519
+ self._objects.append(self._triangle_factory.triangle(p[i][0], p[i+1][0], c[i][0]))
520
+ else:
521
+ for i in range(0,len(p)-1):
522
+ self._objects.append(self._triangle_factory.smooth_triangle(p[i][0], p[i+1][0], c[i][0],p[i][1], p[i+1][1], c[i][1]))
523
+
524
+ def extrema(self, list):
525
+ """
526
+ If the num_colors option has been set, this expands the TrianglePlot's _min and _max
527
+ attributes to include the minimum and maximum of the argument list.
528
+
529
+ TESTS::
530
+
531
+ sage: from sage.plot.plot3d.tri_plot import TrianglePlot, TriangleFactory
532
+ sage: tf = TriangleFactory()
533
+ sage: t = TrianglePlot(tf, lambda x,y: x^2+y^2, (0, 1), (0, 1), num_colors = 3)
534
+ sage: t._min, t._max
535
+ (0, 2)
536
+ sage: t.extrema([-1,2,3,4])
537
+ sage: t._min, t._max
538
+ (-1, 4)
539
+ """
540
+ if self._num_colors is not None:
541
+ self._min = min(list+[self._min])
542
+ self._max = max(list+[self._max])
543
+
544
+
545
+ def crossunit(u, v):
546
+ """
547
+ This function computes triangle normal unit vectors by taking the
548
+ cross-products of the midpoint-to-corner vectors. It always goes
549
+ around clockwise so we're guaranteed to have a positive value near
550
+ 1 when neighboring triangles are parallel. However -- crossunit
551
+ doesn't really return a unit vector. It returns the length of the
552
+ vector to avoid numerical instability when the length is nearly zero
553
+ -- rather than divide by nearly zero, we multiply the other side of
554
+ the inequality by nearly zero -- in general, this should work a bit
555
+ better because of the density of floating-point numbers near zero.
556
+
557
+ TESTS::
558
+
559
+ sage: from sage.plot.plot3d.tri_plot import crossunit
560
+ sage: crossunit([0,-1,0],[0,0,1])
561
+ (-1, 0, 0, 1.0)
562
+ """
563
+ p = (u[1]*v[2] - v[1]*u[2], u[0]*v[2] - v[0]*u[2], u[0]*v[1] - u[1]*v[0])
564
+ l = sqrt(p[0]**2 + p[1]**2 + p[2]**2)
565
+ return (p[0], p[1], p[2], l)
566
+
567
+
568
+ class PlotBlock:
569
+ """
570
+ A container class to hold information about spatial blocks.
571
+ """
572
+ def __init__(self, left, left_c, top, top_c, right, right_c, bottom, bottom_c):
573
+ """
574
+
575
+ TESTS::
576
+
577
+ sage: from sage.plot.plot3d.tri_plot import PlotBlock
578
+ sage: pb = PlotBlock([0,0,0],[0,1,0],[0,0,1],[0,0,.5],[1,0,0],[1,1,0],[-2,-2,0],[0,0,0])
579
+ sage: pb.left
580
+ [0, 0, 0]
581
+ """
582
+ self.left = left
583
+ self.left_c = left_c
584
+ self.top = top
585
+ self.top_c = top_c
586
+ self.right = right
587
+ self.right_c = right_c
588
+ self.bottom = bottom
589
+ self.bottom_c = bottom_c