Changeset 7900:26ce1ccd4219


Ignore:
Timestamp:
12/31/07 14:49:19 (5 years ago)
Author:
William Stein <wstein@…>
Branch:
default
Message:

Lots of misc work on 3d (and jmol) plotting

Location:
sage/plot
Files:
1 added
9 edited

Legend:

Unmodified
Added
Removed
  • sage/plot/plot.py

    r7891 r7900  
    24372437        if parametric: 
    24382438            if len(funcs) == 3: 
    2439                 # 3d 
    2440                 from plot3d.shapes import parametric_plot_3d 
    2441                 return parametric_plot_3d(funcs, xmin, xmax, polar=polar, label=label, show=show, **kwds) 
     2439                raise ValueError, "use parametric_plot3d for parametric plots in 3d dimensions." 
    24422440            elif len(funcs) == 2: 
    24432441                # 2d 
  • sage/plot/plot3d/all.py

    r7897 r7900  
    11from shapes import Box, ColorCube, Cone, Cylinder, LineSegment, Arrow, Sphere, Torus, Text as Text3D 
    2 from parametric_surface import ParametricSurface, MobiusStrip 
     2 
     3from parametric_surface import MobiusStrip 
     4from parametric_plot3d import parametric_plot3d 
     5 
    36from plot3d import plot3d, axes as axes3d 
    47from platonic import Tetrahedron, Cube, Octahedron, Dodecahedron, IndexFaceSet, Icosahedron 
  • sage/plot/plot3d/base.pyx

    r7898 r7900  
    226226            return self.transform(T=T) 
    227227 
    228     def _prepare_for_jmol(self, frame, axes, aspect_ratio): 
    229         b = 6.0 
    230         if aspect_ratio is not None: 
    231             w = 1/float(aspect_ratio) 
    232         else: 
    233             w = 4.0 
    234         return self._transform_to_bounding_box((-b,-b,-b/w), (b,b,b/w), frame=frame, 
     228    def _rescale_for_aspect_ratio_and_zoom(self, b, aspect_ratio, zoom): 
     229        if aspect_ratio is None: 
     230            return (b*zoom,b*zoom,b*zoom), (-b*zoom,-b*zoom,-b*zoom) 
     231        box = [b*w for w in aspect_ratio] 
     232        # Now take the maximum length in box and rescale to b. 
     233        s = b / max(box) 
     234        box_max = tuple([s*w*zoom for w in box]) 
     235        box_min = tuple([-w*zoom for w in box_max]) 
     236        return box_min, box_max 
     237 
     238    def _prepare_for_jmol(self, frame, axes, aspect_ratio, zoom): 
     239        box_min, box_max = self._rescale_for_aspect_ratio_and_zoom(6.0, aspect_ratio, zoom) 
     240        return self._transform_to_bounding_box(box_min, box_max, frame=frame, 
    235241                                               axes=axes, thickness=1) 
    236242 
    237     def _prepare_for_tachyon(self, frame, axes, aspect_ratio): 
    238         b = 1 
    239         if aspect_ratio is not None: 
    240             w = 1/float(aspect_ratio) 
    241         else: 
    242             w = 4.0 
    243         A = self._transform_to_bounding_box((-b,-b,-b/w), (b,b,b/w), 
     243    def _prepare_for_tachyon(self, frame, axes, aspect_ratio, zoom): 
     244        box_min, box_max = self._rescale_for_aspect_ratio_and_zoom(1.0, aspect_ratio, zoom) 
     245        A = self._transform_to_bounding_box(box_min, box_max, 
    244246                                            frame=frame, axes=axes, thickness=0.5) 
    245  
    246         # Fix that Tachyon is left-handed 
    247247        return A 
    248248 
    249249    def _transform_to_bounding_box(self, xyz_min, xyz_max, frame, axes, thickness): 
    250250        a_min, a_max = self.bounding_box() 
     251        a_min = list(a_min); a_max = list(a_max) 
     252        for i in range(3): 
     253            if a_min[i] == a_max[i]: 
     254                a_min[i] = -1 
     255                a_max[i] = 1 
    251256 
    252257        # Rescale in each direction 
    253         scale = [(xyz_max[i] - xyz_min[i]) / max(0.0001, a_max[i] - a_min[i]) for i in range(3)] 
     258        scale = [(xyz_max[i] - xyz_min[i]) / (a_max[i] - a_min[i]) for i in range(3)] 
    254259        X = self.scale(scale) 
    255         a_min, a_max = X.bounding_box() 
    256  
     260        a_min = [scale[i]*a_min[i] for i in range(3)] 
     261        a_max = [scale[i]*a_max[i] for i in range(3)] 
    257262 
    258263        # Translate so lower left corner of original bounding box 
     
    261266        X = X.translate(T) 
    262267        if frame: 
    263             a_min, a_max = X.bounding_box() 
    264268            from shapes2 import frame3d 
    265             F = frame3d(a_min, a_max, opacity=0.5, color=(0,0,0), thickness=thickness) 
     269            F = frame3d(xyz_min, xyz_max, opacity=0.5, color=(0,0,0), thickness=thickness) 
    266270            X += F 
    267271 
     
    280284 
    281285    def show(self, viewer="jmol", filename=None, verbosity=0, figsize=5, 
    282              aspect_ratio = None, 
    283              frame=True, axes = True, **kwds): 
     286             aspect_ratio = None, zoom=1,  
     287             frame=True, axes = False, **kwds): 
    284288        """ 
    285289        INPUT: 
     
    295299            **kwds -- other options, which make sense for particular rendering engines            
    296300        """ 
    297          
    298301        import sage.misc.misc 
    299302        if filename is None: 
     
    315318 
    316319        if DOCTEST_MODE or viewer=='tachyon' or (viewer=='java3d' and EMBEDDED_MODE): 
    317             T = self._prepare_for_tachyon(frame, axes, aspect_ratio) 
     320            T = self._prepare_for_tachyon(frame, axes, aspect_ratio, zoom) 
    318321            tachyon_rt(T.tachyon(**kwds), filename+".png", verbosity, True, opts) 
    319322            ext = "png" 
     
    338341            filename = '%s-size%s%s'%(base, figsize[0]*100, ext) 
    339342 
    340             T = self._prepare_for_jmol(frame, axes, aspect_ratio) 
     343            T = self._prepare_for_jmol(frame, axes, aspect_ratio, zoom) 
    341344            T.export_jmol(filename + ".jmol", force_reload=EMBEDDED_MODE, **kwds) 
    342345            viewer_app = sage.misc.misc.SAGE_LOCAL + "/java/jmol/jmol" 
  • sage/plot/plot3d/bugs.txt

    r7898 r7900  
    11Jmol bugs: 
    22 
     3 * reloading a worksheet kills all jmol applets!  -- note if we get 
     4   rid of jmolSetDocument(cell_writer) this doesn't happen; but then 
     5   other things break.  Probably need to save the javascript and 
     6   execute it each time we releoad. 
    37 * Sphere(0.3,color="red").translate([1,1,-1]) has *holes* in it!! 
    48 * showing anything from the command line also pops up a "red window". 
    59 * Text3d doesn't work at all 
    610 * applet itself should be white 
    7  * Default zoom is useless -- we will have to rescale the whole scene I think. 
     11 * (done) Default zoom is useless -- we will have to rescale the whole scene I think. 
    812   Basically we have to figure out the true range of the 3d plot in each direction, 
    913   then rescale everything into a 10x10x10 square.  
     
    1115 * Invalid color doesn't yield an error message, e.g., Icosahedron(texture="yello") 
    1216 * color --> rgbcolor 
     17 * In parametricsurface:        
     18        except:       # TODO -- this would catch control-C,etc. -- FIX THIS TO CATCH WHAT IS RAISED!!!! 
     19 * Observation:  
     20      jmol embedded applets *crash* when more than 10 or so appear in 
     21      a page... unless I make them all small (e.g. 50 pixels) in which 
     22      case they DO NOT crash. 
    1323 
    1424Jmol todo: 
  • sage/plot/plot3d/index_face_set.pyx

    r7893 r7900  
    1 """nodoctest 
     1""" 
    22Graphics3D object that consists of a list of polygons, also used for  
    33triangulations of other objects.  
     
    356356 
    357357    def bounding_box(self): 
     358        if self.vcount == 0: 
     359            return ((0,0,0),(0,0,0)) 
     360 
    358361        cdef Py_ssize_t i 
    359362        cdef point_c low = self.vs[0], high = self.vs[0] 
     
    537540            f.write('\n') 
    538541        f.close() 
    539         if render_params.force_reload: 
    540             filename += "?%s" % randint(1,1000000) 
    541         return ['pmesh %s "%s"\n%s' % (name, filename, self.texture.jmol_str("pmesh"))] 
     542        #if render_params.force_reload: 
     543        #    filename += "?%s" % randint(1,1000000) 
     544 
     545        s = 'pmesh %s "%s"\n%s' % (name, filename, self.texture.jmol_str("pmesh")) 
     546 
     547        # If we wanted to turn on display of the mesh lines or dots 
     548        # we would uncomment thse.  This should be determined by 
     549        # render_params, probably.  
     550        #s += '\npmesh %s mesh\n'%name 
     551        #s += '\npmesh %s dots\n'%name 
     552        return [s]  
    542553     
    543554    def dual(self, **kwds): 
  • sage/plot/plot3d/parametric_surface.pyx

    r7890 r7900  
    137137            self.triangulate() 
    138138        return IndexFaceSet.dual(self) 
     139 
     140    def bounding_box(self): 
     141        # We must triangulate before computing the bounding box; otherwise 
     142        # we'll get an empty bounding box, as the bounding box is computed 
     143        # using the triangulation, and before triangulating the triangulation 
     144        # is empty.  
     145        self.triangulate() 
     146        return IndexFaceSet.bounding_box(self) 
    139147         
    140148    def triangulate(self, render_params=None): 
     
    159167            # Already triangulated at on this grid.  
    160168            return 
    161          
     169 
    162170        cdef Py_ssize_t i, j 
    163171        cdef Py_ssize_t n = len(urange) - 1 
     
    173181                    self.eval_c(&self.vs[ix], u, v) 
    174182                    ix += 1 
    175         except: 
     183        except:       # TODO -- this would catch control-C,etc. -- FIX THIS TO CATCH WHAT IS RAISED!!!! 
    176184            _sig_off 
    177185            self.fcount = self.vcount = 0 
  • sage/plot/plot3d/plot3d.py

    r7897 r7900  
    8080    #    # Nope -- no prob. 
    8181    #    pass 
     82    if texture is None: 
     83        texture = rainbow(128, 'rgbtuple') 
    8284     
    83     if texture is None: 
    84         texture = rainbow(100, 'rgbtuple') 
    8585    factory = TrivialTriangleFactory() 
    8686    plot = TrianglePlot(factory, f, (xmin, xmax), (ymin, ymax), g = grad_f, 
     
    100100            min_z = bounds[0][2] 
    101101            max_z = bounds[1][2] 
    102             span = len(texture) / (max_z - min_z) 
     102            if max_z == min_z: 
     103                span = 0 
     104            else: 
     105                span = len(texture) / (max_z - min_z)    # max to avoid dividing by 0 
    103106            parts = P.partition(lambda x,y,z: int((z-min_z)*span)) 
    104107        all = [] 
  • sage/plot/plot3d/shapes2.py

    r7897 r7900  
    11import shapes 
    22 
    3 def line3d(points, coerce=True, **kwds): 
     3def line3d(points, coerce=True, color="lightblue", **kwds): 
    44    v = [] 
    55    for i in range(len(points) - 1): 
    6         v.append(shapes.LineSegment(points[i], points[i+1], **kwds)) 
     6        v.append(shapes.LineSegment(points[i], points[i+1], color=color, **kwds)) 
    77    return sum(v) 
    88 
  • sage/plot/plot3d/texture.py

    r7897 r7900  
    2121    "white" : (1,1,1), 
    2222    "black" : (0,0,0), 
    23     "grey"  : (.5,.5,.5) 
     23    "grey"  : (.5,.5,.5), 
     24    "lightblue" : (0.4,0.4,1) 
    2425} 
    2526 
Note: See TracChangeset for help on using the changeset viewer.