grid-apps-cmms/src/geo/slope.js

114 lines
2.7 KiB
JavaScript
Raw Normal View History

2020-06-03 22:39:30 -04:00
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
2017-04-18 22:22:29 -04:00
2017-04-18 17:09:33 -04:00
"use strict";
// dep: geo.base
// use: geo.line
// use: geo.point
gapp.register("geo.slope", [], (root, exports) => {
2022-01-31 20:50:19 -05:00
const { base } = root;
2022-01-31 20:50:19 -05:00
const { config } = base;
2022-01-31 20:50:19 -05:00
const ABS = Math.abs,
DEG2RAD = Math.PI / 180,
RAD2DEG = 180 / Math.PI;
class Slope {
constructor(p1, p2, dx, dy) {
2020-06-03 22:39:30 -04:00
this.dx = p1 && p2 ? p2.x - p1.x : dx;
this.dy = p1 && p2 ? p2.y - p1.y : dy;
this.angle = Math.atan2(this.dy, this.dx) * RAD2DEG;
}
2022-01-31 20:50:19 -05:00
toString() {
2017-04-18 17:09:33 -04:00
return [this.dx, this.dy, this.angle].join(',');
2022-01-31 20:50:19 -05:00
}
2017-04-18 17:09:33 -04:00
2022-01-31 20:50:19 -05:00
clone() {
2020-12-19 23:24:03 -05:00
return new Slope(null, null, this.dx, this.dy);
2022-01-31 20:50:19 -05:00
}
2020-12-19 23:24:03 -05:00
2022-01-31 20:50:19 -05:00
isSame(s) {
2017-04-18 17:09:33 -04:00
// if very close to vertical or horizontal, they're the same
2022-01-31 20:50:19 -05:00
if (ABS(this.dx) <= config.precision_merge && ABS(s.dx) <= config.precision_merge) return true;
if (ABS(this.dy) <= config.precision_merge && ABS(s.dy) <= config.precision_merge) return true;
2017-04-18 17:09:33 -04:00
// check angle within a range
2022-01-31 20:50:19 -05:00
let prec = Math.min(1/Math.sqrt(this.dx * this.dx + this.dy * this.dy), config.precision_slope_merge);
return angleWithinDelta(this.angle, s.angle, prec || config.precision_slope);
}
normal() {
2020-06-03 22:39:30 -04:00
let t = this.dx;
2017-04-18 17:09:33 -04:00
this.dx = -this.dy;
this.dy = t;
this.angle = Math.atan2(this.dy, this.dx) * RAD2DEG;
return this;
2022-01-31 20:50:19 -05:00
}
2017-04-18 17:09:33 -04:00
2022-01-31 20:50:19 -05:00
invert() {
2020-12-19 23:24:03 -05:00
this.dx = -this.dx;
this.dy = -this.dy;
this.angle = Math.atan2(this.dy, this.dx) * RAD2DEG;
return this;
}
2022-01-31 20:50:19 -05:00
toUnit() {
2020-06-03 22:39:30 -04:00
let max = Math.max(ABS(this.dx), ABS(this.dy));
2017-04-18 17:09:33 -04:00
this.dx = this.dx / max;
this.dy = this.dy / max;
return this;
2022-01-31 20:50:19 -05:00
}
2017-04-18 17:09:33 -04:00
2022-01-31 20:50:19 -05:00
factor(f) {
2017-04-18 17:09:33 -04:00
this.dx *= f;
this.dy *= f;
return this;
2022-01-31 20:50:19 -05:00
}
invert() {
2017-04-18 17:09:33 -04:00
this.dx = -this.dx;
this.dy = -this.dy;
2020-11-11 14:40:15 -05:00
this.angle = 180 - this.angle;
2017-04-18 17:09:33 -04:00
return this;
2022-01-31 20:50:19 -05:00
}
2017-04-18 17:09:33 -04:00
2022-01-31 20:50:19 -05:00
angleDiff(s2,sign) {
2020-12-03 14:46:20 -05:00
const n1 = this.angle;
const n2 = s2.angle;
let diff = n2 - n1;
while (diff < -180) diff += 360;
while (diff > 180) diff -= 360;
return sign ? diff : Math.abs(diff);
2017-04-18 17:09:33 -04:00
}
2022-01-31 20:50:19 -05:00
}
/**
* returns true if the difference between a & b is less than v
*/
function minDeltaABS(a,b,v) {
return ABS(a-b) < v;
}
function angleWithinDelta(a1, a2, delta) {
return (ABS(a1-a2) <= delta || 360-ABS(a1-a2) <= delta);
}
function newSlope(p1, p2, dx, dy) {
return new Slope(p1, p2, dx, dy);
}
function newSlopeFromAngle(angle) {
2022-01-31 20:50:19 -05:00
return newSlope(0,0,
Math.cos(angle * DEG2RAD),
Math.sin(angle * DEG2RAD)
);
}
gapp.overlay(base, {
Slope,
newSlope,
newSlopeFromAngle
});
2017-04-18 17:09:33 -04:00
});