Contents

Class WindowingTransformation


Inheritance:

Object  »
  WindowingTransformation

Instances of WindowingTransformation are used to transform objects from a source coordinate system to a destination coordinate system. Each instance contains a scale and a translation which can be applied to objects that respond to scaleBy: and translateBy:. It can be created with a default identity scale and translation, or with a specified scale and translation, or with a scale and translation computed from a window (a Rectangle in the source coordinate system) and a viewport (a Rectangle in the destination coordinate system). In applying a WindowingTransformation to an object, the object is first scaled (around the origin of the source coordinate system) and then translated. WindowingTransformations can be composed to form a single compound transformation.

In the out-of-the box image, a WindowingTransformation can be applied to instances of the following classes: Point, Rectangle as well as most subclasses of Path.

Every View uses two windowing transformations:

Instance Variables:

Instance Creation:

Three class methods are provided to create instances. One of these methods creates the identical transformation, the two remaining methods provide two possibilities to define a windowing transformation:

Instance Methods:

Known Uses:

A WindowingTransformation without a scale is used to implement scrolling.

Example of Use:

There is usually no need to directly use windowing transformations. The following examples demonstrate the implenetation of some geometric operations.

The first example shows the application of a translation to a collection of points and rectangles:

  | transformation items |
transformation := WindowingTransformation scale: 1@1 translation: 0@25.

items := OrderedCollection new.
items add: 0@0.
items add: (10@10 corner: 30@ 25).
items collect: [:obj | transformation applyTo: obj].
an OrderedCollection(0@25 10@35 corner: 30@50)

To undo that transformation, we can now apply the inverse transformation to the transformed objects:

  | transformation items result |
transformation := WindowingTransformation scale: 1@1 translation: 0@25.

items := OrderedCollection new.
items add: 0@0.
items add: (10@10 corner: 30@ 25).
result := items collect: [:obj | transformation applyTo: obj].
result collect: [:obj | transformation applyInverseTo: obj].
an OrderedCollection(0.0@0.0 10.0@10.0 corner: 30.0@25.0)

Note that the application of the inverse transformation does not only undo the previous transformation, it also changes the coordinates of the geometric objects to Float.

A scaling transformation can be used to magnify, to reduce or to mirror geometric objects.

The following example demonstrates the use of two windowing transformations to scale and to erect a data set.

   | displayRect dataPoints ranges scale erect tr pen first |

dataPoints := 
       (0 to: 100 by: 10)
        with: #(0 30 90 50 150 200 170 110 80 20 0)
        collect: [:x :y | x @ y].
ranges := 0@0 corner: 100@200.
displayRect := 10@10 extent: 200@200.
Display fill: displayRect fillColor: Color white.
pen := Pen new.
pen color: Color red.
scale := WindowingTransformation
               window: ranges
               viewport: (0@0 extent: displayRect extent - 1).
erect := WindowingTransformation
               scale: 1@-1
               translation: 0@ (displayRect height - 1) + displayRect origin.
tr := erect compose: scale.
first := true.
dataPoints do:
   [:pt |
      transformedPt := (tr applyTo: pt) rounded.

      first 
        ifTrue: [pen place: transformedPt.
                 first := false.
                ]
        ifFalse: [pen goto: transformedPt.].
   ].
   

Here is a beautiful example from the Squeak developers mailing list:

    | form frames |
   frames :=  { 6@2 corner: 449@238.
                186@210 corner: 434@390.
                505@218 corner: 653@388. }.
   form := Form extent: 700@500 depth: 8.
   form fillWithColor: Color yellow.
     " first loop:
       A subForm has twice the size of a frame.
       A windowing transformation is then used to
       transform the subForm back to the size of the
       frame and to display it in the frame.
       This loop displays blue rectangles "
   frames  do:
       [:frame |  | subForm |
        subForm := Form extent: frame extent * 2 depth: 8.
        subForm fillWithColor: Color blue.
        subForm
          displayOn: form
          transformation:
            (WindowingTransformation window: subForm boundingBox
                                     viewport: frame)
          clippingBox: form boundingBox
          align: 0@0
          with: 0@0
          rule: Form over
          fillColor: nil].
     " second loop:
       Forms that have the exact size of the frames are
       displayed in the frames. A windowing transformation
       is used to correctly position the forms.
       This loop displays red rectangles "
   frames  do:
       [:frame |  | subForm |
        subForm := Form extent: frame extent depth: 8.
        subForm fillWithColor: Color red.
        subForm
          displayOn: form
          transformation:
            (WindowingTransformation window: subForm boundingBox
                                     viewport: frame)
          clippingBox: form boundingBox
          align: 0@0
          with: 0@0
          rule: Form over
          fillColor: nil].

   form displayAt: 10@10.

When you interchange the two loops, you will see blue rectangles in the positions of the red ones.


Contents