坐标系与坐标映射

尽管这四个坐标系在原点位置、坐标轴方向、坐标范围上有所区别,但都是直角坐标系,所以它们都满足直角坐标系的特性:

<aside> 💡 不管原点和轴的方向怎么变,用同样的方法绘制几何图形,它们的形状和相对位置都不变。

</aside>

不管我们用什么绘图系统绘制图形,一般的几何图形都是由点、线段和面构成

其中,点和线段是基础的图元信息,因此,如何描述它们是绘图的关键

首先,向量和标量一样可以进行数学运算

其次,一个向量包含有长度和方向信息

这里的α是与 x 轴的夹角,v 是一个单位向量,它的长度为 1。然后我们把向量 (x0, y0) 与这个向量 v1相加,得到的就是这条线段的终点。

这里的α是与 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;
  }
}