From aad4ef481c96681bc7e71757d241a1c92e3fe91b Mon Sep 17 00:00:00 2001 From: BurntWaffleCake Date: Tue, 26 Sep 2023 00:09:13 -0500 Subject: [PATCH] projection --- javascript/polygonCollision/index.html | 2 +- javascript/polygonCollision/script.js | 236 ++++++++++++++++++------- 2 files changed, 176 insertions(+), 62 deletions(-) diff --git a/javascript/polygonCollision/index.html b/javascript/polygonCollision/index.html index 3dcfd5a..9636041 100644 --- a/javascript/polygonCollision/index.html +++ b/javascript/polygonCollision/index.html @@ -26,7 +26,7 @@ } canvas { - background-color: white; + background-color: black; display: block; aspect-ratio: 1/1; width: 100vh; diff --git a/javascript/polygonCollision/script.js b/javascript/polygonCollision/script.js index aefa653..e7b902d 100644 --- a/javascript/polygonCollision/script.js +++ b/javascript/polygonCollision/script.js @@ -1,89 +1,98 @@ class Box { - constructor(x, y, w, h, rotation = 0.0) { + constructor(x = width / 2, y = height / 2, w = 50, h = 50, r = 0, dx = 0, dy = 0, dr = 0) { this.x = x //box center x this.y = x //box center y + this.dx = dx + this.dy = dy + + this.r = r % 360 * Math.PI / 180 //rotation in radians + this.dr = dr % 360 * Math.PI / 180 //rotation in radians + this.w = w //box width this.h = h //box height - this.rotation = rotation % 360 * Math.PI / 180 } setRotation(degrees) { - this.rotation = degrees % 360 * Math.PI / 180 + this.r = degrees % 360 * Math.PI / 180 } - render(ctx) { - ctx.fillStyle = "rgb(0,0,255)" - ctx.fillRect(this.x - 1.5, this.y - 1.5, 3, 3) - let hw = this.w/2 - let hh = this.h/2 + setRotationDelta(degrees) { + this.dr = degrees % 360 * Math.PI / 180 + } - let tl = {x: -hw, y: -hh} - ctx.fillStyle = "rgb(255,0,0)" - ctx.fillRect(this.x + tl.x - 1.5,this.y + tl.y - 1.5, 3, 3) - let tlm = Math.sqrt(tl.x*tl.x + tl.y*tl.y) - let tlr = this.rotation + Math.tan(-tl.y / tl.x) - Math.PI / 4 - tl = {x: this.x + tlm * Math.cos(tlr), y: this.y + tlm * Math.sin(tlr)} - ctx.fillStyle = "rgb(0,0,255)" - ctx.fillRect(tl.x - 1.5, tl.y - 1.5, 3, 3) - - let tr = {x: +hw, y: -hh} - ctx.fillStyle = "rgb(255,0,0)" - ctx.fillRect(this.x + tr.x - 1.5,this.y + tr.y - 1.5, 3, 3) - let trm = Math.sqrt(tr.x*tr.x + tr.y*tr.y) - let trr = this.rotation + Math.tan(-tr.y / tr.x) - Math.PI * 3 / 4 - tr = {x: this.x + trm * Math.cos(trr), y: this.y + trm * Math.sin(trr)} - ctx.fillStyle = "rgb(0,0,255)" - ctx.fillRect(tr.x - 1.5, tr.y - 1.5, 3, 3) - - let bl = {x: -hw, y: +hh} - ctx.fillStyle = "rgb(255,0,0)" - ctx.fillRect(this.x + bl.x - 1.5,this.y + bl.y - 1.5, 3, 3) - let blm = Math.sqrt(bl.x*bl.x + bl.y*bl.y) - let blr = this.rotation + Math.tan(-bl.y / bl.x) - bl = {x: this.x + blm * Math.cos(blr), y: this.y + blm * Math.sin(blr)} - ctx.fillStyle = "rgb(0,0,255)" - ctx.fillRect(bl.x - 1.5, bl.y - 1.5, 3, 3) - - let br = {x: +hw, y: +hh} + testBounds() { + + } + + getWorldCoordinates() { + let hw = this.w / 2 + let hh = this.h / 2 + + let tl = { x: -hw, y: -hh } + let tlm = Math.sqrt(tl.x * tl.x + tl.y * tl.y) + let tlr = this.r + Math.PI - Math.atan(-tl.y / tl.x) + tl = { x: this.x + tlm * Math.cos(tlr), y: this.y + tlm * Math.sin(tlr) } + + + let tr = { x: +hw, y: -hh } + let trm = Math.sqrt(tr.x * tr.x + tr.y * tr.y) + let trr = this.r - Math.atan(-tr.y / tr.x) + tr = { x: this.x + trm * Math.cos(trr), y: this.y + trm * Math.sin(trr) } + + let bl = { x: -hw, y: +hh } + let blm = Math.sqrt(bl.x * bl.x + bl.y * bl.y) + let blr = this.r + Math.PI - Math.atan(-bl.y / bl.x) + bl = { x: this.x + blm * Math.cos(blr), y: this.y + blm * Math.sin(blr) } + + let br = { x: +hw, y: +hh } + let brm = Math.sqrt(br.x * br.x + br.y * br.y) + let brr = this.r - Math.atan(-br.y / br.x) + br = { x: this.x + brm * Math.cos(brr), y: this.y + brm * Math.sin(brr) } + + return { tl: tl, tr: tr, bl: bl, br: br } + } + + render(ctx) { ctx.fillStyle = "rgb(255,0,0)" - ctx.fillRect(this.x + br.x - 1.5,this.y + br.y - 1.5, 3, 3) - let brm = Math.sqrt(br.x*br.x + br.y*br.y) - let brr = this.rotation + Math.tan(-br.y / br.x) - Math.PI * 3 / 4 - br = {x: this.x + brm * Math.cos(brr), y: this.y + brm * Math.sin(brr)} - ctx.fillStyle = "rgb(0,0,255)" - ctx.fillRect(br.x - 1.5, br.y - 1.5, 3, 3) + ctx.fillRect(this.x - 1.5, this.y - 1.5, 3, 3) - // let tr = {x: +hw, y: +hh} - // let bl = {x: -hw, y: -hh} - // let br = {x: +hw, y: +hh} + let coords = this.getWorldCoordinates() ctx.lineWidth = 1 - ctx.strokeStyle = "rgb(0,0,0)" + ctx.strokeStyle = "rgb(255,255,255)" ctx.beginPath(); ctx.moveTo(this.x, this.y) - ctx.lineTo(tl.x, tl.y) - ctx.stroke(); - - ctx.moveTo(tl.x, tl.y) - ctx.lineTo(tr.x, tr.y) + ctx.lineTo(this.x + this.w / 2 * Math.cos(this.rotation), this.y + this.y / 2 * Math.sin(this.rotation)) + + ctx.moveTo(coords.tl.x, coords.tl.y) + ctx.lineTo(coords.tr.x, coords.tr.y) + ctx.lineTo(coords.br.x, coords.br.y) + ctx.lineTo(coords.bl.x, coords.bl.y) + ctx.lineTo(coords.tl.x, coords.tl.y) ctx.stroke() - } - } -function startup() { - console.log("Starting simulation") +function projectVectorToLine(x, y, lx, ly) { + let dotxl = x * lx + y * ly //dot input vector and plane vector + let dotll = lx * lx + ly * ly //dot plane vector on itself - let newBox = new Box(width / 2, height / 2, 50, 50, 10) - newBox.render(ctx) + let projX = dotxl / dotll * lx + let projY = dotxl / dotll * ly + return { x: projX, y: projY } +} - // window.requestAnimationFrame(loop) +function clearCanvas() { + ctx.clearRect(0, 0, width, height) } -window.addEventListener('load', (event) => { - startup() -}) +function calculatePhysics(dt) { + for (box of boxes) { + box.x += box.dx * dt + box.y += box.dy * dt + box.r += box.dr * dt + } +} const width = 1000 const height = 1000 @@ -93,4 +102,109 @@ const ctx = canvas.getContext("2d"); ctx.canvas.width = width ctx.canvas.height = height +let boxes = [] + + + +let box1 = new Box(width / 2, height / 2, 200, 100, 20, 0, 0, 50) +let box2 = new Box(width / 4, height / 6, 50, 100, 74, 0, 0, -34) + +boxes.push(box1) +boxes.push(box2) + + +let time = 0.0 +function loop(t) { + clearCanvas() + dt = (t / 1000) - time + + calculatePhysics(dt) + + box1.y = height/2 + 200*Math.sin(time/2) + + box1.render(ctx) + let box1Points = box1.getWorldCoordinates() + // let tlnorm = { x: box1Points.tr.x - box1Points.tl.x, y: box1Points.tr.y - box1Points.tl.y } + let tlnorm = {x:0, y:height} + box2.render(ctx) + let box2Points = box2.getWorldCoordinates() + + for (const [pointName, point] of Object.entries(box1Points)) { + let projPoint = projectVectorToLine(point.x, point.y, tlnorm.x, tlnorm.y) + let projmag = Math.sqrt(projPoint.x*projPoint.x + projPoint.y*projPoint.y) + + ctx.fillStyle = "rgb(255, 0, 0)" + ctx.fillRect(projPoint.x, projPoint.y, 5, 5) + + ctx.fillStyle = "rgb(0, 0, 255)" + ctx.fillRect(projmag, 0, 5, 5) + + ctx.strokeStyle = "rgb(0, 255, 0)" + ctx.beginPath() + ctx.moveTo(projPoint.x, projPoint.y) + ctx.lineTo(box1Points[pointName].x, box1Points[pointName].y) + ctx.stroke() + + ctx.strokeStyle = "rgb(255, 0, 0)" + ctx.beginPath() + ctx.moveTo(projmag, 0) + ctx.lineTo(box1Points[pointName].x, box1Points[pointName].y) + ctx.stroke() + } + + for (const [pointName, point] of Object.entries(box2Points)) { + let projPoint = projectVectorToLine(point.x, point.y, tlnorm.x, tlnorm.y) + let projmag = Math.sqrt(projPoint.x*projPoint.x + projPoint.y*projPoint.y) + + ctx.fillStyle = "rgb(255, 0, 0)" + ctx.fillRect(projPoint.x, projPoint.y, 5, 5) + + ctx.fillStyle = "rgb(255, 0, 255)" + ctx.fillRect(projmag, 0, 5, 5) + + ctx.strokeStyle = "rgb(0, 255, 0)" + ctx.beginPath() + ctx.moveTo(projPoint.x, projPoint.y) + ctx.lineTo(box2Points[pointName].x, box2Points[pointName].y) + ctx.stroke() + + ctx.strokeStyle = "rgb(255, 0, 0)" + ctx.beginPath() + ctx.moveTo(projmag, 0) + ctx.lineTo(box2Points[pointName].x, box2Points[pointName].y) + ctx.stroke() + } + + // newBox.setRotation(newBox.rotation * 180 / Math.PI + 100 * dt) + // for (box of boxes) { + // box.render(ctx) + + // let points = box.getWorldCoordinates() + // let tlnorm = {x: points.tr.x-points.tl.x, y: points.tr.y-points.tl.y} + + // for (const [pointName, point] of Object.entries(points)) { + // let projPoint = projectVectorToLine(point.x, point.y, tlnorm.x, tlnorm.y) + // ctx.fillStyle = "rgb(255, 0, 0)" + // ctx.fillRect(projPoint.x, projPoint.y, 5, 5) + + // ctx.strokeStyle = "rgb(0, 255, 0)" + // ctx.beginPath() + // ctx.moveTo(projPoint.x, projPoint.y) + // ctx.lineTo(points[pointName].x, points[pointName].y) + // ctx.stroke() + // } + // } + + time = t / 1000 + window.requestAnimationFrame(loop) +} + +function startup() { + console.log("Starting simulation") + window.requestAnimationFrame(loop) +} + +window.addEventListener('load', (event) => { + startup() +})