I am not sure if it is exactly what you are looking for, but a few months 
ago I wrote some lines of code to create a frame with gridlines for 3D 
plots. 

[image: plot_frame3d.png]

See the link 
<https://sagecell.sagemath.org/?z=eJztW21v48YR_twA-Q-LCwpSFs2TLN-lcaOgKS5NA7TNAXdB0xqOvCJXEmuKJEhKFvmhv70zO0tyl6Tees6hV1g-6yhy3nZ2Xp7dlX2xYIuJby-C5SYVDru4eHjk6TIb3Hz-GYNXKvJNGrE1fxCzRcrXoo_288_w54s_xEkexFFmL9PAn9q_c-Bn4DAvDuM0m95aj6sgF5bDrGXKC-vOYTxMVnzqXjugJgtK0MC9PE6nY_fKYdkqfpzxncimf-JhJtSNkM9FmE3fpxu4Iz_MIrAKxe8sxyrgt0TRkjgPvAeiBRN9GGnvMM60dvLrW9udhhcvXtDF9yISKc8F42DpOgkFXMoBsUWcws3JGxgPT1aBl7F4_i_h5S4xvl8FGYN_nD3G6QNP403kS558JcA074HFi5ZIoI8Ycb_jS4GykzDOM5f9kDMvFWAGypsD81LJk5bMxSqADyCYmJEJxihyJodIHg-DCLmBjpzEeMZyscsnvrI7I2aeszD2uAws5oNt6Ro4UVW8lrbPUXMQLeFih2PAe8SqHKHksft7mvH7exfDFSl--Nvbn97fVJ8uNRJ2eWl4Uwlx0EwegWOynEeeAIXEi68bL-RZdnP_7wy85eKo5dvEd-c8E-73al4m_n2jD11B2sIgy9ljkK_kCKLNei5SHI_pLOnBRiVMEFLvHFbIxyXzgxTsBG9hlCZ4uRVh0Sik-O5T2ZlHSYpiG32VMepZvwqZKKQhT3mUJTwVkVdUk9PW0zAaeUUCsjzFua0CtbzkOwhiGTLamDZzMUsxRs5g0hKUuP4Yx6HgkcvewRMGvFGcq-xAooZTS2TiRDfC4Eht1nh0pyl2Gifio0J7RBPbMtRtWSon_oihSLPm6YNmKxYSX_Gp8sxs4S5dCGScOnLboPJVYySEfrzJk02uIr9Kkh9_em_mDCru5InyAeVzleC-L_w69b77-du_vv3Ldze1JPnCzLlhSzZlWbISqbAHnYcJODlnS-1-k1jsR2Vriwc9aC8HjH0BvmpVua52Duplp5j4kgI491nB_wszuLRDuY0ybQVVJYK5bFLDYRo39pXai6oIyHl2W90BqtesqocZjCLfwEDtMkjsCypsbvUUyHb2YKAGFsaPIp2FYpED0-0mhWm15XsYDi6MrJSBEoYOg8dQfAyFdyRskyQgLA2WKyktDNnwA6RJB81kuWkaB30G6VTN6sHDCNlwiq2m7vLN0BzdMpLlHBKvNXWjnRudXO_dFUSQ7wY8kqV6wSw95yyZtjBqonIfRJHZVb_Hlw9V3S_gt4SBVg485DEtSv0138ko3tkgBqT4pfZU6se5QbKXD1LmA4priO8aahU5uu02VQ0DIhIZQUHEWk8-CQoaPQOrZ2D1DKyegdUzsPokgRW2hU8PV0lpZHwji9qb3tyM3iYzeWr0Nvmh2iFo4QPSoaOXWV2h9uqQexfUREmd2T0b6KElpRwqRnbdWTXQYViBzxTT_hZugCHNub2vRRzlC74OwmJqZSINFpYj7z0KFDa15nHoq1tYsabW-Hr0W6s1DJmx-2wmz0mSfV7TnHa-vS1bjrnvRL99kF8qAEZJZyKwM2xoQyMJBGTHXcf-JhSZu0iFmNGHmQjFWkCqBuskTnO2Fdha2ox6q85WPBHZVcVAJYwYdmBbtMxXTlFdlOoCQWqzdnj98lWFfwn-4sqmf5IrALsdgQgyTqNUjtvumoe3tREjZ3RXERQawagxryEoDYJRbXhFgLOlgPj-UVbCpBxct2WbtW1vpedsymvahXT0ApJDUXyA4pBNUcnF9cvXgAVznubT7Yj6zlZi-u3O2RbOtmxWe1QGSM0tTYQdOmN3fLEdbkdOHQjkbGdbu1oLF03snRmHahjDqrtX4YgZN8vCwDsUkUjUweZ_FiGQsMUmIgC2JKyOUIQT1tLgHEviLKB-rJD7pWoHqqrT-9s0gFIPCcc2GaBeRJ9s1dKD_BKOS9BDyB3vgUQDCGdsG4hHIDqAf5sRNxDRoQW6g1CDvPZ7wkVIy-Ry3ItTGCuJUTCvGksjW_PgceGSmNHy_IB0qmf78LQS3pbdB64rUSci6rBwKWSQR2GZd7Un_w4AGVYJMGUsyJWAsDCxjgIbWrTdjp0rZ3Ln3F47r5zXd9WW_7UDPwMNg3ytAgtGpdCWJsX9GpdLYfaNK8l2SfoNrqFGuy8BVk9Gr_3rxVejb7qGdPBCbc3E-dL5qrZmgrY9uTVGHjWFGSI_X7kZLCJg-akqMn1SZSsXCVYI255f8sFL27scUzXgztzxekpvTxabVcEm8TYfeijCARleuPGhkUR-EgPoo3OaM5RIG1HLb8yWdwigmRL2bga8SfmjuQCHkE7isFhWZQWM03YE6mx8riqHq8oTJPb-fKLs1jKoZ-VwfnZq_few6D2pdgADqYiqYBDuEIKz1sLqbAvKikl3bhXNHZtOmeXDcsWSTy1p6BFWoiFWOuDUwGuLCFAnbl9ZXQK5DwEE7ljht3UQQVmX7yW8Q-FoArMi4Vj55XtJm5NafCmacpaEPEK8VHvGvtWz1zY18d1A3iPRzb1DqL5FHkQgolFx11mW7YqTjaKxSYm2OV6895RGFad7yjRKv3eCpzrOPmSUtAibRj2Pw8Z7w9pmoysQj47LWpvH_Wvgvk3kw8UcalJatVDCJQQOl4A51NJJ1vTLNx-5ljcj_zTreSX9I-ND5PiAJtKOrVMR4gkdZa_oI3DvSToKqqxX1U9Ulb04Tv0MyKqLki6A-PQlXbXQb-ZdLT_JYvvW3nmdcuWZJXFfsTIIoUzppUlm406CSTWQCiAUh2whv3id0ukdt0Uj7LOlkLYUpi3lcVtoeN6g3QS947aQU72uLSWBbNOWOXwQeLaqWXBK0-3pYT1dcM-O24ntqqcnwaCajZCrTlNSfUYPvKEx9UPD-UM1_Koumxtp5-2F0glB_UW6OpHfidzYeT5yvvjrtCH2_7OmoAjS7G-fIoVnHSOdc4ikq91_IERb8XQSpHY9ia1z5PPtSQc-_wtHPVoAd1XjOc8ScknPGRt3R0eYwlfQD6_g4tb6Gb9e-Q98-6fVrLRS4Vsf62CoM4zz2q2xiX1KuxU-kuB7Ce-4wcLx2zFzmHs-eHmldj_Y_MjmdtVOxyANfssxSpprkl6dK4lygBXq_5JCf6pXtNbmsdo3rjhtNbhxXb9V_TPYhjVfUfONG5ecwFeafORt4bf5VN1v9qApWc21ReeUqG9dIZJsOu75YrS5vqiPDqnuqjh73hg6fyEB_iapNkwW34T5DRsPwFsJR9Jc0JfG8IB-wSHEH3nRfGXFOHfOY4an7M0XDZ5u4UCB80EbT72CPsYS4eya9XGXCMGCya3nKRvf0BUbu1cXcFUtIaTPWqdXcgdPrgOuEHZ6Mm0vTgCe6nXSemG_4kIpRqWdtcMZivcsDvYrLruKjy4LevT2LgRq6Ezqh7UHhpVJGNVbntrWjhWW_CsQ_FMSCjvb3v1yhUy_yBlxLifOBC4KdSG_uzaTG_8A20ejweA_HHplPA==&lang=sage&interacts=eJyLjgUAARUAuQ==>.
 
The code is also included in the attachment.

Best

Rogerio

Em segunda-feira, 16 de janeiro de 2023 às 10:32:56 UTC-3, HG escreveu:

> Hi,
>
> I am looking for gridlines in 3d, is it possible with sagemath ?
>
> anyhelp welcome
>
> best
>
> Henri
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"sage-support" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sage-support+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/sage-support/f6f0a42b-eff0-4a1d-857a-503112e521b5n%40googlegroups.com.
###################################################
def f3d(figure, **kwargs):
    return make_frame3d(figure, **kwargs)
    
def ax3d(figure, **kwargs):
    return make_frame3d(figure, alpha=.04, show_axes=True, show_labels=False, show_ticks=False, **kwargs)

#@options(grid=(8,8,8), colors=['white', 'gray'], alpha=.4, resize_factor=1.2, show_axes=False, show_labels=True, label_names=['x','y','z'], show_ticks=True)
def make_frame3d(figure, grid=(8,8,8), colors=['white', 'gray'], alpha=.3, resize_factor=1.2, show_axes=False, show_labels=True, label_names=['x','y','z'], show_ticks=True, **kwargs):
    """
    Generate a complete frame for a 3D graphics object.
    This is a workaround for the lack of complete frames in 
    Sage 3D plots. It creates a background frame behind the
    plot, set ticks, gridlines and labels as text3d objects
    at locations determined from the bounding box of the 
    graphic object ``figure``.

    INPUT:

    - ``figure`` -- a 3D graphic object, as an instance of
        :class:`~sage.plot.plot3d.base.Graphics3d`
    - ``grid`` -- list with the number of gridlines and ticks
        in the x, y and z direction respectively
    - ``colors`` -- list with the background frame color and
        gridline color respectively
    - ``alpha`` -- transparency of the background frame
    - ``resize_factor`` -- string for the z-axis label
    - ``cube_ratio`` -- string for the z-axis label
    - ``show_labels`` -- Boolean. Show or not the labels
    - ``label_names`` -- ist of strings with the x-axis label,
        the y-axis label and the z-axis label.
    - ``show_ticks`` -- Boolean. Show or not the tickmarks
    - ``**kwds`` -- options (e.g. aspect_ratio) for the
        3D output object

    OUTPUT:

    - the 3D graphic object with text3d labels added.

    EXAMPLE::

         sage: g = sphere()
         sage: print g
         Graphics3d Object
         sage: show(g)  # no complete frame
         sage: ga = make_3dframe(g)
         sage: print ga
         Graphics3d Object
         sage: show(ga)  # the 3D frame has now background, 
         axes labels and tickmarks.
    """
    fig_boundings = tuple(zip(*figure.bounding_box()))
    lower_left = [ur - (ur - ll)*resize_factor for ll, ur in fig_boundings]
    upper_right = [ll + (ur - ll)*resize_factor for ll, ur in fig_boundings]
    frame_color, gridline_color = colors
    figure += set_frame3d(lower_left, upper_right, grid, frame_color, gridline_color, show_axes, show_labels, label_names, show_ticks, alpha=alpha, **kwargs)
    if 'aspect_ratio' not in kwargs.keys():
        dx, dy, dz = (ur - ll for ll, ur in fig_boundings)
        dmax = max(dx,dy,dz)
        ratio = [dmax/k for k in (dx,dy,dz)]
        figure.aspect_ratio(ratio)
    return figure


def set_frame3d(lower_left, upper_right, grid, frame_color, gridline_color, show_axes=True, show_labels=True, label_names=['x','y','z'], show_ticks=True, **kwargs):
    """
    Generate a complete frame for a 3D graphics object.
    This is a workaround for the lack of complete frames in 
    Sage 3D plots. It creates a background frame behind the
    plot, set ticks, gridlines and labels as text3d objects
    at locations determined from the bounding box of the 
    graphic object ``figure``.

    INPUT:

    - ``figure`` -- a 3D graphic object, as an instance of
        :class:`~sage.plot.plot3d.base.Graphics3d`
    - ``grid`` -- list with the number of gridlines and ticks
        in the x, y and z direction respectively
    - ``colors`` -- list with the background frame color and
        gridline color respectively
    - ``alpha`` -- transparency of the background frame
    - ``resize_factor`` -- string for the z-axis label
    - ``cube_ratio`` -- string for the z-axis label
    - ``show_labels`` -- Boolean. Show or not the labels
    - ``label_names`` -- ist of strings with the x-axis label,
        the y-axis label and the z-axis label.
    - ``show_ticks`` -- Boolean. Show or not the tickmarks
    - ``**kwds`` -- options (e.g. aspect_ratio) for the
        3D output object

    OUTPUT:

    - the 3D graphic object with text3d labels added.

    EXAMPLE::

         sage: g = sphere()
         sage: print g
         Graphics3d Object
         sage: show(g)  # no complete frame
         sage: ga = set_3dframe(g)
         sage: print ga
         Graphics3d Object
         sage: show(ga)  # the 3D frame has now background, 
         axes labels and tickmarks.
    """
    frame = set_background_frame(lower_left,upper_right, color=frame_color, frame=False, **kwargs)
    frame += set_frame_gridlines(lower_left,upper_right, grid=grid, color=gridline_color)
    if show_labels and not show_axes:
        frame += set_axes_labels(lower_left, upper_right, label_names, 
                              fontfamily='serif', fontweight='bold', fontsize='140%')
    if show_ticks:
        frame += set_frame_ticks(lower_left,upper_right,grid=grid, 
                              fontfamily='serif')
    if show_axes:
        frame += set_axes(lower_left, upper_right, label_names, fontfamily='serif', fontweight='bold', fontsize='140%')
    return frame



def set_axes(lower_left, upper_right, label_names, **kwargs):
    from sage.modules.free_module_element import vector
    from sage.plot.plot3d.shapes2 import text3d
    x_length,y_length,z_length = [(ur - ll)*6/5 for ll,ur in zip(lower_left,upper_right)]
    v0 = vector(lower_left)
    vx = vector([x_length,0,0])
    vy = vector([0,y_length,0])
    vz = vector([0,0,z_length])
    size = max(x_length,y_length,z_length)
    vectors = sum((v.plot(color='gray',frame=False,thickness=size*4/6, start=v0) for v in (vx,vy,vz)))
    labels = sum([text3d(l,1.1*v+v0,**kwargs) for l,v in zip(label_names,(vx,vy,vz))])
    return vectors+labels


def grid_slices(lower_left, upper_right, grid):
    """
    Helper function generating a list of gridline positions for a 3-D frame.
    
    Primarily used as a helper function for creating frames for 3-D
    graphics viewing.

    INPUT:

    - ``lower_left`` -- list, tuple, or vector; the lower left corner
    of the frame.

    - ``upper_right`` -- list, tuple, or vector; the upper right corner
    of the frame.
      
    - ``grid`` -- list, tuple or vector; the number of gridlines 
      in the x, y and z direction respectivelly.


    EXAMPLES:

    We can use it directly::

        sage: grid_slices([1,2,3],[4,5,6], grid=(4,4,4))
        <generator object grid_slices.<locals>.<genexpr> at 0x7fac306d4f90>

        sage: background_frame([1,2,3],[3,7,9], grid=(3,5,6))
        <generator object grid_slices.<locals>.<genexpr> at 0x7fac306d4f90>
    """
    from sage.arith.srange import srange
    steps = ((b-a)/(c-1) for a,b,c in zip(lower_left, upper_right, grid))
    return (srange(a+c,b,c, include_endpoint=True) for a,b,c in zip(lower_left, upper_right, steps))
	


def set_background_frame(lower_left, upper_right, **kwargs):
    """
    Draw a background of polygons for in 3D graphics.

    Primarily used as a helper function for creating frames for 3-D
    graphics viewing.

    INPUT:

    - ``lower_left`` -- list, tuple, or vector; the lower left corner
    of the frame.

    - ``upper_right`` -- list, tuple, or vector; the upper right corner
    of the frame.


    EXAMPLES:

    We can use it directly::

        sage: background_frame([1,2,3],[4,5,6])
        Graphics3d Object

        sage: background_frame([1,2,3],[3,7,9], color='gray)
        Graphics3d Object
    """
    from sage.plot.plot3d.shapes2 import polygon3d
    if 'theme' in kwargs.keys() and kwargs['theme'] == 'dark' and 'color' in kwargs.keys() and kwargs['color'] == 'white':
        kwargs['color']='black'
        kwargs['alpha']=.1
    xmin, ymin, zmin = lower_left
    xmax, ymax, zmax = upper_right
    xz_plane = polygon3d([lower_left, (xmin, ymin, zmax), (xmax, ymin, zmax),
                          (xmax, ymin, zmin), lower_left], **kwargs)
    xy_plane = polygon3d([lower_left, (xmin, ymax, zmin), (xmax, ymax, zmin),
                          (xmax, ymin, zmin), lower_left], **kwargs)
    yz_plane = polygon3d([lower_left, (xmin, ymax, zmin), (xmin, ymax, zmax),
                          (xmin, ymin, zmax), lower_left], **kwargs)
    planes = xz_plane + xy_plane + yz_plane
    return planes
    
    
def set_frame_gridlines(lower_left, upper_right, grid, **kwargs):
    """
    Draw correct gridlines for a given frame in 3-D.

    Primarily used as a helper function for creating frames for 3-D
    graphics viewing.

    INPUT:
    
    - ``lower_left`` -- list, tuple, or vector; the lower left corner
    of the frame.

    - ``upper_right`` -- list, tuple, or vector; the upper right corner
    of the frame.

    - ``grid`` -- list, tuple or vector; the number of gridlines 
      in the x, y and z direction respectivelly.

    EXAMPLES:

    We can use it directly::

        sage: frame_gridlines([1,2,3],[4,5,6], grid=(4,4,4))
        Graphics3d Object

        sage: frame_gridlines([1,2,3],[3,7,9], grid=(3,5,6))
        Graphics3d Object
    """
    from sage.plot.plot3d.shapes2 import line3d
    xmin, ymin, zmin = lower_left
    xmax, ymax, zmax = upper_right
    xcoords, ycoords, zcoords = grid_slices(lower_left, upper_right, grid)
    x_gridlines = sum([line3d([(xc, ymax, zmin), (xc, ymin, zmin),
                      (xc, ymin, zmax)], **kwargs) for xc in xcoords])
    y_gridlines = sum([line3d([(xmax, yc, zmin), (xmin, yc, zmin),
                      (xmin, yc, zmax)], **kwargs) for yc in ycoords])
    z_gridlines = sum([line3d([(xmax, ymin, zc), (xmin, ymin, zc),
                      (xmin, ymax, zc)], **kwargs) for zc in zcoords])
    border = line3d([(xmin, ymin, zmax), (xmax, ymin, zmax),(xmax, ymin, zmin),(xmax, ymax, zmin), 
                    (xmin, ymax, zmin), (xmin, ymax, zmax), (xmin, ymin, zmax)], thickness=2, **kwargs)
    return x_gridlines + y_gridlines + z_gridlines + border
    

def set_axes_labels(lower_left, upper_right, label_names, **kwds):
    r"""
    Set axes labels for a 3D graphics object.
    Primarily used as a helper function for creating frames for 3-D
    graphics viewing. 

    INPUT:

    - ``lower_left`` -- list, tuple, or vector; the lower left corner
    of the frame.

    - ``upper_right`` -- list, tuple, or vector; the upper right corner
    of the frame.
      
    - ``label_names`` -- list of strings with the x-axis label,
      the y-axis label and the z-axis label.
      
    - ``**kwds`` -- options (e.g. color) for text3d

    OUTPUT:

    - A 3D graphic object with text3d labels.

    EXAMPLE::

         sage: g = sphere()
         sage: print g
         Graphics3d Object
         sage: show(g)  # no axes labels
         sage: ga = g + axes_labels((0,0,0), (2,2,2), ['X', 'Y', 'Z'], color='red')
         sage: print ga
         Graphics3d Object
         sage: show(ga)  # the 3D frame has now axes labels
    """
    from sage.plot.plot3d.shapes2 import text3d
    xmin, ymin, zmin = lower_left
    xmed, ymed, zmed = (a + (b - a)/2 for a, b in zip(lower_left,upper_right))
    x1, y1, z1 = (b + (b - a)/5 for a, b in zip(lower_left,upper_right))
    xlabel, ylabel, zlabel = label_names
    labels = text3d(xlabel, (xmed, y1, zmin), **kwds)
    labels += text3d(ylabel, (x1, ymed, zmin), **kwds)
    labels += text3d(zlabel, (x1, ymin, zmed), **kwds)
    return labels

    
def set_frame_ticks(lower_left, upper_right, grid, eps=1, **kwargs):
    r"""
    Draw tickmarks for 3D frames.

    Primarily used as a helper function for creating frames for 3-D
    graphics viewing.

    INPUT:

    - ``lower_left`` -- list, tuple, or vector; the lower left corner
    of the frame.

    - ``upper_right`` -- list, tuple, or vector; the upper right corner
    of the frame.

    - ``eps`` -- (default: 1) a parameter for how far away from the frame
      to put the labels.

    EXAMPLES:

    We can use it directly::

        sage: frame_ticks([1,2,3],[4,5,6])
        Graphics3d Object

        sage: frame_ticks([1,2,3],[3,7,9], grid=(3,5,6))
        Graphics3d Object
    """
    from sage.plot.plot3d.shapes2 import text3d
    xmin, ymin, zmin = lower_left
    xmax, ymax, zmax = upper_right
    xcoords, ycoords, zcoords = grid_slices(lower_left, upper_right, grid)
    if eps == 1: eps = 1.2*eps
    x_ticks = sum([text3d(round(xc, 2),(xc, eps*ymax, zmin), 
                           **kwargs) for xc in xcoords])
    y_ticks = sum([text3d(round(yc, 2),(eps*xmax, yc, zmin), 
                           **kwargs) for yc in ycoords])
    z_ticks = sum([text3d(round(zc, 2),(eps*xmax, ymin, zc),
                           **kwargs) for zc in zcoords])
    return x_ticks + y_ticks + z_ticks

Reply via email to