Base Site Upload
This commit is contained in:
1 parent
414e123a85
commit
96a4aef921
7 files changed
+21503
No files matched your search
+132
@@ -0,0 +1,132 @@
|
||||
'use strict';
|
||||
import * as Vector from './vectorlib.js';
|
||||
/** A 3D vector
|
||||
* @typedef {Object} Vector
|
||||
* @property {number} x
|
||||
* @property {number} y
|
||||
* @property {number} z
|
||||
*/
|
||||
|
||||
/** Estimate the maximum grade of the bezier.
|
||||
* @param {Vector} p1 - Start
|
||||
* @param {Vector} h1 - Handle 1
|
||||
* @param {Vector} h2 - Handle 2
|
||||
* @param {Vector} p2 - End
|
||||
* @param {number} iterationCount - How many steps along the bezier to check
|
||||
* @returns {number} Grade as a decimal
|
||||
*/
|
||||
export function estimateMaxGrade(p1, h1, h2, p2, iterationCount = 50){
|
||||
let grade = 0;
|
||||
let totalGrade = 0;
|
||||
for(let i=0; i<=iterationCount; i++){
|
||||
let tan = evaluateVelocity(p1, h1, h2, p2, i/iterationCount);
|
||||
let newGrade = Math.abs(tan.y)/Math.sqrt(tan.x*tan.x + tan.z*tan.z);
|
||||
grade = Math.max(grade, newGrade);
|
||||
totalGrade += newGrade;
|
||||
}
|
||||
return grade;
|
||||
}
|
||||
|
||||
/** Estimate the length of the bezier.
|
||||
* @param {Vector} p1 - Start
|
||||
* @param {Vector} h1 - Handle 1
|
||||
* @param {Vector} h2 - Handle 2
|
||||
* @param {Vector} p2 - End
|
||||
* @param {number} iterationCount - How many steps along the bezier to check
|
||||
* @returns {number} Length
|
||||
*/
|
||||
export function estimateLength(p1, h1, h2, p2, iterationCount = 50){
|
||||
let length = 0;
|
||||
let prevPos = p1;
|
||||
let curPos = {};
|
||||
for(let i=1; i<=iterationCount; i++){
|
||||
curPos = evaluatePoint(p1, h1, h2, p2, i/iterationCount);
|
||||
length += Vector.distance(prevPos, curPos);
|
||||
prevPos = curPos;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
/** Estimate the maximum 3D curvature of the bezier.
|
||||
* @param {Vector} p1 - Start
|
||||
* @param {Vector} h1 - Handle 1
|
||||
* @param {Vector} h2 - Handle 2
|
||||
* @param {Vector} p2 - End
|
||||
* @param {number} iterationCount - How many steps along the bezier to check
|
||||
* @returns {number} Curvature, take `1/curvature` to get radius.
|
||||
*/
|
||||
export function estimateMaxCurvature(p1, h1, h2, p2, iterationCount = 50){
|
||||
let curvature = 0;
|
||||
let t = 0;
|
||||
let vel = {};
|
||||
for(let i=0; i<iterationCount; i++){
|
||||
t = i/iterationCount;
|
||||
vel = evaluateVelocity(p1, h1, h2, p2, t);
|
||||
curvature = Math.max(curvature,
|
||||
Vector.length(Vector.cross(vel, evaluateAcceleration(p1, h1, h2, p2, t)))
|
||||
/Math.pow(Vector.length(vel),3));
|
||||
}
|
||||
return curvature;
|
||||
}
|
||||
|
||||
/** Evaluate the bezier at `t`, getting position.
|
||||
* @param {Vector} p1 - Start
|
||||
* @param {Vector} h1 - Handle 1
|
||||
* @param {Vector} h2 - Handle 2
|
||||
* @param {Vector} p2 - End
|
||||
* @param {number} t - 0 to 1 of how far into the curve to check.
|
||||
* @returns {Vector}
|
||||
*/
|
||||
export function evaluatePoint(p1, h1, h2, p2, t){
|
||||
let result = {};
|
||||
let t3 = t*t*t;
|
||||
let t2 = t*t;
|
||||
let p1v = -t3 + 3*t2 - 3*t + 1;
|
||||
let h1v = 3*t3 - 6*t2 + 3*t;
|
||||
let h2v = -3*t3 + 3*t2;
|
||||
for(const axis of ['x', 'y', 'z']){
|
||||
result[axis] = p1[axis]*p1v + h1[axis]*h1v + h2[axis]*h2v + p2[axis]*t3;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Evaluate the bezier's first derivative at `t`, getting velocity.
|
||||
* @param {Vector} p1 - Start
|
||||
* @param {Vector} h1 - Handle 1
|
||||
* @param {Vector} h2 - Handle 2
|
||||
* @param {Vector} p2 - End
|
||||
* @param {number} t - 0 to 1 of how far into the curve to check.
|
||||
* @returns {Vector}
|
||||
*/
|
||||
export function evaluateVelocity(p1, h1, h2, p2, t){
|
||||
let result = {};
|
||||
let t2 = t*t;
|
||||
let p1v = -3*t2 + 6*t -3;
|
||||
let h1v = 9*t2 - 12*t +3;
|
||||
let h2v = -9*t2 + 6*t;
|
||||
let p2v = 3*t2;
|
||||
for(const axis of ['x', 'y', 'z']){
|
||||
result[axis] = p1[axis]*p1v + h1[axis]*h1v + h2[axis]*h2v + p2[axis]*p2v;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Evaluate the bezier's second derivative at `t`, getting acceleration.
|
||||
* @param {Vector} p1 - Start
|
||||
* @param {Vector} h1 - Handle 1
|
||||
* @param {Vector} h2 - Handle 2
|
||||
* @param {Vector} p2 - End
|
||||
* @param {number} t - 0 to 1 of how far into the curve to check.
|
||||
* @returns {Vector}
|
||||
*/
|
||||
export function evaluateAcceleration(p1, h1, h2, p2, t){
|
||||
let result = {};
|
||||
let p1v = -6*t + 6;
|
||||
let h1v = 18*t -12;
|
||||
let h2v = -18*t + 6;
|
||||
let p2v = 6*t;
|
||||
for(const axis of ['x', 'y', 'z']){
|
||||
result[axis] = p1[axis]*p1v + h1[axis]*h1v + h2[axis]*h2v + p2[axis]*p2v;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
'use strict';
|
||||
|
||||
const gradeIncrements = [
|
||||
0.0498,
|
||||
0.04,
|
||||
0.035,
|
||||
0.03,
|
||||
0.025,
|
||||
0.02,
|
||||
0.015,
|
||||
0.01,
|
||||
0.005,
|
||||
0.001
|
||||
]
|
||||
|
||||
export function randomRange(min=0.0, max=1.0){
|
||||
return Math.random()*(max-min) + min;
|
||||
}
|
||||
|
||||
export function rgba2hex(r,g,b,a=1.0){
|
||||
r = Math.min(Math.max(r,0),1);
|
||||
g = Math.min(Math.max(g,0),1);
|
||||
b = Math.min(Math.max(b,0),1);
|
||||
a = Math.min(Math.max(a,0),1);
|
||||
return `#${
|
||||
Math.round(r*255).toString(16).padStart(2, '0').substring(0,2)
|
||||
}${
|
||||
Math.round(g*255).toString(16).padStart(2, '0').substring(0,2)
|
||||
}${
|
||||
Math.round(b*255).toString(16).padStart(2, '0').substring(0,2)
|
||||
}${
|
||||
Math.round(a*255).toString(16).padStart(2, '0').substring(0,2)
|
||||
}`;
|
||||
}
|
||||
|
||||
export function gradeToClass(grade){
|
||||
let result = '';
|
||||
for(let j=0; j<gradeIncrements.length; j++){
|
||||
if(grade > gradeIncrements[j]){
|
||||
result = `grade_${gradeIncrements.length-(j+1)}`;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(result) return result;
|
||||
}
|
||||
|
||||
export function radiusToSpeed(radius){
|
||||
if(radius < 50) return 10;
|
||||
else if(radius < 70) return 20;
|
||||
else if(radius < 95) return 30;
|
||||
else if(radius < 130) return 40;
|
||||
else if(radius < 170) return 50;
|
||||
else if(radius < 230) return 60;
|
||||
else if(radius < 360) return 70;
|
||||
else if(radius < 700) return 80;
|
||||
else if(radius < 900) return 90;
|
||||
else if(radius < 1200) return 100;
|
||||
return 120;
|
||||
}
|
||||
|
||||
export function clamp(v, min = 0, max = 1){
|
||||
return Math.max(Math.min(v, max), min);
|
||||
}
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
'use strict';
|
||||
|
||||
/** A 3D vector
|
||||
* @typedef {Object} Vector
|
||||
* @property {number} x
|
||||
* @property {number} y
|
||||
* @property {number} z
|
||||
*/
|
||||
|
||||
/** Get Euclidean Distance between v1 and v2.
|
||||
* @param {Vector} v1
|
||||
* @param {Vector} v2
|
||||
* @returns {number}
|
||||
*/
|
||||
export function distance(v1, v2){
|
||||
return Math.sqrt(Math.pow(v1.x-v2.x, 2)+Math.pow(v1.y-v2.y, 2)+Math.pow(v1.z-v2.z, 2));
|
||||
}
|
||||
|
||||
/** Get Manhattan Distance between v1 and v2.
|
||||
* @param {Vector} v1
|
||||
* @param {Vector} v2
|
||||
* @returns {number}
|
||||
*/
|
||||
export function manhattanDistance(v1, v2){
|
||||
return Math.abs(v1.x-v2.x) + Math.abs(v1.y-v2.y) + Math.abs(v1.z-v2.z);
|
||||
}
|
||||
|
||||
/** Get Distance between v1 and v2 with decreasing accuracy over distance.
|
||||
* @param {Vector} v1
|
||||
* @param {Vector} v2
|
||||
* @returns {number}
|
||||
*/
|
||||
export function roughDistance(v1, v2, farThreshold = 1600){
|
||||
const halfFar = farThreshold/2;
|
||||
let subvec = absSubtract(v1, v2);
|
||||
if(subvec.x > farThreshold) return subvec.x;
|
||||
else if(subvec.y > farThreshold) return subvec.y;
|
||||
else if(subvec.z > farThreshold) return subvec.z;
|
||||
else if(subvec.x > halfFar || subvec.y > halfFar || subvec.z > halfFar) return subvec.x+subvec.y+subvec.z;
|
||||
return distance(v1, v2);
|
||||
}
|
||||
|
||||
/** Get length of a vector.
|
||||
* @param {Vector} v1
|
||||
* @returns {number}
|
||||
*/
|
||||
export function length(v1){
|
||||
return Math.sqrt(v1.x*v1.x + v1.y*v1.y + v1.z*v1.z);
|
||||
}
|
||||
|
||||
/** Return the same vector with a length of 1.
|
||||
* @param {Vector} v1
|
||||
* @returns {Vector}
|
||||
*/
|
||||
export function normalize(v1){
|
||||
const len = length(v1);
|
||||
if(len === 0) return v1;
|
||||
return {x:v1.x/len, y:v1.y/len, z:v1.z/len};
|
||||
}
|
||||
|
||||
/** Get the cross-product of v1 and v2
|
||||
* @param {Vector} v1
|
||||
* @param {Vector} v2
|
||||
* @param {boolean} normalize - normalize the input vectors
|
||||
* @returns {Vector}
|
||||
*/
|
||||
export function cross(v1, v2, normalize = false){
|
||||
if(normalize){
|
||||
v1 = normalize(v1);
|
||||
v2 = normalize(v2);
|
||||
}
|
||||
return {
|
||||
x: v1.y*v2.z - v1.z*v2.y,
|
||||
y: v1.z*v2.x - v1.x*v2.z,
|
||||
z: v1.x*v2.y - v1.y*v2.x
|
||||
};
|
||||
}
|
||||
|
||||
/** Get the dot-product of v1 and v2
|
||||
* @param {Vector} v1
|
||||
* @param {Vector} v2
|
||||
* @param {boolean} normalize - normalize the input vectors
|
||||
* @returns {number}
|
||||
*/
|
||||
export function dot(v1, v2, normalize = false){
|
||||
let len = 1;
|
||||
if(normalize) len = 1/(length(v1) * length(v2));
|
||||
return v1.x*v2.x*len + v1.y*v2.y*len + v1.z*v2.z*len;
|
||||
}
|
||||
|
||||
/** Are v1 and v2 within range of each other.
|
||||
* @param {Vector} v1
|
||||
* @param {Vector} v2
|
||||
* @param {number} range
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isWithinAARange(v1, v2, range){
|
||||
return !(Math.abs(v2.x-v1.x) > range || Math.abs(v2.y-v1.y) > range || Math.abs(v2.z-v1.z) > range);
|
||||
}
|
||||
|
||||
export function subtract(v1, v2){
|
||||
return {x:v1.x-v2.x, y:v1.y-v2.y, z:v1.y-v2.y};
|
||||
}
|
||||
|
||||
export function absSubtract(v1, v2){
|
||||
return {x:Math.abs(v1.x-v2.x), y:Math.abs(v1.y-v2.y), z:Math.abs(v1.y-v2.y)};
|
||||
}
|
||||
|
||||
class vector {
|
||||
constructor(x,y,z){
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user