# lobby → traits → rectangle

```A rectangle is defined by two points making up opposing corners.
Make that a PAIR of points--incredibly useful-dmu```

CopyDowns: vector

CreatorPath: traits rectangle

Module: rectangle

 parent* = traits pair

### accessing

 bottom = `( corner y)` bottom: = `( copy corner: right @ n)` bottomCenter = `( (left mean: right) @ bottom)` bottomLeft = `( left @ bottom)` bottomLeft: = `( copy from: topRight To: pt)` bottomRight = `( corner)` bottomRight: = `( copy corner: pt)` center = `( (left mean: right) @ (top mean: bottom))` center: = `( center: pt Size: size)` left = `( origin x)` left: = `( copy origin: n @ top)` leftCenter = `( left @ (top mean: bottom))` right = `( corner x)` right: = `( copy corner: n @ bottom)` rightCenter = `( right @ (top mean: bottom))` top = `( origin y)` top: = `( copy origin: left @ n)` topCenter = `( (left mean: right) @ top)` topLeft = `( origin)` topLeft: = `( copy origin: pt)` topRight = `( right @ top)` topRight: = `( copy from: bottomLeft To: pt)`

### comparing

 = = `( r equalsRectangle: self)` equalsRectangle: = `( (origin = r origin) && [corner = r corner])`

### composing

 extend: = `( indent: n negate)` indent: = ```( ((origin x + n) @ (origin y + n)) # ((corner x - n) @ (corner y - n)))``` intersect: = ```( | b. l. r. t | l: left max: rect left. r: right min: rect right. t: top max: rect top. b: bottom min: rect bottom. (l >= r) || [t >= b] ifTrue: [ ^ (0@0) # (-1 @ -1) ]. (l @ t) # (r @ b))``` union: = `( (origin min: rect origin) # (corner max: rect corner))`

### creating

 center:Size: = ```( | or | or: c - (s / 2). from: or To: or + s)``` from:To: = ```( | r | r: copy. r origin: pt1 min: pt2. r corner: pt1 max: pt2. r)```

### filing out

 isImmutableForFilingOut = true storeStringWorks = true

### pairNess

 copyX:Y: = `( (copy origin: newX) corner: newY)` x = `( origin)` y = `( corner)`

### printing

 separator = ' # '

### sizing

 area = `( width * height)` height = `( bottom - top)` size = `( width @ height)` width = `( right - left)`

### stretching

 shrinkBottom: = `( origin # (corner subtractY: n))` shrinkBottomRight: = `( origin # (corner - p))` shrinkLeft: = `( (origin addX: n) # corner)` shrinkRight: = `( origin # (corner subtractX: n))` shrinkTop: = `( (origin addY: n) # corner)` shrinkTopLeft: = `( (origin + p) # corner)` stretchBottom: = `( origin # (corner addY: n))` stretchBottomRight: = `( origin # (corner + p))` stretchLeft: = `( (origin subtractX: n) # corner)` stretchRight: = `( origin # (corner addX: n))` stretchTop: = `( (origin subtractY: n) # corner)` stretchTopLeft: = `( (origin - p) # corner)`

### testing

 encloses: = ```( (left < rect left ) && [ (right > rect right) && [ (top < rect top ) && [ bottom > rect bottom ]]])``` enclosesOrEquals: = ```( (left <= rect left ) && [ (right >= rect right) && [ (top <= rect top ) && [ bottom >= rect bottom ]]])``` includes: = ```( (pt x >= left ) && [(pt x <= right) && [(pt y >= top ) && [ pt y <= bottom ]]])``` intersects: = ```( ((left max: rect left) <= (right min: rect right )) && [(top max: rect top ) <= (bottom min: rect bottom)])```

### translating

 translateBy: = `( copy from: origin + offset To: corner + offset)` translateTo: = `( copy from: pt To: pt + size)` move origin of rectangle to pt

### ui

 deltaList: = ```( | c | c: list copyRemoveAll. (intersects: rect) ifFalse: [ ^ c add: self ]. top < rect top ifTrue: [ c add: topLeft # (right @ rect top predecessor) ]. left < rect left ifTrue: [ c add: bottomLeft # (rect left predecessor @ (top max: rect top)) ]. right > rect right ifTrue: [ c add: (rect right successor @ (top max: rect top)) # bottomRight ]. bottom > rect bottom ifTrue: [ c add: ((left max: rect left) @ rect bottom successor) # ((right min: rect right) @ bottom) ]. c)``` return a list of rectangles composing the region the returned rectangles do not overlap rect. These methods may go better somewhere else, but I don't know where yet--dmu 2/91 pointClosestToPoint: = ```( | x. y | x: left > p x ifTrue: [ left ] False: [ right <= p x ifTrue: [ right ] False: [ p x ]]. y: top > p y ifTrue: [ top ] False: [ bottom <= p y ifTrue: [ bottom ] False: [ p y ]]. x @ y)``` pointClosestToRectangle: = ```( | x. y | x: left > r right ifTrue: [ left ] False: [ right <= r left ifTrue: [ right ] False: [ (left max: r left) mean: (right min: r right) ]]. y: top > r bottom ifTrue: [ top ] False: [ bottom <= r top ifTrue: [ bottom ] False: [ (top max: r top) mean: (bottom min: r bottom) ]]. x @ y)``` restrictTo: = ```( | x. y | x: case if: [ width >= enclosingRect width ] Then: [ enclosingRect center x - width half ] If: [ left < enclosingRect left ] Then: [ enclosingRect left ] If: [ right > enclosingRect right ] Then: [ enclosingRect right - width ] Else: [ left ]. y: case if: [ height >= enclosingRect height ] Then: [ enclosingRect center y - height half ] If: [ top < enclosingRect top ] Then: [ enclosingRect top ] If: [ bottom > enclosingRect bottom ] Then: [ enclosingRect bottom - height ] Else: [ top ]. translateTo: x @ y)``` Translate me if need be so I will not stick out from enclosingRect. If hopeless, center me. -- Ungar, 6/19/95 skippedAreaTo: = ```( "must not include x (new box)" ( isWestOf: x ) ifTrue: [ skippedAreaEastwardsTo: x ] False: [ (x isWestOf: self) ifTrue: [ skippedAreaWestwardsTo: x ] False: [ ( isNorthOf: x ) ifTrue: [ skippedAreaSouthwardsTo: x ] False: [ (x isNorthOf: self) ifTrue: [ skippedAreaNorthwardsTo: x ] False: [ vector]]]])``` isNorthOf: = `( (x top - top ) > 1)` isWestOf: = `( (x left - left) > 1)` skippedAreaEastwardsTo: = ```( | pts | " self is west of x, so go east to fill " ( isNorthOf: x ) ifTrue: [skippedAreaSEwardsTo: x] False: [ (x isNorthOf: self) ifTrue: [skippedAreaNEwardsTo: x] False: [ pts: vector copySize: 4. pts at: 0 Put: topLeft. pts at: 1 Put: bottomLeft. pts at: 2 Put: x bottomLeft. pts at: 3 Put: x topLeft. pts ]])``` skippedAreaNEwardsTo: = ```( | pts | pts: vector copySize: 6. pts at: 0 Put: topLeft. pts at: 1 Put: bottomLeft. pts at: 2 Put: bottomRight. pts at: 3 Put: x bottomRight + (0 @ 1). pts at: 4 Put: x bottomLeft + (0 @ 1). pts at: 5 Put: x topLeft + (0 @ 0). pts)``` return a polygon in between two rectangles for inserting motion blur. There are lots of +1 hacks to get around GX polygons skippedAreaNWwardsTo: = ```( | pts | pts: vector copySize: 6. pts at: 0 Put: topRight. pts at: 1 Put: bottomRight. pts at: 2 Put: bottomLeft. pts at: 3 Put: x bottomLeft + (0 @ 1). pts at: 4 Put: x bottomRight + (1 @ 1). pts at: 5 Put: x topRight + (1 @ 0). pts)``` skippedAreaNorthwardsTo: = ```( | pts | pts: vector copySize: 4. pts at: 0 Put: bottomLeft. pts at: 1 Put: bottomRight. pts at: 2 Put: x bottomRight + (0 @ 1). pts at: 3 Put: x bottomLeft + (0 @ 1). pts)``` skippedAreaSEwardsTo: = ```( | pts | pts: vector copySize: 6. pts at: 0 Put: bottomLeft. pts at: 1 Put: topLeft. pts at: 2 Put: topRight. pts at: 3 Put: x topRight. pts at: 4 Put: x topLeft. pts at: 5 Put: x bottomLeft. pts)``` skippedAreaSWwardsTo: = ```( | pts | pts: vector copySize: 6. pts at: 0 Put: bottomRight. pts at: 1 Put: topRight. pts at: 2 Put: topLeft. pts at: 3 Put: x topLeft + (1 @ 0). pts at: 4 Put: x topRight + (1 @ 0). pts at: 5 Put: x bottomRight + (1 @ 0). pts)``` skippedAreaSouthwardsTo: = ```( | pts | pts: vector copySize: 4. pts at: 0 Put: topLeft. pts at: 1 Put: topRight. pts at: 2 Put: x topRight. pts at: 3 Put: x topLeft. pts)``` skippedAreaWestwardsTo: = ```( | pts | " self is west of x, so go east to fill " ( isNorthOf: x ) ifTrue: [skippedAreaSWwardsTo: x] False: [ (x isNorthOf: self) ifTrue: [skippedAreaNWwardsTo: x] False: [ pts: vector copySize: 4. pts at: 0 Put: topRight. pts at: 1 Put: bottomRight. pts at: 2 Put: x bottomRight + (1 @ 0). pts at: 3 Put: x topRight + (1 @ 0). pts ]])```