Changeset 7922:0357fa4b519b
- Timestamp:
- 01/03/08 12:08:25 (5 years ago)
- Branch:
- default
- Parents:
- 7921:bc8c4b756d60 (diff), 7919:feb90d6ac1e9 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent. - Location:
- sage/plot/plot3d
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
sage/plot/plot3d/all.py
r7919 r7922 3 3 4 4 from shapes import Box, ColorCube, Cone, Cylinder, LineSegment, Arrow, Sphere, Torus, Text as Text3D 5 6 from parametric_surface import MobiusStrip 7 8 5 from parametric_surface import ParametricSurface, MobiusStrip 9 6 from plot3d import plot3d, axes as axes3d 10 7 from platonic import Tetrahedron, Cube, Octahedron, Dodecahedron, IndexFaceSet, Icosahedron -
sage/plot/plot3d/all.py
r7906 r7922 1 from parametric_plot3d import parametric_plot3d 2 from list_plot3d import list_plot3d 3 1 4 from shapes import Box, ColorCube, Cone, Cylinder, LineSegment, Arrow, Sphere, Torus, Text as Text3D 2 5 from parametric_surface import ParametricSurface, MobiusStrip 3 from parametric_plot3d import parametric_plot3d4 6 from plot3d import plot3d, axes as axes3d 5 7 from platonic import Tetrahedron, Cube, Octahedron, Dodecahedron, IndexFaceSet, Icosahedron -
sage/plot/plot3d/base.pyx
r7919 r7922 47 47 from math import atan2 48 48 from random import randint 49 import zipfile 50 from cStringIO import StringIO 49 51 50 52 import sage.misc.misc … … 205 207 render_params.output_file = filename 206 208 render_params.force_reload = render_params.randomize_counter = force_reload 207 f = open(filename, 'w') 209 render_params.output_archive = zipfile.ZipFile(filename, 'w', zipfile.ZIP_DEFLATED, True) 210 211 f = StringIO() 212 208 213 # Set the scene background color 209 214 f.write('background [%s,%s,%s]\n'%tuple([int(a*255) for a in background])) … … 227 232 # Put the rest of the object in 228 233 f.write("\n".join(flatten_list([self.jmol_repr(render_params), ""]))) 229 f.close() 234 235 render_params.output_archive.writestr('SCRIPT', f.getvalue()) 236 render_params.output_archive.close() 230 237 231 238 def jmol_repr(self, render_params): … … 434 441 # fg = 2 435 442 filename = '%s-size%s%s'%(base, fg*100, ext) 443 ext = "jmol" 444 archive_name = "%s.%s.zip" % (filename, ext) 436 445 437 446 T = self._prepare_for_jmol(frame, axes, frame_aspect_ratio, aspect_ratio, zoom) 438 T.export_jmol( filename + ".jmol", force_reload=EMBEDDED_MODE, **kwds)447 T.export_jmol(archive_name, force_reload=EMBEDDED_MODE, **kwds) 439 448 viewer_app = sage.misc.misc.SAGE_LOCAL + "/java/jmol/jmol" 440 ext = "jmol" 449 450 # We need a script to load the file 451 f = open(filename + '.jmol', 'w') 452 f.write('set defaultdirectory "%s"\n' % archive_name) 453 f.write('script SCRIPT\n') 454 f.close() 441 455 442 456 if ext is None: … … 675 689 self.transform = None 676 690 self.ds = 1 691 self.crease_threshold = .8 677 692 self.__dict__.update(kwds) 678 693 -
sage/plot/plot3d/base.pyx
r7909 r7922 77 77 return other 78 78 return Graphics3dGroup([self, other]) 79 80 def aspect_ratio(self, v=None): 81 if not v is None: 82 if not isinstance(v, (tuple, list)): 83 raise TypeError, "v must be a list or tuple of length 3" 84 self._aspect_ratio = [float(a) for a in v] 85 else: 86 if self._aspect_ratio is None: 87 self._aspect_ratio = [1.0,1.0,1.0] 88 return self._aspect_ratio 89 90 def frame_aspect_ratio(self, v=None): 91 if not v is None: 92 self._frame_aspect_ratio = v 93 else: 94 if self._frame_aspect_ratio is None: 95 self._frame_aspect_ratio = [1,1,1] 96 return self._frame_aspect_ratio 79 97 80 98 def bounding_box(self): … … 233 251 return self.transform(T=T) 234 252 235 def _rescale_for_ aspect_ratio_and_zoom(self, b,aspect_ratio, zoom):236 if aspect_ratio is None:253 def _rescale_for_frame_aspect_ratio_and_zoom(self, b, frame_aspect_ratio, zoom): 254 if frame_aspect_ratio is None: 237 255 return (b*zoom,b*zoom,b*zoom), (-b*zoom,-b*zoom,-b*zoom) 238 box = [b*w for w in aspect_ratio]256 box = [b*w for w in frame_aspect_ratio] 239 257 # Now take the maximum length in box and rescale to b. 240 258 s = b / max(box) … … 243 261 return box_min, box_max 244 262 245 def _prepare_for_jmol(self, frame, axes, aspect_ratio, zoom): 246 box_min, box_max = self._rescale_for_aspect_ratio_and_zoom(6.0, aspect_ratio, zoom) 247 return self._transform_to_bounding_box(box_min, box_max, frame=frame, 248 axes=axes, thickness=1) 249 250 def _prepare_for_tachyon(self, frame, axes, aspect_ratio, zoom): 251 box_min, box_max = self._rescale_for_aspect_ratio_and_zoom(1.0, aspect_ratio, zoom) 252 A = self._transform_to_bounding_box(box_min, box_max, 263 def _prepare_for_jmol(self, frame, axes, frame_aspect_ratio, aspect_ratio, zoom): 264 box_min, box_max = self._rescale_for_frame_aspect_ratio_and_zoom(6.0, frame_aspect_ratio, zoom) 265 a_min, a_max = self._box_for_aspect_ratio(aspect_ratio, box_min, box_max) 266 return self._transform_to_bounding_box(box_min, box_max, a_min, a_max, frame=frame, 267 axes=axes, thickness=1) 268 269 def _prepare_for_tachyon(self, frame, axes, frame_aspect_ratio, aspect_ratio, zoom): 270 box_min, box_max = self._rescale_for_frame_aspect_ratio_and_zoom(1.0, frame_aspect_ratio, zoom) 271 a_min, a_max = self._box_for_aspect_ratio(aspect_ratio, box_min, box_max) 272 return self._transform_to_bounding_box(box_min, box_max, a_min, a_max, 253 273 frame=frame, axes=axes, thickness=0.5) 254 return A 255 256 def _transform_to_bounding_box(self, xyz_min, xyz_max, frame, axes, thickness): 274 275 def _box_for_aspect_ratio(self, aspect_ratio, box_min, box_max): 276 # Lengths of new box 277 new_box = [box_max[i] - box_min[i] for i in range(3)] 278 279 # Find a box around self so that when self gets rescaled into the 280 # box defined by box_min, box_max, it has the right aspect ratio 281 if aspect_ratio == "automatic": 282 return self.bounding_box() 257 283 a_min, a_max = self.bounding_box() 258 284 a_min = list(a_min); a_max = list(a_max) … … 261 287 a_min[i] = -1 262 288 a_max[i] = 1 289 290 # 1. 291 longest_side = 0; longest_length = 0 292 shortest_side = 0; shortest_length = a_max[0] - a_min[0] 293 294 for i in range(3): 295 s = a_max[i] - a_min[i] 296 if s > longest_length: 297 longest_length = s 298 longest_side = i 299 if s < shortest_length: 300 shortest_length = s 301 shortest_side = i 302 303 # 2. Rescale aspect_ratio so the shortest side is 1. 304 r = float(aspect_ratio[shortest_side]) 305 aspect_ratio = [a/r for a in aspect_ratio] 306 307 # 3. Extend the bounding box of self by rescaling so the sides 308 # have the same ratio as aspect_ratio, and without changing 309 # the longest side. 310 long_box_side = box_max[longest_side] - box_min[longest_side] 311 sc = [1.0,1.0,1.0] 312 for i in range(3): 313 if i != longest_side: 314 # compute the length we want: 315 new_length = longest_length / aspect_ratio[i] 316 # change the side length by a_min and a_max so 317 # that a_max[i] - a_min[i] = new_length 318 319 # We have to take into account the ratio of the sides after transforming 320 # to the bounding box. 321 z = long_box_side / (box_max[i] - box_min[i]) 322 w = new_length / ((a_max[i] - a_min[i]) * z) 323 sc[i] = w 324 325 w = min(sc) 326 sc = [z/w for z in sc] 327 for i in range(3): 328 a_min[i] *= sc[i] 329 a_max[i] *= sc[i] 330 331 return a_min, a_max 332 333 def _transform_to_bounding_box(self, xyz_min, xyz_max, a_min, a_max, frame, axes, thickness): 263 334 264 335 # Rescale in each direction … … 291 362 292 363 def show(self, viewer="jmol", filename=None, verbosity=0, figsize=5, 293 aspect_ratio = None, zoom=1, 364 aspect_ratio = "automatic", 365 frame_aspect_ratio = "automatic", 366 zoom=1, 294 367 frame=True, axes = False, **kwds): 295 368 """ … … 305 378 pixels in each direction is 100 times figsize[0]. 306 379 This is ignored for the jmol embedded renderer. 307 **kwds -- other options, which make sense for particular rendering engines 380 **kwds -- other options, which make sense for particular rendering engines 381 382 EXAMPLES: 383 384 We illustrate use of the aspect_ratio option: 385 sage: var('x,y') 386 sage: p = plot3d(2*sin(x*y), (x, -pi, pi), (y, -pi, pi)) 387 sage: p.show(aspect_ratio=[1,1,1]) 388 389 This looks flattened, but filled with the plot: 390 sage: p.show(frame_aspect_ratio=[1,1,1/16]) 391 392 This looks flattened, but the plot is square and smaller: 393 sage: p.show(aspect_ratio=[1,1,1], frame_aspect_ratio=[1,1,1/8]) 394 308 395 """ 396 if frame_aspect_ratio == "automatic": 397 frame_aspect_ratio = self.frame_aspect_ratio() 398 309 399 import sage.misc.misc 310 400 if filename is None: … … 326 416 327 417 if DOCTEST_MODE or viewer=='tachyon' or (viewer=='java3d' and EMBEDDED_MODE): 328 T = self._prepare_for_tachyon(frame, axes, aspect_ratio, zoom)418 T = self._prepare_for_tachyon(frame, axes, frame_aspect_ratio, aspect_ratio, zoom) 329 419 tachyon_rt(T.tachyon(**kwds), filename+".png", verbosity, True, opts) 330 420 ext = "png" … … 354 444 archive_name = "%s.%s.zip" % (filename, ext) 355 445 356 T = self._prepare_for_jmol(frame, axes, aspect_ratio, zoom)446 T = self._prepare_for_jmol(frame, axes, frame_aspect_ratio, aspect_ratio, zoom) 357 447 T.export_jmol(archive_name, force_reload=EMBEDDED_MODE, **kwds) 358 448 viewer_app = sage.misc.misc.SAGE_LOCAL + "/java/jmol/jmol" … … 377 467 def __init__(self, all=[]): 378 468 self.all = all 469 self.frame_aspect_ratio(optimal_aspect_ratios([a.frame_aspect_ratio() for a in all])) 470 self.aspect_ratio(optimal_aspect_ratios([a.aspect_ratio() for a in all])) 379 471 380 472 def bounding_box(self): … … 429 521 if T is not None: 430 522 self.T = T 523 self.frame_aspect_ratio(optimal_aspect_ratios([a.frame_aspect_ratio() for a in all])) 524 self.aspect_ratio(optimal_aspect_ratios([a.aspect_ratio() for a in all])) 431 525 432 526 def bounding_box(self): … … 670 764 """ 671 765 return tuple([max([a[i] for a in v]) for i in range(3)]) 766 767 768 def optimal_aspect_ratios(ratios): 769 # average the aspect ratios 770 n = len(ratios) 771 if n > 0: 772 return [max([z[i] for z in ratios]) for i in range(3)] 773 else: 774 return [1.0,1.0,1.0] 775 -
sage/plot/plot3d/plot3d.py
r7906 r7922 59 59 return [a,b,c] 60 60 61 import parametric_plot3d 62 def plot3d(f, urange, vrange, **kwds): 63 """ 64 EXAMPLES: 65 We plot a 3d function defined as a Python function: 66 sage: show(plot3d(lambda x, y: x^2 + y^2, (-2,2), (-2,2))) 61 67 62 def plot3d(f,(xmin,xmax),(ymin,ymax),texture=None, opacity=1, grad_f=None, 68 We plot some 3d symbolic functions: 69 sage: var('x,y') 70 sage: show(plot3d(x^2 + y^2, (x,-2,2), (y,-2,2))) 71 sage: show(plot3d(sin(x*y), (x, -pi, pi), (y, -pi, pi))) 72 73 We draw two parametric surfaces and a transparent plane: 74 sage: L = plot3d(lambda x,y: 0, (-5,5), (-5,5), texture=Texture("lightblue", opacity=0.8)) 75 sage: P = plot3d(lambda x,y: 4 - x^3 - y^2, (-2,2), (-2,2), texture=Texture('green')) 76 sage: Q = plot3d(lambda x,y: x^3 + y^2 - 4, (-2,2), (-2,2), texture=Texture('orange')) 77 sage: show(L + P + Q) 78 """ 79 if len(urange) == 2: 80 w = (lambda u,v: u, lambda u,v: v, f) 81 else: 82 u = urange[0] 83 v = vrange[0] 84 w = (u, v, f) 85 P = parametric_plot3d.parametric_plot3d(w, urange, vrange, **kwds) 86 P.frame_aspect_ratio([1.0,1.0,0.5]) 87 return P 88 89 # This sucks. It looks like crap. Simple grid sampling looks way better?! 90 def plot3d_old(f,(xmin,xmax),(ymin,ymax),texture=None, opacity=1, grad_f=None, 63 91 max_bend=.5, max_depth=5, initial_depth=4, num_colors=None): 64 92 """ 65 93 EXAMPLES: 66 67 68 94 """ 69 95 if initial_depth >= max_depth: -
sage/plot/plot3d/shapes.pyx
r7897 r7922 184 184 return ParametricSurface.tachyon_repr(self, render_params) 185 185 186 if transform is None: 187 base = (0,0,0) 188 top = (0,0,self.height) 189 rad = self.radius 190 else: 191 base = transform.transform_point((0,0,0)) 192 top = transform.transform_point((0,0,self.height)) 193 radv = transform.transform_vector((self.radius,0,0)) 194 rad = sqrt(sum([x*x for x in radv])) 186 base, top = self.get_endpoints(transform) 187 rad = self.get_radius(transform) 195 188 cyl = """FCylinder 196 189 Base %s %s %s … … 207 200 else: 208 201 return cyl 202 203 def jmol_repr(self, render_params): 204 transform = render_params.transform 205 base, top = self.get_endpoints(transform) 206 rad = self.get_radius(transform) 207 208 cdef double ratio = sqrt(rad*rad / ((base[0]-top[0])**2 + (base[1]-top[1])**2 + (base[2]-top[2])**2)) 209 210 if ratio > .02: 211 if not (transform is None or transform.is_uniform_on([(1,0,0),(0,1,0)])) or ratio > .05: 212 # Jmol can't do sqashed 213 return ParametricSurface.jmol_repr(self, render_params) 214 215 name = render_params.unique_name('line') 216 return [""" 217 draw %s width %s {%s %s %s} {%s %s %s}\n%s 218 """ % (name, 219 rad, 220 base[0], base[1], base[2], 221 top [0], top [1], top [2], 222 self.texture.jmol_str("$" + name)) ] 223 224 def get_endpoints(self, transform=None): 225 if transform is None: 226 return (0,0,0), (0,0,self.height) 227 else: 228 return transform.transform_point((0,0,0)), transform.transform_point((0,0,self.height)) 229 230 def get_radius(self, transform=None): 231 if transform is None: 232 return self.radius 233 else: 234 radv = transform.transform_vector((self.radius,0,0)) 235 return sqrt(sum([x*x for x in radv])) 236 209 237 210 238 def get_grid(self, ds): -
sage/plot/plot3d/shapes.pyx
r7911 r7922 207 207 208 208 cdef double ratio = sqrt(rad*rad / ((base[0]-top[0])**2 + (base[1]-top[1])**2 + (base[2]-top[2])**2)) 209 print ratio210 209 211 210 if ratio > .02:
Note: See TracChangeset
for help on using the changeset viewer.
