Suppose we have an Axes object and a graph plotted in the coordinate system defined by these axes.
Is it possible to "zoom-out" by one or both axes, so we can see more of the graph, while the dimensions of the Coordinate system on the screen are kept constant?
For example, I've tried using the ValueTracker for both x_range properties of the Axes and the graph but it gives strange and unexpected results.
class Test(Scene):
def construct(self):
x_max_tracker = ValueTracker(0.0)
axes = always_redraw(lambda: Axes(
(-np.pi, x_max_tracker.get_value(), 0.5), (-5., 5.),
width=8, height=10
))
xsin_graph = always_redraw(
lambda: axes.get_graph(
lambda x: 0.5*x*np.sin(x)-1, color=BLUE,
x_range=[-np.pi, x_max_tracker.get_value()]
)
)
self.play(
Write(axes, lag_ratio=0.01, run_time=1), ShowCreation(xsin_graph)
)
self.wait(2)
self.play(x_max_tracker.animate.set_value(4*np.pi), run_time=2)
Additional, but connected question: is it possible to give the position of the coordinate system (Axes) at initiation?
UPDATE
I have defined a method generate_axes() which: 1) generates the Axes object; 2) Places it at specified coordinates on the Scene.
Now, if I am calling the always_redraw method on this generate_axes() method (keeping the x_tracker from the code above to control the x_range) then I could obtain nice "zoom-out/in" animation by calling play(x_tracker.animate.set_value(X)).
However, this doesn't change the axes variable, which is, apparently, still keeping the pointer on the first initial Axes object with not modified x_range. I thought that always_redraw() creates a new mobject each frame? Somehow this updated object is transferred to the Scene to be displayed but can't be accessed! For example, if I print axes.x_range after the end of the animation I am getting the initial x_range value.
P.S.: I am using the manimgl package, so the method always_redraw is probably not from the standard manim package. But it is generally the add_updater with become
Currently, Axes unfortunately do not support the sort of rescaling you would like to use. The easiest way to achieve this sort of behavior probably is by implementing a custom animation that repeatedly updates the axes and any curves within with become.
And as for your second question: Axes are always drawn in a way such that the center of the mobject is in the scene origin. You can move them to where you would like to show them, and only add them after moving.
Update
.become creates a new mobject, yes, but then only transfers some of the new mobject's properties and attributes to the original mobject. If there are some attributes that you need updated, it is best if you simply updated them yourself in your method -- which is also why using a general updater function is more flexible than always_redraw.
And for future reference: make sure to say right away whether you are working with manim or manimgl, they are substantially different in some aspects.
Related
I'm working on a program in Godot using Gdscript, and I ran into a problem when trying to use the Transform.translated(Vector3) function. My code is supposed to move a bone to (0,0,0) by translating it by its current coordinates but with negative sign. Example: (1,2,3) would be translated by (-1,-2,-3) so it would end up at (0,0,0). For some reason when I do this, the end position of the bone is not (0,0,0), but some other coordinate. In the Godot documents, it says the .translated function is "relative to the transform's basis vectors", so maybe that's why? Also if there is a better way to change a bones position than using the Transform.translated(Vector3) function that would be helpful too. Thanks!
My Code:
bonePose = skel.get_bone_global_pose(bone)
var globalBonePose = skel.to_global(bonePose.origin)
translateVector = -globalBonePose
var newPose = bonePose.translated(translateVector)
skel.set_bone_pose(bone, newPose)
Code Output / Results:
bonePose (the original position of the bone) is around (-0.82,0.49,0.50)
translateVector (the amount the bone will be translated) is around (0.82,-0.49,-0.50)
newPose (the final position of the bone -- should be [0,0,0]) is around (0.82,-0.66,-0.46). Even when I call skel.to_global(newPose.origin) to see the global coordinates, it's (-0.76,0.44,0.42), which is not (0,0,0)
In Godot a Transform is composed of a basis (a Basis) and an origin (a Vector3). Where the origin handles the translation part of the transform, and the Basis the rest.
A Basis is the set of vectors that define the coordinate system. There is a vector that defines the x axis, another for the y axis, and another for the z axis. And this is the way Godot will encode rotation and scaling transformations.
When the documentation says "relative to the transform's basis vectors" it means the Basis will be applied to the vector you pass in. Thus, in your case, you are getting a translation on the local space of the bone. Which implies that if the bone is rotated or scaled (or something like that), that will affect the translation.
If you don't want to deal with rotation, scaling, et.al. I suggest you work with the origin of the Transform instead.
If you have a Transform and you want another that is otherwise equal but located at (0, 0, 0), you do this:
var new_transform = Transform(transform.basis, Vector.ZERO)
Or replace Vector.ZERO with whatever origin you want to give the new transform.
I also need to remind you that get_bone_global_pose and set_bone_pose do not operate on the same thing. On one hand set_bone_pose is relative to the parent bone, on the other get_bone_global_pose is relative to the Skeleton. Thus, I suggest you use set_bone_global_pose_override instead.
The final piece you need is the opposite of Spatial.to_global. Because setting the pose like as follows…
bonePose = skel.get_bone_global_pose(bone)
var newPose = Transform(bonePose.basis, Vector.ZERO)
skel.set_bone_global_pose_override(bone, newPose, 1.0)
… Would place it at the origin of the Skeleton.
Well, the opposite of Spatial.to_global is Spatial.to_local, and you would use it like this:
bonePose = skel.get_bone_global_pose(bone)
var newPose = Transform(bonePose.basis, skel.to_local(Vector.ZERO))
skel.set_bone_global_pose_override(bone, newPose, 1.0)
Here skel.to_local(Vector.ZERO) should give the origin of the world relative to the Skeleton. And given that set_bone_global_pose_override wants a Transform relative to the Skeleton, the result should be that the bone is placed at the origin of the world. With its rotation and scaling preserved.
I'm writing a program in Godot with GDscript that aims to change the position of multiple bones in an armature. The bone gets translated by a value calculated by the point I want the bone to move to minus the current position of the bone. translateValue = endPoint - currentPoint However, all values must be in world coordinates or global position for the code to work. Godot has various methods to retrieve the bone Transform in order to access the position such as : skeleton.get_bone_pose() , skeleton.get_bone_global_pose , skeleton.get_bone_rest . I tried using skeleton.get_bone_global_pose but it didn't give the global position and seemed to still be relative to something. There's also the to_global() method, but i'm not entirely sure what it does. Could someone explain the differences between these methods and how to get global position? Thanks!
I'll start with these methods:
get_bone_rest
get_bone_custom_pose
get_bone_pose
First of all, get_bone_rest gives you the default transform of the bone, relative to its parent bone. Then the other transform are stacked, in the above order.
Then we have:
get_bone_global_pose
This method gives you the final transform of the bone. And it is relative to the Skeleton. That is, this transform already includes the previously mentioned transforms, combined from parent to child bone.
Thus, converting its result to world space is a matter of composing the transform of the Skeleton:
$Skeleton.global_transform * $Skeleton.get_bone_global_pose(bone_index)
And we have:
get_bone_global_pose_no_override
As the name suggest get_bone_global_pose_no_override ignores any global pose override. That's right, you you can override the global pose. To do that, use set_bone_global_pose_override. See also clear_bones_global_pose_override. These are all, of course, relative to the Skeleton.
The method Spatial.to_global(vector3) is unrelated to the Skeleton. It transforms a vector from the local space of the node on which you call it, to world space. Which might also be useful:
$Skeleton.to_global($Skeleton.get_bone_global_pose(bone_index).origin)
I have defined some plots which I now like to arrange using subplots. So I will pass an axis object to the plot definition and tell it to plot on that instead of making a new plot. However, to make this fool-proof I like to check that the passed object is actually of the right type, i.e. an axis.
When I make a subplot like so: f, ax = pyplot.subfigure(2,2) and inspect type(ax[1,1]) it returns matplotlib.axes._subplots.AxesSubplot, however I cannot use isinstance() to test against that value. What works is isinstace(ax[1,1],matplotlib.axes._subplots.Subplot). But I can also test against matplotlib.axes._subplots.Axes or matplotlib.axes._subplots.SubplotBase, all equate to True. I'm a bit confused by the ambiguity here. What is the correct way to test if something is an object one can plot on?
In PyQt 5, is there a way to obtain all pixel positions that would be modified by a call to QPainter.drawPolygon for a QPainter object constructed with some QImage as an argument without actually drawing the polygon? Ideally I would like to obtain separate sets of pixel positions for the polygon's border and for all pixels inside the polygon.
Just like #ekhumoro said, QPolygon is a subclass of QVector (that is, a QList). However, in Pyqt this is a Python array and not a QList. I got runtime errors when trying to iterate over this list, because it was inside the QPolygon object and there was no getter. In this case, in PyQt the solution is not very efficient. You need to iterate over each pixel of the image, creating a QPoint with pixel coordinates and checking if the QPolygon contains this point through the containsPoint method. There aren't many implementation details, but consider the following code snippet.
array_qpoints = [] # this array will have all the QPoints
polygon = QPolygon([
QPoint(140,234),
QPoint(126,362),
QPoint(282,409),
QPoint(307,273),
QPoint(307,233),
])
# let's consider a 640x480 image
for x in range(640):
for y in range(480):
point = QPoint(x, y)
if polygon.containsPoint(point, Qt.FillRule.OddEvenFill):
array_qpoints.append(point)
You can get the coordinates of each pixel by calling the x() and y() methods for each element in array_qpoints.
for point in array_qpoints:
x = point.x()
y = point.y()
# do what you want with the information
I'm posting this answer for others who visit this question and are looking for a solution by code. Since it's been several years, if you've found a better solution, please post :)
I've already know how to dark-down a CCSprite object by:
sprite.color = ccc3(x, x, x); // x is a value less then 255
(As far as i know, it should be a direct mapping of openGL functions, so its easy to achieve.)
But when it comes to light-up, my current solution is adding another mask sprite (same shape but all in white), changing its blendFunc to { GL_SRC_ALPHA, GL_ONE } and overlaying it onto the target. Besides all the codes added, there should be a mask image for each need-to-light-up one.
Is there a way to do light-up as easily as dark-down?
However, not as easy as setColor, in Cocos2d 2.x, with OpenGL ES 2.0 support, you can achieve this by using custom shaders. You can get started here:
http://www.raywenderlich.com/10862/how-to-create-cool-effects-with-custom-shaders-in-opengl-es-2-0-and-cocos2d-2-x
You may also try inverting the sprite's darker color to get a lighter one.