mirror of
https://github.com/penpot/penpot.git
synced 2025-03-13 00:01:51 -05: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
Reference in a new issue