--- a/WindowingTransformation.st Fri Oct 28 04:16:56 1994 +0100
+++ b/WindowingTransformation.st Fri Oct 28 04:20:20 1994 +0100
@@ -23,9 +23,106 @@
COPYRIGHT (c) 1992 by Claus Gittinger
All Rights Reserved
-$Header: /cvs/stx/stx/libview/WindowingTransformation.st,v 1.6 1994-10-10 02:34:07 claus Exp $
+$Header: /cvs/stx/stx/libview/WindowingTransformation.st,v 1.7 1994-10-28 03:18:22 claus Exp $
'!
+!WindowingTransformation class methodsFor:'documentation '!
+
+copyright
+"
+ 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.
+"
+!
+
+version
+"
+$Header: /cvs/stx/stx/libview/WindowingTransformation.st,v 1.7 1994-10-28 03:18:22 claus Exp $
+"
+!
+
+documentation
+"
+ instances of WindowingTransformation can be used to scale, translate or
+ generally transform other objects in 2D space.
+ They can also be set as the translation in a graphic context,
+ which will then apply this to all of its drawing operations
+ (see GraphicContext>>transformation:).
+
+ All 2-D objects are supposed to be able to be transformed using
+ instances of me. Multiple instances of me can also be combined to form a
+ single composite transformation.
+
+ Instance variables are:
+ scale <Number> or <Point> representing a linear scaling factor.
+ nil is interpreted as 1@1
+
+ translation <Number> or <Point> representing a translation in 2-D.
+ nil is interpreted as 0@0
+
+
+ example (drawing in inches):
+
+ |v|
+
+ v := View new realize.
+ (Delay forSeconds:3) wait.
+ v transformation:(WindowingTransformation unit:#inch on:Display).
+ 'now, we can think of drawing in inches ...'.
+ v displayLineFrom:0.5@0.5 to:1@1
+
+
+ example (drawing in millimeters):
+
+ |v|
+
+ v := View new realize.
+ (Delay forSeconds:3) wait.
+ v transformation:(WindowingTransformation unit:#mm on:Display).
+ 'now, we can think of drawing in millimeters ...'.
+ v displayLineFrom:5@5 to:20@5
+
+
+ example (drawing magnified):
+
+ |v|
+
+ v := View new realize.
+ (Delay forSeconds:3) wait.
+ v transformation:(WindowingTransformation scale:2 translation:0).
+ 'now, everything is magnfied by 2'.
+ v displayLineFrom:10@10 to:30@30
+
+
+ example (drawing shrunk):
+
+ |v|
+
+ v := View new realize.
+ (Delay forSeconds:3) wait.
+ v transformation:(WindowingTransformation scale:0.5 translation:0).
+ 'now, everything is shrunk by 2'.
+ v displayLineFrom:10@10 to:30@30
+
+
+ example (transforming Points, Rectangles etc.)
+
+
+ |p pNew|
+
+ p := 10@10.
+ pNew := (WindowingTransformation scale:2 translation:10) applyTo:p.
+ pNew
+"
+! !
+
!WindowingTransformation class methodsFor:'instance creation'!
unit:unitSymbol on:device
@@ -61,20 +158,49 @@
pixelPerUnitH := device horizontalPixelPerInch
] ifFalse:[
"sorry: unknown unit is taken as pixel"
- ^ self new scale:nil translation:(0 @ 0)
+ ^ self new scale:nil translation:nil
]
]
]
]
].
- ^ self new scale:(pixelPerUnitH @ pixelPerUnitV) translation:0
+ ^ self basicNew scale:(pixelPerUnitH @ pixelPerUnitV) translation:nil
+
+ "
+ |v|
+
+ v := View new realize.
+ (Delay forSeconds:3) wait.
+ v transformation:(WindowingTransformation unit:#inch on:Display).
+ 'now, we can think of drawing in inches ...'.
+ v displayLineFrom:0.5@0.5 to:1@1
+ "
!
scale:aScale translation:aTranslation
"returns a windowing transformation with a scale factor of
aScale and a translation offset of aTranslation."
- ^ self new scale:aScale translation:aTranslation
+ ^ self basicNew scale:aScale translation:aTranslation
+
+ "
+ |v|
+
+ v := View new realize.
+ (Delay forSeconds:3) wait.
+ v transformation:(WindowingTransformation scale:2 translation:0).
+ 'now, everything is magnfied by 2'.
+ v displayLineFrom:10@10 to:30@30
+ "
+ "
+ |v|
+
+ v := View new realize.
+ (Delay forSeconds:3) wait.
+ v transformation:(WindowingTransformation scale:0.5 translation:0).
+ 'now, everything is shrunk by 2'.
+ v displayLineFrom:10@10 to:30@30
+ "
!
window:sourceRectangle viewport:destinationRectangle
@@ -85,61 +211,42 @@
represents the logical coordinateSpace while destinationRectangle
represents the device coordinateSpace."
- |sX sY tX tY newScale|
+ |sX sY tX tY newScale newTranslation|
sX := destinationRectangle width / sourceRectangle width.
sY := destinationRectangle height / sourceRectangle height.
tX := destinationRectangle left - sourceRectangle left.
tY := destinationRectangle top - sourceRectangle top.
+ ((tX = 1.0) and:[tY = 1.0]) ifTrue:[
+ newTranslation := nil
+ ] ifFalse:[
+ newTranslation := tX @ tY
+ ].
((sX = 1.0) and:[sY = 1.0]) ifTrue:[
- newScale := 1 @ 1
+ newScale := nil
] ifFalse:[
newScale := sX @ sY
].
- ^ self new scale:newScale translation:(tX @ tY)
+ ^ self basicNew scale:newScale translation:newTranslation
+
+ "
+ |v|
+
+ v := View new realize.
+ (Delay forSeconds:3) wait.
+ v transformation:(WindowingTransformation
+ window:(0@0 corner:1@1)
+ viewport:(0@0 corner:100@100)).
+ 'now, we can think of drawing in 0..1/0..1 coordinates'.
+ v displayLineFrom:0.1@0.1 to:0.9@0.9
+ "
!
identity
- "returns a windowing transformation with no scaling (nil)
+ "returns a windowing transformation with no scaling (1@1)
and no translation (0@0)."
- ^ self new scale:1 translation:0
-! !
-
-!WindowingTransformation class methodsFor:'documentation'!
-
-copyright
-"
- 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.
-"
-!
-
-version
-"
-$Header: /cvs/stx/stx/libview/WindowingTransformation.st,v 1.6 1994-10-10 02:34:07 claus Exp $
-"
-!
-
-documentation
-"
- 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.
-"
+ ^ self basicNew scale:nil translation:nil
! !
!WindowingTransformation methodsFor:'applying transform'!
@@ -148,47 +255,36 @@
"Apply the receiver to a number representing an x-coordinate
and return the result."
- scale isNil ifTrue:[
- ^ aNumber + translation x
- ].
- ^ (aNumber * scale x + translation x) asInteger
+ |t s|
+
+ scale isNil ifTrue:[s := 1] ifFalse:[s := scale x].
+ translation isNil ifTrue:[t := 0] ifFalse:[t := translation x].
+ ^ aNumber * s + t
!
applyToY:aNumber
"Apply the receiver to a number representing an y-coordinate
and return the result."
- scale isNil ifTrue:[
- ^ aNumber + translation y
- ].
- ^ (aNumber * scale y + translation y) asInteger
+ |t s|
+
+ scale isNil ifTrue:[s := 1] ifFalse:[s := scale y].
+ translation isNil ifTrue:[t := 0] ifFalse:[t := translation y].
+ ^ aNumber * s + t
+!
+
+applyScaleX:aNumber
+ "apply the scale only (if widths are to be transformed)"
+
+ scale isNil ifTrue:[^ aNumber].
+ ^ aNumber * scale x
!
applyScaleY:aNumber
"apply the scale only (if heights are to be transformed)"
scale isNil ifTrue:[^ aNumber].
- ^ (aNumber * scale y) asInteger
-!
-
-applyScaleX:aNumber
- "apply the scale only (if widths are to be transformed)"
-
- scale isNil ifTrue:[^ aNumber].
- ^ (aNumber * scale x) asInteger
-!
-
-applyInverseTo:anObject
- "Apply the inverse of the receiver to anObject
- and return the result."
-
- |transformedObject|
-
- transformedObject := anObject translatedBy:(self inverseTranslation).
- scale == nil ifFalse:[
- transformedObject scaleBy:(self inverseScale)
- ].
- ^ transformedObject
+ ^ aNumber * scale y
!
applyTo:anObject
@@ -196,14 +292,92 @@
|transformedObject|
- scale == nil ifTrue:[
- ^ anObject translateBy:translation.
+ scale isNil ifTrue:[
+ translation isNil ifTrue:[
+ ^ anObject
+ ].
+ ^ anObject translatedBy:translation
+ ].
+ transformedObject := anObject scaledBy:scale.
+ translation notNil ifTrue:[
+ transformedObject translateBy:translation.
].
- transformedObject := anObject scaledBy:scale
- transformedObject translateBy:translation.
^ transformedObject
!
+applyInverseToX:aNumber
+ "Apply the receiver to a number representing an x-coordinate
+ and return the result."
+
+ |t s|
+
+ scale isNil ifTrue:[s := 1] ifFalse:[s := scale x].
+ translation isNil ifTrue:[t := 0] ifFalse:[t := translation x].
+ ^ (aNumber - t) / s
+!
+
+applyInverseToY:aNumber
+ "Apply the receiver to a number representing an y-coordinate
+ and return the result."
+
+ |t s|
+
+ scale isNil ifTrue:[s := 1] ifFalse:[s := scale y].
+ translation isNil ifTrue:[t := 0] ifFalse:[t := translation y].
+ ^ (aNumber - t) / s
+!
+
+applyInverseScaleX:aNumber
+ "apply the scale only (if widths are to be transformed)"
+
+ scale isNil ifTrue:[^ aNumber].
+ ^ aNumber / scale x
+!
+
+applyInverseScaleY:aNumber
+ "apply the scale only (if heights are to be transformed)"
+
+ scale isNil ifTrue:[^ aNumber].
+ ^ aNumber / scale y
+!
+
+applyInverseTo:anObject
+ "Apply the inverse of the receiver to anObject
+ and return the result. This can be used to map back from logical
+ to physical coordinates, for example."
+
+ |transformedObject|
+
+ translation isNil ifTrue:[
+ scale isNil ifTrue:[
+ ^ anObject
+ ].
+ ^ anObject scaledBy:self inverseScale
+ ].
+ transformedObject := anObject translatedBy:(self inverseTranslation).
+ scale notNil ifTrue:[
+ transformedObject scaleBy:(self inverseScale).
+ ].
+ ^ transformedObject
+!
+
+transformPoint:p
+ "Apply the receiver to a point.
+ This is destructive in that the point is being modified,
+ not a copy."
+
+ scale isNil ifTrue:[
+ translation isNil ifTrue:[
+ ^ p
+ ].
+ ^ p + translation
+ ].
+ translation isNil ifTrue:[
+ ^ p * scale
+ ].
+ ^ (p * scale + translation)
+!
+
compose:aTransformation
"return a new WindowingTransformation that is the
composition of the receiver and aTransformation.
@@ -215,7 +389,7 @@
|aTransformationScale newScale newTranslation|
aTransformationScale := aTransformation scale.
- scale == nil ifTrue:[
+ scale isNil ifTrue:[
aTransformation noScale ifTrue:[
newScale := nil
] ifFalse:[
@@ -243,7 +417,7 @@
This is a destructive operation, modifying the transformation
represented by the receiver"
- |newScale newTranslation|
+ |newScale|
aScale isNil ifTrue:[^ self].
@@ -252,7 +426,9 @@
] ifFalse:[
newScale := scale * aScale
].
- translation := translation * aScale.
+ translation notNil ifTrue:[
+ translation := translation * aScale.
+ ].
scale := newScale.
!
@@ -279,17 +455,19 @@
|checkedScale newScale newTranslation|
- aScale == nil ifTrue:[
+ aScale isNil ifTrue:[
newScale := scale.
newTranslation := translation
] ifFalse:[
checkedScale := self checkScale:aScale.
- scale == nil ifTrue:[
+ scale isNil ifTrue:[
newScale := checkedScale
] ifFalse:[
newScale := scale * checkedScale
].
- newTranslation := checkedScale * translation
+ translation notNil ifTrue:[
+ newTranslation := checkedScale * translation
+ ]
].
^ (self class)
scale:newScale
@@ -345,35 +523,50 @@
scale:aScale translation:aTranslation
"sets the scale to aScale and the translation to aTranslation."
- scale := aScale asPoint.
- translation := aTranslation asPoint
+ aScale isNil ifTrue:[
+ scale := aScale
+ ] ifFalse:[
+ scale := aScale asPoint.
+ ].
+ aTranslation isNil ifTrue:[
+ translation := aTranslation
+ ] ifFalse:[
+ translation := aTranslation asPoint
+ ]
!
-translation:aValue
- "Set the receiver's translation to aValue, a Point or Number."
+translation:aTranslation
+ "Set the receiver's translation to aTranslation, a Point or Number."
- translation := aValue asPoint
+ aTranslation isNil ifTrue:[
+ translation := aTranslation
+ ] ifFalse:[
+ translation := aTranslation asPoint
+ ]
!
-scale:aValue
- "Set the receiver's scale to aValue, a Point or Number."
+scale:aScale
+ "Set the receiver's scale to aScale, a Point or Number."
- scale := aValue asPoint
+ aScale isNil ifTrue:[
+ scale := aScale
+ ] ifFalse:[
+ scale := aScale asPoint.
+ ].
!
scale
"return a copy of the Point that represents the
current scale of the receiver."
- scale == nil ifTrue:[
- ^ Point x:1 y:1
- ].
+ scale isNil ifTrue:[^ (1@1) copy].
^ scale copy
!
translation
"return a copy of the receiver's translation."
+ translation isNil ifTrue:[^ (0@0) copy].
^ translation copy
!
@@ -397,7 +590,7 @@
printOn:aStream
aStream nextPutAll:self class name.
aStream nextPutAll:' scale: '.
- scale printOn:aStream
+ scale printOn:aStream.
aStream nextPutAll:' translation: '.
translation printOn:aStream
! !