I have a Raphael set that I'd like to move by 400px vertically.
When I drew the paths, I applied individual x-axis transformations to all of the paths in the set. When I try to apply the y-axis transformation, I lose my x values. What's the solution?
sampleIcon = self.paper.path(path).attr({'transform': 't' + (someWidth*index) + ',60' });
iconSet.push(sampleIcon);
// when I click on something
iconSet.animate({transform: 't' + (original x-transform value for each icon) + ',400'});
Or is there a way to omit the x-transform entirely?
Raphael's lack of a comprehensive solution for this issue (bulk animation of arbitrary sets of objects) is one of its most serious limitations in my opinion. If all you need to do is translate items, however (and without using overlapping animations), you're in luck!
Simply add the "append" modifier to your translation strings, like this:
iconSet.animate({transform: '...t' + (original x-transform value for each icon) + ',400'});
This will effectively "add" the given translation to the currently translated state of each item in the set. You can do the same thing with rotation and scaling, of course.
Related
Is there a easy way to center an sf::Text object in an sf::RectangleShape object?
The text has variable lengths, but isn't changing after creation.
I'm using SFML 2.4.
Centering one object over the other is usually a trivial task: Just determine the size difference between the objects and use it as an offset by dividing it by 2.
However, once you use (True Type) font rendering, things become a tiny bit more tricky, because the origin of these font glyphs isn't necessarily on the top left of the actual glyph. It might be anywhere, depending on the font and the character/glyph to be rendered (serifs and other decoration elements are a typical example for this).
Getting back to the basic formula:
offset = (shape.size() - text.size()) / 2
Now let's add the text offset:
offset = (shape.size() - text.size()) / 2 - text.offset()
There are multiple ways to do this using SFML. Personally I'd probably create my custom sf::Drawable derived class drawing both the box and the text.
For standalone drawing (like you do), I actually prefer setting the text's origin to account for the offset. This way you're able to set both shape and text's position identically and they'll be perfectly aligned without touching the origin/offset again (unless you change the text).
const sf::FloatRect bounds(text.getLocalBounds());
const sf::Vector2f box(shape.getSize());
text.setOrigin((bounds.width - box.x) / 2 + bounds.left, (bounds.height - box.y) / 2 + bounds.top);
Note that I've basically swapped operands since I'm setting the origin rather than offset. For example, to move the text 5 units to the right, I have to set the origin to -5 rather than 5.
The constant is really just there to make the whole line a bit more readable. You could also do everything inline, but I prefer the cleaner way.
Here's the whole thing in action using Arial and Lucida Handwriting:
Note how "Hello World" is aligned differently depending on whether the font glyphs take more space downwards. If you don't want that behavior, you'd have to use some fixed line height rather than relying on the height of the sf::Text object.
Just getting into matplot lib and running into odd problem - I'm trying to plot 10 items, and use their names on the x-axis. I followed this suggestion and it worked great, except that my label names are long and they were all scrunched up. So I found that you can rotate labels, and got the following:
plt.plot([x for x in range(len(df.columns))], df[df.columns[0]], 'ro',)
plt.xticks(range(10), df.columns, rotation=45)
The labels all seem to be off by a tick ("Arthrobacter" should be aligned with 0). So I thought my indexing was wrong, and tried a bunch of other crap to fix it, but it turns out it's just odd (at least to me) behavior of the rotation. If I do rotation='vertical', I get what I want:
I see now that the center of the labels are clearly aligned with the ticks, but I expected that they'd terminate on the ticks. Like this (done in photoshop):
Is there a way to get this done automatically?
The labels are not "off", labels are actually placed via their "center". In your second image, the corresponding tick is above the center of the label, not above its endpoint. You can change that by adding ha='right' which modifies the horizontal alignement of the label.
plt.plot([x for x in range(len(df.columns))], df[df.columns[0]], 'ro',)
plt.xticks(range(10), df.columns, rotation=45, ha='right')
See the comparison below :
1)
plt.plot(np.arange(4), np.arange(4))
plt.xticks(np.arange(4), ['veryverylongname']*4, rotation=45)
plt.tight_layout()
2)
plt.plot(np.arange(4), np.arange(4))
plt.xticks(np.arange(4), ['veryverylongname']*4, rotation=45, ha='right')
plt.tight_layout()
I make a candlestick using two rectangles and making a set.
Then I make 100 candlesticks and make that a set.
When I try to move all 100 candlesticks, they either all move to one coordinate, or all move correctly, but the sticks all move to the edge of the candle.
How can I move the whole set, but retain the inner transforms of the candlesticks?
It is possible to "append" or "prepend" transformations to a set of Raphael objects using the forms "...Tx,y" and "Tx,y..." respectively. In your example, prepending will probably be more functional since you want the absolute movement of the set in the viewbox to occur before any other transformations assigned on a per-element basis.
You should be able to do this or something much like it:
var shift_x = 100, shift_y = 50;
set.attr( { transform: "T" + shift_x + "," + shift_y + "..." } );
You'll notice some elliptical commentary with respect to transform prepend/append in the formal documentation for that function which, sadly, leaves much to be desired.
I'm having an issue with sets and how transforms are applied. I'm coming from a graphics background, so I'm familiar with scene graphs as well as the normal SVG group syntax, but Raphael is confusing me. Say I have a circle and a set, on which I want to apply a transform.
circle = paper.circle(0,0.5)
set = paper.set()
If I add the circle first, and then transform, it works.
set.push circle
set.transform("s100,100")
To make a 50 radius circle. If I reverse the order, however,
set.transform("s100,100")
set.push circle
The transform is not applied.
This seems as though it will break many, many rendering and animation type algorithms, where your groups/transforms hold your articulation state, and you add or remove objects to them instead of recreating the entire transform every time. Is there an option somewhere in the documentation that I am not seeing that addresses this, or was this functionality discarded in favor of simplicity? It seems very odd to be missing, given that it is supported directly and easily in the group hierarchy of SVG itself... do I need to manually apply the transform from the set to any children added after the set is transformed?
Sets in Raphael are just simple Arrays.
When you perform some actions on set, Raphael goes through all members via for(...){} loop.
Raphael doesn't support SVG groups <g></g>
UPDATE Raphael's code:
// Set
var Set = function (items) {
this.items = [];
this.length = 0;
this.type = "set";
if (items) {
for (var i = 0, ii = items.length; i < ii; i++) {
if (items[i] && (items[i].constructor == elproto.constructor || items[i].constructor == Set)) {
this[this.items.length] = this.items[this.items.length] = items[i];
this.length++;
}
}
}
},
As you can see, all items are stored in this.items which is array.
Raphaël's sets are merely intended to provide a convenient way of managing groups of shapes as unified sets of objects, by aggregating element related actions and delegating them (by proxying the corresponding methods in the set level) to each shape sequentially.
It seems very odd to be missing, given that it is supported directly
and easily in the group hierarchy of SVG itself...
Well, Raphaël is not an attempt to elevate the SVG specs to a JavaScript based API, but rather to offer an abstraction for vector graphics manipulation regardless of the underlying implementation (be it SVG in modern browsers, or VML in IE<9). Thus, sets are by no means representations of SVG groups.
do I need to manually apply the transform from the set to any
children added after the set is transformed?
Absolutely not, you only need to make sure to add any shapes to the set before applying transformations.
After interacting with the XTK camera in some way -- translation, rotation, zooming -- is there a way to retrieve from the camera the new values of the position, the focus and the up vector? It looks like the getter and setters are defined in the camera javascript, but the attributes corresponding to these are not updated during the interaction. The value returned by camera.position, for instance, is not updated even following a translation.
Is there either a mechanism that can provide these values, or a way to add an additional watcher to all interactions that modify the camera?
the position, up vector and focus are used to configure the 3d space at first. then, all interactions just modify the created view matrix.
You can query the view matrix like this
ren = new X.renderer3D()
console.log(ren.camera.view + "") // prints the view matrix as a string
I see a few solutions depending of who does the job.
First : adding a option to the cameras to enable tracking (disabled by default), an option that would update up/position/focus would be easy no ? Since it's just to multiply the previous vector by the transformation matrix at the same moment than we multiply the view matrix by the transformation matrix. But it may bring an additionnal cost in operations. Or we can compute it like in my "Second"
Second : if my memories are good, the transformation matrix T in a base B(O(x,y,z),i,*j*,k) has a well known-structure no ? Something like this (maybe I forget a transposition) :
i1 j1 k1 u1
i2 j2 k2 u2
i3 j3 k3 u3
0 0 0 1
Where :
([u1,u2,u3])=T(0(x,y,z)) i.e. gives the translation in the base B
([i1,i2,i3])=T(**i**)
([j1,j2,j3])=T(**j**)
([k1,k2,k3])=T(**k**)
Then if you want the 3 angles it is very harsh (see euler's calculations), but if you want something else it could be easier. For example you want the up vector which is the image of the "k" vector of the base B by our transformation T, so it is [j1,j2,j3] no ? Then, you cannot get easy the focus point, but you can easy get the focus vector : it is [k1,k2,k3] ! (actualy maybe it is -1*[k1,k2,k3]). If you look well the LookAt_ method of X.camera3D, it does not give a focus point to webgl but a normalized focus vector : the point position doesn't matter, you just need 1 point on the focus vector, and you can compute it now, no ? It's just a sum of currentposition & currentfocusvector coordinates.
I wish my memories are well and I am not saying total sh*t.
Just one question : there is a setter for the view matrix, so why do you want to store & set up/focus/position instead of directly storing and setting view ?
PS : caution, There could be a scale operator k, so the matrix would be different different, but I don't think there is in xtk.
PS 2 : in bold are vectors. [number,number,number] is a 3D vector shown by his coordinates.