0
Fork 0
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:
Andrey Antukh 2020-02-01 01:16:47 +01:00
parent 89f65a15de
commit 065ed23c79
2 changed files with 471 additions and 0 deletions

View 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))
);
}
};
});

View 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");
// }
});