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

139 lines
3.5 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";
(function() {
if (self.base.Slope) return;
2020-06-03 22:39:30 -04:00
const BASE = self.base,
2017-04-18 17:09:33 -04:00
CONF = BASE.config,
ABS = Math.abs,
2017-10-28 13:30:08 -04:00
PRO = Slope.prototype,
2017-04-18 17:09:33 -04:00
DEG2RAD = Math.PI / 180,
RAD2DEG = 180 / Math.PI;
BASE.Slope = Slope;
BASE.newSlope = newSlope;
BASE.newSlopeFromAngle = function(angle) {
return newSlope(0,0,
Math.cos(angle * DEG2RAD),
Math.sin(angle * DEG2RAD)
);
};
2020-06-03 22:39:30 -04:00
/**
*
* @param p1
* @param p2
* @param dx
* @param dy
* @constructor
*/
function Slope(p1, p2, dx, dy) {
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;
}
2017-04-18 17:09:33 -04:00
/** ******************************************************************
* Slope Prototype Functions
******************************************************************* */
2017-10-28 13:30:08 -04:00
PRO.toString = function() {
2017-04-18 17:09:33 -04:00
return [this.dx, this.dy, this.angle].join(',');
};
/**
* @param {Slope} s
* @returns {boolean}
*/
2017-10-28 13:30:08 -04:00
PRO.isSame = function(s) {
2017-04-18 17:09:33 -04:00
// if very close to vertical or horizontal, they're the same
if (ABS(this.dx) <= CONF.precision_merge && ABS(s.dx) <= CONF.precision_merge) return true;
if (ABS(this.dy) <= CONF.precision_merge && ABS(s.dy) <= CONF.precision_merge) return true;
// check angle within a range
2020-06-03 22:39:30 -04:00
let prec = Math.min(1/Math.sqrt(this.dx * this.dx + this.dy * this.dy), CONF.precision_slope_merge);
2017-04-18 17:09:33 -04:00
return angleWithinDelta(this.angle, s.angle, prec || CONF.precision_slope);
};
/**
* turn slope 90 degrees
*
* @returns {Slope}
*/
2017-10-28 13:30:08 -04:00
PRO.normal = function() {
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;
};
2017-10-28 13:30:08 -04:00
PRO.toUnit = function() {
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;
};
2017-10-28 13:30:08 -04:00
PRO.factor = function(f) {
2017-04-18 17:09:33 -04:00
this.dx *= f;
this.dy *= f;
return this;
};
/**
* reverse (180 degree) slope
*
* @returns {Slope}
*/
2017-10-28 13:30:08 -04:00
PRO.invert = function() {
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;
};
2020-12-03 14:46:20 -05:00
PRO.angleDiff = function(s2,sign) {
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
/** ******************************************************************
* Connect to base and Helpers
******************************************************************* */
/**
* returns true if the difference between a & b is less than v
*
* @param {number} a
* @param {number} b
* @param {number} v
* @returns {boolean}
*/
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);
}
/**
*
* @param p1
* @param p2
* @param dx
* @param dy
* @returns {Slope}
*/
function newSlope(p1, p2, dx, dy) {
return new Slope(p1, p2, dx, dy);
}
})();