"
COPYRIGHT (c) 1989 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.
"
Geometric subclass:#Rectangle
instanceVariableNames:'left top width height'
classVariableNames:''
poolDictionaries:''
category:'Graphics-Geometry'
!
!Rectangle class methodsFor:'documentation'!
copyright
"
COPYRIGHT (c) 1989 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.
"
!
documentation
"
Rectangles represent a rectangular area in 2D space.
notice, my implementation does not use origin/corner as instance objects
but left/top/width/height to save space and allocations. This means, that my
Rectangles cannot be used to represent Rectangles in a higher than 2D
space. (i.e. only valid if origin/corner are 2D Points)
(aside from that, you will not see any difference from the outside)
Instance variables:
left <Number> the left coordinate (i.e origin x)
top <Number> the top coordinate (i.e origin y)
width <Number> the width of the rectangle
height <Number> the height of the rectangle
I am not certain, if implementing Rectangle different was a good idea -
subclasses may expect things to be different ...
Therefore, this may change.
"
! !
!Rectangle class methodsFor:'instance creation'!
fromUser
"let user specify a rectangle on the screen, return it"
^ Screen current rectangleFromUser
"
Rectangle fromUser
"
!
left:left right:right top:top bottom:bottom
"create and return a new Rectangle giving left, top, right and bottom coordinates"
^ (self basicNew) left:left right:right top:top bottom:bottom
!
left:left top:top right:right bottom:bottom
"create and return a new Rectangle giving left, top, right and bottom coordinates"
^ (self basicNew) left:left top:top right:right bottom:bottom
!
left:left top:top width:w height:h
"create and return a new Rectangle giving left and top coordinates
and width, height"
%{ /* NOCONTEXT */
REGISTER OBJ newRect;
OBJ t;
int spc;
if (__CanDoQuickNew(OHDR_SIZE + 4*sizeof(OBJ))) {
if (self == Rectangle) {
/*
* short cut - rectangles are created so often ...
*/
__qCheckedAlignedNew(newRect, OHDR_SIZE + 4*sizeof(OBJ));
_InstPtr(newRect)->o_class = Rectangle;
_InstPtr(newRect)->i_instvars[0] = left;
_InstPtr(newRect)->i_instvars[1] = top;
_InstPtr(newRect)->i_instvars[2] = w;
_InstPtr(newRect)->i_instvars[3] = h;
if (! (__bothSmallInteger(left, top) &&
__bothSmallInteger(w, h))) {
spc = __qSpace(newRect);
__STORE_SPC(newRect, left, spc);
__STORE_SPC(newRect, top, spc);
__STORE_SPC(newRect, w, spc);
__STORE_SPC(newRect, h, spc);
}
RETURN ( newRect );
}
}
%}
.
^ (self basicNew) left:left top:top width:w height:h
!
origin:origin corner:corner
"create and return a new Rectangle giving top-left and bottom-right points"
^ (self basicNew) origin:origin corner:corner
!
origin:origin extent:extent
"create and return a new Rectangle giving top-left point and extent point"
%{ /* NOCONTEXT */
REGISTER OBJ newRect;
OBJ t;
int spc;
if (__CanDoQuickNew(OHDR_SIZE + 4*sizeof(OBJ))) {
/*
* short cut - rectangles are created so often ...
*/
if (self == Rectangle) {
if (__isPoint(origin) && __isPoint(extent)) {
__qCheckedAlignedNew(newRect, OHDR_SIZE + 4*sizeof(OBJ));
_InstPtr(newRect)->o_class = Rectangle;
spc = __qSpace(newRect);
t = _PointInstPtr(origin)->p_x;
_InstPtr(newRect)->i_instvars[0] = t;
__STORE_SPC(newRect, t, spc);
t = _PointInstPtr(origin)->p_y;
_InstPtr(newRect)->i_instvars[1] = t;
__STORE_SPC(newRect, t, spc);
t = _PointInstPtr(extent)->p_x;
_InstPtr(newRect)->i_instvars[2] = t;
__STORE_SPC(newRect, t, spc);
t = _PointInstPtr(extent)->p_y;
_InstPtr(newRect)->i_instvars[3] = t;
__STORE_SPC(newRect, t, spc);
RETURN ( newRect );
}
}
}
%}
.
^ (self basicNew) origin:origin extent:extent
! !
!Rectangle methodsFor:'accessing'!
area
"return the area
- for screen Rectangles this is the number of pixels"
^ width * height
!
bottom
"return the y coordinate of the bottom"
^ (top + height)
!
bottom:aNumber
"set the bottom edge"
height := aNumber - top
!
bottomCenter
"return the bottom center point"
^ (left + (width // 2)) @ (top + height)
!
bottomLeft
"return the bottom-left point"
^ left @ (top + height)
!
bottomRight
"return the bottom-right point"
^ (left + width) @ (top + height)
!
center
"return the point in the center of the receiver"
^ (left + (width // 2)) @ (top + (height // 2))
!
corner
"return the corner"
^ (left + width) @ (top + height)
!
corner:aPoint
"set the bottom-right corner"
width := aPoint x - left.
height := aPoint y - top
!
extent
"return the extent"
^ width @ height
!
extent:aPoint
"set the extent from the argument, aPoint with width taken from aPoint x
and height taken from aPoint y"
width := aPoint x.
height := aPoint y
!
height
"return the height of the rectangle"
^ height
!
left
"return the x-coordinate of the top-left origin"
^ left
!
left:aNumber
"set the left edge"
width := width + (left - aNumber).
left := aNumber
!
left:newLeft right:right top:newTop bottom:bottom
"set the rectangle given left, top, right and bottom coordinates."
left := newLeft.
top := newTop.
width := right - left.
height := bottom - top
!
left:newLeft top:newTop right:right bottom:bottom
"set the rectangle given left, top, right and bottom coordinates"
left := newLeft.
top := newTop.
width := right - left.
height := bottom - top
!
left:newLeft top:newTop width:newWidth height:newHeight
"set the rectangle given left, top coordinates and width, height"
left := newLeft.
top := newTop.
width := newWidth.
height := newHeight
!
leftCenter
"return the left center point"
^ left @ (top + (height // 2))
!
origin
"return the origin"
^ left @ top
!
origin:aPoint
"set the top-left origin. The corner remains unchanged."
|newTop newLeft|
newTop := aPoint y.
newLeft := aPoint x.
height := height + (top - newTop).
width := width + (left - newLeft).
left := newLeft.
top := newTop
!
origin:origin corner:corner
"set both origin and corner"
left := origin x.
top := origin y.
width := corner x - left.
height := corner y - top
!
origin:origin extent:extent
"set both origin and extent"
left := origin x.
top := origin y.
width := extent x.
height := extent y
!
right
"return the x coordinate of the right"
^ (left + width)
!
right:aNumber
"set the right edge"
width := aNumber - left
!
rightCenter
"return the right center point"
^ (left + width) @ (top + (height // 2))
!
top
"return the y-coordinate of the top-left"
^ top
!
top:aNumber
"set the top edge"
height := height + (top - aNumber).
top := aNumber
!
topCenter
"return the top center point"
^ (left + (width // 2)) @ top
!
topLeft
"return the top-left point - the same as origin"
^ left @ top
!
topLeft:aPoint
"Set the top and left edges.
The bottom right remains unchanged."
|newTop|
newTop := aPoint y.
height := height + (top - newTop).
top := newTop.
width := aPoint x - left
!
topRight
"return the top-right point"
^ (left + width) @ top
!
topRight:aPoint
"Set the top and right edges.
The bottom left remains unchanged."
|newTop|
newTop := aPoint y.
height := height + (top - newTop).
top := newTop.
width := aPoint x - left
!
width
"return the width of the rectangle"
^ width
! !
!Rectangle methodsFor:'comparing'!
= aRectangle
"return true, if the argument aRectangle represents the same
rectangle as the receiver"
%{ /* NOCONTEXT */
/*
* handle the common case quickly
*/
if (__isNonNilObject(aRectangle)
&& __qClass(aRectangle) == Rectangle) {
if ((_InstPtr(self)->i_instvars[0] == _InstPtr(aRectangle)->i_instvars[0])
&& (_InstPtr(self)->i_instvars[1] == _InstPtr(aRectangle)->i_instvars[1])
&& (_InstPtr(self)->i_instvars[2] == _InstPtr(aRectangle)->i_instvars[2])
&& (_InstPtr(self)->i_instvars[3] == _InstPtr(aRectangle)->i_instvars[3])) {
RETURN ( true );
}
if (__bothSmallInteger(_InstPtr(self)->i_instvars[0], _InstPtr(aRectangle)->i_instvars[0])
&& __bothSmallInteger(_InstPtr(self)->i_instvars[1], _InstPtr(aRectangle)->i_instvars[1])
&& __bothSmallInteger(_InstPtr(self)->i_instvars[2], _InstPtr(aRectangle)->i_instvars[2])
&& __bothSmallInteger(_InstPtr(self)->i_instvars[3], _InstPtr(aRectangle)->i_instvars[3])) {
RETURN ( false );
}
}
%}
.
(aRectangle species ~~ self species) ifTrue:[^ false].
left = aRectangle left ifFalse:[^ false].
top = aRectangle top ifFalse:[^ false].
width = aRectangle width ifFalse:[^ false].
height = aRectangle height ifFalse:[^ false].
^ true
!
hash
"return an integer useful for hashing -
redefined since = is redefined here"
^ ((left hash bitShift:16) bitXor:(top hash bitShift:16))
+ ((width hash) bitXor:(height hash))
! !
!Rectangle methodsFor:'converting'!
asFractionalLayout
"return a layoutFrame in which fractions (top, left, bottom, right)
are taken from corresponding edges of the receiver.
You have to make certain that those are in 0..1."
|l|
l := LayoutFrame new.
l
leftFraction:(self left);
rightFraction:(self right);
topFraction:(self top);
bottomFraction:(self bottom).
^ l
"
(0.5@0.5 corner:0.75@0.75) asFractionalLayout
(0.5@0.5 corner:0.75@0.75) asOffsetLayout
(0.5@0.5 corner:0.75@0.75) asLayout
"
!
asLayout
"return a layoutFrame in which offsets (top, left, bottom, right)
are taken from corresponding edges of the receiver.
If all values are between 0..1, a fractionalLayout is created,
otherwise, an offsetLayout"
|l left right top bot|
l := LayoutFrame new.
left := (self left).
right := (self right).
top := (self top).
bot := (self bottom).
((left between:0 and:1)
and:[(right between:0 and:1)
and:[(top between:0 and:1)
and:[(bot between:0 and:1)]]]) ifTrue:[
l
leftFraction:left;
rightFraction:right;
topFraction:top;
bottomFraction:bot.
] ifFalse:[
l
leftOffset:left;
rightFraction:0 offset:right;
topOffset:top;
bottomFraction:0 offset:bot.
].
^ l
"
(0.5@0.5 corner:0.75@0.75) asFractionalLayout
(0.5@0.5 corner:0.75@0.75) asOffsetLayout
(0.5@0.5 corner:0.75@0.75) asLayout
(0@0 corner:1@1) asLayout
(0@0 corner:1@1) asFractionalLayout
(0@0 corner:1@1) asOffsetLayout
"
!
asOffsetLayout
"return a layoutFrame in which offsets (top, left, bottom, right)
are taken from corresponding edges of the receiver.
You have to make certain that those are in 0..1."
|l|
l := LayoutFrame new.
l
leftOffset:(self left);
rightFraction:0 offset:(self right);
topOffset:(self top);
bottomFraction:0 offset:(self bottom).
^ l
"
(0.5@0.5 corner:0.75@0.75) asFractionalLayout
(0.5@0.5 corner:0.75@0.75) asOffsetLayout
(0.5@0.5 corner:0.75@0.75) asLayout
(10@10 corner:20@20) asFractionalLayout
(10@10 corner:20@20) asOffsetLayout
(10@10 corner:20@20) asLayout
"
!
asPointArray
"return an array containing my corners (clockwise) and
the origin again as 5th element. Can be used to convert
a rectangle into a polygon."
|org|
^ Array with:(org := self origin)
with:self topRight
with:self corner
with:self bottomLeft
with:org
"
(10@10 corner:100@100) asPointArray
"
!
fromLiteralArrayEncoding:encoding
"read my values from an encoding.
The encoding is supposed to be of the form: (Rectangle orgX orgY cornX cornY)"
left := encoding at:2.
top := encoding at:3.
width := (encoding at:4) - left.
height := (encoding at:5) - top
"
Rectangle new fromLiteralArrayEncoding:#(Rectangle 100 200 300 500)
"
!
literalArrayEncoding
"encode myself as an array.
The encoding is: (Rectangle orgX orgY cornX cornY)"
^ Array
with:#Rectangle
with:left
with:top
with:width
with:height
"
Rectangle new fromLiteralArrayEncoding:#(Rectangle 100 200 300 500)
(100@200 corner:300@500) literalArrayEncoding
"
"Modified: 1.9.1995 / 02:16:54 / claus"
!
rectangleRelativeTo:aRectangle preferred:prefRect
"compute a displayRectangle, treating the receiver like a
layoutorigin. This allows point to be used interchangable with
LayoutOrigins."
^ (self asLayout) rectangleRelativeTo:aRectangle preferred:prefRect
"
(10@20 corner:20@30) rectangleRelativeTo:(0@0 corner:100@100) preferred:(0@0 corner:50@50)
(0.5@0.5) rectangleRelativeTo:(0@0 corner:100@100) preferred:(0@0 corner:50@50)
"
! !
!Rectangle methodsFor:'destructive rectangle operations'!
expandBy:delta
"destructively expanded the receiver in all directions
by amount, a Point, Rectangle or Number.
Warning: this is a destructive operation, modifying the receiver
NOT returning a copy. You have to be certain to be the exclusive
owner of the receiver to avoid side effects. See also: #expandedBy:"
|amountPoint deltaLeft deltaTop deltaWidth deltaHeight|
delta isNumber ifTrue:[
deltaLeft := deltaTop := delta.
deltaWidth := deltaHeight := delta * 2.
] ifFalse:[
delta isRectangle ifTrue:[
deltaLeft := delta left.
deltaTop := delta top.
deltaWidth := deltaLeft + delta right.
deltaHeight := deltaTop + delta bottom
] ifFalse:[
amountPoint := delta asPoint.
deltaLeft := amountPoint x.
deltaTop := amountPoint y.
deltaWidth := deltaLeft * 2.
deltaHeight := deltaTop * 2.
]
].
left := (left - deltaLeft).
top := (top - deltaTop).
width := (width + deltaWidth).
height := (height + deltaHeight).
"
|r|
r := Rectangle origin:10@10 corner:100@100.
r expandBy:5.
r := Rectangle origin:10@10 corner:100@100.
r expandBy:(5 @ 0).
r := Rectangle origin:10@10 corner:100@100.
r expandBy:(10 @ 10).
r := Rectangle origin:10@10 corner:100@100.
r expandBy:( 10@10 corner:20@20 )
"
!
moveBy:aPoint
"destructively translate the rectangle by some distance.
sorry for the name inconsistency - but GNU-ST named it that way"
left := left + aPoint x.
top := top + aPoint y
!
moveTo:aPoint
"destructively translate the rectangle to have its origin at aPoint."
|diff|
diff := aPoint - self origin.
self origin:aPoint corner:self corner + diff
!
scaleBy:scale
"scale the receiver rectangle by scale (a Number or Point).
This is destructive (modifies the receiver, not a copy) and
should only be used if you know, that you are the exclusive owner
of the receiver. (use scaledBy if in doubt)"
|scalePoint sx sy|
(scale isMemberOf:Point) ifTrue:[ "type hint to stc"
sx := scale x.
sy := scale y
] ifFalse:[
scalePoint := scale asPoint.
sx := scalePoint x.
sy := scalePoint y
].
width := width * sx.
height := height * sy.
left := left * sx.
top := top * sy
"
(Rectangle origin:10@10 corner:50@50) scaleBy:2
"
"its destructive:"
"
|r1 r2|
r1 := Rectangle origin:10@10 corner:50@50.
r2 := r1 scaleBy:2.
r1
"
!
translateBy:amount
"translate (i.e. move) the receiver rectangle
by amount, a Point or Number.
This is destructive (modifies the receiver, not a copy) and
should only be used if you know, that you are the exclusive owner
of the receiver. (use translatedBy if in doubt)"
|amountPoint|
(amount isMemberOf:Point) ifTrue:[ "type hint to stc"
left := left + amount x.
top := top + amount y
] ifFalse:[
amountPoint := amount asPoint.
left := left + amountPoint x.
top := top + amountPoint y
]
"
(Rectangle origin:10@10 corner:50@50) translateBy:10
"
"its destructive:"
"
|r1 r2|
r1 := Rectangle origin:10@10 corner:50@50.
r2 := r1 translateBy:10.
r1
"
! !
!Rectangle methodsFor:'displaying'!
displayFilledOn:aGC
aGC fillRectangleX:left y:top width:width height:height
"
|v|
v := View new open.
[v shown] whileFalse:[Processor yield].
(Rectangle origin:10@10 corner:50@50) displayFilledOn:v
"
!
displayStrokedOn:aGC
aGC displayRectangleX:left y:top width:width height:height
"
|v|
v := View new open.
[v shown] whileFalse:[Processor yield].
(Rectangle origin:10@10 corner:50@50) displayStrokedOn:v
"
! !
!Rectangle methodsFor:'printing & storing'!
printOn:aStream
"print the receiver on aStream"
aStream nextPutAll:(self class name).
aStream nextPutAll:' origin:'.
(self origin) printOn:aStream.
aStream nextPutAll:' corner:'.
(self corner) printOn:aStream
!
storeOn:aStream
"store the receiver on aStream; i.e. print an expression which will
reconstruct the receiver"
aStream nextPut:$(.
aStream nextPutAll:(self class name).
aStream nextPutAll:' origin:'.
(self origin) storeOn:aStream.
aStream nextPutAll:' corner:'.
(self corner) storeOn:aStream.
aStream nextPut:$)
! !
!Rectangle methodsFor:'queries'!
isRectangle
"return true, if the receiver is some kind of rectangle"
^ true
! !
!Rectangle methodsFor:'rectangle operations'!
+ aPoint
"return a new rectangle with same extent as receiver but
origin translated by the argument, aPoint"
|amountPoint|
amountPoint := aPoint asPoint.
^ Rectangle left:(left + amountPoint x)
top:(top + amountPoint y)
width:width
height:height
!
align:offset with:someCoordinate
"return a new rectangle which is translated (i.e. moved)
such that the point offset in mySelf is placed on someCoordinate."
^ Rectangle origin:(someCoordinate - offset + self origin)
extent:(self extent)
"
|r|
r := Rectangle origin:10@10 corner:50@50.
r align:(r center) with:100@100.
"
!
amountToTranslateWithin: aRectangle
"for GNU-ST compatibility"
^(aRectangle origin) - self origin
!
areasOutside: aRectangle
"----------------------------------------------------------------
| added for GNU-ST compatibility
|
| author: Doug McCallum <uunet!!ico.isc.com!!dougm>
|
|areasOutside: aRectangle
| most complicated of the Rectangle primitives
| The basic methodology is to first determine that there is an
| intersection by finding the overlapping rectangle. From the
| overlapping rectangle, first determine if it runs along an edge.
| If it doesn't, extend the rectangle up to the top edge and add
| the new rectangle to the collection and start the rest of the
| process. If the left edge does not touch the left edge of self,
| extend it to the edge saving the new rectangle. Then do the
| same to the right edge. Then check top and bottom edges. Most
| of the time only 2 or 3 rectangles get formed, occasionally 4.
| It should be possible to never get more than 3 but requires more
| work.
----------------------------------------------------------------"
| collect iRect tmp |
iRect := self intersect: aRectangle.
(iRect = nil) ifTrue: [^nil]. "case of no intersection"
"the collect collection gathers Rectangles"
collect := OrderedCollection new: 4.
"is it floating or on the edge?"
(((((iRect top) ~= self top)
and: [ (iRect bottom) ~= self bottom ])
and: [ (iRect left) ~= self left ])
and: [ (iRect right) ~= self right ] )
ifTrue: "entirely in the center."
[tmp := Rectangle origin: (Point x: iRect left y: self top)
corner: iRect bottomRight.
collect add: tmp.
iRect := iRect merge: tmp].
((iRect left) ~= self left)
ifTrue: "doesn't touch left edge so make it touch"
[tmp := Rectangle origin: (Point x: self left y: iRect top)
corner: iRect bottomLeft.
collect add: tmp.
"merge new (tmp) with overlap to keep track"
iRect := iRect merge: tmp].
((iRect right) ~= self right)
ifTrue: "doesn't touch right edge so extend it"
[tmp := Rectangle origin: iRect topRight
corner: (Point x: self right y: iRect bottom).
collect add: tmp.
iRect := iRect merge: tmp].
(((iRect left) ~= self left) or: [(iRect top) ~= self top])
ifTrue: "whole top part can be taken now"
[tmp := Rectangle origin: self origin corner: iRect topRight.
collect add: tmp].
(((iRect right) ~= self right) or: [(iRect bottom) ~= self bottom])
ifTrue: "whole bottom open and can be taken"
[tmp := Rectangle origin: iRect bottomLeft corner: self corner.
collect add: tmp].
^collect
!
expandedBy:delta
"return a new rectangle which is expanded in all directions
by amount, a Point, Rectangle or Number"
^ self copy expandBy:delta
"
|r|
r := Rectangle origin:10@10 corner:100@100.
r expandedBy:5.
r expandedBy:(5 @ 0).
r expandedBy:(10 @ 10).
r expandedBy:( 10@10 corner:20@20 )
"
!
insetBy: delta
"return a new rectangle which is inset in all directions
by delta, a Point, Rectangle or Number"
|amountPoint deltaLeft deltaTop deltaWidth deltaHeight|
delta isNumber ifTrue:[
deltaLeft := deltaTop := delta.
deltaWidth := deltaHeight := delta * 2.
] ifFalse:[
delta isRectangle ifTrue:[
deltaLeft := delta left.
deltaTop := delta top.
deltaWidth := deltaLeft + delta right.
deltaHeight := deltaTop + delta bottom
] ifFalse:[
amountPoint := delta asPoint.
deltaLeft := amountPoint x.
deltaTop := amountPoint y.
deltaWidth := deltaLeft * 2.
deltaHeight := deltaTop * 2.
]
].
^ Rectangle left:(left + deltaLeft)
top:(top + deltaTop)
width:(width - deltaWidth)
height:(height - deltaHeight)
"
|r|
r := Rectangle origin:10@10 corner:100@100.
r insetBy:5.
r insetBy:(5 @ 0).
r insetBy:(10 @ 10).
r insetBy:( 10@10 corner:20@20 )
"
!
insetOriginBy:originDelta cornerBy:cornerDelta
"return a new rectangle which is inset by originDelta
and cornerDelta; both may be instances of Point or Number"
^ Rectangle
origin:(left @ top) + originDelta asPoint
corner:(self corner - cornerDelta asPoint)
"
|r|
r := Rectangle origin:10@10 corner:100@100.
r insetOriginBy:5 cornerBy:10.
r insetOriginBy:10@5 cornerBy:10.
r insetOriginBy:10 cornerBy:10@5.
r insetOriginBy:10@10 cornerBy:20@20.
"
!
intersect:aRectangle
"return a new rectangle covering the intersection of the receiver
and the argument, aRectangle.
the rectangles must intersect for a valid return"
^ Rectangle left:(left max:(aRectangle left))
right:((left + width) min:(aRectangle right))
top:(top max:(aRectangle top))
bottom:((top + height) min:(aRectangle bottom))
"
|r1 r2|
r1 := Rectangle origin:10@10 corner:100@100.
r2 := Rectangle origin:50@50 corner:150@75.
r1 intersect:r2
"
!
merge:aRectangle
"return a new rectangle covering both the receiver
and the argument, aRectangle"
^ Rectangle left:(left min:(aRectangle left))
right:((left + width) max:(aRectangle right))
top:(top min:(aRectangle top))
bottom:((top + height) max:(aRectangle bottom))
!
nonIntersections:aRectangle
"this is the same as areasOutside: - for ST/V compatibility only"
^ self areasOutside:aRectangle
!
rounded
"return a copy of the receiver with rounded coordinates"
^ Rectangle left:(left rounded)
top:(top rounded)
width:(width rounded)
height:(height rounded)
!
scaledBy:scale
"return a new rectangle which is the receiver
scaled by scale"
|scalePoint sx sy|
scalePoint := scale asPoint.
sx := scalePoint x.
sy := scalePoint y.
^ Rectangle left:left * sx
top:top * sy
width:(width * sx)
height:(height * sy)
"
(Rectangle origin:10@10 corner:50@50) scaledBy:2
"
"its NOT destructive:"
"
|r1 r2|
r1 := Rectangle origin:10@10 corner:50@50.
r2 := r1 scaledBy:2.
r1
"
!
translatedBy:amount
"return a new rectangle which is translated (i.e. moved)
by amount, aPoint or Number"
|amountPoint|
amountPoint := amount asPoint.
^ Rectangle left:(left + amountPoint x)
top:(top + amountPoint y)
width:width
height:height
"
(Rectangle origin:10@10 corner:50@50) translatedBy:10
"
"its NOT destructive:"
"
|r1 r2|
r1 := Rectangle origin:10@10 corner:50@50.
r2 := r1 translatedBy:10.
r1
"
! !
!Rectangle methodsFor:'testing'!
contains:aRectangle
"return true, if the argument, aRectangle is equal to or
is contained fully within the receiver"
(left <= aRectangle left) ifTrue:[
((left + width) >= aRectangle right) ifTrue:[
(top <= aRectangle top) ifTrue:[
((top + height) >= aRectangle bottom) ifTrue:[
^ true
]
]
]
].
^ false
!
containsPoint:aPoint
"return true, if the argument, aPoint is contained in the receiver"
|px py|
px := aPoint x.
(px < left) ifTrue:[^ false].
(px > (left + width)) ifTrue:[^ false].
py := aPoint y.
(py < top) ifTrue:[^ false].
(py > (top + height)) ifTrue:[^ false].
^ true
!
containsPointX:x y:y
"return true, if the point defined by x@y is contained in the receiver.
This is the same as containsPoint:, but can be used if the coordinates
are already available as separate numbers to avoid useless creation of a
temporary point."
(x < left) ifTrue:[^ false].
(x > (left + width)) ifTrue:[^ false].
(y < top) ifTrue:[^ false].
(y > (top + height)) ifTrue:[^ false].
^ true
!
intersects:aRectangle
"return true, if the intersection between the argument, aRectangle
and the receiver is not empty"
|b r|
(aRectangle right) < left ifTrue:[^ false].
(aRectangle bottom) < top ifTrue:[^ false].
r := left + width.
(aRectangle left) > r ifTrue:[^ false].
b := top + height.
(aRectangle top) > b ifTrue:[^ false].
^ true
!
isContainedIn:aRectangle
"return true, if the receiver is fully contained within
the argument, aRectangle"
(aRectangle left <= left) ifTrue:[
(aRectangle right >= (left + width)) ifTrue:[
(aRectangle top <= top) ifTrue:[
(aRectangle bottom >= (top + height)) ifTrue:[
^ true
]
]
]
].
^ false
! !
!Rectangle class methodsFor:'documentation'!
version
^ '$Header: /cvs/stx/stx/libbasic/Rectangle.st,v 1.31 1996-01-15 22:55:37 cg Exp $'
! !