点关于直线的对称点
<!DOCTYPE HTML>
<html>
<head>
<script>
class Vector2D {
constructor (x, y) {
this.x = x;
this.y = y;
}
// add
add_ (b) {
this.x += b.x;
this.y += b.y;
return this;
}
add (b) {
return Vector2D.Add(this, b);
}
add_scalar_ (s) {
this.x += s;
this.y += s;
return this;
}
add_scalar (s) {
return Vector2D.Add_Scalar(this, s);
}
// minus
minus_ (b) {
this.x -= b.x;
this.y -= b.y;
return this;
}
minus (b) {
return Vector2D.Minus(this, b);
}
minus_scalar_ (s) {
this.x -= s;
this.y -= s;
return this;
}
minus_scalar (s) {
return Vector2D.Minus_scalar(this, s);
}
// mul
mul(b) {
return Vector2D.Mul(this, b);
}
mul_scalar_ (s) {
this.x *= s;
this.y *= s;
return this;
}
mul_scalar (s) {
return Vector2D.Mul_Scalar(this, s);
}
mul_mat_left (M) {
return Vector2D.Mul_Mat_Left(this, M);
}
mul_mat_left_ (M) {
var x = this.x * M.a + this.y * M.c;
var y = this.x * M.b + this.y * M.d;
this.x = x;
this.y = y;
return this;
}
// static method
static Ones () {
return new Vector2D (1, 1);
}
static Add (a, b) {
return new Vector2D (a.x + b.x, a.y + b.y);
}
static Add_Scalar(a, s) {
return new Vector2D (a.x + s, a.y + s);
}
static Minus (a, b) {
return new Vector2D (a.x - b.x, a.y - b.y);
}
static Minus_Scalar (a, s) {
return new Vector2D (a.x - s, a.y - s);
}
static Mul(a, b) {
return a.x * b.x + a.y * b.y;
}
static Mul_Scalar (a, s) {
return new Vector2D(a.x * s, a.y * s);
}
static Mul_Mat_Left (v, M) {
return new Vector2D (v.x * M.a + v.y * M.c, v.x * M.b + v.y * M.d);
}
static Mul_Mat_Right (v, M) {
return new Vector2D (M.a * v.x + M.b * v.y, M.c * v.x + M.d * v.y);
}
};
class Matrix2x2 {
/*
a b
c d
*/
constructor (a, b, c, d) {
this.a = a;
this.b = b;
this.c = c;
this.d = d;
}
// add
add_ (B) {
this.a += B.a;
this.b += B.b;
this.c += B.c;
this.d += B.d;
return this;
}
add (B) {
return Matrix2x2.Add(this, B);
}
add_scalar_ (s) {
this.a += s;
this.b += s;
this.c += s;
this.d += s;
return this;
}
add_scalar (s) {
return Matrix2x2.Add_Scalar(this, s)
}
// minus
minus_ (B) {
this.a -= B.a;
this.b -= B.b;
this.c -= B.c;
this.d -= B.d;
return this;
}
minus (B) {
return Matrix2x2.Minus(this, B);
}
minus_scalar_ (s) {
this.a -= s;
this.b -= s;
this.c -= s;
this.d -= s;
return this;
}
minus_scalar (s) {
return Matrix2x2.Minus_scalar(this, s)
}
// mul
mul(B) {
return Matrix2x2.Mul(this, B);
}
mul_(B) {
var a = this.a * B.a + this.b * B.c;
var b = this.a * B.b + this.b * B.d;
var c = this.c * B.a + this.d * B.c;
var d = this.c * B.b + this.d * b.d;
this.a = a; this.b = b; this.c = c; this.d = d;
return this;
}
mul_scalar (s) {
return Matrix2x2.Mul_Scalar(this, s);
}
mul_scalar_ (s) {
this.a *= s;
this.b *= s;
this.c *= s;
this.d *= s;
return this;
}
mul_vector_left (v) {
return Matrix2x2.Mul_Vector_Left(v, this);
}
mul_vector_right (v) {
return Matrix2x2.Mul_Vector_Right(v, this);
}
transport () {
return Matrix2x2.Transport(this);
}
transport_ () {
var c = this.c;
this.c = this.b;
this.b = c;
return this;
}
minor () {
return Matrix2x2.Minor(this);
}
minor_ () {
var a = this.d;
var b = -1 * this.b;
var c = -1 * this.c;
var d = this.a;
this.a = a; this.b = b; this.c = c; this.d = d;
return this;
}
det () {
return Matrix2x2.Det(this);
}
inv () {
return Matrix2x2.Inv(this);
}
inv_ () {
var _det = this.det();
if (_det == 0) {
console.error("Det of matrix is 0");
return this;
}
this.minor_();
this.mul_scalar_(1 / _det);
return this;
}
// static method
static Eye () {
return new Matrix2x2 (1, 0, 0, 1);
}
static Add (A, B) {
return new Matrix2x2 (
A.a + B.a,
A.b + B.b,
A.c + B.c,
A.d + B.d);
}
static Add_Scalar (A, s) {
return new Matrix2x2 (
A.a + s,
A.b + s,
A.c + s,
A.d + s);
}
static Minus (A, B) {
return new Matrix2x2 (
A.a - B.a,
A.b - B.b,
A.c - B.c,
A.d - B.d);
}
static Minus_Scalar (A, s) {
return new Matrix2x2 (
A.a - s,
A.b - s,
A.c - s,
A.d - s);
}
static Mul (A, B) {
return new Matrix2x2(
A.a * B.a + A.b * B.c, A.a * B.b + A.b * B.d,
A.c * B.a + A.d * B.c, A.c * B.b + A.d * B.d
);
}
static Mul_Scalar (A, s) {
return new Matrix2x2 (
A.a * s,
A.b * s,
A.c * s,
A.d * s);
}
static Mul_Vector_Left (v, M) {
return Vector2D.Mul_Mat_Left(v, M);
}
static Mul_Vector_Right (v, M) {
return Vector2D.Mul_Mat_Right(v, M);
}
static Transport (M) {
return new Matrix2x2 (
M.a, M.c,
M.b, M.d
);
}
static Minor (M) {
return new Matrix2x2 (
M.d, -M.b,
-M.c, M.a,
);
}
static Det (M) {
return M.a * M.d - M.b * M.c;
}
static Inv (M) {
var _det = Matrix2x2.Det(M);
if (_det == 0) {
console.error("Det of matrix is 0");
return null;
}
var minor = Matrix2x2.Minor (M);
return Matrix2x2.Mul_Scalar(minor, 1 / _det);
}
};
function randomInt(left, right) {
return Math.floor(Math.random() * (right - left + 1)) + left;
}
</script>
</head>
<body>
<canvas id="m_canvas" width="900" height="600"></canvas>
<script>
function drawPoint (ctx, point, size, color) {
ctx.beginPath();
ctx.arc(point.x, point.y, size, 0, 2*Math.PI);
ctx.fillStyle = color;
ctx.fill();
}
function drawLine (a, b, width, color) {
ctx.beginPath();
ctx.moveTo(a.x, a.y);
ctx.lineTo(b.x, b.y);
ctx.strokeStyle = color;
ctx.lineWidth = width;
ctx.stroke();
}
</script>
<script>
var m_canvas = document.getElementById("m_canvas");
var ctx = m_canvas.getContext("2d");
// 随机两点为l1
var pa = new Vector2D(randomInt(0, 300), randomInt(0, 200));
pa = new Vector2D(100, 150);
var pb = new Vector2D(randomInt(600, 900), randomInt(400, 600));
ctx.strokeStyle = "rgba(0, 0, 255, 1.0)";
ctx.strokeRect(0, 0, 900, 600);
// 添加鼠标跟踪
m_canvas.onmousemove = function (e) {
// 清空
ctx.clearRect(0, 0, 900, 600);
// 绘制边界
ctx.strokeStyle = "rgba(0, 0, 255, 1.0)";
ctx.strokeRect(0, 0, 900, 600);
// 画l1直线
drawLine(pa, pb, 3, "rgba(255, 0, 0, 1.0)");
// 绘制l1两点
drawPoint(ctx, pa, 5, "rgba(0, 0, 0, 1.0)");
drawPoint(ctx, pb, 5, "rgba(0, 0, 0, 1.0)");
// 鼠标当前坐标
var x = e.offsetX;
var y = e.offsetY;
var pc = new Vector2D(x, y);
drawPoint(ctx, pc, 5, "rgba(0, 0, 0, 1.0)");
// 计算点坐标
var xl = pa.x - pb.x; var yl = pa.y - pb.y;
var matrix_l = new Matrix2x2(yl, -xl, xl, yl);
var matrix_A = new Matrix2x2(pb.x, -pb.y, pc.y, pc.x);
var vector_l = new Vector2D(yl, xl);
var po = matrix_l.inv().mul(matrix_A).mul_vector_right(vector_l);
drawPoint(ctx, po, 5, "rgba(0, 0, 0, 1.0)");
// 绘制d点
var pd = po.mul_scalar(2).minus(pc);
drawPoint(ctx, pd, 5, "rgba(0, 0, 0, 1.0)");
};
</script>
</body>
</html>