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