Changeset 7925:d2793ceb859b


Ignore:
Timestamp:
01/03/08 21:53:28 (5 years ago)
Author:
Robert Bradshaw <robertwb@…>
Branch:
default
Message:

3d rulers and ruler frames

File:
1 edited

Legend:

Unmodified
Added
Removed
  • sage/plot/plot3d/shapes2.py

    r7901 r7925  
     1import math 
    12import shapes 
     3 
     4from sage.rings.real_double import RDF 
     5from sage.modules.free_module_element import vector 
     6from sage.misc.misc import srange 
    27 
    38def line3d(points, coerce=True, color="lightblue", **kwds): 
     
    2025    v4 = line3d([(x1,y1,z0), (x1,y1,z1)], **kwds) 
    2126    return L1 + v2 + v3 + v4 
    22      
    2327 
    2428def validate_frame_size(size): 
     
    3842     
    3943     
     44def ruler(start, end, ticks=4, sub_ticks=4, absolute=False, snap=False, **kwds): 
     45    start = vector(RDF, start) 
     46    end   = vector(RDF, end) 
     47    dir = end - start 
     48    dist = math.sqrt(dir.dot_product(dir)) 
     49    dir /= dist 
     50     
     51    one_tick = dist/ticks * 1.414 
     52    unit = 10 ** math.floor(math.log(dist/ticks, 10)) 
     53    if unit * 5 < one_tick: 
     54        unit *= 5 
     55    elif unit * 2 < one_tick: 
     56        unit *= 2 
     57     
     58    if dir[0]: 
     59        tick = dir.cross_product(vector(RDF, (0,0,-dist/30))) 
     60    elif dir[1]: 
     61        tick = dir.cross_product(vector(RDF, (0,0,dist/30))) 
     62    else: 
     63        tick = vector(RDF, (dist/30,0,0)) 
     64         
     65    if snap: 
     66        for i in range(3): 
     67            start[i] = unit * math.floor(start[i]/unit + 1e-5) 
     68            end[i] = unit * math.ceil(end[i]/unit - 1e-5) 
     69 
     70    if absolute: 
     71        if dir[0]*dir[1] or dir[1]*dir[2] or dir[0]*dir[2]: 
     72            raise ValueError, "Absolute rulers only valid for axis-aligned paths" 
     73        m = max(dir[0], dir[1], dir[2]) 
     74        if dir[0] == m: 
     75            off = start[0] 
     76        elif dir[1] == m: 
     77            off = start[1] 
     78        else: 
     79            off = start[2] 
     80        first_tick = unit * math.ceil(off/unit - 1e-5) - off 
     81    else: 
     82        off = 0 
     83        first_tick = 0 
     84         
     85    ruler = shapes.LineSegment(start, end, **kwds) 
     86    for k in range(1, int(sub_ticks * first_tick/unit)): 
     87        P = start + dir*(k*unit/sub_ticks) 
     88        ruler += shapes.LineSegment(P, P + tick/2, **kwds) 
     89    for d in srange(first_tick, dist + unit/(sub_ticks+1), unit): 
     90        P = start + dir*d 
     91        ruler += shapes.LineSegment(P, P + tick, **kwds) 
     92        ruler += shapes.Text(str(d+off), **kwds).translate(P - tick) 
     93        if dist - d < unit: 
     94            sub_ticks = int(sub_ticks * (dist - d)/unit) 
     95        for k in range(1, sub_ticks): 
     96            P += dir * (unit/sub_ticks) 
     97            ruler += shapes.LineSegment(P, P + tick/2, **kwds) 
     98    return ruler 
     99     
     100def ruler_frame(lower_left, upper_right, ticks=4, sub_ticks=4, **kwds): 
     101    return ruler(lower_left, (upper_right[0], lower_left[1], lower_left[2]), ticks=ticks, sub_ticks=sub_ticks, absolute=True) \ 
     102         + ruler(lower_left, (lower_left[0], upper_right[1], lower_left[2]), ticks=ticks, sub_ticks=sub_ticks, absolute=True) \ 
     103         + ruler(lower_left, (lower_left[0], lower_left[1], upper_right[2]), ticks=ticks, sub_ticks=sub_ticks, absolute=True) 
     104     
Note: See TracChangeset for help on using the changeset viewer.