home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 3 / CDPDIII.bin / pd / programming / gnusmalltalk / contrib / rectangle.st < prev    next >
Text File  |  1992-02-15  |  9KB  |  348 lines

  1. "========================================================================
  2. |   Rectangle Class
  3.  ========================================================================
  4.  
  5. By Doug McCallum <uunet!ico.isc.com!dougm>
  6. "
  7.  
  8. "
  9. |     Change Log
  10. | ============================================================================
  11. | Author       Date       Change 
  12. | dougm         25 Apr 90      General cleanup of code - including some changes
  13. |                         recommended by sbyrne.
  14. |
  15. | dougm         19 Apr 90      Initial definitions for Rectangle class (needs Point)
  16. |
  17. "
  18.  
  19. Object subclass: #Rectangle
  20.        instanceVariableNames: 'origin corner'
  21.        classVariableNames: ''
  22.        poolDictionaries: ''
  23.        category: nil !
  24.  
  25. Rectangle comment:
  26. 'Beginning of the Rectangle class for simple display manipulation.
  27.  Rectangles require the Point class to be available.  An extension
  28.  to the Point class is made here that since it requires Rectangles
  29.  to be defined (see converting)' !
  30.  
  31. "VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV"
  32. !Number methodsFor: 'rectangle creation'!
  33.  
  34. asRectangle
  35.     ^(self asPoint) corner: self asPoint
  36. !!
  37. "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"
  38.  
  39. "VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV"
  40. !Point methodsFor: 'rectangle creation'!
  41.  
  42. corner: aPoint
  43.     ^Rectangle origin: self corner: aPoint
  44. !
  45.  
  46. extent: aPoint
  47.     ^Rectangle origin: self extent: aPoint
  48. !!
  49.  
  50. !Point methodsFor: 'rectangle conversion'!
  51.  
  52. asRectangle
  53.     ^self corner: self
  54. !!
  55. "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"
  56.  
  57. !Rectangle class methodsFor: 'instance creation'!
  58.  
  59. origin: originPoint corner: cornerPoint
  60.     ^self new origin: originPoint corner: cornerPoint
  61. !
  62.  
  63. origin: originPoint extent: extentPoint
  64.     ^self new origin: originPoint corner: (originPoint + extentPoint)
  65. !
  66.  
  67. left: leftNumber right: rightNumber top: topNumber bottom: bottomNumber
  68.     ^self new origin: (Point x: leftNumber y: topNumber)
  69.           corner: (Point x: rightNumber y: bottomNumber)
  70. !!
  71.  
  72. !Rectangle methodsFor: 'accessing'!
  73.  
  74. origin: originPoint corner: cornerPoint
  75.     origin _ originPoint.
  76.     corner _ cornerPoint
  77. !
  78.  
  79. origin
  80.     ^origin
  81. !
  82.  
  83. corner
  84.     ^corner
  85. !
  86.  
  87. topLeft
  88.     ^origin
  89. !
  90.  
  91. topCenter
  92.     ^Point x: ((origin x) + ((((corner x)-(origin x)))/2)) y: (origin y)
  93. !
  94.  
  95. topRight
  96.     ^Point x: (corner x) y: (origin y)
  97. !
  98.  
  99. rightCenter
  100.     ^Point x: (corner x) y: ((origin y) + ((((corner y)-(origin y)))/2))
  101. !
  102.  
  103. bottomCenter
  104.     ^Point x: ((origin x) + ((((corner x)-(origin x)))/2)) y: (corner y)
  105. !
  106.  
  107. bottomLeft
  108.     ^Point x: (origin x) y: (corner y)
  109. !
  110.  
  111. bottomRight
  112.     ^corner
  113. !
  114.  
  115. leftCenter
  116.     ^Point x: (origin x) y: ((origin y) + ((((corner y)-(origin y)))/2))
  117. !
  118.  
  119. center
  120.     ^Point x: ((origin x) + ((((corner x)-(origin x)))/2)) 
  121.            y: ((origin y) + ((((corner y)-(origin y)))/2))
  122. !
  123.  
  124. width
  125.     ^(corner x) - (origin x)
  126. !
  127.  
  128. area
  129.     ^ (self width) * (self height)
  130. !
  131.  
  132. height
  133.     ^(corner y) - (origin y)
  134. !
  135.  
  136. extent
  137.     ^Point x: (self width) y: (self height)
  138. !
  139.  
  140. top
  141.     ^(origin y)
  142. !
  143.  
  144. right
  145.     ^(corner x)
  146. !
  147.  
  148. bottom
  149.     ^(corner y)
  150. !
  151.  
  152. left
  153.     ^(origin x)
  154. !
  155. asRectangle
  156.     ^self
  157. !!
  158.  
  159. !Rectangle methodsFor: 'testing'!
  160.  
  161. containsPoint: aPoint
  162.     ^(origin < aPoint) and: [ (corner > aPoint) ]
  163. !
  164.  
  165. contains: aRectangle
  166.     ^(self containsPoint: (aRectangle origin)) 
  167.     and: [ (self containsPoint: (aRectangle corner)) ]
  168. !
  169.  
  170. intersects: aRectangle
  171.     ^(self containsPoint: aRectangle topLeft) or:
  172.     [(self containsPoint: aRectangle topRight) or:
  173.         [(self containsPoint: aRectangle bottomLeft) or:
  174.         [(self containsPoint: aRectangle bottomRight)]]]
  175. !!
  176.  
  177. !Rectangle methodsFor: 'rectangle functions'!
  178.  
  179. amountToTranslateWithin: aRectangle
  180.     ^(aRectangle origin)-origin
  181. !
  182.  
  183. "----------------------------------------------------------------
  184. |areasOutside: aRectangle
  185. | most complicated of the Rectangle primitives
  186. | The basic methodology is to first determine that there is an 
  187. | intersection by finding the overlapping rectangle.  From the
  188. | overlapping rectangle, first determine if it runs along an edge.
  189. | If it doesn't, extend the rectangle up to the top edge and add
  190. | the new rectangle to the collection and start the rest of the
  191. | process.  If the left edge does not touch the left edge of self,
  192. | extend it to the edge saving the new rectangle.  Then do the 
  193. | same to the right edge.  Then check top and bottom edges.  Most
  194. | of the time only 2 or 3 rectangles get formed, occasionally 4.
  195. | It should be possible to never get more than 3 but requires more
  196. | work.
  197.  ----------------------------------------------------------------"
  198.  
  199. areasOutside: aRectangle
  200.     | collect iRect tmp |
  201.     iRect _ self intersect: aRectangle.
  202.     (iRect = nil) ifTrue: [^nil]. "case of no intersection"
  203.                 "the collect collection gathers Rectangles"
  204.     collect _ OrderedCollection new: 4.
  205.                 "is it floating or on the edge?"
  206.     (((((iRect top) ~= self top) 
  207.      and: [ (iRect bottom) ~= self bottom ])
  208.      and: [ (iRect left) ~= self left ])
  209.      and: [ (iRect right) ~= self right ] )
  210.         ifTrue: "entirely in the center."
  211.         [tmp _ Rectangle origin: (Point x: iRect left y: self top)
  212.                  corner: iRect bottomRight.
  213.          collect add: tmp.
  214.          iRect _ iRect merge: tmp].
  215.     ((iRect left) ~= self left)
  216.     ifTrue:            "doesn't touch left edge so make it touch"
  217.         [tmp _ Rectangle origin: (Point x: self left y: iRect top)
  218.                  corner: iRect bottomLeft.
  219.          collect add: tmp.
  220.                 "merge new (tmp) with overlap to keep track"
  221.          iRect _ iRect merge: tmp].
  222.     ((iRect right) ~= self right)
  223.     ifTrue:            "doesn't touch right edge so extend it"
  224.         [tmp _ Rectangle origin: iRect topRight
  225.                  corner: (Point x: self right y: iRect bottom).
  226.          collect add: tmp.
  227.          iRect _ iRect merge: tmp].
  228.     (((iRect left) ~= self left) | ((iRect top) ~= self top))
  229.     ifTrue:            "whole top part can be taken now"
  230.         [tmp _ Rectangle origin: origin corner: iRect topRight.
  231.          collect add: tmp].
  232.     (((iRect right) ~= self right) | ((iRect bottom) ~= self bottom))
  233.     ifTrue:            "whole bottom open and can be taken"
  234.         [tmp _ Rectangle origin: iRect bottomLeft corner: corner.
  235.          collect add: tmp].
  236.     ^collect
  237. !
  238.  
  239. expandBy: delta
  240.     | newrect |
  241.     newrect _ delta asRectangle.
  242.     ^Rectangle origin: (origin-(newrect origin))
  243.            corner: (corner+(newrect corner))
  244. !
  245.  
  246. insetBy: delta
  247.     | newrect |
  248.     newrect _ delta asRectangle.
  249.     ^Rectangle origin: (origin+(newrect origin))
  250.            corner: (corner-(newrect corner))
  251. !
  252.  
  253. insetOriginBy: originDeltaPoint corner: cornerDeltaPoint
  254.     ^Rectangle origin: origin + originDeltaPoint
  255.            corner: corner + cornerDeltaPoint
  256. !
  257.  
  258. merge: aRectangle
  259.     | orig corn |
  260.     orig _ Point x: ((origin x) min: (aRectangle origin x))
  261.          y: ((origin y) min: (aRectangle origin y)).
  262.     corn _ Point x: ((corner x) max: (aRectangle corner x))
  263.          y: ((corner y) max: (aRectangle corner y)).
  264.     ^Rectangle origin: orig corner: corn
  265. !
  266.  
  267. "--------------------------------------------------------------
  268. | A intersect: B
  269. |   returns the rectangle (if any) created by the overlap of
  270. |   rectangles A and B.  There are 10 possible overlap situations:
  271. |       A inside B
  272. |       B inside A
  273. |       A overlaps B at one of the four corners (1 point inside)
  274. |       A overlaps B on one of the four sides (2 points inside)
  275.  ---------------------------------------------------------------"
  276.  
  277. intersect: aRectangle
  278.     (self contains: aRectangle) ifTrue: [^Rectangle origin: aRectangle origin
  279.                             corner: aRectangle corner].
  280.     (aRectangle contains: self)  ifTrue: [^Rectangle origin: origin 
  281.                                    corner: corner].
  282.     (self containsPoint: aRectangle topLeft)
  283.     ifTrue: [ (self containsPoint: aRectangle topRight)
  284.               ifTrue: [^Rectangle origin: aRectangle origin
  285.                       corner: (Point x: aRectangle corner x
  286.                                     y: corner y)]
  287.               ifFalse: [^Rectangle origin: aRectangle origin
  288.                        corner: corner]].
  289.     (self containsPoint: aRectangle topRight)
  290.     ifTrue: [^Rectangle origin: (Point x: origin x y: aRectangle origin y)
  291.                 corner: (Point x: aRectangle corner x y: corner y)].
  292.     (self containsPoint: aRectangle bottomLeft)
  293.     ifTrue: [ (self containsPoint: aRectangle bottomRight)
  294.               ifTrue: [^Rectangle origin: (Point x: aRectangle origin x 
  295.                              y: origin y)
  296.                       corner: aRectangle corner]
  297.               ifFalse: [^Rectangle origin: (Point x: aRectangle origin x
  298.                               y: origin y)
  299.                        corner: aRectangle corner]].
  300.     (self containsPoint: aRectangle bottomRight)
  301.     ifTrue: [^Rectangle origin: origin corner: aRectangle corner]
  302.     ifFalse: [^nil]
  303. !!
  304.  
  305. !Rectangle methodsFor: 'printing'!
  306.  
  307. printOn: aStream
  308.     origin printOn: aStream.
  309.     ' corner: ' printOn: aStream.
  310.     corner printOn: aStream
  311. !
  312.  
  313. storeOn: aStream
  314.     '(Rectangle origin: ' storeOn: aStream.
  315.     origin storeOn: aStream.
  316.     ' corner: ' storeOn: aStream.
  317.     corner storeOn: aStream.
  318.     ')' storeOn: aStream
  319. !!
  320.  
  321. !Rectangle methodsFor: 'truncation and round off'!
  322.  
  323. rounded
  324.     ^Rectangle origin: origin rounded corner: corner rounded
  325. !!
  326.  
  327. !Rectangle methodsFor: 'transforming'!
  328. moveBy: aPoint
  329.     origin _ origin + aPoint.
  330.     corner _ corner + aPoint
  331. !
  332.  
  333. moveTo: aPoint
  334.     | diff |
  335.     diff _ aPoint - origin.
  336.     origin _ aPoint.
  337.     corner _ corner + diff
  338. !
  339.  
  340. scaleBy: scale
  341.     ^Rectangle origin: origin * scale corner: corner * scale
  342. !
  343.  
  344. translateBy: factor
  345.     ^Rectangle origin: origin + factor corner: corner + factor
  346. !!
  347.  
  348.