Opened 14 months ago
Last modified 7 months ago
#26410 new defect
Make threejs / three.js viewer respect thickness in parametric_plot3d
Reported by: | slelievre | Owned by: | |
---|---|---|---|
Priority: | major | Milestone: | sage-wishlist |
Component: | graphics | Keywords: | threejs, three.js, parametric_plot3d, thickness, graphic options |
Cc: | slelievre | Merged in: | |
Authors: | Reviewers: | ||
Report Upstream: | N/A | Work issues: | |
Branch: | Commit: | ||
Dependencies: | Stopgaps: |
Description (last modified by )
On Windows and macOS, WebGL line thickness support is absent or limited, so that the three.js / threejs viewer appears not to respect the thickness optional parameter in parametric_plot3d, while other viewers such as Jmol and Tachyon do.
For example, in Sage 8.3 or 8.7 on macOS 10.10.5, the thickness is not taken into account in the following -- whether launching it from the Sage REPL, the Jupyter notebook, or even SageCell online:
sage: pi = RDF.pi() sage: tau = 2*pi sage: a = (lambda t: cos(t), lambda t: sin(t), lambda t: 2*t/tau) sage: b = (lambda t: cos(t), lambda t: sin(t), lambda t: 2*t/tau + 1) sage: aa = parametric_plot(a, (-tau, tau), color='blue', thickness=1) sage: bb = parametric_plot(b, (-3*pi, pi), color='red', thickness=10) sage: p = aa + bb sage: p.show(viewer='threejs') Launched html viewer for Graphics3d Object sage: p.show(viewer='jmol') Launched jmol viewer for Graphics3d Object sage: p.show(viewer='tachyon') Launched png viewer for Graphics3d Object
Suggested workarounds:
- use
radius
instead ofthickness
. - use THREE.Meshline
Change History (8)
comment:1 Changed 14 months ago by
- Description modified (diff)
- Keywords threejs three.js parametric_plot3d thickness graphic options added
comment:2 Changed 8 months ago by
comment:3 Changed 8 months ago by
Paul, thanks a lot for having a look. For me the red line looks thicker in jmol and tachyon, but not in threejs. Not only on my computer, but also on sagecell.
comment:4 Changed 8 months ago by
That's probably because you're using a Windows machine. WebGL line thickness isn't supported at all in Windows, and support for it in macOS has limitations. It looks like line thickness will be removed from future versions of WebGL entirely.
The way to visualize thick lines is to use the radius
parameter listed in the documentation, which creates a cylinder along the path:
pi = RDF.pi() tau = 2*pi a = (lambda t: cos(t), lambda t: sin(t), lambda t: 2*t/tau) b = (lambda t: cos(t), lambda t: sin(t), lambda t: 2*t/tau + 1) aa = parametric_plot(a, (-tau, tau), color='blue', thickness=1) bb = parametric_plot(b, (-3*pi, pi), color='red', radius=.1) p = aa + bb p.show(viewer='threejs')
Three.js has its own workaround for thick lines, but it's only in the examples, not the main library. I wouldn't implement it here until it's an official part of the main library.
comment:5 Changed 8 months ago by
Thanks for explaining and for the workaround.
This was under macOS 10.10.5, using either Firefox 66.0.2 (64-bit), Opera 58.0.3135.118, Safari 10.1.2 (10603.3.8), so surely illustrating the limitations you refer to.
Using radius
as you suggest does the trick. A small enough radius works well.
If the curve is long and the radius gets somewhat large it is worth increasing the
number of plot points so that the (piecewise linear) cylinder still looks more
curved than piecewise linear.
The following works well:
pi = RDF.pi() tau = 2*pi a = (lambda t: cos(t), lambda t: sin(t), lambda t: 2*t/tau) b = (lambda t: cos(t), lambda t: sin(t), lambda t: 2*t/tau + 1) aa = parametric_plot(a, (-tau, tau), color='blue', radius=.02, plot_points=400) bb = parametric_plot(b, (-3*pi, pi), color='red', radius=.04, plot_points=400) p = aa + bb p.show(viewer='threejs')
I also notice that the cylinders have a polygonal base, with a number of sides depending on the radius; it seems to start 5-sided for small radius, and then the number of sides grows with the radius. Is there a way to control that number of sides?
The following example shows the number of sides starting at 5 then
increasing to 6, 7, 8, 8, 9, 10, 11 (makes one want to guess the fomula
for number_of_sides
as a function of radius
):
pp = parametric_plot cyl = lambda x, y: (lambda t: x, lambda t: y, lambda t: t) pcyl = lambda x, y, r, h: pp(cyl(x, y), (0, 1), radius=r, rgbcolor=hue(h)) param = (.03, .04, .05, .06, .07, .08, .09, .10, .11, .12, .13, .14, .15, .16) np = RDF(len(param)) cylparam = lambda i, r: (0, 2.05*sum(param[:i])+r, r, (i+1)/(np+1)) p = sum((pcyl(*cylparam(i, r)) for i, r in enumerate(param)), Graphics()) p.show(frame=False, viewer='threejs')
comment:6 Changed 8 months ago by
I have encountered this problem myself, about a year ago, with my own threejs experiments outside of Sage. It's really too bad this is still a problem. IIRC the best workaround I found was to use the THREE.MeshLine
plugin: https://github.com/spite/THREE.MeshLine
In particular, check out this cool demo: https://www.clicktorelease.com/code/THREE.MeshLine/demo/index.html
Perhaps we could work that into Sage for use in parametric plots?
comment:7 Changed 7 months ago by
- Description modified (diff)
- Milestone changed from sage-8.4 to sage-wishlist
comment:8 Changed 7 months ago by
Thanks! Very cool demo indeed -- it would be very nice to work that into Sage.
Samuel, I don't see what the problem is: the red line looks thicker to me than the blue in the Three.js viewer. What are your expecting?