mirror of
https://github.com/penpot/penpot.git
synced 2025-06-19 04:01:51 +02:00
🎉 Add javascript variants of geom.point and geom.matrix.
Only for have them in backup, they are not in use right now and we dont expect to use them in a near future.
This commit is contained in:
parent
89f65a15de
commit
065ed23c79
2 changed files with 471 additions and 0 deletions
229
frontend/src/uxbox/util/geom/_matrix.js
Normal file
229
frontend/src/uxbox/util/geom/_matrix.js
Normal file
|
@ -0,0 +1,229 @@
|
||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*
|
||||||
|
* This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||||
|
* defined by the Mozilla Public License, v. 2.0.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Andrey Antukh <niwi@niwi.nz>
|
||||||
|
*/
|
||||||
|
|
||||||
|
// NOTE: this code is unused, but is preserved for the case when we
|
||||||
|
// note that the cljs impl has not not enough performance.
|
||||||
|
|
||||||
|
goog.provide("uxbox.util.geom.matrix_impl");
|
||||||
|
goog.provide("uxbox.util.geom.matrix_impl.Matrix");
|
||||||
|
goog.require("goog.math");
|
||||||
|
goog.require("uxbox.util.geom.point_impl");
|
||||||
|
|
||||||
|
goog.scope(function() {
|
||||||
|
const self = uxbox.util.geom.matrix_impl;
|
||||||
|
const gpt = uxbox.util.geom.point_impl;
|
||||||
|
const math = goog.math;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number} a
|
||||||
|
* @param {number} b
|
||||||
|
* @param {number} c
|
||||||
|
* @param {number} d
|
||||||
|
* @param {number} e
|
||||||
|
* @param {number} f
|
||||||
|
* @struct
|
||||||
|
*/
|
||||||
|
class Matrix {
|
||||||
|
constructor(a, b, c, d, e, f) {
|
||||||
|
this.a = a;
|
||||||
|
this.b = b;
|
||||||
|
this.c = c;
|
||||||
|
this.d = d;
|
||||||
|
this.e = e;
|
||||||
|
this.f = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Symbol.iterator]() {
|
||||||
|
return [["a", this.a]
|
||||||
|
["b", this.b]];
|
||||||
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return `matrix(${this.a},${this.b},${this.c},${this.d},${this.e},${this.f})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
copy() {
|
||||||
|
return new Matrix(
|
||||||
|
this.a,
|
||||||
|
this.b,
|
||||||
|
this.c,
|
||||||
|
this.d,
|
||||||
|
this.e,
|
||||||
|
this.f
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.Matrix = Matrix;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number?} a
|
||||||
|
* @param {number?} b
|
||||||
|
* @param {number?} c
|
||||||
|
* @param {number?} d
|
||||||
|
* @param {number?} e
|
||||||
|
* @param {number?} f
|
||||||
|
* @return {Matrix}
|
||||||
|
*/
|
||||||
|
self.matrix = function(a, b, c, d, e, f) {
|
||||||
|
if (a === undefined) {
|
||||||
|
return new Matrix(1,0,0,1,0,0);
|
||||||
|
} else {
|
||||||
|
return new Matrix(a,b,c,d,e,f);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {?} m
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
function isMatrix(m) {
|
||||||
|
return m instanceof Matrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.isMatrix = isMatrix
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Matrix} m1
|
||||||
|
* @param {Matrix} m2
|
||||||
|
* @return {Matrix}
|
||||||
|
*/
|
||||||
|
self.multiplyUnsafe = function(m1, m2) {
|
||||||
|
const a = m1.a * m2.a + m1.c * m2.b;
|
||||||
|
const b = m1.b * m2.a + m1.d * m2.b;
|
||||||
|
const c = m1.a * m2.c + m1.c * m2.d;
|
||||||
|
const d = m1.b * m2.c + m1.d * m2.d;
|
||||||
|
const e = m1.a * m2.e + m1.c * m2.f + m1.e;
|
||||||
|
const f = m1.b * m2.e + m1.d * m2.f + m1.f;
|
||||||
|
m1.a = a;
|
||||||
|
m1.b = b;
|
||||||
|
m1.c = c;
|
||||||
|
m1.d = d;
|
||||||
|
m1.e = e;
|
||||||
|
m1.f = f;
|
||||||
|
return m1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Matrix} m1
|
||||||
|
* @param {Matrix} m2
|
||||||
|
* @return {Matrix}
|
||||||
|
*/
|
||||||
|
self.multiply = function(m1, m2) {
|
||||||
|
m1 = m1.copy();
|
||||||
|
return self.multiplyUnsafe(m1, m2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {...Matrix} matrices
|
||||||
|
* @return {Matrix}
|
||||||
|
*/
|
||||||
|
self.compose = function(...matrices) {
|
||||||
|
switch (matrices.length) {
|
||||||
|
case 0:
|
||||||
|
throw new Error('no matrices provided')
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
return matrices[0]
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
return self.multiply(matrices[0], matrices[1])
|
||||||
|
|
||||||
|
default: {
|
||||||
|
let result = matrices[0].copy();
|
||||||
|
for (let i=1; i<matrices.length; i++) {
|
||||||
|
result = self.multiplyUnsafe(result, matrices[i]);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {gpt.Point} p
|
||||||
|
* @return {Matrix}
|
||||||
|
*/
|
||||||
|
self.translateMatrix = function(p) {
|
||||||
|
return new Matrix(1, 0, 0, 1, p.x, p.y);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {gpt.Point} p
|
||||||
|
* @return {Matrix}
|
||||||
|
*/
|
||||||
|
self.scaleMatrix = function(p) {
|
||||||
|
return new Matrix(p.x, 0, 0, p.y, 0, 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number} angle
|
||||||
|
* @return {Matrix}
|
||||||
|
*/
|
||||||
|
self.rotateMatrix = function(angle) {
|
||||||
|
const r = math.toRadiants(angle);
|
||||||
|
return new Matrix(
|
||||||
|
Math.cos(r),
|
||||||
|
Math.sin(r),
|
||||||
|
-Math.sin(r),
|
||||||
|
Math.cos(r),
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Matrix} m
|
||||||
|
* @param {gpt.Point} p
|
||||||
|
* @return {Matrix}
|
||||||
|
*/
|
||||||
|
self.translate = function(m, p) {
|
||||||
|
return self.multiply(m, self.translateMatrix(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Matrix} m
|
||||||
|
* @param {angle} angle
|
||||||
|
* @param {gpt.Point?} center
|
||||||
|
* @return {Matrix}
|
||||||
|
*/
|
||||||
|
self.rotate = function(m, angle, center) {
|
||||||
|
if (center === undefined) {
|
||||||
|
return self.multiply(m, self.rotateMatrix(angle));
|
||||||
|
} else {
|
||||||
|
return self.compose(
|
||||||
|
m,
|
||||||
|
self.translateMatrix(center),
|
||||||
|
self.rotateMatrix(angle),
|
||||||
|
self.translateMatrix(gpt.negate(center))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Matrix} m
|
||||||
|
* @param {gpt.Point} scale
|
||||||
|
* @param {gpt.Point?} center
|
||||||
|
* @return {Matrix}
|
||||||
|
*/
|
||||||
|
self.scale = function(m, scale, center) {
|
||||||
|
if (center === undefined) {
|
||||||
|
return self.multiply(m, self.scaleMatrix(scale));
|
||||||
|
} else {
|
||||||
|
return self.compose(
|
||||||
|
m,
|
||||||
|
self.translateMatrix(center),
|
||||||
|
self.scaleMatrix(scale),
|
||||||
|
self.translateMatrix(gpt.negate(center))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
242
frontend/src/uxbox/util/geom/_point.js
Normal file
242
frontend/src/uxbox/util/geom/_point.js
Normal file
|
@ -0,0 +1,242 @@
|
||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*
|
||||||
|
* This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||||
|
* defined by the Mozilla Public License, v. 2.0.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Andrey Antukh <niwi@niwi.nz>
|
||||||
|
*/
|
||||||
|
|
||||||
|
// NOTE: this code is unused, but is preserved for the case when we
|
||||||
|
// note that the cljs impl has not not enough performance.
|
||||||
|
|
||||||
|
goog.provide("uxbox.util.geom.point_impl");
|
||||||
|
goog.provide("uxbox.util.geom.point_impl.Point");
|
||||||
|
goog.require("goog.math");
|
||||||
|
|
||||||
|
goog.scope(function() {
|
||||||
|
const self = uxbox.util.geom.point_impl;
|
||||||
|
const math = goog.math;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number} x
|
||||||
|
* @param {number} y
|
||||||
|
* @struct
|
||||||
|
*/
|
||||||
|
class Point {
|
||||||
|
constructor(x, y) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return "point(" + this.x + ", " + this.y + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.Point = Point;
|
||||||
|
|
||||||
|
self.point = function(x, y) {
|
||||||
|
let xv = null;
|
||||||
|
let yv = null;
|
||||||
|
|
||||||
|
if (x === undefined) {
|
||||||
|
return new Point(0, 0);
|
||||||
|
} else {
|
||||||
|
xv = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y === undefined) {
|
||||||
|
yv = x;
|
||||||
|
} else {
|
||||||
|
yv = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Point(xv, yv);
|
||||||
|
};
|
||||||
|
|
||||||
|
function isPoint(p) {
|
||||||
|
return p instanceof Point;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.isPoint = isPoint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Point} p
|
||||||
|
* @param {number} angle
|
||||||
|
* @return {Point}
|
||||||
|
*/
|
||||||
|
self.rotate = function(p, angle) {
|
||||||
|
const r = math.toRadians(angle);
|
||||||
|
const sin = Math.sin(r);
|
||||||
|
const cos = Math.cos(r);
|
||||||
|
|
||||||
|
const x = p.x;
|
||||||
|
const y = p.y;
|
||||||
|
|
||||||
|
const point = new Point(
|
||||||
|
x * cos - y * sin,
|
||||||
|
x * sin + y * cos
|
||||||
|
);
|
||||||
|
|
||||||
|
return self.roundTo(point, 6)
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Point} p
|
||||||
|
* @param {Point} other
|
||||||
|
* @return {Point}
|
||||||
|
*/
|
||||||
|
self.add = function(p, other) {
|
||||||
|
return new Point(
|
||||||
|
p.x + other.x,
|
||||||
|
p.y + other.y
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Point} p
|
||||||
|
* @param {Point} other
|
||||||
|
* @return {Point}
|
||||||
|
*/
|
||||||
|
self.subtract = function(p, other) {
|
||||||
|
return new Point(
|
||||||
|
p.x - other.x,
|
||||||
|
p.y - other.y
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Point} p
|
||||||
|
* @param {Point} other
|
||||||
|
* @return {Point}
|
||||||
|
*/
|
||||||
|
self.multiply = function(p, other) {
|
||||||
|
return new Point(
|
||||||
|
p.x * other.x,
|
||||||
|
p.y * other.y
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Point} p
|
||||||
|
* @param {Point} other
|
||||||
|
* @return {Point}
|
||||||
|
*/
|
||||||
|
self.divide = function(p, other) {
|
||||||
|
return new Point(
|
||||||
|
p.x / other.x,
|
||||||
|
p.y / other.y
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Point} p
|
||||||
|
* @return {Point}
|
||||||
|
*/
|
||||||
|
self.negate = function(p) {
|
||||||
|
const x = p.x, y = p.y;
|
||||||
|
return new Point(
|
||||||
|
x === 0 ? x : x * -1,
|
||||||
|
y === 0 ? y : y * -1
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Point} p
|
||||||
|
* @param {Point} other
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
self.distance = function(p, other) {
|
||||||
|
const dx = p.x - other.x;
|
||||||
|
const dy = p.y - other.y;
|
||||||
|
return Math.sqrt(Math.pow(dx, 2),
|
||||||
|
Math.pow(dy, 2));
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Point} p
|
||||||
|
* @param {Point} center
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
self.angle = function(p, center) {
|
||||||
|
if (center !== undefined) {
|
||||||
|
p = self.subtract(p, center);
|
||||||
|
}
|
||||||
|
|
||||||
|
return math.toDegrees(Math.atan2(p.y, p.x));
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Point} p
|
||||||
|
* @param {Point} other
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
self.length = function(p) {
|
||||||
|
return Math.sqrt(Math.pow(p.x, 2) + Math.pow(p.y, 2));
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Point} p
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
self.angle2other = function(p, other) {
|
||||||
|
let angle = ((p.x * other.x) + (p.y * other.y)) / (self.length(p) * self.length(other));
|
||||||
|
|
||||||
|
if (angle < -1) {
|
||||||
|
angle = -1;
|
||||||
|
} else if (angle > 1) {
|
||||||
|
angle = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
angle = Math.acos(angle);
|
||||||
|
angle = math.toDegrees(angle);
|
||||||
|
return parseFloat(angle.toFixed(6));
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Point} p
|
||||||
|
* @param {number} angle
|
||||||
|
* @return {Point}
|
||||||
|
*/
|
||||||
|
self.updateAngle = function(p, angle) {
|
||||||
|
const len = self.length(p);
|
||||||
|
const r = math.toRadiants(angle);
|
||||||
|
|
||||||
|
return new Point(
|
||||||
|
Math.cos(r) * len,
|
||||||
|
Math.sin(r) * len
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Point} p
|
||||||
|
* @param {number} decimals
|
||||||
|
* @return {Point}
|
||||||
|
*/
|
||||||
|
self.roundTo = function(p, decimals) {
|
||||||
|
return new Point(
|
||||||
|
parseFloat(p.x.toFixed(decimals)),
|
||||||
|
parseFloat(p.y.toFixed(decimals))
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// class Matrix {
|
||||||
|
// constructor() {
|
||||||
|
// this.a = 1;
|
||||||
|
// this.b = 0;
|
||||||
|
// this.c = 0;
|
||||||
|
// this.d = 1;
|
||||||
|
// this.e = 0;
|
||||||
|
// this.f = 0;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// self = uxbox.util.geom.matrix_impl;
|
||||||
|
// self.Matrix = Matrix;
|
||||||
|
// self.sayHello = function() {
|
||||||
|
// console.log("hello");
|
||||||
|
// }
|
||||||
|
});
|
Loading…
Add table
Add a link
Reference in a new issue