More math added to math.js bluepixle currently broken as I'm in the middle of cleaning

This commit is contained in:
bluesaxman 2022-02-08 17:10:24 -07:00
parent 1611f58512
commit 2ed2791528
2 changed files with 224 additions and 428 deletions

View File

@ -12,32 +12,62 @@ function rad2deg (rad) {
class vector { class vector {
constructor(dimentions=[0]) { constructor(dimentions=[0]) {
var me = this; var me = this;
this.d = Array.isArray(dimentions) ? dimentions.map(d => !isNaN(d)) : [0]; this.d = Array.isArray(dimentions) ? dimentions.map(d => !isNaN(d) ? d : 0) : [0];
if (me.d.length == 2) { if (me.d.length == 2) {
this.getRadAngle = function (vec) { this.getRadAngle = function (from) {
vec = vec instanceof vector ? vec : new vector([0,0]); from = from instanceof vector ? from : new vector([0,0]);
var xydims = vec.d.length == 2 ? vec.d : [...me.d.map((d,i) => vec[i] ? vec[i] : 0)]; return Math.atan2(me.d[1] - from.d[1], me.d[0] - from.d[0]);
return Math.atan2(xydims[1] - me.d[1], xydims[0] - me.d[0]);
} }
this.getDegAngle = function (vec) { this.getDegAngle = function (from) {
return rad2deg(me.getRadAngle(vec)); return rad2deg(me.getRadAngle(from));
} }
this.resize = function (newLength) { this.resize = function (newLength) {
var angle = me.getDegAngle(); var angle = me.getDegAngle();
var soh = Math.sin(angle) * newLength; var soh = Math.sin(angle) * newLength;
var cah = Math.cos(angle) * newLength; var cah = Math.cos(angle) * newLength;
me.d = [cah,soh]; return new vector([cah,soh]);
}
this.rotate = function (rad) {
var theta = me.getRadAngle() + rad;
var amp = me.getDistance();
return new vector([Math.cos(theta)*amp,Math.sin(theta)*amp]);
}
this.reflect = function (surfaceVector) {
var theta = (2 * (surfaceVector.getDegAngle() + 90)) - me.getDegAngle();
var amp = me.getDistance();
return new vector([Math.cos(theta)*amp,Math.sin(theta)*amp]);
} }
this.getPerp = function () {
return me.rotate(deg2rad(90));
}
this.slope = function () {
return me.d[1] / me.d[0];
}
this.yIntercept = function () {
if (Math.abs(me.slope()) != Infinity) {
return -(me.slope()*me.d[0])+me.d[1];
} else {
return me.d[0];
}
}
this.xIntercept = function () {
return -me.yIntercept()/me.slope();
}
} }
} }
add(vec=new vector([...this.d.map(d => 0)])) { add(vec=new vector([...this.d.map(d => 0)])) {
vec = vec instanceof vector ? vec : new vector([0]); vec = vec instanceof vector ? vec : new vector([0]);
var longest = vec.d.length > this.d.length ? vec.d : this.d; var longest = vec.d.length >= this.d.length ? vec.d : this.d;
var shortest = vec.d.length < this.d.length ? vec.d : this.d; var shortest = vec.d.length < this.d.length ? vec.d : this.d;
return new vector([...longest.map(function (value,index) { return new vector([...longest.map(function (value,index) {
var small = shortest[index]; var small = shortest[index];
@ -46,8 +76,8 @@ class vector {
} }
mult(vec=new vector([...this.d.map(d => 1)])) { mult(vec=new vector([...this.d.map(d => 1)])) {
vec = vec instanceof vector ? vec : new vector([0]); vec = vec instanceof vector ? vec : new vector([...this.d.map(d => 1)]);
var longest = vec.d.length > this.d.length ? vec.d : this.d; var longest = vec.d.length >= this.d.length ? vec.d : this.d;
var shortest = vec.d.length < this.d.length ? vec.d : this.d; var shortest = vec.d.length < this.d.length ? vec.d : this.d;
return new vector([...longest.map(function (value,index) { return new vector([...longest.map(function (value,index) {
var small = shortest[index]; var small = shortest[index];
@ -68,11 +98,59 @@ class vector {
origin = origin instanceof vector ? origin : new vector([...this.d.map(d => 0)]); origin = origin instanceof vector ? origin : new vector([...this.d.map(d => 0)]);
return Math.sqrt(this.d.map(function (value, index) { return Math.sqrt(this.d.map(function (value, index) {
var ori = !isNaN(origin.d[index]) ? origin.d[index] : 0; var ori = !isNaN(origin.d[index]) ? origin.d[index] : 0;
return Math.pow(ori - value, 2); return Math.pow(Math.abs(ori - value), 2);
}).reduce((a,b) => a + b)); }).reduce((a,b) => a + b));
} }
} }
class lineSeg {
constructor (pointA,pointB) {
this.pointA = pointA;
this.pointB = pointB;
}
intersect(line) {
if (line instanceof lineSeg) {
var x1 = this.pointA.d[0];
var x2 = this.pointB.d[0];
var x3 = line.pointA.d[0];
var x4 = line.pointB.d[0];
var y1 = this.pointA.d[1];
var y2 = this.pointB.d[1];
var y3 = line.pointA.d[1];
var y4 = line.pointB.d[1];
var deltaAX = x1 - x2;
var deltaBX = x3 - x4;
var deltaAY = y1 - y2;
var deltaBY = y3 - y4;
// I don't know wtf to call these
var ground = deltaAX*deltaBY-deltaAY*deltaBX;
var Across = x1*y2 - y1*x2;
var Bcross = x3*y4 - y3*x4;
var x = (Across*deltaBX-deltaAX*Bcross)/ground;
var y = (Across*deltaBY-deltaAY*Bcross)/ground;
if (
(new bound([x1],[x2])).inbounds([x]) &&
(new bound([x3],[x4])).inbounds([x]) &&
(new bound([y1],[y2])).inbounds([y]) &&
(new bound([y3],[y4])).inbounds([y])) {
return new vector([x,y]);
} else {
return false;
}
} else {
throw new TypeError("must check against line");
}
}
}
function rad2vec (rad) { function rad2vec (rad) {
var x = Math.cos(rad); var x = Math.cos(rad);
var y = Math.sin(rad); var y = Math.sin(rad);
@ -83,19 +161,6 @@ function deg2vec (deg) { //abstraction, really just for sanity
return rad2vec(deg2rad(deg)); return rad2vec(deg2rad(deg));
} }
function getAngle(ax,ay,bx,by) {
var deltaX = bx - ax;
var deltaY = by - ay;
return rad2deg(Math.atan2(deltaY,deltaX));
}
function reflect(inAngle,surfaceAngle) {
var normal = surfaceAngle+90;
var theta1 = normal - inAngle;
var theta2 = normal + theta1;
return theta2;
}
class bound { class bound {
constructor (min=[-Infinity],max=[Infinity]) { constructor (min=[-Infinity],max=[Infinity]) {
// Insure both inputs are arrays with valid numbers // Insure both inputs are arrays with valid numbers
@ -238,4 +303,3 @@ class matrix {
} }
} }
} }

View File

@ -2,37 +2,145 @@
// This library is to help make using canvas tags easier // This library is to help make using canvas tags easier
// requires bluemath.js // requires bluemath.js
function drift(object) { class shape {
if (object instanceof container) { constructor(type,coordinates,dimentions,rotation,fColor,bColor,bStyle,extraObject) {
object.direction = "number" == typeof object.direction ? this.type = "string" == typeof type ? (["rect","elipse","image"].includes(type) ? type : "rect") : "rect";
object.direction : Math.floor(Math.random()*360); this.coordinates = coordinates instanceof vector ? coordinates : new vector([0,0]);
object.speed = "number" == typeof object.speed ? object.speed : 1; this.dimentions = dimentions instanceof vector ? dimentions : new vector([1,1]);
object.move(object.direction,object.speed); this.rotation = rotation instanceof vector ? rotation : new vector([0,1]);
} else { this.fColor = "string" == typeof fColor ? fColor : undefined;
return new TypeError("must provide a container object"); this.bColor = "string" == typeof bColor ? bColor : undefined;
this.bStyle = "number" == typeof bStyle ? bStyle : undefined;
this.extraObject = "object" == typeof extraObject ? extraObject : {};
if ("image" == this.type) {
this.imageData =
this.extraObject.imageData instanceof ImageData ?
this.extraObject.imageData :
new ImageData(
new Uint8ClampedArray([
255,0,0,255,
0,0,0,0,
255,0,0,255,
0,0,0,0,
255,0,0,255,
0,0,0,0,
255,0,0,255,
0,0,0,0,
255,0,0,255
]),3,3);
this.image = createImageBitmap(this.imageData);
}
}
render(ctx,position,rotation) {
// Save current defaults
var local = {};
local.fillStyle = "string" == typeof ctx.fillStyle ? ctx.fillStyle : undefined;
local.strokeStyle = "string" == ctx.strokeStyle ? ctx.strokeStyle : undefined;
local.lineWidth = "number" == ctx.lineWidth ? ctx.lineWidth : undefined;
local.imageSmoothingEnabled = ctx.imageSmoothingEnabled;
// calculate origin and rotation
var origin = this.coordinates.add(position instanceof vector ? position : new vector([0,0]));
var origRot = this.rotation.getRadAngle() + (rotation instanceof vector ? rotation : new vector([0,1])).getRadAngle();
var center = origin.add(this.dimentions.mag(0.5));
// Rotate
ctx.translate(center.d[0],center.d[1]);
ctx.rotate(origRot);
ctx.translate(-center.d[0],-center.d[1]);
// Draw
ctx.fillStyle = this.fcolor;
ctx.strokeStyle = this.bColor;
ctx.lineWidth = this.bStyle;
if("rect" == this.type) {
ctx.fillRect(origin.d[0],origin.d[1],this.dimentions.d[0],this.dimentions.d[1]);
ctx.strokeRect(origin.d[0],origin.d[1],this.dimentions.d[0],this.dimentions.d[1]);
} else if ("elipse" == this.type) {
ctx.beginPath();
ctx.ellipse(center.d[0],center.d[1],dimentions.d[0]/2,dimentions.d[1]/2,0,0,360);
ctx.stroke();
ctx.fill();
} else if ("image" == this.type) {
this.image.then(function (image) {
ctx.imageSmoothingEnabled = false;
ctx.drawImage(image,origin.d[0],origin.d[0],this.dimentions.d[0],this.dimentions.d[1]);
});
}
// restore context defaults
ctx.setTransform(1,0,0,1,0,0);
ctx.fillStyle = local.fillStyle;
ctx.strokeStyle = local.strokeStyle;
ctx.lineWidth = local.lineWidth;
ctx.imageSmoothingEnabled = local.imageSmoothingEnabled;
}
grow (amp) {
this.dimentions = this.dimentions.amp(amp);
} }
} }
function bounce(object, surface, impactTime) { class container {
object.direction = reflect(object.direction,surface.direction-90); constructor(coordinates,dimentions,rotation) {
object.speed = object.speed; this.coordinates = coordinates instanceof vector ? coordinates : new vector([0,0]);
} this.size = dimentions instanceof vector ? dimentions : new vector([1,1]);
this.rotation = rotation instanceof vector ? rotation : new vector([0,1]);
function valueBetween (value,low,high) { this.movementVector = new vector([0,0]);
var Tlow = low <= high ? low : high; this.shapes = [];
var Thigh = high >= low ? high : low; this.containers = [];
if ( (value >= Tlow) & (value <= Thigh) ) {
return true;
} else {
return false;
} }
}
function pointInside (x,y,top,right,bottom,left) { addShape(myShape) {
if ( valueBetween(x,left,right) & valueBetween(y,top,bottom) ) { if (myShape instanceof shape) {
return true; this.shapes.push(myShape);
} else { } else {
return false; throw new TypeError("addShape Method must be given a shape object");
}
}
addContainer(myContainer) {
if (myContainer instanceof container) {
this.containers.push(container);
} else {
throw new TypeError("addContainer Method must be given a container object");
}
}
move(delta) {
delta = !isNaN(delta) ? delta : 0;
this.coordinates = this.coordinates.add(this.movementVector.mag(delta));
}
renderContainer(ctx,position,rotation) {
position = position instanceof vector ? position : new vector([0,0]);
rotation = rotation instanceof vector ? rotation : new vector([0,1]);
var refPos = this.coordinates.add(position);
var refRot = this.rotation.add(rotation);
if (this.shapes.length) {
this.shapes.forEach(shape => shape.render(ctx,refPos,refRot));
}
if (this.containers.length) {
this.containers.forEach(container => container.renderContainer(ctx,refPos,refRot));
}
}
grow(amp) {
amp = !isNaN(amp) ? amp : 1;
this.position.mag(amp);
if (this.shapes.length) {
this.shapes.forEach(shape => shape.grow(amp));
}
if (this.containers.length) {
this.containers.forEach( container => container.grow(amp));
}
}
bounce(surface) {
this.movementVector = this.movementVector.reflect(surface);
}
overlap(otherContainer, callbackFunction) {
///////////////////////////////// work starts here
this.
} }
} }
@ -103,44 +211,6 @@ function chase (source,target,max,minDis,acc) {
} }
} }
function rect (ctx,xOrigin,yOrigin,width,height,fill,stroke,outlineWidth) {
// Save current defaults
var local = {};
local.fillStyle = "string" == typeof ctx.fillStyle ? ctx.fillStyle : undefined;
local.strokeStyle = "string" == ctx.strokeStyle ? ctx.strokeStyle : undefined;
local.lineWidth = "number" == ctx.lineWidth ? ctx.lineWidth : undefined;
// Check inputs
ctx.fillStyle = "string" == typeof fill ? fill : local.fillStyle;
ctx.strokeStyle = "string" == typeof stroke ? stroke : "rgba(0,0,0,0)";
ctx.lineWidth = "number" == typeof outlineWidth ? outlineWidth : 1;
ctx.fillRect(xOrigin,yOrigin,width,height);
ctx.strokeRect(xOrigin,yOrigin,width,height);
// restore context defaults
ctx.fillStyle = local.fillStyle;
ctx.strokeStyle = local.strokeStyle;
ctx.lineWidth = local.lineWidth;
}
function elip (ctx,xOrigin,yOrigin,width,height,fill,stroke,outlineWidth) {
// Save current defaults
var local = {};
local.fillStyle = ctx.fillStyle;
local.strokeStyle = ctx.strokeStyle;
local.lineWidth = ctx.lineWidth;
// Check inputs
ctx.fillStyle = "string" == typeof fill ? fill : local.fillStyle;
ctx.strokeStyle = "string" == typeof stroke ? stroke : "rgba(0,0,0,0)";
ctx.lineWidth = "number" == typeof outlineWidth ? outlineWidth : 1;
ctx.beginPath();
ctx.ellipse(xOrigin,yOrigin,width,height,0,0,360);
ctx.stroke();
ctx.fill();
// restore context defaults
ctx.fillStyle = local.fillStyle;
ctx.strokeStyle = local.strokeStyle;
ctx.lineWidth = local.lineWidth;
}
function drawPixel (ctx, x, y, r, g, b, a) { function drawPixel (ctx, x, y, r, g, b, a) {
// Always validate your input // Always validate your input
if (false == ctx instanceof CanvasRenderingContext2D) { if (false == ctx instanceof CanvasRenderingContext2D) {
@ -160,344 +230,6 @@ function drawPixel (ctx, x, y, r, g, b, a) {
ctx.putImageData(new ImageData(new Uint8ClampedArray([r,g,b,a]),1,1),x,y); ctx.putImageData(new ImageData(new Uint8ClampedArray([r,g,b,a]),1,1),x,y);
} }
class lineSeg {
constructor(x1,y1,x2,y2) {
this.pointA = new point(x1,y1);
this.pointB = new point(x2,y2);
this.center = new point((x1+x2)/2,(y1+y2)/2);
this.length = Math.sqrt(
Math.pow(Math.abs(x2-x1),2)
+Math.pow(Math.abs(y2-y1),2)
);
this.angle = getAngle(x1,y1,x2,y2);
}
adjustA(length) {
length = "number" == typeof length ? length : 0;
var vecC2A = new vector(getAngle(
this.center.x,
this.center.y,
this.pointA.x,
this.pointA.y),
this.length/2);
vecC2A.adjustMag(length);
this.pointA = vecC2A.executeVector(this.center.x,this.center.y);
this.center.setCoords(
(this.pointA.x+this.pointB.x)/2,
(this.pointA.y+this.pointB.y)/2);
this.length += length;
}
adjustB(length) {
length = "number" == typeof length ? length : 0;
var vecC2B = new vector(
getAngle(
this.center.x,
this.center.y,
this.pointB.x,
this.pointB.y),
this.length/2);
vecC2B.adjustMag(length);
this.pointB = vecC2B.executeVector(this.center.x,this.center.y);
this.center.setCoords(
(this.pointA.x+this.pointB.x)/2,
(this.pointA.y+this.pointB.y)/2);
this.length += length;
}
adjustCenter(length) {
adjustA(length/2);
adjustB(length/2);
}
rotateA(deg) {
var abVec = new vector(
getAngle(
this.pointA.x,
this.pointA.y,
this.pointB.x,
this.pointB.y),
this.length);
abVec.adjustDir(deg);
this.pointB = abVec.executeVector(this.pointA.x,this.pointA.y);
this.center.setCoords(
(this.pointA.x+this.pointB.x)/2,
(this.pointA.y+this.pointB.y)/2);
}
rotateB(deg) {
var baVec = new vector(
getAngle(
this.pointB.x,
this.pointB.y,
this.pointA.x,
this.pointA.y),
this.length);
baVec.adjustDir(deg);
this.pointA = baVec.executeVector(this.pointB.x,this.pointB.y);
this.center.setCoords(
(this.pointA.x+this.pointB.x)/2,
(this.pointA.y+this.pointB.y)/2);
}
rotateCenter(deg) {
var vecC2A = new vector(
getAngle(
this.center.x,
this.center.y,
this.pointA.x,
this.pointA.y),
this.length/2);
var vecC2B = new vector(
getAngle(
this.center.x,
this.center.y,
this.pointB.x,
this.pointB.y),
this.length/2);
vecC2A.adjust(deg);
vecC2B.adjust(deg);
this.pointA = vecC2A.executeVector(this.center.x,this.center.y);
this.pointB = vecC2B.executeVector(this.center.x,this.center.y);
}
getPerp() {
this.rotateCenter(90);
var newline = new lineSeg(
this.pointA.x,
this.pointA.y,
this.pointB.x,
this.pointB.y);
this.rotateCenter(-90);
return newline;
}
slope() {
var deltaX = this.pointB.x - this.pointA.x;
var deltaY = this.pointB.y - this.pointA.y;
return deltaY / deltaX;
}
xIntercept() {
return -this.yIntercept()/this.slope();
}
yIntercept() {
var slope = this.slope();
if (Math.abs(slope) != Infinity) {
return -(slope*this.pointA.x)+this.pointA.y;
} else {
return this.pointA.x;
}
}
intersect(line) {
if (line instanceof lineSeg) {
var x1 = this.pointA.x;
var x2 = this.pointB.x;
var x3 = line.pointA.x;
var x4 = line.pointB.x;
var y1 = this.pointA.y;
var y2 = this.pointB.y;
var y3 = line.pointA.y;
var y4 = line.pointB.y;
var deltaAX = x1 - x2;
var deltaBX = x3 - x4;
var deltaAY = y1 - y2;
var deltaBY = y3 - y4;
// I don't know wtf to call these
var ground = deltaAX*deltaBY-deltaAY*deltaBX;
var Across = x1*y2 - y1*x2;
var Bcross = x3*y4 - y3*x4;
var x = (Across*deltaBX-deltaAX*Bcross)/ground;
var y = (Across*deltaBY-deltaAY*Bcross)/ground;
if (
valueBetween(x,this.pointA.x,this.pointB.x) &&
valueBetween(x,line.pointA.x,line.pointB.x) &&
valueBetween(y,this.pointA.y,this.pointB.y) &&
valueBetween(y,line.pointA.y,line.pointB.y)) {
return new point(x,y);
} else {
return false;
}
} else {
throw new TypeError("must check against line");
}
}
}
class shape {
constructor(type,x,y,sizeX,sizeY,fColor,bColor,bStyle,extraObject) {
this.type = "string" == typeof type ? type : "rect";
this.x = "number" == typeof x ? x : 0;
this.y = "number" == typeof y ? y : 0;
this.sizeX = "number" == typeof sizeX ? sizeX : 1;
this.sizeY = "number" == typeof sizeY ? sizeY : 1;
this.fColor = "string" == typeof fColor ? fColor : undefined;
this.bColor = "string" == typeof bColor ? bColor : undefined;
this.bStyle = "number" == typeof bStyle ? bStyle : undefined;
this.extraObject = "object" == typeof extraObject ? extraObject : {};
if ("rect" == this.type) {
this.render = function (ctx,xPos,yPos) {
rect(
ctx,
this.x+xPos,
this.y+yPos,
this.sizeX,
this.sizeY,
this.fColor,
this.bColor,
this.bStyle);
}
} else if ("elipse" == this.type) {
this.render = function (ctx,xPos,yPos) {
var centerX = this.x+xPos+(this.sizeX/2);
var centerY = this.y+yPos+(this.sizeY/2);
elip(
ctx,
centerX,
centerY,
(this.sizeX/2),
(this.sizeY/2),
this.fColor,
this.bColor,
this.bStyle);
}
} else if ("image" == this.type) {
this.imageData =
this.extraObject.imageData instanceof ImageData ?
this.extraObject.imageData :
new ImageData(
new Uint8ClampedArray([
255,0,0,255,
0,0,0,0,
255,0,0,255,
0,0,0,0,
255,0,0,255,
0,0,0,0,
255,0,0,255,
0,0,0,0,
255,0,0,255
]),3,3);
this.image = createImageBitmap(this.imageData);
this.render = function (ctx,xPos,yPos) {
var x = this.x;
var y = this.y;
var sizeX = this.sizeX;
var sizeY = this.sizeY;
var contextBlur = ctx.imageSmoothingEnabled;
this.image.then(function (image) {
ctx.imageSmoothingEnabled = false;
ctx.drawImage(image,x+xPos,y+yPos,sizeX,sizeY);
ctx.imageSmoothingEnabled = contextBlur;
});
}
} else {
console.log("no valid type defined for shape, defalting to 'rect'");
this.render = function (ctx,xPos,yPos) {
rect(
ctx,
this.x+xPos,
this.y+yPos,
this.sizeX,
this.sizeY,
this.fColor,
this.bColor,
this.bStyle);
}
}
}
grow (amp) {
this.sizeX+=amp;
this.sizeY+=amp;
}
}
class container {
constructor(x,y,height,width,speed,direction) {
this.x = x;
this.y = y;
this.sizeY = height;
this.sizeX = width;
this.speed = "number" == typeof speed ? speed : 0;
this.direction = "number" == typeof direction ? direction : 0;
// Vectors are the future
this.netMovementVector = new vector(
this.direction,
this.speed);
}
setShape(myShape) {
if (myShape instanceof shape) {
this.shape = myShape;
} else {
throw new TypeError("addShape Method must be given a shape object");
}
}
nestContainer() {
this.containerArray = [];
this.addShape = function (newShape) {
if (newShape instanceof shape) {
var containerIndex = this.containerArray.push(
new container(0,0,this.sizeY,this.sizeX));
this.containerArray[containerIndex-1].setShape(newShape);
return this.containerArray[containerIndex-1];
} else {
throw new TypeError("addShape Method must be given a shape object");
}
};
if (this.shape instanceof shape) { this.addShape(me.shape); }
this.shape = undefined;
this.setShape = undefined;
}
move(direction,amplitude) {
this.direction = direction;
this.speed = amplitude;
var theta = deg2rad(direction);
this.x += Math.cos(theta) * amplitude;
this.y += Math.sin(theta) * amplitude;
}
renderContainer(ctx,xPos,yPos) {
var refX = this.x + ("number" == typeof xPos ? xPos : 0);
var refY = this.y + ("number" == typeof yPos ? yPos : 0);
if ("object" == typeof this.shape) {
this.shape.render(ctx,refX,refY);
} else if ("object" == typeof this.containerArray) {
this.containerArray.forEach(
function (container) {
container.renderContainer(ctx,refX,refY);
});
} else {
console.log("Container is empty!!!");
}
}
grow(amp) {
amp = "number"== typeof amp ? amp : 1;
this.x -= amp;
this.y -= amp;
if ("object" == typeof this.shape) {
this.shape.grow(amp);
} else if ("object" == typeof this.containerArray) {
this.containerArray.forEach(
function (container) { container.grow(amp); });
}
}
}
class frameBuffer { class frameBuffer {
constructor(ctx, height, width) { constructor(ctx, height, width) {
this.ctx = ctx; this.ctx = ctx;