1
0
Prechádzať zdrojové kódy

Merge branch 'add-math' of stevenremot/amber into master

Herby Vojčík 7 rokov pred
rodič
commit
7a6e319a6d
5 zmenil súbory, kde vykonal 1497 pridanie a 8 odobranie
  1. 28 0
      API-CHANGES.txt
  2. 685 0
      src/Kernel-Objects.js
  3. 143 0
      src/Kernel-Objects.st
  4. 564 7
      src/Kernel-Tests.js
  5. 77 1
      src/Kernel-Tests.st

+ 28 - 0
API-CHANGES.txt

@@ -48,6 +48,34 @@
   + basicOrganization:
 + UndefinedObject >>
   + ==
++ Number >>
+  + min:max:
+  + degreesToRadians
+  + radiansToDegrees
+  + arcTan:
+  + between:and:
++ Number class >>
+  + radiansPerDegree
++ Point >>
+  + dotProduct:
+  + normal
+  + angle
+  + normalized
+  + r
+  + corner:
+  + extent:
+  + rectangle:
++ Rectangle >>
+  + =
+  + corner
+  + origin
+  + containsPoint:
+  + containsRect:
+  + printOn:
++ Rectangle class >>
+  + origin:corner:
+  + origin:extent:
+  + point:point:
 
 - Package >>
   - basicName:

+ 685 - 0
src/Kernel-Objects.js

@@ -3616,6 +3616,30 @@ messageSends: []
 }),
 $globals.Number);
 
+$core.addMethod(
+$core.method({
+selector: "arcTan:",
+protocol: "mathematical functions",
+fn: function(aNumber){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return Math.atan2(self, aNumber);;
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"arcTan:",{aNumber:aNumber},$globals.Number)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aNumber"],
+source: "arcTan: aNumber\x0a\x09<inlineJS: 'return Math.atan2(self, aNumber);'>",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: []
+}),
+$globals.Number);
+
 $core.addMethod(
 $core.method({
 selector: "asJavaScriptObject",
@@ -3750,6 +3774,37 @@ messageSends: ["+", "truncated", "*", "next", "new"]
 }),
 $globals.Number);
 
+$core.addMethod(
+$core.method({
+selector: "between:and:",
+protocol: "testing",
+fn: function(min,max){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $recv($self.__gt_eq(min))._and_((function(){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+return $self.__lt_eq(max);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)});
+//>>excludeEnd("ctx");
+}));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"between:and:",{min:min,max:max},$globals.Number)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["min", "max"],
+source: "between: min and: max\x0a ^ self >= min and: [ self <= max ]",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["and:", ">=", "<="]
+}),
+$globals.Number);
+
 $core.addMethod(
 $core.method({
 selector: "ceiling",
@@ -3839,6 +3894,29 @@ messageSends: ["copy"]
 }),
 $globals.Number);
 
+$core.addMethod(
+$core.method({
+selector: "degreesToRadians",
+protocol: "converting",
+fn: function(){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $self.__star($recv($globals.Number)._radiansPerDegree());
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"degreesToRadians",{},$globals.Number)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "degreesToRadians\x0a\x09^ self * Number radiansPerDegree",
+referencedClasses: ["Number"],
+//>>excludeEnd("ide");
+messageSends: ["*", "radiansPerDegree"]
+}),
+$globals.Number);
+
 $core.addMethod(
 $core.method({
 selector: "even",
@@ -4065,6 +4143,29 @@ messageSends: []
 }),
 $globals.Number);
 
+$core.addMethod(
+$core.method({
+selector: "min:max:",
+protocol: "arithmetic",
+fn: function(aMin,aMax){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $recv($self._min_(aMin))._max_(aMax);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"min:max:",{aMin:aMin,aMax:aMax},$globals.Number)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aMin", "aMax"],
+source: "min: aMin max: aMax\x0a\x09^ (self min: aMin) max: aMax",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["max:", "min:"]
+}),
+$globals.Number);
+
 $core.addMethod(
 $core.method({
 selector: "negated",
@@ -4205,6 +4306,29 @@ messageSends: []
 }),
 $globals.Number);
 
+$core.addMethod(
+$core.method({
+selector: "radiansToDegrees",
+protocol: "converting",
+fn: function(){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $self.__slash($recv($globals.Number)._radiansPerDegree());
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"radiansToDegrees",{},$globals.Number)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "radiansToDegrees\x0a\x09^ self / Number radiansPerDegree",
+referencedClasses: ["Number"],
+//>>excludeEnd("ide");
+messageSends: ["/", "radiansPerDegree"]
+}),
+$globals.Number);
+
 $core.addMethod(
 $core.method({
 selector: "raisedTo:",
@@ -4815,6 +4939,29 @@ messageSends: []
 }),
 $globals.Number.a$cls);
 
+$core.addMethod(
+$core.method({
+selector: "radiansPerDegree",
+protocol: "instance creation",
+fn: function(){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $recv($self._pi()).__slash((180));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"radiansPerDegree",{},$globals.Number.a$cls)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "radiansPerDegree\x0a\x09^ (self pi) / 180",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["/", "pi"]
+}),
+$globals.Number.a$cls);
+
 
 $core.addClass("Point", $globals.Object, ["x", "y"], "Kernel-Objects");
 //>>excludeStart("ide", pragmas.excludeIdeData);
@@ -5217,6 +5364,29 @@ messageSends: ["and:", ">=", "x", "y"]
 }),
 $globals.Point);
 
+$core.addMethod(
+$core.method({
+selector: "angle",
+protocol: "geometry",
+fn: function(){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $recv($self._y())._arcTan_($self._x());
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"angle",{},$globals.Point)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "angle\x0a\x09^ self y arcTan: self x",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["arcTan:", "y", "x"]
+}),
+$globals.Point);
+
 $core.addMethod(
 $core.method({
 selector: "asPoint",
@@ -5235,6 +5405,29 @@ messageSends: []
 }),
 $globals.Point);
 
+$core.addMethod(
+$core.method({
+selector: "corner:",
+protocol: "rectangle creation",
+fn: function(aPoint){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $recv($globals.Rectangle)._origin_corner_(self,aPoint);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"corner:",{aPoint:aPoint},$globals.Point)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aPoint"],
+source: "corner: aPoint\x0a\x09^ Rectangle origin: self corner: aPoint",
+referencedClasses: ["Rectangle"],
+//>>excludeEnd("ide");
+messageSends: ["origin:corner:"]
+}),
+$globals.Point);
+
 $core.addMethod(
 $core.method({
 selector: "dist:",
@@ -5270,6 +5463,145 @@ messageSends: ["-", "x", "y", "sqrt", "+", "*"]
 }),
 $globals.Point);
 
+$core.addMethod(
+$core.method({
+selector: "dotProduct:",
+protocol: "point functions",
+fn: function(aPoint){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $1;
+$1=$recv($self["@x"]).__star($recv(aPoint)._x());
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["*"]=1;
+//>>excludeEnd("ctx");
+return $recv($1).__plus($recv($self["@y"]).__star($recv(aPoint)._y()));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"dotProduct:",{aPoint:aPoint},$globals.Point)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aPoint"],
+source: "dotProduct: aPoint\x0a\x09^ (x * aPoint x) + (y * aPoint y)",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["+", "*", "x", "y"]
+}),
+$globals.Point);
+
+$core.addMethod(
+$core.method({
+selector: "extent:",
+protocol: "rectangle creation",
+fn: function(aPoint){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $recv($globals.Rectangle)._origin_extent_(self,aPoint);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"extent:",{aPoint:aPoint},$globals.Point)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aPoint"],
+source: "extent: aPoint\x0a\x09^ Rectangle origin: self extent: aPoint",
+referencedClasses: ["Rectangle"],
+//>>excludeEnd("ide");
+messageSends: ["origin:extent:"]
+}),
+$globals.Point);
+
+$core.addMethod(
+$core.method({
+selector: "normal",
+protocol: "point functions",
+fn: function(){
+var self=this,$self=this;
+var n,d;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $4,$3,$6,$5,$2,$1;
+n=$recv($recv($self["@y"])._negated()).__at($self["@x"]);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["@"]=1;
+//>>excludeEnd("ctx");
+$4=$recv(n)._x();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["x"]=1;
+//>>excludeEnd("ctx");
+$3=$recv($4).__star($recv(n)._x());
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["*"]=1;
+//>>excludeEnd("ctx");
+$6=$recv(n)._y();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["y"]=1;
+//>>excludeEnd("ctx");
+$5=$recv($6).__star($recv(n)._y());
+d=$recv($3).__plus($5);
+$2=d;
+$1=$recv($2).__eq((0));
+if($core.assert($1)){
+return (-1).__at((0));
+}
+return $recv(n).__slash($recv(d)._sqrt());
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"normal",{n:n,d:d},$globals.Point)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "normal\x0a\x09\x22Answer a Point representing the unit vector rotated 90 deg clockwise. For the zero point return -1@0.\x22\x0a\x0a\x09| n d |\x0a\x09n := y negated @ x.\x0a\x09(d := (n x * n x + (n y * n y))) = 0\x0a\x09\x09 ifTrue: [ ^ -1 @0 ].\x0a\x09^ n / d sqrt",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["@", "negated", "ifTrue:", "=", "+", "*", "x", "y", "/", "sqrt"]
+}),
+$globals.Point);
+
+$core.addMethod(
+$core.method({
+selector: "normalized",
+protocol: "point functions",
+fn: function(){
+var self=this,$self=this;
+var r;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $1,$2,$3;
+r=$self._r();
+$1=$recv(r).__eq((0));
+if($core.assert($1)){
+$2=$recv($globals.Point)._x_y_((0),(0));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["x:y:"]=1;
+//>>excludeEnd("ctx");
+return $2;
+} else {
+$3=$recv($self["@x"]).__slash(r);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["/"]=1;
+//>>excludeEnd("ctx");
+return $recv($globals.Point)._x_y_($3,$recv($self["@y"]).__slash(r));
+}
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"normalized",{r:r},$globals.Point)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "normalized\x0a\x09| r |\x0a\x09r := self r.\x0a\x09\x0a\x09r = 0\x0a\x09\x09ifTrue: [ ^ Point x: 0 y: 0 ]\x0a\x09\x09ifFalse: [ ^ Point x: x / r y: y / r ]",
+referencedClasses: ["Point"],
+//>>excludeEnd("ide");
+messageSends: ["r", "ifTrue:ifFalse:", "=", "x:y:", "/"]
+}),
+$globals.Point);
+
 $core.addMethod(
 $core.method({
 selector: "printOn:",
@@ -5312,6 +5644,58 @@ messageSends: ["printOn:", "nextPutAll:", "ifTrue:", "and:", "notNil", "negative
 }),
 $globals.Point);
 
+$core.addMethod(
+$core.method({
+selector: "r",
+protocol: "polar coordinates",
+fn: function(){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $2,$1;
+$2=$recv($self["@x"]).__star($self["@x"]);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["*"]=1;
+//>>excludeEnd("ctx");
+$1=$recv($2).__plus($recv($self["@y"]).__star($self["@y"]));
+return $recv($1)._sqrt();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"r",{},$globals.Point)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "r\x0a\x09^ ((x * x) + (y * y)) sqrt",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["sqrt", "+", "*"]
+}),
+$globals.Point);
+
+$core.addMethod(
+$core.method({
+selector: "rectangle:",
+protocol: "rectangle creation",
+fn: function(aPoint){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $recv($globals.Rectangle)._point_point_(self,aPoint);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"rectangle:",{aPoint:aPoint},$globals.Point)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aPoint"],
+source: "rectangle: aPoint\x0a\x09^ Rectangle point: self point: aPoint",
+referencedClasses: ["Rectangle"],
+//>>excludeEnd("ide");
+messageSends: ["point:point:"]
+}),
+$globals.Point);
+
 $core.addMethod(
 $core.method({
 selector: "translateBy:",
@@ -5522,6 +5906,307 @@ $globals.Random);
 
 
 
+$core.addClass("Rectangle", $globals.Object, ["origin", "corner"], "Kernel-Objects");
+//>>excludeStart("ide", pragmas.excludeIdeData);
+$globals.Rectangle.comment="I represent a Rectangle defined by my two corners.\x0a\x0aThe simplest way to create an instance is using Point methods:\x0a\x0a    1@1 corner: 2@2\x0a\x0aWIll create a rectangle with 1@1 as the top left and 2@2 at the bottom right.\x0a\x0a    1@1 extent: 1@1\x0a\x0aWill create the same rectangle, defining an origin and a size instead of an origin and a corner.";
+//>>excludeEnd("ide");
+$core.addMethod(
+$core.method({
+selector: "=",
+protocol: "testing",
+fn: function(aRectangle){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $1;
+$1=$recv($self["@origin"]).__eq($recv(aRectangle)._origin());
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["="]=1;
+//>>excludeEnd("ctx");
+return $recv($1)._and_((function(){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+return $recv($self["@corner"]).__eq($recv(aRectangle)._corner());
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)});
+//>>excludeEnd("ctx");
+}));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"=",{aRectangle:aRectangle},$globals.Rectangle)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aRectangle"],
+source: "= aRectangle\x0a\x09^ origin = aRectangle origin and: [ corner = aRectangle corner ]",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["and:", "=", "origin", "corner"]
+}),
+$globals.Rectangle);
+
+$core.addMethod(
+$core.method({
+selector: "containsPoint:",
+protocol: "testing",
+fn: function(aPoint){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $recv($recv($self["@origin"]).__lt_eq(aPoint))._and_((function(){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+return $recv($self["@corner"]).__gt_eq(aPoint);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)});
+//>>excludeEnd("ctx");
+}));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"containsPoint:",{aPoint:aPoint},$globals.Rectangle)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aPoint"],
+source: "containsPoint: aPoint\x0a\x09^ origin <= aPoint and: [ corner >= aPoint ]",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["and:", "<=", ">="]
+}),
+$globals.Rectangle);
+
+$core.addMethod(
+$core.method({
+selector: "containsRect:",
+protocol: "testing",
+fn: function(aRect){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $recv($recv($recv(aRect)._origin()).__gt_eq($self["@origin"]))._and_((function(){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+return $recv($recv(aRect)._corner()).__lt_eq($self["@corner"]);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)});
+//>>excludeEnd("ctx");
+}));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"containsRect:",{aRect:aRect},$globals.Rectangle)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aRect"],
+source: "containsRect: aRect\x0a\x09^ aRect origin >= origin and: [ aRect corner <= corner ]",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["and:", ">=", "origin", "<=", "corner"]
+}),
+$globals.Rectangle);
+
+$core.addMethod(
+$core.method({
+selector: "corner",
+protocol: "accessing",
+fn: function(){
+var self=this,$self=this;
+return $self["@corner"];
+
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "corner\x0a\x09^ corner",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: []
+}),
+$globals.Rectangle);
+
+$core.addMethod(
+$core.method({
+selector: "origin",
+protocol: "accessing",
+fn: function(){
+var self=this,$self=this;
+return $self["@origin"];
+
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "origin\x0a\x09^ origin",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: []
+}),
+$globals.Rectangle);
+
+$core.addMethod(
+$core.method({
+selector: "printOn:",
+protocol: "testing",
+fn: function(aStream){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+$recv($self["@origin"])._printOn_(aStream);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["printOn:"]=1;
+//>>excludeEnd("ctx");
+$recv(aStream)._nextPutAll_(" corner: ");
+$recv($self["@corner"])._printOn_(aStream);
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"printOn:",{aStream:aStream},$globals.Rectangle)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aStream"],
+source: "printOn: aStream\x0a\x09origin printOn: aStream.\x0a\x09aStream nextPutAll: ' corner: '.\x0a\x09corner printOn: aStream.",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["printOn:", "nextPutAll:"]
+}),
+$globals.Rectangle);
+
+$core.addMethod(
+$core.method({
+selector: "setPoint:point:",
+protocol: "private",
+fn: function(pt1,pt2){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $2,$3,$1,$5,$6,$4,$8,$7,$10,$9;
+$2=$recv(pt1)._x();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["x"]=1;
+//>>excludeEnd("ctx");
+$3=$recv(pt2)._x();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["x"]=2;
+//>>excludeEnd("ctx");
+$1=$recv($2)._min_($3);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["min:"]=1;
+//>>excludeEnd("ctx");
+$5=$recv(pt1)._y();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["y"]=1;
+//>>excludeEnd("ctx");
+$6=$recv(pt2)._y();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["y"]=2;
+//>>excludeEnd("ctx");
+$4=$recv($5)._min_($6);
+$self["@origin"]=$recv($1).__at($4);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["@"]=1;
+//>>excludeEnd("ctx");
+$8=$recv(pt1)._x();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["x"]=3;
+//>>excludeEnd("ctx");
+$7=$recv($8)._max_($recv(pt2)._x());
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["max:"]=1;
+//>>excludeEnd("ctx");
+$10=$recv(pt1)._y();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["y"]=3;
+//>>excludeEnd("ctx");
+$9=$recv($10)._max_($recv(pt2)._y());
+$self["@corner"]=$recv($7).__at($9);
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"setPoint:point:",{pt1:pt1,pt2:pt2},$globals.Rectangle)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["pt1", "pt2"],
+source: "setPoint: pt1 point: pt2\x0a\x0a\x09origin := (pt1 x min: pt2 x)@(pt1 y min: pt2 y).\x0a\x09corner := (pt1 x max: pt2 x)@(pt1 y max: pt2 y).",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["@", "min:", "x", "y", "max:"]
+}),
+$globals.Rectangle);
+
+
+$core.addMethod(
+$core.method({
+selector: "origin:corner:",
+protocol: "instance creation",
+fn: function(anOrigin,aCorner){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $recv($self._basicNew())._setPoint_point_(anOrigin,aCorner);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"origin:corner:",{anOrigin:anOrigin,aCorner:aCorner},$globals.Rectangle.a$cls)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["anOrigin", "aCorner"],
+source: "origin: anOrigin corner: aCorner\x0a\x09^ self basicNew setPoint: anOrigin point: aCorner.",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["setPoint:point:", "basicNew"]
+}),
+$globals.Rectangle.a$cls);
+
+$core.addMethod(
+$core.method({
+selector: "origin:extent:",
+protocol: "instance creation",
+fn: function(anOrigin,anExtent){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $recv($self._basicNew())._setPoint_point_(anOrigin,$recv(anOrigin).__plus(anExtent));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"origin:extent:",{anOrigin:anOrigin,anExtent:anExtent},$globals.Rectangle.a$cls)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["anOrigin", "anExtent"],
+source: "origin: anOrigin extent: anExtent\x0a\x09^ self basicNew setPoint: anOrigin point: anOrigin + anExtent.",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["setPoint:point:", "basicNew", "+"]
+}),
+$globals.Rectangle.a$cls);
+
+$core.addMethod(
+$core.method({
+selector: "point:point:",
+protocol: "instance creation",
+fn: function(anOrigin,aCorner){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $recv($self._basicNew())._setPoint_point_(anOrigin,aCorner);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"point:point:",{anOrigin:anOrigin,aCorner:aCorner},$globals.Rectangle.a$cls)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["anOrigin", "aCorner"],
+source: "point: anOrigin point: aCorner\x0a\x09^ self basicNew setPoint: anOrigin point: aCorner.",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["setPoint:point:", "basicNew"]
+}),
+$globals.Rectangle.a$cls);
+
+
 $core.addClass("UndefinedObject", $globals.Object, [], "Kernel-Objects");
 //>>excludeStart("ide", pragmas.excludeIdeData);
 $globals.UndefinedObject.comment="I describe the behavior of my sole instance, `nil`. `nil` represents a prior value for variables that have not been initialized, or for results which are meaningless.\x0a\x0a`nil` is the Smalltalk equivalent of the `undefined` JavaScript object.\x0a\x0a__note:__ When sending messages to the `undefined` JavaScript object, it will be replaced by `nil`.";

+ 143 - 0
src/Kernel-Objects.st

@@ -816,6 +816,10 @@ min: aNumber
 	<inlineJS: 'return Math.min(self, aNumber);'>
 !
 
+min: aMin max: aMax
+	^ (self min: aMin) max: aMax
+!
+
 negated
 	^ 0 - self
 ! !
@@ -888,10 +892,18 @@ ceiling
 	<inlineJS: 'return Math.ceil(self);'>
 !
 
+degreesToRadians
+	^ self * Number radiansPerDegree
+!
+
 floor
 	<inlineJS: 'return Math.floor(self);'>
 !
 
+radiansToDegrees
+	^ self / Number radiansPerDegree
+!
+
 rounded
 	<inlineJS: 'return Math.round(self);'>
 !
@@ -1002,6 +1014,10 @@ arcTan
 	<inlineJS: 'return Math.atan(self);'>
 !
 
+arcTan: aNumber
+	<inlineJS: 'return Math.atan2(self, aNumber);'>
+!
+
 cos
 	<inlineJS: 'return Math.cos(self);'>
 !
@@ -1058,6 +1074,10 @@ printShowingDecimalPlaces: placesDesired
 
 !Number methodsFor: 'testing'!
 
+between: min and: max
+ ^ self >= min and: [ self <= max ]
+!
+
 even
 	^ 0 = (self \\ 2)
 !
@@ -1108,6 +1128,10 @@ e
 
 pi
 	<inlineJS: 'return Math.PI'>
+!
+
+radiansPerDegree
+	^ (self pi) / 180
 ! !
 
 Object subclass: #Point
@@ -1203,6 +1227,43 @@ asPoint
 	^ self
 ! !
 
+!Point methodsFor: 'geometry'!
+
+angle
+	^ self y arcTan: self x
+! !
+
+!Point methodsFor: 'point functions'!
+
+dotProduct: aPoint
+	^ (x * aPoint x) + (y * aPoint y)
+!
+
+normal
+	"Answer a Point representing the unit vector rotated 90 deg clockwise. For the zero point return -1@0."
+
+	| n d |
+	n := y negated @ x.
+	(d := (n x * n x + (n y * n y))) = 0
+		 ifTrue: [ ^ -1 @0 ].
+	^ n / d sqrt
+!
+
+normalized
+	| r |
+	r := self r.
+	
+	r = 0
+		ifTrue: [ ^ Point x: 0 y: 0 ]
+		ifFalse: [ ^ Point x: x / r y: y / r ]
+! !
+
+!Point methodsFor: 'polar coordinates'!
+
+r
+	^ ((x * x) + (y * y)) sqrt
+! !
+
 !Point methodsFor: 'printing'!
 
 printOn: aStream
@@ -1218,6 +1279,20 @@ printOn: aStream
 	y printOn: aStream
 ! !
 
+!Point methodsFor: 'rectangle creation'!
+
+corner: aPoint
+	^ Rectangle origin: self corner: aPoint
+!
+
+extent: aPoint
+	^ Rectangle origin: self extent: aPoint
+!
+
+rectangle: aPoint
+	^ Rectangle point: self point: aPoint
+! !
+
 !Point methodsFor: 'transforming'!
 
 dist: aPoint 
@@ -1296,6 +1371,74 @@ next: anInteger
 	^ (1 to: anInteger) collect: [ :each | self next ]
 ! !
 
+Object subclass: #Rectangle
+	instanceVariableNames: 'origin corner'
+	package: 'Kernel-Objects'!
+!Rectangle commentStamp!
+I represent a Rectangle defined by my two corners.
+
+The simplest way to create an instance is using Point methods:
+
+    1@1 corner: 2@2
+
+WIll create a rectangle with 1@1 as the top left and 2@2 at the bottom right.
+
+    1@1 extent: 1@1
+
+Will create the same rectangle, defining an origin and a size instead of an origin and a corner.!
+
+!Rectangle methodsFor: 'accessing'!
+
+corner
+	^ corner
+!
+
+origin
+	^ origin
+! !
+
+!Rectangle methodsFor: 'private'!
+
+setPoint: pt1 point: pt2
+
+	origin := (pt1 x min: pt2 x)@(pt1 y min: pt2 y).
+	corner := (pt1 x max: pt2 x)@(pt1 y max: pt2 y).
+! !
+
+!Rectangle methodsFor: 'testing'!
+
+= aRectangle
+	^ origin = aRectangle origin and: [ corner = aRectangle corner ]
+!
+
+containsPoint: aPoint
+	^ origin <= aPoint and: [ corner >= aPoint ]
+!
+
+containsRect: aRect
+	^ aRect origin >= origin and: [ aRect corner <= corner ]
+!
+
+printOn: aStream
+	origin printOn: aStream.
+	aStream nextPutAll: ' corner: '.
+	corner printOn: aStream.
+! !
+
+!Rectangle class methodsFor: 'instance creation'!
+
+origin: anOrigin corner: aCorner
+	^ self basicNew setPoint: anOrigin point: aCorner.
+!
+
+origin: anOrigin extent: anExtent
+	^ self basicNew setPoint: anOrigin point: anOrigin + anExtent.
+!
+
+point: anOrigin point: aCorner
+	^ self basicNew setPoint: anOrigin point: aCorner.
+! !
+
 Object subclass: #UndefinedObject
 	instanceVariableNames: ''
 	package: 'Kernel-Objects'!

+ 564 - 7
src/Kernel-Tests.js

@@ -12211,6 +12211,60 @@ messageSends: ["assert:equals:", "asNumber"]
 }),
 $globals.NumberTest);
 
+$core.addMethod(
+$core.method({
+selector: "testBetweenAnd",
+protocol: "tests",
+fn: function(){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $1,$3,$2,$5,$4;
+$1=(4)._between_and_((3),(5));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["between:and:"]=1;
+//>>excludeEnd("ctx");
+$self._assert_($1);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["assert:"]=1;
+//>>excludeEnd("ctx");
+$3=(1)._between_and_((5),(6));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["between:and:"]=2;
+//>>excludeEnd("ctx");
+$2=$recv($3)._not();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["not"]=1;
+//>>excludeEnd("ctx");
+$self._assert_($2);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["assert:"]=2;
+//>>excludeEnd("ctx");
+$5=(90)._between_and_((67),(87));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["between:and:"]=3;
+//>>excludeEnd("ctx");
+$4=$recv($5)._not();
+$self._assert_($4);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["assert:"]=3;
+//>>excludeEnd("ctx");
+$self._assert_((1)._between_and_((1),(1)));
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"testBetweenAnd",{},$globals.NumberTest)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "testBetweenAnd\x0a\x09self assert: (4 between: 3 and: 5).\x0a\x09self assert: (1 between: 5 and: 6) not.\x0a\x09self assert: (90 between: 67 and: 87) not.\x0a\x09self assert: (1 between: 1 and: 1).",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["assert:", "between:and:", "not"]
+}),
+$globals.NumberTest);
+
 $core.addMethod(
 $core.method({
 selector: "testCeiling",
@@ -12351,6 +12405,30 @@ messageSends: ["assert:", "==", "copy", "deepCopy"]
 }),
 $globals.NumberTest);
 
+$core.addMethod(
+$core.method({
+selector: "testDegreesToRadians",
+protocol: "tests",
+fn: function(){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+$self._assert_($recv($recv($recv((180)._degreesToRadians()).__minus($recv($globals.Number)._pi()))._abs()).__lt_eq((0.01)));
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"testDegreesToRadians",{},$globals.NumberTest)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "testDegreesToRadians\x0a\x09self assert: (180 degreesToRadians - Number pi) abs <= 0.01.",
+referencedClasses: ["Number"],
+//>>excludeEnd("ide");
+messageSends: ["assert:", "<=", "abs", "-", "degreesToRadians", "pi"]
+}),
+$globals.NumberTest);
+
 $core.addMethod(
 $core.method({
 selector: "testEquality",
@@ -13197,16 +13275,37 @@ $core.addMethod(
 $core.method({
 selector: "testMinMax",
 protocol: "tests",
-fn: function (){
+fn: function(){
 var self=this,$self=this;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
+var $1,$2;
 $self._assert_equals_((2)._max_((5)),(5));
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 $ctx1.sendIdx["assert:equals:"]=1;
 //>>excludeEnd("ctx");
 $self._assert_equals_((2)._min_((5)),(2));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["assert:equals:"]=2;
+//>>excludeEnd("ctx");
+$1=(2)._min_max_((5),(3));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["min:max:"]=1;
+//>>excludeEnd("ctx");
+$self._assert_equals_($1,(3));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["assert:equals:"]=3;
+//>>excludeEnd("ctx");
+$2=(7)._min_max_((5),(3));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["min:max:"]=2;
+//>>excludeEnd("ctx");
+$self._assert_equals_($2,(5));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["assert:equals:"]=4;
+//>>excludeEnd("ctx");
+$self._assert_equals_((4)._min_max_((5),(3)),(4));
 return self;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 }, function($ctx1) {$ctx1.fill(self,"testMinMax",{},$globals.NumberTest)});
@@ -13214,10 +13313,10 @@ return self;
 },
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: [],
-source: "testMinMax\x0a\x09\x0a\x09self assert: (2 max: 5) equals: 5.\x0a\x09self assert: (2 min: 5) equals: 2",
+source: "testMinMax\x0a\x09\x0a\x09self assert: (2 max: 5) equals: 5.\x0a\x09self assert: (2 min: 5) equals: 2.\x0a\x09self assert: (2 min: 5 max: 3) equals: 3.\x0a\x09self assert: (7 min: 5 max: 3) equals: 5.\x0a\x09self assert: (4 min: 5 max: 3) equals: 4.",
 referencedClasses: [],
 //>>excludeEnd("ide");
-messageSends: ["assert:equals:", "max:", "min:"]
+messageSends: ["assert:equals:", "max:", "min:", "min:max:"]
 }),
 $globals.NumberTest);
 
@@ -13387,6 +13486,30 @@ messageSends: ["assert:equals:", "printShowingDecimalPlaces:", "negated"]
 }),
 $globals.NumberTest);
 
+$core.addMethod(
+$core.method({
+selector: "testRadiansToDegrees",
+protocol: "tests",
+fn: function(){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+$self._assert_($recv($recv($recv($recv($recv($globals.Number)._pi())._radiansToDegrees()).__minus((180)))._abs()).__lt_eq((0.01)));
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"testRadiansToDegrees",{},$globals.NumberTest)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "testRadiansToDegrees\x0a\x09self assert: (Number pi radiansToDegrees - 180) abs <= 0.01.",
+referencedClasses: ["Number"],
+//>>excludeEnd("ide");
+messageSends: ["assert:", "<=", "abs", "-", "radiansToDegrees", "pi"]
+}),
+$globals.NumberTest);
+
 $core.addMethod(
 $core.method({
 selector: "testRaisedTo",
@@ -13701,11 +13824,12 @@ $core.addMethod(
 $core.method({
 selector: "testTrigonometry",
 protocol: "tests",
-fn: function (){
+fn: function(){
 var self=this,$self=this;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
+var $1;
 $self._assert_equals_((0)._cos(),(1));
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 $ctx1.sendIdx["assert:equals:"]=1;
@@ -13727,6 +13851,18 @@ $self._assert_equals_((0)._arcSin(),(0));
 $ctx1.sendIdx["assert:equals:"]=5;
 //>>excludeEnd("ctx");
 $self._assert_equals_((0)._arcTan(),(0));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["assert:equals:"]=6;
+//>>excludeEnd("ctx");
+$1=(0)._arcTan_((1));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["arcTan:"]=1;
+//>>excludeEnd("ctx");
+$self._assert_equals_($1,(0));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["assert:equals:"]=7;
+//>>excludeEnd("ctx");
+$self._assert_equals_((1)._arcTan_((0)),$recv($recv($globals.Number)._pi()).__slash((2)));
 return self;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 }, function($ctx1) {$ctx1.fill(self,"testTrigonometry",{},$globals.NumberTest)});
@@ -13734,10 +13870,10 @@ return self;
 },
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: [],
-source: "testTrigonometry\x0a\x09self assert: 0 cos equals: 1.\x0a\x09self assert: 0 sin equals: 0.\x0a\x09self assert: 0 tan equals: 0.\x0a\x09self assert: 1 arcCos equals: 0.\x0a\x09self assert: 0 arcSin equals: 0.\x0a\x09self assert: 0 arcTan equals: 0.",
-referencedClasses: [],
+source: "testTrigonometry\x0a\x09self assert: 0 cos equals: 1.\x0a\x09self assert: 0 sin equals: 0.\x0a\x09self assert: 0 tan equals: 0.\x0a\x09self assert: 1 arcCos equals: 0.\x0a\x09self assert: 0 arcSin equals: 0.\x0a\x09self assert: 0 arcTan equals: 0.\x0a\x09\x0a\x09self assert: (0 arcTan: 1) equals: 0.\x0a\x09self assert: (1 arcTan: 0) equals: (Number pi / 2)",
+referencedClasses: ["Number"],
 //>>excludeEnd("ide");
-messageSends: ["assert:equals:", "cos", "sin", "tan", "arcCos", "arcSin", "arcTan"]
+messageSends: ["assert:equals:", "cos", "sin", "tan", "arcCos", "arcSin", "arcTan", "arcTan:", "/", "pi"]
 }),
 $globals.NumberTest);
 
@@ -14337,6 +14473,30 @@ messageSends: ["assert:equals:", "x", "x:y:", "y", "x:", "new", "y:"]
 }),
 $globals.PointTest);
 
+$core.addMethod(
+$core.method({
+selector: "testAngle",
+protocol: "tests",
+fn: function(){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+$self._assert_equals_($recv((-1).__at((0)))._angle(),$recv($globals.Number)._pi());
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"testAngle",{},$globals.PointTest)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "testAngle\x0a\x09self assert: (-1@0) angle equals: Number pi",
+referencedClasses: ["Number"],
+//>>excludeEnd("ide");
+messageSends: ["assert:equals:", "angle", "@", "pi"]
+}),
+$globals.PointTest);
+
 $core.addMethod(
 $core.method({
 selector: "testArithmetic",
@@ -14572,6 +14732,36 @@ messageSends: ["assert:", "<", "@", "deny:", "<=", ">", ">="]
 }),
 $globals.PointTest);
 
+$core.addMethod(
+$core.method({
+selector: "testDotProduct",
+protocol: "tests",
+fn: function(){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $2,$1;
+$2=(2).__at((3));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["@"]=1;
+//>>excludeEnd("ctx");
+$1=$recv($2)._dotProduct_((3).__at((7)));
+$self._assert_equals_($1,(27));
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"testDotProduct",{},$globals.PointTest)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "testDotProduct\x0a\x09self assert: (2@3 dotProduct: 3@7) equals: 27",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["assert:equals:", "dotProduct:", "@"]
+}),
+$globals.PointTest);
+
 $core.addMethod(
 $core.method({
 selector: "testEgality",
@@ -14683,6 +14873,202 @@ messageSends: ["assert:equals:", "y", "x:", "new", "deny:", "=", "x", "y:"]
 }),
 $globals.PointTest);
 
+$core.addMethod(
+$core.method({
+selector: "testNormal",
+protocol: "tests",
+fn: function(){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $2,$1;
+$2=(1).__at((0));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["@"]=1;
+//>>excludeEnd("ctx");
+$1=$recv($2)._normal();
+$self._assert_equals_($1,(0).__at((1)));
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"testNormal",{},$globals.PointTest)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "testNormal\x0a\x09self assert: (1@0) normal equals: 0@1",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["assert:equals:", "normal", "@"]
+}),
+$globals.PointTest);
+
+$core.addMethod(
+$core.method({
+selector: "testNormalized",
+protocol: "tests",
+fn: function(){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $2,$1,$3,$5,$4;
+$2=(0).__at((2));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["@"]=1;
+//>>excludeEnd("ctx");
+$1=$recv($2)._normalized();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["normalized"]=1;
+//>>excludeEnd("ctx");
+$3=(0).__at((1));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["@"]=2;
+//>>excludeEnd("ctx");
+$self._assert_equals_($1,$3);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["assert:equals:"]=1;
+//>>excludeEnd("ctx");
+$5=(0).__at((0));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["@"]=3;
+//>>excludeEnd("ctx");
+$4=$recv($5)._normalized();
+$self._assert_equals_($4,(0).__at((0)));
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"testNormalized",{},$globals.PointTest)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "testNormalized\x0a\x09self assert: (0@2) normalized equals: 0@1.\x0a\x09self assert: (0@0) normalized equals: 0@0.",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["assert:equals:", "normalized", "@"]
+}),
+$globals.PointTest);
+
+$core.addMethod(
+$core.method({
+selector: "testPolarCoordinates",
+protocol: "tests",
+fn: function(){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $2,$1;
+$2=(1).__at((0));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["@"]=1;
+//>>excludeEnd("ctx");
+$1=$recv($2)._r();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["r"]=1;
+//>>excludeEnd("ctx");
+$self._assert_equals_($1,(1));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["assert:equals:"]=1;
+//>>excludeEnd("ctx");
+$self._assert_equals_($recv((0).__at((0)))._r(),(0));
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"testPolarCoordinates",{},$globals.PointTest)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "testPolarCoordinates\x0a\x09self assert: (1@0) r equals: 1.\x0a\x09self assert: (0@0) r equals: 0.",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["assert:equals:", "r", "@"]
+}),
+$globals.PointTest);
+
+$core.addMethod(
+$core.method({
+selector: "testRectangleCreation",
+protocol: "tests",
+fn: function(){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $2,$3,$1,$5,$6,$4,$8,$9,$7,$11,$12,$10,$14,$15,$13,$17,$16;
+$2=(1).__at((1));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["@"]=1;
+//>>excludeEnd("ctx");
+$3=(2).__at((2));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["@"]=2;
+//>>excludeEnd("ctx");
+$1=$recv($2)._corner_($3);
+$5=(1).__at((1));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["@"]=3;
+//>>excludeEnd("ctx");
+$6=(2).__at((2));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["@"]=4;
+//>>excludeEnd("ctx");
+$4=$recv($globals.Rectangle)._origin_corner_($5,$6);
+$self._assert_equals_($1,$4);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["assert:equals:"]=1;
+//>>excludeEnd("ctx");
+$8=(1).__at((1));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["@"]=5;
+//>>excludeEnd("ctx");
+$9=(2).__at((2));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["@"]=6;
+//>>excludeEnd("ctx");
+$7=$recv($8)._rectangle_($9);
+$11=(1).__at((1));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["@"]=7;
+//>>excludeEnd("ctx");
+$12=(2).__at((2));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["@"]=8;
+//>>excludeEnd("ctx");
+$10=$recv($globals.Rectangle)._point_point_($11,$12);
+$self._assert_equals_($7,$10);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["assert:equals:"]=2;
+//>>excludeEnd("ctx");
+$14=(1).__at((1));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["@"]=9;
+//>>excludeEnd("ctx");
+$15=(2).__at((2));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["@"]=10;
+//>>excludeEnd("ctx");
+$13=$recv($14)._extent_($15);
+$17=(1).__at((1));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["@"]=11;
+//>>excludeEnd("ctx");
+$16=$recv($globals.Rectangle)._origin_extent_($17,(2).__at((2)));
+$self._assert_equals_($13,$16);
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"testRectangleCreation",{},$globals.PointTest)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "testRectangleCreation\x0a\x09self assert: (1@1 corner: 2@2) equals: (Rectangle origin: 1@1 corner: 2@2).\x0a\x09self assert: (1@1 rectangle: 2@2) equals: (Rectangle point: 1@1 point: 2@2).\x0a\x09self assert: (1@1 extent: 2@2) equals: (Rectangle origin: 1@1 extent: 2@2)",
+referencedClasses: ["Rectangle"],
+//>>excludeEnd("ide");
+messageSends: ["assert:equals:", "corner:", "@", "origin:corner:", "rectangle:", "point:point:", "extent:", "origin:extent:"]
+}),
+$globals.PointTest);
+
 $core.addMethod(
 $core.method({
 selector: "testTranslateBy",
@@ -15016,6 +15402,177 @@ $globals.RandomTest);
 
 
 
+$core.addClass("RectangleTest", $globals.TestCase, [], "Kernel-Tests");
+$core.addMethod(
+$core.method({
+selector: "testContainsPoint",
+protocol: "tests",
+fn: function(){
+var self=this,$self=this;
+var rect;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $1,$2,$4,$5,$3;
+$1=(0).__at((0));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["@"]=1;
+//>>excludeEnd("ctx");
+$2=(4).__at((4));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["@"]=2;
+//>>excludeEnd("ctx");
+rect=$recv($globals.Rectangle)._origin_corner_($1,$2);
+$4=rect;
+$5=(1).__at((2));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["@"]=3;
+//>>excludeEnd("ctx");
+$3=$recv($4)._containsPoint_($5);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["containsPoint:"]=1;
+//>>excludeEnd("ctx");
+$self._assert_($3);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["assert:"]=1;
+//>>excludeEnd("ctx");
+$self._assert_($recv($recv(rect)._containsPoint_((5).__at((4))))._not());
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"testContainsPoint",{rect:rect},$globals.RectangleTest)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "testContainsPoint\x0a\x09| rect |\x0a\x09rect := Rectangle origin: 0@0 corner: 4@4.\x0a\x09\x0a\x09self assert: (rect containsPoint: 1@2).\x0a\x09self assert: (rect containsPoint: 5@4) not.",
+referencedClasses: ["Rectangle"],
+//>>excludeEnd("ide");
+messageSends: ["origin:corner:", "@", "assert:", "containsPoint:", "not"]
+}),
+$globals.RectangleTest);
+
+$core.addMethod(
+$core.method({
+selector: "testContainsRect",
+protocol: "tests",
+fn: function(){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $3,$4,$2,$6,$7,$5,$1,$11,$12,$10,$14,$13,$9,$8;
+$3=(0).__at((0));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["@"]=1;
+//>>excludeEnd("ctx");
+$4=(6).__at((6));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["@"]=2;
+//>>excludeEnd("ctx");
+$2=$recv($globals.Rectangle)._origin_corner_($3,$4);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["origin:corner:"]=1;
+//>>excludeEnd("ctx");
+$6=(1).__at((1));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["@"]=3;
+//>>excludeEnd("ctx");
+$7=(5).__at((5));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["@"]=4;
+//>>excludeEnd("ctx");
+$5=$recv($globals.Rectangle)._origin_corner_($6,$7);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["origin:corner:"]=2;
+//>>excludeEnd("ctx");
+$1=$recv($2)._containsRect_($5);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["containsRect:"]=1;
+//>>excludeEnd("ctx");
+$self._assert_($1);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["assert:"]=1;
+//>>excludeEnd("ctx");
+$11=(0).__at((0));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["@"]=5;
+//>>excludeEnd("ctx");
+$12=(6).__at((6));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["@"]=6;
+//>>excludeEnd("ctx");
+$10=$recv($globals.Rectangle)._origin_corner_($11,$12);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["origin:corner:"]=3;
+//>>excludeEnd("ctx");
+$14=(1).__at((-1));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["@"]=7;
+//>>excludeEnd("ctx");
+$13=$recv($globals.Rectangle)._origin_corner_($14,(5).__at((5)));
+$9=$recv($10)._containsRect_($13);
+$8=$recv($9)._not();
+$self._assert_($8);
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"testContainsRect",{},$globals.RectangleTest)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "testContainsRect\x0a\x09self assert: ((Rectangle origin: 0@0 corner: 6@6) containsRect: (Rectangle origin: 1@1 corner: 5@5)).\x0a\x09self assert: ((Rectangle origin: 0@0 corner: 6@6) containsRect: (Rectangle origin: 1@(-1) corner: 5@5)) not.",
+referencedClasses: ["Rectangle"],
+//>>excludeEnd("ide");
+messageSends: ["assert:", "containsRect:", "origin:corner:", "@", "not"]
+}),
+$globals.RectangleTest);
+
+$core.addMethod(
+$core.method({
+selector: "testOriginExtent",
+protocol: "tests",
+fn: function(){
+var self=this,$self=this;
+var rectangle;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $1,$2,$3,$4;
+$1=(3).__at((4));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["@"]=1;
+//>>excludeEnd("ctx");
+$2=(7).__at((8));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["@"]=2;
+//>>excludeEnd("ctx");
+rectangle=$recv($globals.Rectangle)._origin_extent_($1,$2);
+$3=$recv(rectangle)._origin();
+$4=(3).__at((4));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["@"]=3;
+//>>excludeEnd("ctx");
+$self._assert_equals_($3,$4);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["assert:equals:"]=1;
+//>>excludeEnd("ctx");
+$self._assert_equals_($recv(rectangle)._corner(),(10).__at((12)));
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"testOriginExtent",{rectangle:rectangle},$globals.RectangleTest)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "testOriginExtent\x0a\x09| rectangle |\x0a\x09rectangle := Rectangle origin: 3@4 extent: 7@8.\x0a\x09\x0a\x09self assert: rectangle origin equals: 3@4.\x0a\x09self assert: rectangle corner equals: 10@12.",
+referencedClasses: ["Rectangle"],
+//>>excludeEnd("ide");
+messageSends: ["origin:extent:", "@", "assert:equals:", "origin", "corner"]
+}),
+$globals.RectangleTest);
+
+
+
 $core.addClass("StreamTest", $globals.TestCase, [], "Kernel-Tests");
 $core.addMethod(
 $core.method({

+ 77 - 1
src/Kernel-Tests.st

@@ -2271,6 +2271,13 @@ testAsNumber
 	self assert: 3 asNumber equals: 3.
 !
 
+testBetweenAnd
+	self assert: (4 between: 3 and: 5).
+	self assert: (1 between: 5 and: 6) not.
+	self assert: (90 between: 67 and: 87) not.
+	self assert: (1 between: 1 and: 1).
+!
+
 testCeiling
 	self assert: 1.2 ceiling equals: 2.
 	self assert: -1.2 ceiling equals: -1.
@@ -2296,6 +2303,10 @@ testCopying
 	self assert: 1 deepCopy == 1
 !
 
+testDegreesToRadians
+	self assert: (180 degreesToRadians - Number pi) abs <= 0.01.
+!
+
 testEquality
 	self assert: (1 = 1).
 	self assert: (0 = 0).
@@ -2394,7 +2405,10 @@ testLog
 testMinMax
 	
 	self assert: (2 max: 5) equals: 5.
-	self assert: (2 min: 5) equals: 2
+	self assert: (2 min: 5) equals: 2.
+	self assert: (2 min: 5 max: 3) equals: 3.
+	self assert: (7 min: 5 max: 3) equals: 5.
+	self assert: (4 min: 5 max: 3) equals: 4.
 !
 
 testNegated
@@ -2418,6 +2432,10 @@ testPrintShowingDecimalPlaces
 	self assert: (0 printShowingDecimalPlaces: 2) equals: '0.00'.
 !
 
+testRadiansToDegrees
+	self assert: (Number pi radiansToDegrees - 180) abs <= 0.01.
+!
+
 testRaisedTo
 	self assert: (2 raisedTo: 4) equals: 16.
 	self assert: (2 raisedTo: 0) equals: 1.
@@ -2479,6 +2497,9 @@ testTrigonometry
 	self assert: 1 arcCos equals: 0.
 	self assert: 0 arcSin equals: 0.
 	self assert: 0 arcTan equals: 0.
+	
+	self assert: (0 arcTan: 1) equals: 0.
+	self assert: (1 arcTan: 0) equals: (Number pi / 2)
 !
 
 testTruncated
@@ -2602,6 +2623,10 @@ testAccessing
 	self assert: (Point new y: 4) y equals: 4
 !
 
+testAngle
+	self assert: (-1@0) angle equals: Number pi
+!
+
 testArithmetic
 	self assert: 3@4 * (3@4 ) equals: (Point x: 9 y: 16).
 	self assert: 3@4 + (3@4 ) equals: (Point x: 6 y: 8).
@@ -2627,6 +2652,10 @@ testComparison
 	self deny: 4@5 >= (5@5)
 !
 
+testDotProduct
+	self assert: (2@3 dotProduct: 3@7) equals: 27
+!
+
 testEgality
 	self assert: (3@4 = (3@4)).
 	self deny: 3@5 = (3@6)
@@ -2640,6 +2669,26 @@ testNew
 	self deny: (Point new y: 4) y = 0
 !
 
+testNormal
+	self assert: (1@0) normal equals: 0@1
+!
+
+testNormalized
+	self assert: (0@2) normalized equals: 0@1.
+	self assert: (0@0) normalized equals: 0@0.
+!
+
+testPolarCoordinates
+	self assert: (1@0) r equals: 1.
+	self assert: (0@0) r equals: 0.
+!
+
+testRectangleCreation
+	self assert: (1@1 corner: 2@2) equals: (Rectangle origin: 1@1 corner: 2@2).
+	self assert: (1@1 rectangle: 2@2) equals: (Rectangle point: 1@1 point: 2@2).
+	self assert: (1@1 extent: 2@2) equals: (Rectangle origin: 1@1 extent: 2@2)
+!
+
 testTranslateBy
 	self assert: (3@3 translateBy: 0@1) equals: 3@4.
 	self assert: (3@3 translateBy: 0@1 negated) equals: 3@2.
@@ -2710,6 +2759,33 @@ textNext
 			next = current ]
 ! !
 
+TestCase subclass: #RectangleTest
+	instanceVariableNames: ''
+	package: 'Kernel-Tests'!
+
+!RectangleTest methodsFor: 'tests'!
+
+testContainsPoint
+	| rect |
+	rect := Rectangle origin: 0@0 corner: 4@4.
+	
+	self assert: (rect containsPoint: 1@2).
+	self assert: (rect containsPoint: 5@4) not.
+!
+
+testContainsRect
+	self assert: ((Rectangle origin: 0@0 corner: 6@6) containsRect: (Rectangle origin: 1@1 corner: 5@5)).
+	self assert: ((Rectangle origin: 0@0 corner: 6@6) containsRect: (Rectangle origin: 1@(-1) corner: 5@5)) not.
+!
+
+testOriginExtent
+	| rectangle |
+	rectangle := Rectangle origin: 3@4 extent: 7@8.
+	
+	self assert: rectangle origin equals: 3@4.
+	self assert: rectangle corner equals: 10@12.
+! !
+
 TestCase subclass: #StreamTest
 	instanceVariableNames: ''
 	package: 'Kernel-Tests'!