New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enabled filling color by value for :class:.OpenGLSurface
, replaced colors
keyword argument of :meth:.Surface.set_fill_by_value
with colorscale
#2186
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me in general, thank you for your contribution! I've approved the PR, but also added some minor comments that I would like to discuss before having this merged.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left some comments about typing/implementation. But this is definitely a step in the right direction!
axes | ||
Axes on which the surface is to be drawn. Optional | ||
parameter used when coloring a surface by z-value. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO it's odd to have the surface mobject be related to an axes mob. I think it would make more sense to have a method in coordinate_system.py
that ties in the axes
(maybe a plot_surface
similar to plot
after #2187) , rather have it be a parameter in this mob?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have implemented axes.plot_surface()
, but am unable to find a way to not make axes
an attribute of OpenGLSurface
.
pivot_min = self.axes.z_range[0] | ||
pivot_max = self.axes.z_range[1] | ||
pivot_frequency = (pivot_max - pivot_min) / (len(new_colors) - 1) | ||
pivots = np.arange( | ||
start=pivot_min, | ||
stop=pivot_max + pivot_frequency, | ||
step=pivot_frequency, | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What exactly do these pivots do? I'm asking because I think it's a bit odd for axes
to be involved in colouring the surface
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will address your other questions too, but wanted to start with this one as it may explain some of the above.
The pivots are where the colors transition from one color to another color. So if we define the colorscale to be:
SURFACE_COLORS = [
(BLUE, 0),
(GREEN, 2),
(YELLOW, 5)
]
some_surface = OpenGLSurface(color=SURFACE_COLORS)
Then where the surface has z=0
the surface at that point will be exactly BLUE
. Likewise, at z=2
the surface will be exactly GREEN
. And in between those two z-values the surface will be a linear gradient between blue and green. This is handy when you want to do something like having z-values below zero be one color and z-values above zero be another color. Also, notice the pivots do not have to be equally spaced. And if the user defines pivots that do not encompass the entire range of z-values, for example if the above surface ranged from z=-2
to z=8
, then the values above or below the ending pivots will be colored a solid with the color of the ending pivot (meaning z-values below 0
will be solid BLUE
and z-values above 5
will be solid YELLOW
). And if you don't define pivots and only pass a list of colors, then it will define the pivots to be equally spaced over the range of the z-axis passed in from axes
.
The reason axes is needed is how else would you know what the z-value is? The values available for the surface are the points on the screen, not the coordinates in an axes. So you pass in the axes in order to know what the z-values are. I wouldn't be against making this a method in coordinate_systems.py
, as you suggest in a comment above, but would want to make sure others agree.
178ad36
to
2a753b7
Compare
@behackl and @hydrobeam, I have been thinking a lot about the implementation of this enhancement and the concerns raised. I think it would be best if I spent some time completely re-doing the implementation. So with that in mind, I have some questions for you, or anyone else who is interested:
For me, the key functionality is the ability to apply a colorscale by z-value to surfaces and to be able to have below zero be one color and above zero be another color (I am making finance videos, so want to show below zero as red for loss and above zero as green for profit). Feel free to add anything I may have missed. |
I have made the below changes:
I hope this resolves most of the issues raised. One issue that I could not solve was not making
Ignore the above, used |
for more information, see https://pre-commit.ci
Agreed. Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>
for more information, see https://pre-commit.ci
b68b366
to
690b26a
Compare
Rebased to account for PR #2476 and cleaned up the docstring. Edit: Example now renders in the docs: |
for more information, see https://pre-commit.ci
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added one commit properly deprecating the color
parameter Surface.set_fill_by_value
to avoid introducing a hard breaking change, please cross-check! Otherwise this still looks fine to me, if someone using the OpenGL renderer a bit more than myself could try to run this locally too it would be much appreciated.
Thanks for your contribution!
OpenGLSurface
.OpenGLSurface
, replaced colors
keyword argument of :meth:.Surface.set_fill_by_value
with colorscale
This pull requests closes #2173 .
Overview: What does this pull request change?
Enables coloring
OpenGLSurface
gradient colors by z-value, by passing in a list of colors and an axes when aOpenGLSurface
is initialized. The methodOpenGLSurface.set_fill_by_value()
has been deprecated, as it never worked properly forOpenGLSurface
.Motivation and Explanation: Why and how do your changes improve the library?
Adds similar functionality as
Surface.set_fill_by_value()
, but forOpenGLSurface
. Here is an example:And the code used to generate this example:
Links to added or changed documentation pages
Further Information and Comments
The method
OpenGLSurface.set_fill_by_value()
has been deprecated as it never worked properly. The same method worked forSurface
becauseSurface
is made up of many small squares lined up next to each other, so it could color each square a different color and it would give a gradient effect. ButOpenGLSurface
is made up of triangles, which are fused together to create a singlemobject
. So to color aOpenGLSurface
it is necessary to pass in the colors to the shaders, along with the vertex data at the time the surface is initialized.Reviewer Checklist