Rect
Contents
Definition
A rect is a list-like object with four numerical parameters, used to define a 2D rect.
Theory
A rectangle is defined by the coordinates of its left, top, right and bottom sides, in that order. Vertical co-ordinates increase from top to bottom. (In 3D co-ordinates, the y value increases from bottom to top). The values are expected to be integers:
rect(left, top, right, bottom) rect(point(left, top), point(right, bottom))
Practice
It is possible to create a rect which does not adhere to this strict definition. Director will accept these unorthodox rects, in other cases it will produce unexpected results.
- Floating point values
vRect1 = rect(0.5, 0.5, 10.5, 10.5) put vRect1 -- rect(0.5000, 0.5000, 10.5000, 10.5000) put vRect1.width -- 10
put rect(10, 20, 40, 80) / 3.0 -- rect(3.3333, 6.6667, 13.3333, 26.6667)
- Reversed top/bottom or left/right
vRect2 = rect(point(10, 10), point(0, 0)) put vRect2 -- rect(10, 10, 0, 0) put vRect2.width -- -10
Properties
rects have the following properties:
- left
- top
- right
- bottom
- width
- height
The fastest method for testing whether a rect is equal to rect(0, 0, 0, 0) is to test its width and height:
vRect1 = rect(10, 20, 30, 40) vRect2 = rect(0, 0, 10, 10)
vIntersect = vRect1.intersect(vRect2)
if vIntersect.width and vIntersect.height then -- The two rects intersect else -- There is no intersection end if
Methods
You can use the following methods with rects. values are reversed: They will all round floating point values to the nearest integer. Those marked with an asterisk may all produce unexpected output values if the top and bottom or left and right are reversed.
Because it rounds to integers, the map() method is not accurate. Inversing the operation may not return the starting rect. See the entry for map() for a more accurate method.
You can also use certain list operations on rects:
vRect = rect(-10, 10, 20 , 40) put vRect.getAt(2) -- 10
put vRect.getLast() -- 40
put vRect.min() -- -10
Additional Methods
The following method scales one rect so that it fits inside another. This can be useful for displaying images of various dimensions inside a fixed-size area, at the optimum size.
on FitToRect(aSourceRect, aTargetRect) ------------------------------- -- INPUT: <aSourceRect> and <aTargetRect> should both be rects -- OUTPUT: Returns the largest rect with the same proportions as -- aSourceRect which fits inside aTargetRect. The output -- rect will be centered with respect to aTargetRect. -- NOTE: The elements of the output rect may be floating point -- numbers. Subsequent rect operations such as inflate() -- offset() or map() will round these elements to integers. -------------------------------------------------------------------- vLeft = aTargetRect.left vTop = aTargetRect.top vRight = aTargetRect.right vBottom = aTargetRect.bottom vWidth = vRight - vLeft vHeight = vBottom - vTop vTargetRatio = vWidth / float(vHeight) vSourceRatio = aSourceRect.width / float(aSourceRect.height) if vTargetRatio > vSourceRatio then vAdjust = (vWidth - vHeight * vSourceRatio) / 2 vLeft = vLeft + vAdjust vRight = vRight - vAdjust else vAdjust = (vHeight - vWidth / vSourceRatio) / 2 vTop = vTop + vAdjust vBottom = vBottom - vTop end if vRect = rect(vLeft, vTop, vRight, vBottom) return vRect end FitToRect
The following methods align a rect with another rect or with a point.
on RectAlign( aRect, aBaseRect, aSymMode ) --------------------------- -- INPUT: <aRect> and <aBaseRect> must be rect objects -- <aSymMode> may be an optional mode symbol: -- #centerH | #centerV | #leftEdge | #topEdge | -- #rightEdge | #bottomEdge -- If none of these symbols is given #center is assumed. -- OUTPUT: Returns a rect with the same dimensions as aRect, -- aligned to <aBaseRect> in <aSymMode>. Rect values are -- rounded to the nearest integer. -------------------------------------------------------------------- case aSymMode of #leftEdge: vOffset = aBaseRect.left - aRect.left vOutput = aRect.offset(vOffset, 0) #topEdge: vOffset = aBaseRect.top - aRect.top vOutput = aRect.offset(0, vOffset) #rightEdge: vOffset = aBaseRect.right - aRect.right vOutput = aRect.offset(vOffset, 0) #bottomEdge: vOffset = aBaseRect.bottom - aRect.bottom vOutput = aRect.offset(0, vOffset) #centerH: vCenterH = (aBaseRect.left + aBaseRect.right) / 2 vCenterV = (aRect.top + aRect.bottom) / 2 vCenter = point(vCenterH, vCenterV) vOutput = RectAroundCenter(aRect, vCenter) #centerV: vCenterH = (aRect.left + aRect.right) / 2 vCenterV = (aBaseRect.top + aBaseRect.bottom) / 2 vCenter = point(vCenterH, vCenterV) vOutput = RectAroundCenter(aRect, vCenter) otherwise: -- center vCenter = RectCenter(aBaseRect) vOutput = RectAroundCenter(aRect, vCenter) end case return vOutput end RectAlign
on RectAroundCenter(aRect, aPoint) ----------------------------------- -- INPUT: <aRect> must be a rect object -- <aPoint> must be a point object -- OUTPUT: Returns a rect with the same dimensions as aRect, -- centered on aPoint. The rect will extend one pixel more -- to the right or bottom than to the left and top if its -- width or height is an odd number of pixels. -------------------------------------------------------------------- vWidth = aRect.width vHeight = aRect.height vLeft = aPoint.locH - vWidth / 2 vTop = aPoint.locV - vHeight / 2 vRight = vLeft + vWidth vBottom = vTop + vHeight vOutput = rect(vLeft, vTop, vRight, vBottom) return vOutput end RectAroundCenter
The following method returns the center of a rect using the nearest integer values.
on RectCenter(aRect) ------------------------------------------------- -- INPUT: <aRect> must be a rect object -- OUTPUT: Returns the center point of a rect, rounded to the -- nearest integer -------------------------------------------------------------------- vCenterH = (aRect.left + aRect.right) / 2 vCenterV = (aRect.top + aRect.bottom) / 2 vCenter = point(vCenterH, vCenterV) return vCenter end RectCenter
See also
- the deskTopRectList()
- window sourceRect
- window drawRect
- quad