WindowingTransformation.st
changeset 0 48194c26a46c
child 2 b35336ab0de3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WindowingTransformation.st	Fri Jul 16 11:42:20 1993 +0200
@@ -0,0 +1,256 @@
+"
+ COPYRIGHT (c) 1992 by Claus Gittinger
+              All Rights Reserved
+
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice.   This software may not
+ be provided or otherwise made available to, or used by, any
+ other person.  No title to or ownership of the software is
+ hereby transferred.
+"
+
+Object subclass: #WindowingTransformation
+        instanceVariableNames: 'scale translation'
+        classVariableNames: ''
+        poolDictionaries: ''
+        category: 'Graphics-Support'!
+
+WindowingTransformation comment:'
+COPYRIGHT (c) 1992 by Claus Gittinger
+              All Rights Reserved
+
+I represent the ability to perform transformations in 2-D space.
+
+Instance variables are:
+scale           <Number> or <Point> representing a
+                                    linear scaling factor.
+translation     <Number> or <Point> representing a
+                                    translation in 2-D.
+
+All 2-D objects are supposed to be able to be transformed using
+instances of me.  Instances of me can also be combined to form a
+single composite transformation.
+
+%W% %E%
+
+written summer 92 by claus
+'!
+
+!WindowingTransformation methodsFor: 'accessing'!
+
+scale
+    "return a copy of the Point that represents the
+     current scale of the receiver."
+
+    scale == nil ifTrue:[
+        ^ Point x:1 y:1
+    ].
+    ^ scale copy
+!
+
+scaleOfOne
+    "Set the scale of the receiver to the identity scale"
+
+    scale := nil
+!
+
+translation
+    "return a copy of the receiver's translation."
+
+    ^ translation copy
+!
+
+translation: aValue
+    "Set the receiver's translation to aValue."
+
+    translation := aValue
+! !
+
+!WindowingTransformation methodsFor: 'testing'!
+
+noScale
+    "return true if the identity scale is in effect;
+         answer false, otherwise."
+
+    ^ scale == nil
+! !
+
+!WindowingTransformation methodsFor: 'applying transform'!
+
+applyInverseTo:anObject 
+    "Apply the inverse of the receiver to anObject
+     and answer the result."
+
+    |transformedObject|
+
+    transformedObject := anObject translateBy:(self inverseTranslation).
+    scale == nil ifFalse:[
+        transformedObject := transformedObject scaleBy:(self inverseScale)
+    ].
+    ^ transformedObject
+!
+
+applyTo:anObject 
+    "Apply the receiver to anObject and answer the result."
+
+    |transformedObject|
+
+    scale == nil ifTrue:[
+        transformedObject := anObject
+    ] ifFalse:[
+        transformedObject := anObject scaleBy:scale
+    ].
+    transformedObject := transformedObject translateBy:translation.
+    ^ transformedObject
+!
+
+compose:aTransformation 
+    "return a new WindowingTransformation that is the
+     composition of the receiver and aTransformation.
+     The effect of applying the resulting WindowingTransformation
+     to an object is the same as that of first applying
+     aTransformation to the object and then applying the 
+     receiver to its result."
+
+    |aTransformationScale newScale newTranslation|
+
+    aTransformationScale := aTransformation scale.
+    scale == nil ifTrue:[
+        aTransformation noScale ifTrue:[
+            newScale := nil
+        ] ifFalse:[
+            newScale := aTransformationScale
+        ].
+        newTranslation := translation + aTransformation translation
+    ] ifFalse:[
+        aTransformation noScale ifTrue:[
+            newScale := scale
+        ] ifFalse:[
+            newScale := scale * aTransformationScale
+        ].
+        newTranslation := translation
+                          + (scale * aTransformation translation)
+    ].
+    ^ WindowingTransformation scale:newScale
+                        translation:newTranslation
+! !
+
+!WindowingTransformation methodsFor: 'transforming'!
+
+scaleBy:aScale 
+    "return a new WindowingTransformation with the scale and translation of 
+     the receiver both scaled by aScale."
+
+    |checkedScale newScale newTranslation|
+
+    aScale == nil ifTrue:[
+        newScale := scale.
+        newTranslation := translation
+    ] ifFalse:[
+        checkedScale := self checkScale:aScale.
+        scale == nil ifTrue:[
+            newScale := checkedScale
+        ] ifFalse:[
+            newScale := scale * checkedScale
+        ].
+        newTranslation := checkedScale * translation
+    ].
+    ^ WindowingTransformation scale:newScale
+                        translation:newTranslation
+!
+
+translateBy:aPoint 
+    "return a new WindowingTransformation with the same scale and 
+     rotations as the receiver and with a translation of the current 
+     translation plus aPoint."
+
+    ^ WindowingTransformation scale:scale
+                        translation:(translation + aPoint)
+! !
+
+!WindowingTransformation methodsFor: 'printing'!
+
+printString
+    ^ (self class name, ' scale: ', scale printString,
+                  ' translation: ', translation printString)
+! !
+
+!WindowingTransformation methodsFor: 'private'!
+
+checkScale:aScale
+    "Converts aScale to the internal format of a floating-point Point."
+
+    |checkedScale|
+
+    checkedScale := aScale asPoint.
+    ^ Point x:checkedScale x asFloat
+            y:checkedScale y asFloat
+!
+
+inverseScale
+    "return with a Point representing the inverse of my
+     scale."
+
+    |newScale|
+
+    newScale := self checkScale:scale.
+    ^ Point x:(1.0 / newScale x)
+            y:(1.0 / newScale y)
+!
+
+inverseTranslation
+    "return with a Point representing the inverse of my
+     translation."
+
+    |trans|
+
+    trans := translation asPoint.
+    ^ Point x:trans x negated
+            y:trans y negated
+!
+
+setScale:aScale translation:aTranslation
+    "Sets the scale to aScale and the translation to aTranslation."
+
+    scale := aScale.
+    translation := aTranslation
+! !
+
+!WindowingTransformation class methodsFor: 'instance creation'!
+
+identity
+    "returns a windowing transformation with no scaling (nil) 
+     and no translation (0@0)."
+
+    ^ self new setScale:nil
+            translation:(Point x:0.0 y:0.0)
+!
+
+scale:aScale translation:aTranslation 
+    "returns a windowing transformation with a scale factor of  
+     aScale and a translation offset of aTranslation."
+
+    ^ self new setScale:aScale
+            translation:aTranslation
+!
+
+window:sourceRectangle viewport:destinationRectangle 
+    "returns a windowing transformation with a scale and
+     translation computed from sourceRectangle and destinationRectangle.
+     The scale and transformation are computed such that sourceRectangle
+     is transformed to destinationRectangle."
+
+    |sX sY tX tY newScale|
+    sX := destinationRectangle width / sourceRectangle width.
+    sY := destinationRectangle height / sourceRectangle height.
+    tX := destinationRectangle left - sourceRectangle left.
+    tY := destinationRectangle top - sourceRectangle top.
+    ((sX = 1.0) and:[sY = 1.0]) ifTrue:[
+        newScale := nil
+    ] ifFalse:[
+        newScale := Point x:sX y:sY
+    ].
+    ^ self new setScale:newScale
+            translation:(Point x:tX y:tY)
+! !