坐标系与坐标映射
尽管这四个坐标系在原点位置、坐标轴方向、坐标范围上有所区别,但都是直角坐标系,所以它们都满足直角坐标系的特性:
<aside> 💡 不管原点和轴的方向怎么变,用同样的方法绘制几何图形,它们的形状和相对位置都不变。
</aside>
不管我们用什么绘图系统绘制图形,一般的几何图形都是由点、线段和面构成
其中,点和线段是基础的图元信息,因此,如何描述它们是绘图的关键
首先,向量和标量一样可以进行数学运算
其次,一个向量包含有长度和方向信息
v.length = function(){return Math.hypot(this.x, this.y)};v.dir = function() { return Math.atan2(this.y, this.x);}
这里的α是与 x 轴的夹角,v 是一个单位向量,它的长度为 1。然后我们把向量 (x0, y0) 与这个向量 v1相加,得到的就是这条线段的终点。
v.x = v.length * Math.cos(v.dir);
v.y = v.length * Math.sin(v.dir);
// 这个推论意味着一个重要的事实:我们可以很简单地构造出一个绘图向量
// 也就是说,如果我们希望以点 (x0, y0) 为起点,沿着某个方向画一段长度为 length 的线段,我们只需要构造出如下的一个向量就可以了
封装 Vector2D
export class Vector2D extends Array {
constructor(x = 1, y = 0) {
super(x, y);
}
set x(v) {
this[0] = v;
}
set y(v) {
this[1] = v;
}
get x() {
return this[0];
}
get y() {
return this[1];
}
get length() {
return Math.hypot(this.x, this.y);
}
get dir() {
return Math.atan2(this.y, this.x);
}
copy() {
return new Vector2D(this.x, this.y);
}
add(v) {
this.x += v.x;
this.y += v.y;
return this;
}
sub(v) {
this.x -= v.x;
this.y -= v.y;
return this;
}
scale(a) {
this.x *= a;
this.y *= a;
return this;
}
cross(v) {
return this.x * v.y - v.x * this.y;
}
dot(v) {
return this.x * v.x + v.y * this.y;
}
normalize() {
return this.scale(1 / this.length);
}
rotate(rad) {
const c = Math.cos(rad),
s = Math.sin(rad);
const [x, y] = this;
this.x = x * c + y * -s;
this.y = x * s + y * c;
return this;
}
}