penrose icon indicating copy to clipboard operation
penrose copied to clipboard

Generic transformations

Open samestep opened this issue 3 years ago • 2 comments

As mentioned in https://github.com/penrose/penrose/issues/478#issuecomment-952312338 by @joshsunshine:

Penrose should allow generic transformations, including transformations of any shape. These transformations should be consistent and expressive.

Related:

  • #709
  • #712
  • #724

samestep avatar Dec 20 '21 19:12 samestep

Here we should lean heavily on the way SVG performs transformations (especially since this is our main output format): https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform

In past discussions, I don't think we've done a great job of separating out two questions:

  • Internal representation of transformations. How should the layout and rendering engine represent transformations? Here the right choice in most graphics systems is to have a uniform encoding of all transformations, via transformation matrices. This way we don't need heterogeneous/redundant logic on how to rotate a rectangle vs. stretch an ellipse vs. ... Everything just boils down to application and differentiation of matrices.
  • External interface to transformations. This has been the biggest debate in the past: how should Style programmers specify transformations? Should we give them natural parameters like angle:, or should we ask them to define transformation matrices, or should we do something in between? I think the answer here is "all of the above"—but: all transformations should ultimately get transformed into matrices.

A uniform interface in style might look like

Shape {
   transform: rotate(30.) then translate(10.,20.) then mat3( 1., 0., 4; 0., 1., 5.; 0., 0., 1. )
}

This line composes three transformations: a rotation by 30 degrees, a translation by 10 in the x-direction and 20 in the y-direction, and then another transformation given by a 3x3 matrix in homogeneous coordinates (here representing a translation by (4,5)). Internally each of these gets turned into a transformation matrix, and these matrices are multiplied. (Note by the way the use of the then keyword, which is critical for disambiguating the composition order. Many graphics APIs assume left-to-right or right-to-left without making this composition order clear from the syntax.)

There are some semantics to work out. For instance, I don't think we should ditch parameters like center and radius for a circle, even though these parameters could in principle be emulated by applying a translation and scale (respectively) to a canonical circle, like the unit circle centered at the origin. Instead, I would adopt this mental model:

  • The shape parameters (like center and radius) define the reference shape.
  • All subsequent transformations get applied to this reference shape.

Especially important is the meaning of center. For instance, should transformations get applied relative to the shape's center? Seems like that would be the best way to satisfy the "principle of least surprise." Though we have to keep in mind that a rotation matrix by default represents a rotation around the origin (0,0). So, consider a shape like this one:

Rectangle {
   center: (10.,20.)
   w: 15.
   h: 5.
   transform: rotate(30.)
}

The transformation we actually need to apply here is:

  • first translate by -center
  • then apply a rotation by 30 degrees
  • then translate by +center This is not hard to implement internally, and the programmer never has to think about it. They simply need to know that "all transformations are expressed relative to the given center."

keenancrane avatar Dec 30 '21 16:12 keenancrane

Another related issue is that we at some point need to support groups, a la the SVG group tag: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/g

Here we will need to think carefully about how transformations get applied to groups, and to elements within those groups. Basically this is the idea of a scene graph: https://en.wikipedia.org/wiki/Scene_graph.

keenancrane avatar Dec 30 '21 16:12 keenancrane

Closing in favor of #1329.

samestep avatar Mar 01 '23 19:03 samestep