Point.st
changeset 1 a27a279701f8
child 2 6526dde5f3ac
equal deleted inserted replaced
0:aa2498ef6470 1:a27a279701f8
       
     1 "
       
     2  COPYRIGHT (c) 1989-93 by Claus Gittinger
       
     3               All Rights Reserved
       
     4 
       
     5  This software is furnished under a license and may be used
       
     6  only in accordance with the terms of that license and with the
       
     7  inclusion of the above copyright notice.   This software may not
       
     8  be provided or otherwise made available to, or used by, any
       
     9  other person.  No title to or ownership of the software is
       
    10  hereby transferred.
       
    11 "
       
    12 
       
    13 ArithmeticValue subclass:#Point
       
    14        instanceVariableNames:'x y'
       
    15        classVariableNames:'PointZero PointOne'
       
    16        poolDictionaries:''
       
    17        category:'Graphics-Primitives'
       
    18 !
       
    19 
       
    20 Point comment:'
       
    21 
       
    22 COPYRIGHT (c) 1989-93 by Claus Gittinger
       
    23               All Rights Reserved
       
    24 
       
    25 I represent a point in 2D space. Or I can be used to represent
       
    26 an extent (of a rectangle for example), in which case my x-coordinate 
       
    27 represents the width, and y-coordinate the height of something.
       
    28 
       
    29 The x and y coordinate are usually numbers.
       
    30 
       
    31 Instance variables:
       
    32 
       
    33 x              <Number>        the x-coordinate of myself
       
    34 y              <Number>        the y-coordinate of myself
       
    35 
       
    36 %W% %E%
       
    37 written 89 by claus
       
    38 '!
       
    39 
       
    40 !Point class methodsFor:'initialization'!
       
    41 
       
    42 initialize
       
    43     PointZero := 0 @ 0.
       
    44     PointOne  := 1 @ 1
       
    45 ! !
       
    46 
       
    47 !Point class methodsFor:'constants'!
       
    48 
       
    49 zero
       
    50     ^ PointZero
       
    51 !
       
    52 
       
    53 unity
       
    54     ^ PointOne
       
    55 ! !
       
    56 
       
    57 !Point class methodsFor:'instance creation'!
       
    58 
       
    59 x:newX y:newY
       
    60     "create and return a new point with coordinates newX and newY"
       
    61 
       
    62 %{  /* NOCONTEXT */
       
    63     extern char *newNextPtr, *newEndPtr;
       
    64 
       
    65     if (self == Point) {
       
    66         if (_CanDoQuickNew(sizeof(struct point))) {
       
    67             OBJ newPoint;
       
    68 
       
    69             _qCheckedAlignedNew(newPoint, sizeof(struct point), __context);
       
    70             _InstPtr(newPoint)->o_class = Point;
       
    71             _PointInstPtr(newPoint)->p_x = newX;
       
    72             _PointInstPtr(newPoint)->p_y = newY;
       
    73 	    /* no store check needed - its definitely in newSpace */
       
    74             RETURN ( newPoint );
       
    75         }
       
    76     }
       
    77 %}
       
    78 .
       
    79     ^ (self basicNew) x:newX y:newY
       
    80 !
       
    81 
       
    82 readFrom:aStream
       
    83     "return the next Point from the (character-)stream aStream;
       
    84      skipping all whitespace first; return nil if no point"
       
    85 
       
    86     |newX newY|
       
    87 
       
    88     newX := Number readFrom:aStream.
       
    89     newX isNil ifTrue:[^ nil].
       
    90     (aStream skipSeparators ~~ $@) ifTrue:[^nil].
       
    91     aStream next.
       
    92     newY := Number readFrom:aStream.
       
    93     newY isNil ifTrue:[^ nil].
       
    94     ^ (self basicNew) x:newX y:newY
       
    95 ! !
       
    96 
       
    97 !Point methodsFor:'accessing'!
       
    98 
       
    99 x
       
   100     "return the x coordinate"
       
   101 
       
   102     ^x
       
   103 !
       
   104 
       
   105 y
       
   106     "return the y coordinate"
       
   107 
       
   108     ^y
       
   109 !
       
   110 
       
   111 x:newX
       
   112     "set the x coordinate to be the argument, aNumber"
       
   113 
       
   114     x := newX
       
   115 !
       
   116 
       
   117 y:newY
       
   118     "set the y coordinate to be the argument, aNumber"
       
   119 
       
   120     y := newY
       
   121 !
       
   122 
       
   123 x:newX y:newY
       
   124     "set both the x and y coordinates"
       
   125 
       
   126     x := newX.
       
   127     y := newY
       
   128 ! !
       
   129 
       
   130 !Point methodsFor:'comparing'!
       
   131 
       
   132 hash
       
   133     "return a number for hashing"
       
   134 
       
   135     ^ (x hash) bitXor:(y hash)
       
   136 !
       
   137 
       
   138 < aPoint
       
   139     "return true if the receiver is above and to the left
       
   140      of the argument, aPoint"
       
   141 
       
   142     |p|
       
   143 
       
   144     p := aPoint asPoint.
       
   145     x >= (p x) ifTrue:[^ false].
       
   146     y >= (p y) ifTrue:[^ false].
       
   147     ^ true
       
   148 !
       
   149 
       
   150 > aPoint
       
   151     "return true if  the receiver is below and to the right
       
   152      of the argument, aPoint"
       
   153 
       
   154     |p|
       
   155 
       
   156     p := aPoint asPoint.
       
   157     x <= (p x) ifTrue:[^ false].
       
   158     y <= (p y) ifTrue:[^ false].
       
   159     ^ true
       
   160 !
       
   161 
       
   162 = aPoint
       
   163     "return true if the receiver represents the same point as
       
   164      the argument, aPoint"
       
   165 
       
   166     |p|
       
   167 
       
   168     (aPoint isMemberOf:Point) ifTrue:[
       
   169 	x ~~ (aPoint x) ifTrue:[^ false].
       
   170 	y ~~ (aPoint y) ifTrue:[^ false].
       
   171 	^ true
       
   172     ].
       
   173     aPoint respondsToArithmetic ifFalse:[ ^ false].
       
   174     p := aPoint asPoint.
       
   175     x ~~ (p x) ifTrue:[^ false].
       
   176     y ~~ (p y) ifTrue:[^ false].
       
   177     ^ true
       
   178 !
       
   179 
       
   180 max:aPoint
       
   181     "return the lower right corner of the rectangle uniquely defined by
       
   182      the receiver and the argument, aPoint"
       
   183 
       
   184     |p maxX maxY|
       
   185 
       
   186     p := aPoint asPoint.
       
   187     maxX := x max:(p x).
       
   188     maxY := y max:(p y).
       
   189     ^ maxX @ maxY
       
   190 !
       
   191 
       
   192 min:aPoint
       
   193     "return the upper left corner of the rectangle uniquely defined by
       
   194      the receiver and the argument, aPoint"
       
   195 
       
   196     |p minX minY|
       
   197 
       
   198     p := aPoint asPoint.
       
   199     minX := x min:(p x).
       
   200     minY := y min:(p y).
       
   201     ^ minX @ minY
       
   202 ! !
       
   203 
       
   204 !Point methodsFor:'converting'!
       
   205 
       
   206 generality
       
   207     ^ 120
       
   208 !
       
   209 
       
   210 coerce:anObject
       
   211     ^ anObject asPoint
       
   212 !
       
   213 
       
   214 asPoint
       
   215     "return the receiver as Point - this is the receiver"
       
   216 
       
   217     ^ self
       
   218 !
       
   219 
       
   220 asRectangle
       
   221     "return a zero-width rectangle consisting of origin 
       
   222      and corner beeing the receiver"
       
   223 
       
   224     ^ self corner:self
       
   225 ! !
       
   226 
       
   227 !Point methodsFor:'creating rectangles'!
       
   228 
       
   229 corner:aPoint
       
   230     "return a rectangle whose origin is self and corner is aPoint"
       
   231 
       
   232     ^ Rectangle origin:self corner:aPoint
       
   233 !
       
   234 
       
   235 extent:aPoint
       
   236     "return a rectangle whose origin is self and extent is aPoint"
       
   237 
       
   238     ^ Rectangle origin:self extent:aPoint
       
   239 ! !
       
   240 
       
   241 !Point methodsFor:'transformations'!
       
   242 
       
   243 + scale 
       
   244     "Return a new Point that is the sum of the 
       
   245      receiver and scale (which is a Point or Number)."
       
   246 
       
   247     |scalePoint|
       
   248 
       
   249     scalePoint := scale asPoint.
       
   250     ^ (x + scalePoint x) @ (y + scalePoint y)
       
   251 !
       
   252 
       
   253 - scale 
       
   254     "Return a new Point that is the difference of the 
       
   255      receiver and scale (which is a Point or Number)."
       
   256 
       
   257     |scalePoint|
       
   258 
       
   259     scalePoint := scale asPoint.
       
   260     ^ (x - scalePoint x) @ (y - scalePoint y)
       
   261 !
       
   262 
       
   263 * scale 
       
   264     "Return a new Point that is the product of the 
       
   265      receiver and scale (which is a Point or Number)."
       
   266 
       
   267     |scalePoint|
       
   268 
       
   269     scalePoint := scale asPoint.
       
   270     ^ (x * scalePoint x) @ (y * scalePoint y)
       
   271 !
       
   272 
       
   273 / scale 
       
   274     "Return a new Point that is the integer quotient of the 
       
   275      receiver and scale (which is a Point or Number)."
       
   276 
       
   277     |scalePoint|
       
   278 
       
   279     scalePoint := scale asPoint.
       
   280     ^ (x / scalePoint x) @ (y / scalePoint y)
       
   281 !
       
   282 
       
   283 // scale 
       
   284     "Return a new Point that is the quotient of the 
       
   285      receiver and scale (which is a Point or Number)."
       
   286 
       
   287     |scalePoint|
       
   288 
       
   289     scalePoint := scale asPoint.
       
   290     ^ (x // scalePoint x) @ (y // scalePoint y)
       
   291 !
       
   292 
       
   293 reciprocal
       
   294     "return a new point where the coordinates are
       
   295      the reciproce of mine"
       
   296 
       
   297     ^ (1 / x) @ (1 / y)
       
   298 !
       
   299 
       
   300 negated
       
   301     "return a new point with my coordinates negated i.e.
       
   302      the receiver mirrored at the origin"
       
   303 
       
   304     ^ (x negated) @ (y negated)
       
   305 !
       
   306 
       
   307 scaleBy:aScale
       
   308     "Return a new Point that is the product of the 
       
   309      receiver and scale (which is a Point or Number)."
       
   310 
       
   311     ^ self * aScale
       
   312 !
       
   313 
       
   314 translateBy:anOffset
       
   315     "Return a new Point that is the sum of the 
       
   316      receiver and scale (which is a Point or Number)."
       
   317 
       
   318     ^ self + anOffset
       
   319 ! !
       
   320 
       
   321 !Point methodsFor:'misc'!
       
   322 
       
   323 dist:aPoint 
       
   324     "return the distance between aPoint and the receiver."
       
   325 
       
   326     ^ (aPoint - self) r
       
   327 !
       
   328 
       
   329 dotProduct:aPoint 
       
   330     "return a Number that is the dot product of the receiver and
       
   331      the argument, aPoint.  That is, the two points are
       
   332      multipled and the coordinates of the result summed."
       
   333 
       
   334     |temp|
       
   335 
       
   336     temp := self * aPoint.
       
   337     ^ temp x abs + temp y abs
       
   338 !
       
   339 
       
   340 r
       
   341     "return the receiver's radius in polar coordinate system."
       
   342 
       
   343     ^ (self dotProduct:self) sqrt
       
   344 !
       
   345 
       
   346 abs
       
   347     "return a new point with my coordinates taken from the absolute values"
       
   348 
       
   349     ^ (x abs) @ (y abs)
       
   350 !
       
   351 
       
   352 truncated
       
   353     "return a new point with my coordinates truncated as integer"
       
   354 
       
   355     ^ (x truncated) @ (y truncated)
       
   356 !
       
   357 
       
   358 rounded
       
   359     "return a new point with my coordinates rounded to the next integer
       
   360      coordinated (use for gridding)"
       
   361 
       
   362     ^ (x rounded) @ (y rounded)
       
   363 !
       
   364 
       
   365 grid:gridPoint
       
   366     "return a new point with coordinates grided (i.e. rounded to the
       
   367      nearest point on the grid)"
       
   368 
       
   369     |newX newY gridX gridY|
       
   370 
       
   371     gridX := gridPoint x.
       
   372     (gridX <= 1) ifTrue:[
       
   373         newX := x asInteger
       
   374     ] ifFalse:[
       
   375         newX := ((x + (gridX // 2)) // gridX) * gridX
       
   376     ].
       
   377     gridY := gridPoint y.
       
   378     (gridY <= 1) ifTrue:[
       
   379         newY := y asInteger
       
   380     ] ifFalse:[
       
   381         newY := ((y + (gridY // 2)) // gridY) * gridY
       
   382     ].
       
   383     ^ newX @ newY
       
   384 ! !
       
   385 
       
   386 !Point methodsFor:'printing & storing'!
       
   387 
       
   388 printString
       
   389     "return my printString"
       
   390 
       
   391     ^ x printString , '@' , y printString
       
   392 !
       
   393 
       
   394 storeString
       
   395     "return my storeString"
       
   396 
       
   397     ^ self printString
       
   398 ! !