>However, the rotated shapes probably have a different average center; which means that your second rotation (ie to rotate things back) is pivoting around a different point. And that's what causes the change of position.
Uhh, what? Why doesn't the rotated group have the same centre as the original? The article glosses right over this without explaining it. Is it floating point imprecision? Is it from rasterization?
You probably already have xy bounding boxes for every element and the selection itself as it helps with selecting, drawing, etc., so using them is the easiest option.
Computational geometry is hard. Let's go shopping!
If I'm being less un-charitable, the reason is that this bug is way down the list of priorities and fixing it with a proper solution is a lot of code and work that won't result in any new revenue.
then the center of the bounding box has now moved towards the corner of what was originally the upper right square (because there isn't a fourth square to complete the symmetry and push the bottom of the box around the three squares down). Rotating again will now pivot around this new point rather than the original and a rotation 45 degrees clockwise back to the original angle will now have shifted the boxes.
Honestly, I'd think the correct solution here would be to pivot around the center-of-mass or some other rotationally-invariant point.
The bounding box is the natural implementation because it matches what the user sees -- when you select multiple objects, the rotation handle is at the corner, because where else would it be? Plus it’s very easy to code and to test.
But yeah, using a rotationally-invariant point would be better than the stateful fix the article goes for.
Center-of-mass would make sense except it might do strange things if you have a mix of solid shapes and lines. How much mass should the lines have?
Using the centre of the bounding circle is probably best, as others in this discussion have suggested.
There should also be strategies for the choice of center to be invariant even after re-selecting the rotated set of shapes. You should be able to do this by finding the two points farthest from each other, and choosing the midpoint between the two, for instance. But that point might not be unique, so maybe finding the center of the smallest circle enclosing all objects would be a better example?
I ran into this problem in my app and found that rotating around the center of the bounding circle instead of the bounding box was a suitable solution.
If you have a page full of writing, all sorts of things get slow. I do a lot of digital writing, and have encountered a number of strange slowdowns, even in apps designed for the purpose. In particular, selecting a large number of strokes can be quite a problem.
There are minimum bounding circle algorithms that are O(n) where n is the number of points, but n can get big enough that you may not want to be doing that in an interactive program. You can put objects in a quadtree or similar to look them up quickly, and that may let you discard entire strokes in e.g. Welzl's bounding circle algorithm, but with stroke or curve data you'll still need to search along each one somehow for the extreme points by whatever measure you're using (and a Bezier curve has uncountably infinitely many points, so maybe you can only find an approximate bounding circle?).
Curves aren’t important in this scenario because the circle isn’t visible, it’s purely there to provide a consistent center of rotation. It doesn’t matter if it hugs the curves or not.
This is the kind of thing where there are plenty of well-established algorithms (although there might not be a good off-the-shelf implementation in your language of choice). I doubt efficiency is going to be a problem unless you have many thousands of points.
Good point, but the centre of the circle is the important thing, and that is visible if you want good UX. It does matter that it consistently leaves out the same part of sticking-out curves in different rotations. You could sample some number of points along each curve or something.
Many thousands of points is exactly what you have in a page of handwriting. They're organised into strokes, which should help.
Just spit-balling here, but it seems to me that you could probably get away with just using the endpoints and maybe the control points. There might be some odd cases where this falls apart, but in general I suspect it would work pretty well and in the edge cases it probably wouldn't be too confusing; you'd still get a point to rotate around in the vicinity of the curve at the centre of a line between the endpoints. If you included the control points, it would still end up roughly close to the centre of the visual curve.
as someone who works with vector drawings often I would say that's unintuitive simply because the selection highlights are usually rectangular... there are many cases (lets say 3 objects in a triangle) where if you show a rectangular selection the rotation "center" will then be quite off the intuitive center
It should be easy enough to compute the "center of mass" (quite efficiently too, by considering a weighted average of component centers of mass recursively) for the objects, rather than something even more naive like the center of the bounding box. The former, being a sensible physical quantity is much more likely to be well-behaved under physical transformations.
It is rotation invariant, so it behaves well under rotation, but I think it sometimes would give highly surprising/undesirable results.
For example, the center of mass between earth and the sun is deep inside the sun, IIRC, so it would almost rotate around the sun.
So, if you have the sun showing at the left of your screen, earth at the right, and rotate that pair over 180 degrees, the sun would stay put, and earth would move off-screen.
You could auto-scroll to keep both on-screen, but I don’t think users would find either a good choice.
In general, I think users would expect a rectangle with some parts cut out if it to keep the same bounds after a 180 degree rotation, or a circle with some parts after any rotation.
The author treats this kind of destructive rotation as a positive, but this is exactly why rotation modifier as part of the object tree is generally a good thing! There's no need to recompute a center because it's the same center, only a rotate operation has been applied on top of the node. Also, that's how rotation works in the web browser, which these design apps are often targeting.
That would mean that these shapes get a common parent once rotated. And if you change the selection to include some but not all, and maybe some other shapes, and rotate, you'd create a many to many relationship?
Maybe the appropriate choice here is grouping, like we see app use folders for these. That way you get what you're talking about and it's obvious to the user / it's based on their choice.
I think you're mis-reading the situation the rotation of each individual shape isnt destructive (been following the author's work for a while, this is a vector based solution) what he's talking about is rotating multiple nodes at once around a common center, so each individual shape receives a new rotation but also a translation.
as an artist who uses these kinds of tools, and someone who'se had to design easy to use interfaces, it's hard to convay "invariant center of mass" when the selection for multiple shapes usually involves drawing a screen aligned rectangle (which has a convenient and intuitive center point)
I think instead of the center of the bounding box, I'd instead use the average center of each selected item. Each primitive will have a rotation agnostic invariant center relative to its location, so the average of those will always be invariant
28 comments
[ 2.3 ms ] story [ 78.7 ms ] threadUhh, what? Why doesn't the rotated group have the same centre as the original? The article glosses right over this without explaining it. Is it floating point imprecision? Is it from rasterization?
If I'm being less un-charitable, the reason is that this bug is way down the list of priorities and fixing it with a proper solution is a lot of code and work that won't result in any new revenue.
Suppose that you have three boxes like this:
The pivot for rotating them will be at the @ in the center of the bounding box around the three. If you then turn that counterclockwise by 45 degrees: then the center of the bounding box has now moved towards the corner of what was originally the upper right square (because there isn't a fourth square to complete the symmetry and push the bottom of the box around the three squares down). Rotating again will now pivot around this new point rather than the original and a rotation 45 degrees clockwise back to the original angle will now have shifted the boxes.Honestly, I'd think the correct solution here would be to pivot around the center-of-mass or some other rotationally-invariant point.
But yeah, using a rotationally-invariant point would be better than the stateful fix the article goes for.
Center-of-mass would make sense except it might do strange things if you have a mix of solid shapes and lines. How much mass should the lines have?
Using the centre of the bounding circle is probably best, as others in this discussion have suggested.
There are minimum bounding circle algorithms that are O(n) where n is the number of points, but n can get big enough that you may not want to be doing that in an interactive program. You can put objects in a quadtree or similar to look them up quickly, and that may let you discard entire strokes in e.g. Welzl's bounding circle algorithm, but with stroke or curve data you'll still need to search along each one somehow for the extreme points by whatever measure you're using (and a Bezier curve has uncountably infinitely many points, so maybe you can only find an approximate bounding circle?).
This is the kind of thing where there are plenty of well-established algorithms (although there might not be a good off-the-shelf implementation in your language of choice). I doubt efficiency is going to be a problem unless you have many thousands of points.
Many thousands of points is exactly what you have in a page of handwriting. They're organised into strokes, which should help.
For example, the center of mass between earth and the sun is deep inside the sun, IIRC, so it would almost rotate around the sun.
So, if you have the sun showing at the left of your screen, earth at the right, and rotate that pair over 180 degrees, the sun would stay put, and earth would move off-screen.
You could auto-scroll to keep both on-screen, but I don’t think users would find either a good choice.
In general, I think users would expect a rectangle with some parts cut out if it to keep the same bounds after a 180 degree rotation, or a circle with some parts after any rotation.
Maybe the appropriate choice here is grouping, like we see app use folders for these. That way you get what you're talking about and it's obvious to the user / it's based on their choice.
as an artist who uses these kinds of tools, and someone who'se had to design easy to use interfaces, it's hard to convay "invariant center of mass" when the selection for multiple shapes usually involves drawing a screen aligned rectangle (which has a convenient and intuitive center point)