'From Squeak3.9alpha of 4 July 2005 [latest update: #7001] on 23 February 2006 at 2:28:34 am'!
"Change Set: CurveBoundsTRFix-wiz
Date: 23 February 2006
Author: (wiz) Jerome Peace
wiz 2/23/2006 02:22
Rectangle and point methods needed to fix truncation and roundoff errors.
These are for now in catagory.
*Morphic-Truncation and Roundoff.
As a practical execise we fix the roundoff/truncation error in polygon computeBounds and curveBounds."!
!Point methodsFor: '*Morphic-Truncation and Roundoff' stamp: 'nice 2/5/2006 16:43'!
ceiling
"Answer a Point that is the receiver's x and y ceiling. Answer the receiver if its coordinates are already integral."
(x isInteger and: [y isInteger]) ifTrue: [^ self].
^ x ceiling @ y ceiling
! !
!Point methodsFor: '*Morphic-Truncation and Roundoff' stamp: 'nice 2/5/2006 16:43'!
floor
"Answer a Point that is the receiver's x and y floor. Answer the receiver if its coordinates are already integral."
(x isInteger and: [y isInteger]) ifTrue: [^ self].
^ x floor @ y floor
! !
!Point methodsFor: '*Morphic-Truncation and Roundoff' stamp: 'wiz 1/11/2006 18:32'!
isIntegerPoint
^ x isInteger and: [ y isInteger ] ! !
!Point methodsFor: '*Morphic-Truncation and Roundoff' stamp: 'nice 2/5/2006 16:42'!
roundDownTo: grid
"Answer a Point that is the receiver's x and y rounded to grid x and
grid y by lower value (toward negative infinity)."
| gridPoint |
gridPoint := grid asPoint.
^(x roundDownTo: gridPoint x) @ (y roundDownTo: gridPoint y)! !
!Point methodsFor: '*Morphic-Truncation and Roundoff' stamp: 'nice 2/5/2006 16:35'!
roundTo: grid
"Answer a Point that is the receiver's x and y rounded to grid x and
grid y."
| gridPoint |
gridPoint := grid asPoint.
^(x roundTo: gridPoint x) @ (y roundTo: gridPoint y)! !
!Point methodsFor: '*Morphic-Truncation and Roundoff' stamp: 'nice 2/5/2006 16:41'!
roundUpTo: grid
"Answer a Point that is the receiver's x and y rounded to grid x and
grid y by upper value (toward infinity)."
| gridPoint |
gridPoint := grid asPoint.
^(x roundUpTo: gridPoint x) @ (y roundUpTo: gridPoint y)! !
!PolygonMorph methodsFor: 'private' stamp: 'wiz 2/12/2006 00:04'!
computeBounds
| oldBounds delta excludeHandles |
vertices ifNil: [^ self].
self changed.
oldBounds _ bounds.
self releaseCachedState.
bounds _ self curveBounds expanded.
self arrowForms do:
[:f | bounds _ bounds merge: (f offset extent: f extent)].
handles ifNotNil: [self updateHandles].
"since we are directly updating bounds, see if any ordinary submorphs exist and move them accordingly"
(oldBounds notNil and: [(delta _ bounds origin - oldBounds origin) ~= (0@0)]) ifTrue: [
excludeHandles _ IdentitySet new.
handles ifNotNil: [excludeHandles addAll: handles].
self submorphsDo: [ :each |
(excludeHandles includes: each) ifFalse: [
each position: each position + delta
].
].
].
self layoutChanged.
self changed.
! !
!PolygonMorph methodsFor: 'private' stamp: 'wiz 2/12/2006 02:58'!
curveBounds
"Compute the bounds from actual curve traversal, with
leeway for borderWidth.
Also note the next-to-first and next-to-last points for arrow
directions."
"wiz - to avoid roundoff errors we return unrounded curvebounds."
"we expect our receiver to take responsibility for approriate rounding adjustment."
"hint: this is most likely 'self curveBounds expanded' "
| pointAfterFirst pointBeforeLast oX oY cX cY |
self isCurvy
ifFalse: [^ (Rectangle encompassing: vertices)
expandBy: borderWidth * 0.5 ].
curveState := nil.
"Force recomputation"
"curveBounds := vertices first corner: vertices last."
pointAfterFirst := nil.
self
lineSegmentsDo: [:p1 :p2 |
pointAfterFirst isNil
ifTrue: [pointAfterFirst := p2 floor .
oX := cX := p1 x.
oY := cY := p1 y. ].
"curveBounds := curveBounds encompass: p2 ."
oX:= oX min: p2 x.
cX := cX max: p2 x.
oY := oY min: p2 y.
cY := cY max: p2 y.
pointBeforeLast := p1 floor ].
curveState at: 2 put: pointAfterFirst.
curveState at: 3 put: pointBeforeLast.
^ ( oX @ oY corner: cX @ cY ) expandBy: borderWidth * 0.5 ! !
!Rectangle methodsFor: '*Morphic-Truncation and Roundoff' stamp: 'wiz 2/12/2006 15:58'!
ceiling
"Answer the integer rectange to the bottom right of receiver.
Return reciever if it already and integerRectange."
self isIntegerRectangle ifTrue: [ ^ self ] .
^origin ceiling corner: corner ceiling! !
!Rectangle methodsFor: '*Morphic-Truncation and Roundoff' stamp: 'wiz 2/12/2006 01:37'!
compressed
"Answer a Rectangle whose origin and corner are rounded to integers.
Rounding is done by upper value on origin and lower value on corner so that
rounded rectangle is inside self."
^Rectangle origin: origin ceiling corner: corner floor! !
!Rectangle methodsFor: '*Morphic-Truncation and Roundoff' stamp: 'wiz 2/12/2006 01:37'!
compressTo: grid
"Answer a Rectangle whose origin and corner are rounded to grid x and grid y.
Rounding is done by upper value on origin and lower value on corner so that
rounded rectangle is inside self."
^Rectangle origin: (origin roundUpTo: grid)
corner: (corner roundDownTo: grid)! !
!Rectangle methodsFor: '*Morphic-Truncation and Roundoff' stamp: 'nice 2/5/2006 16:52'!
expanded
"Answer a Rectangle whose origin and corner are rounded to integers.
Rounding is done by upper value on origin and lower value on corner so that
self is inside rounded rectangle."
^Rectangle origin: origin floor corner: corner ceiling! !
!Rectangle methodsFor: '*Morphic-Truncation and Roundoff' stamp: 'nice 2/5/2006 16:51'!
expandTo: grid
"Answer a Rectangle whose origin and corner are rounded to grid x and grid y.
Rounding is done by upper value on origin and lower value on corner so that
self is inside rounded rectangle."
^Rectangle origin: (origin roundDownTo: grid)
corner: (corner roundUpTo: grid)! !
!Rectangle methodsFor: '*Morphic-Truncation and Roundoff' stamp: 'wiz 2/12/2006 15:56'!
floor
"Answer the integer rectange to the topleft of receiver.
Return reciever if it already and integerRectange."
self isIntegerRectangle ifTrue: [ ^ self ] .
^origin floor corner: corner floor! !
!Rectangle methodsFor: '*Morphic-Truncation and Roundoff' stamp: 'wiz 1/11/2006 18:39'!
isIntegerRectangle
"Answer true if all component of receiver are integral."
^origin isIntegerPoint and: [ corner isIntegerPoint ]! !
!Rectangle methodsFor: '*Morphic-Truncation and Roundoff' stamp: 'nice 2/5/2006 16:53'!
roundTo: grid
"Answer a Rectangle whose origin and corner are rounded to grid x and grid y."
^Rectangle origin: (origin roundTo: grid)
corner: (corner roundTo: grid)! !