"
COPYRIGHT (c) 1989-93 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.
"
ArithmeticValue subclass:#Point
instanceVariableNames:'x y'
classVariableNames:'PointZero PointOne'
poolDictionaries:''
category:'Graphics-Primitives'
!
Point comment:'
COPYRIGHT (c) 1989-93 by Claus Gittinger
All Rights Reserved
I represent a point in 2D space. Or I can be used to represent
an extent (of a rectangle for example), in which case my x-coordinate
represents the width, and y-coordinate the height of something.
The x and y coordinate are usually numbers.
Instance variables:
x <Number> the x-coordinate of myself
y <Number> the y-coordinate of myself
%W% %E%
written 89 by claus
'!
!Point class methodsFor:'initialization'!
initialize
PointZero := 0 @ 0.
PointOne := 1 @ 1
! !
!Point class methodsFor:'constants'!
zero
^ PointZero
!
unity
^ PointOne
! !
!Point class methodsFor:'instance creation'!
x:newX y:newY
"create and return a new point with coordinates newX and newY"
%{ /* NOCONTEXT */
extern char *newNextPtr, *newEndPtr;
if (self == Point) {
if (_CanDoQuickNew(sizeof(struct point))) {
OBJ newPoint;
_qCheckedAlignedNew(newPoint, sizeof(struct point), __context);
_InstPtr(newPoint)->o_class = Point;
_PointInstPtr(newPoint)->p_x = newX;
_PointInstPtr(newPoint)->p_y = newY;
/* no store check needed - its definitely in newSpace */
RETURN ( newPoint );
}
}
%}
.
^ (self basicNew) x:newX y:newY
!
readFrom:aStream
"return the next Point from the (character-)stream aStream;
skipping all whitespace first; return nil if no point"
|newX newY|
newX := Number readFrom:aStream.
newX isNil ifTrue:[^ nil].
(aStream skipSeparators ~~ $@) ifTrue:[^nil].
aStream next.
newY := Number readFrom:aStream.
newY isNil ifTrue:[^ nil].
^ (self basicNew) x:newX y:newY
! !
!Point methodsFor:'accessing'!
x
"return the x coordinate"
^x
!
y
"return the y coordinate"
^y
!
x:newX
"set the x coordinate to be the argument, aNumber"
x := newX
!
y:newY
"set the y coordinate to be the argument, aNumber"
y := newY
!
x:newX y:newY
"set both the x and y coordinates"
x := newX.
y := newY
! !
!Point methodsFor:'comparing'!
hash
"return a number for hashing"
^ (x hash) bitXor:(y hash)
!
< aPoint
"return true if the receiver is above and to the left
of the argument, aPoint"
|p|
p := aPoint asPoint.
x >= (p x) ifTrue:[^ false].
y >= (p y) ifTrue:[^ false].
^ true
!
> aPoint
"return true if the receiver is below and to the right
of the argument, aPoint"
|p|
p := aPoint asPoint.
x <= (p x) ifTrue:[^ false].
y <= (p y) ifTrue:[^ false].
^ true
!
= aPoint
"return true if the receiver represents the same point as
the argument, aPoint"
|p|
(aPoint isMemberOf:Point) ifTrue:[
x ~~ (aPoint x) ifTrue:[^ false].
y ~~ (aPoint y) ifTrue:[^ false].
^ true
].
aPoint respondsToArithmetic ifFalse:[ ^ false].
p := aPoint asPoint.
x ~~ (p x) ifTrue:[^ false].
y ~~ (p y) ifTrue:[^ false].
^ true
!
max:aPoint
"return the lower right corner of the rectangle uniquely defined by
the receiver and the argument, aPoint"
|p maxX maxY|
p := aPoint asPoint.
maxX := x max:(p x).
maxY := y max:(p y).
^ maxX @ maxY
!
min:aPoint
"return the upper left corner of the rectangle uniquely defined by
the receiver and the argument, aPoint"
|p minX minY|
p := aPoint asPoint.
minX := x min:(p x).
minY := y min:(p y).
^ minX @ minY
! !
!Point methodsFor:'converting'!
generality
^ 120
!
coerce:anObject
^ anObject asPoint
!
asPoint
"return the receiver as Point - this is the receiver"
^ self
!
asRectangle
"return a zero-width rectangle consisting of origin
and corner beeing the receiver"
^ self corner:self
! !
!Point methodsFor:'creating rectangles'!
corner:aPoint
"return a rectangle whose origin is self and corner is aPoint"
^ Rectangle origin:self corner:aPoint
!
extent:aPoint
"return a rectangle whose origin is self and extent is aPoint"
^ Rectangle origin:self extent:aPoint
! !
!Point methodsFor:'transformations'!
+ scale
"Return a new Point that is the sum of the
receiver and scale (which is a Point or Number)."
|scalePoint|
scalePoint := scale asPoint.
^ (x + scalePoint x) @ (y + scalePoint y)
!
- scale
"Return a new Point that is the difference of the
receiver and scale (which is a Point or Number)."
|scalePoint|
scalePoint := scale asPoint.
^ (x - scalePoint x) @ (y - scalePoint y)
!
* scale
"Return a new Point that is the product of the
receiver and scale (which is a Point or Number)."
|scalePoint|
scalePoint := scale asPoint.
^ (x * scalePoint x) @ (y * scalePoint y)
!
/ scale
"Return a new Point that is the integer quotient of the
receiver and scale (which is a Point or Number)."
|scalePoint|
scalePoint := scale asPoint.
^ (x / scalePoint x) @ (y / scalePoint y)
!
// scale
"Return a new Point that is the quotient of the
receiver and scale (which is a Point or Number)."
|scalePoint|
scalePoint := scale asPoint.
^ (x // scalePoint x) @ (y // scalePoint y)
!
reciprocal
"return a new point where the coordinates are
the reciproce of mine"
^ (1 / x) @ (1 / y)
!
negated
"return a new point with my coordinates negated i.e.
the receiver mirrored at the origin"
^ (x negated) @ (y negated)
!
scaleBy:aScale
"Return a new Point that is the product of the
receiver and scale (which is a Point or Number)."
^ self * aScale
!
translateBy:anOffset
"Return a new Point that is the sum of the
receiver and scale (which is a Point or Number)."
^ self + anOffset
! !
!Point methodsFor:'misc'!
dist:aPoint
"return the distance between aPoint and the receiver."
^ (aPoint - self) r
!
dotProduct:aPoint
"return a Number that is the dot product of the receiver and
the argument, aPoint. That is, the two points are
multipled and the coordinates of the result summed."
|temp|
temp := self * aPoint.
^ temp x abs + temp y abs
!
r
"return the receiver's radius in polar coordinate system."
^ (self dotProduct:self) sqrt
!
abs
"return a new point with my coordinates taken from the absolute values"
^ (x abs) @ (y abs)
!
truncated
"return a new point with my coordinates truncated as integer"
^ (x truncated) @ (y truncated)
!
rounded
"return a new point with my coordinates rounded to the next integer
coordinated (use for gridding)"
^ (x rounded) @ (y rounded)
!
grid:gridPoint
"return a new point with coordinates grided (i.e. rounded to the
nearest point on the grid)"
|newX newY gridX gridY|
gridX := gridPoint x.
(gridX <= 1) ifTrue:[
newX := x asInteger
] ifFalse:[
newX := ((x + (gridX // 2)) // gridX) * gridX
].
gridY := gridPoint y.
(gridY <= 1) ifTrue:[
newY := y asInteger
] ifFalse:[
newY := ((y + (gridY // 2)) // gridY) * gridY
].
^ newX @ newY
! !
!Point methodsFor:'printing & storing'!
printString
"return my printString"
^ x printString , '@' , y printString
!
storeString
"return my storeString"
^ self printString
! !