Find "curve + straight + curve" path - algorithm

I'm trying to calculate a path from Start point (T-like black shape) with Start direction (green) to Finish point with finish direction in 2D space. The whole path (light blue) is a bunch of points. I need to find positions of two red points. The problem is that in most cases circle sections (I and III purple) has not equal amount of points i.e. different length. Start and finish directions can be any from 0 to 359 degrees.

To make this a programming question, here is an implementation for getting the two tangent points (the red points).
This implementation defines Vector and Circle classes, each with methods to create new results from them. The Circle class has a tangentWith method, which takes another circle as argument and returns an array with two Vectors, i.e. the coordinates of the two red points.
The snippet below is interactive. It starts with the initial two circles, as depicted in your question, but allows you to draw alternative circles using the mouse (click to determine center of circle, and drag to set its radius):
class Vector {
constructor(x, y) {
this.x = x;
this.y = y;
// Derive polar coordinates:
this.size = (x ** 2 + y ** 2) ** 0.5;
this.angle = Math.atan2(this.y, this.x);
}
subtract(v) {
return new Vector(this.x - v.x, this.y - v.y);
}
add(v) {
return new Vector(this.x + v.x, this.y + v.y);
}
multiplyBy(scalar) {
return new Vector(this.x * scalar, this.y * scalar);
}
resize(size) {
return this.multiplyBy(size / this.size);
}
rotate(angle) {
angle += this.angle;
return new Vector(this.size * Math.cos(angle), this.size * Math.sin(angle));
}
}
class Circle extends Vector {
constructor(x=0, y=0, radius=0) {
super(x, y);
this.radius = radius;
}
touch(v) { // Set radius so that v is on the circle
return Circle.fromVector(this, this.subtract(v).size);
}
tangentWith(other) { // Main algorithm
let v = this.subtract(other);
const sinus = (this.radius - other.radius) / v.size;
if (Math.abs(sinus) > 1) return []; // One circle includes the other: no tangent
v = v.rotate(Math.asin(sinus) + Math.PI / 2);
return [v.resize(this.radius).add(this), v.resize(other.radius).add(other)];
}
static fromVector(v, radius=0) {
return new Circle(v.x, v.y, radius);
}
}
// The circles as depicted in the question
const circles = [new Circle(50, 50, 25), new Circle(80, 120, 25)];
// I/O management, allowing to draw different circles
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
function mouseVector(e) {
return new Vector(e.clientX - canvas.offsetLeft, e.clientY - canvas.offsetTop);
}
canvas.addEventListener("mousedown", e => {
circles.reverse()[0] = Circle.fromVector(mouseVector(e));
});
canvas.addEventListener("mousemove", e => {
if (!e.buttons) return;
circles[0] = circles[0].touch(mouseVector(e));
draw();
});
function drawCircle(c) {
ctx.beginPath();
ctx.arc(c.x, c.y, c.radius, 0, 2*Math.PI);
ctx.stroke();
}
function drawSegment(start, end) {
if (!start) return;
ctx.beginPath();
ctx.moveTo(start.x, start.y);
ctx.lineTo(end.x, end.y);
ctx.stroke();
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
circles.map(drawCircle);
drawSegment(...circles[0].tangentWith(circles[1]));
}
draw();
canvas { border: 1px solid }
First draw C1, then C2 (use mouse drag)<br>
<canvas width="600" height="150"></canvas>

I drawn a simple figure:
As you see, red line directional component of the vector (C1 - C2) or (C2 - C1) equals difference of radius.
(Roughly) writing this relation as a equation,
Inner-Product( C1 -C2, U ) = dr
dr = | r1 - r2 |
where U is unit vector has direction along the red line, and 2 scalars {r1, r2} are circle radius.
This becomes to:
| C1 - C2 | * | U | * cos(theta) = | C1 - C2 | * 1 * cos(theta) = dr
where theta is the angle between (C1-C2) and U.
Now you can calculate the cos(theta) value as:
cos(theta) = dr / | C1-C2 |

Related

How to a make a curved sheet (cube) in OpenSCAD?

How can I curve a sheet (cube)? I'd like to control the angle of the bend/curve.
e.g.
cube([50,50,2]);
You can rotate_extrude() an rectangle with the parameter angle. This requires the openscad version 2016.xx or newer, see documentation.
It is necessary to install a development snapshot, see download openscad
$fn= 360;
width = 10; // width of rectangle
height = 2; // height of rectangle
r = 50; // radius of the curve
a = 30; // angle of the curve
rotate_extrude(angle = a) translate([r, 0, 0]) square(size = [height, width], center = true);
looks like this:
The curve is defined by radius and angle. I think it is more realistic, to use other dimensions like length or dh in this sketch
and calculate radius and angle
$fn= 360;
w = 10; // width of rectangle
h = 2; // height of rectangle
l = 25; // length of chord of the curve
dh = 2; // delta height of the curve
module curve(width, height, length, dh) {
// calculate radius and angle
r = ((length/2)*(length/2) - dh*dh)/(2*dh);
a = asin((length/2)/r);
rotate_extrude(angle = a) translate([r, 0, 0]) square(size = [height, width], center = true);
}
curve(w, h, l, dh);
Edit 30.09.2019:
considering comment of Cfreitas, additionally moved the resulting shape to origin, so dimensions can be seen on axes of coordinates
$fn= 360;
w = 10; // width of rectangle
h = 2; // height of rectangle
l = 30; // length of chord of the curve
dh = 4; // delta height of the curve
module curve(width, height, length, dh) {
r = (pow(length/2, 2) + pow(dh, 2))/(2*dh);
a = 2*asin((length/2)/r);
translate([-(r -dh), 0, -width/2]) rotate([0, 0, -a/2]) rotate_extrude(angle = a) translate([r, 0, 0]) square(size = [height, width], center = true);
}
curve(w, h, l, dh);
and the result:
Edit 19.09.2020: There was a typo in the last edit: In the first 'translate' the local 'width' should be used instead of 'w'. Corrected it in the code above.
I can do it this way but it would be better if you could specify the bend/curve in #degrees as an argument to the function:
$fn=300;
module oval(w, h, height, center = false) {
scale([1, h/w, 1]) cylinder(h=height, r=w, center=center);
}
module curved(w,l,h) {
difference() {
oval(w,l,h);
translate([0.5,-1,-1]) color("red") oval(w,l+2,h+2);
}
}
curved(10,20,30);
Using the concept used by a_manthey_67, corrected the math and centered (aligned the chord with y axis) the resulting object:
module bentCube(width, height, length, dh) {
// calculate radius and angle
r = (length*length + 4*dh*dh)/(8*dh);
a = 2*asin(length/(2*r));
translate([-r,0,0]) rotate([0,0,-a/2])
rotate_extrude(angle = a) translate([r, 0, 0]) square(size = [height, width], center = true);}
Or, if you just want something with a fixed length, and a certain bent angle do this:
module curve(width, height, length, a) {
if( a > 0 ) {
r = (360 * (length/a)) / (2 * pi);
translate( [-r-height/2,0,0] )
rotate_extrude(angle = a)
translate([r, 0, 0])
square(size = [height, width], center = false);
} else {
translate( [-height/2,0,width] )
rotate( a=270, v=[1,0,0] )
linear_extrude( height = length )
square(size = [height, width], center = false);
}
}
The if (a > 0) statement is needed to make an exception when the bending angle is 0 (which, if drawing a curved surface, would result in an infinite radius).
Animated GIF here

XNA/Monogame Creating rectangle around texture regardless of rotation?

I know Rectangle is axis aligned, that's fine, I just can't figure out how to create a rectangle so it is always encompassing the entire sprite, regardless of rotation. I have been looking everywhere for an answer but I can't get a straight one anywhere.
For example:
Assuming the origin point is the middle of the texture, how can I go about this?
EDIT
Fiddling around with it a little, I've gotten this far:
public Rectangle BoundingBox
{
get
{
var cos = Math.Cos(SpriteAngle);
var sin = Math.Cos(SpriteAngle);
var t1_opp = Width * cos;
var t1_adj = Math.Sqrt(Math.Pow(Width, 2) - Math.Pow(t1_opp, 2));
var t2_opp = Height * sin;
var t2_adj = Math.Sqrt(Math.Pow(Height, 2) - Math.Pow(t2_opp, 2));
int w = Math.Abs((int)(t1_opp + t2_opp));
int h = Math.Abs((int)(t1_adj + t2_adj));
int x = Math.Abs((int)(Position.X) - (w / 2));
int y = Math.Abs((int)(Position.Y) - (h / 2));
return new Rectangle(x, y, w, h);
}
}
(doing this off the top of my head.. but the principle should work)
Create a matrix to rotate around the center of the rectangle - that is a translate of -(x+width/2), -(y+height/2)
followed by a rotation of angle
followed by a translate of (x+width/2), (y+height/2)
Use Vector2.Transform to transform each corner of the original rectangle
Then make a new rectangle with
x = min(p1.x, p2.x, p3.x, p4.x)
width = max(p1.x, p2.x, p3.x, p4.x) - x
similar for y
Sorry this is coming so late, but I figured this out a while ago and forgot to post an answer.
public virtual Rectangle BoundingBox
{
get
{
int x, y, w, h;
if (Angle != 0)
{
var cos = Math.Abs(Math.Cos(Angle));
var sin = Math.Abs(Math.Sin(Angle));
var t1_opp = Width * cos;
var t1_adj = Math.Sqrt(Math.Pow(Width, 2) - Math.Pow(t1_opp, 2));
var t2_opp = Height * sin;
var t2_adj = Math.Sqrt(Math.Pow(Height, 2) - Math.Pow(t2_opp, 2));
w = (int)(t1_opp + t2_opp);
h = (int)(t1_adj + t2_adj);
x = (int)(Position.X - (w / 2));
y = (int)(Position.Y - (h / 2));
}
else
{
x = (int)Position.X;
y = (int)Position.Y;
w = Width;
h = Height;
}
return new Rectangle(x, y, w, h);
}
}
This is it here. In my work in the edit, I accidentally had Math.Cos in the sin variable, which didn't help.
So it's just basic trigonometry. If the textures angle is something other than zero, calculate the sides of the two triangles formed by the width and the height, and use the sides as the values for the width and the height, then center the rectangle around the texture. If that makes sense.
Here's a picture to help explain:
Here's a gif of the final result:

Determine original coordinates of corner before rotation

I'm having a brain-freeze trying to calculate the original coordinates of the top, left corner of a rectangle before it was rotated.
Given that I know rectangle was rotated n degrees/radians, and I know the new x and y coordinates, how would I calculate the x and y (? and ?) coordinates using trigonometry in JavaScript? I also know the width and height of the rectangle. The axis of the rotation is central to the rectangle.
The rotated rectangle is in blue, the original is in green.
you have to counter-rotate it around the pivot. (center of the rect)
//utils
function nr(v){ return +v || 0 }
class Point{
constructor(x,y){
this.x = nr(x);
this.y = nr(y);
}
add(pt){
var a = this, b = Point.from(pt);
return new Point(a.x + b.x, a.y + b.y);
}
subtract(pt){
var a = this, b = Point.from(pt);
return new Point(a.x - b.x, a.y - b.y);
}
rotate(radians, pivot){
if(pivot){
return this.subtract(pivot).rotate(radians).add(pivot);
}
var r = nr(radians), c = Math.cos(r), s = Math.sin(r);
return new Point(
this.x * c - this.y * s,
this.x * s + this.x * c
);
//return delta.matrixTransform( c, s, -s, c );
}
matrixTransform(a, b, c, d, tx, ty){
return new Point(
this.x * nr(a) + this.y * nr(c) + nr(tx),
this.x * nr(b) + this.y * nr(d) + nr(ty)
)
}
static from(pt){
if(pt instanceof Point) return pt;
return new Point(pt && pt.x, pt && pt.y);
}
}
and the computation:
var RAD = Math.PI/180, DEG = 180/Math.PI;
var knownPoint = new Point(100, 100);
var angle = 30*RAD;
var unrotatedRect = { width: 150, height: 100 };
//the pivot to (counter-)rotate your known point
//if you know this point, you don't have to compute it
var pivot = new Point(unrotatedRect.width/2, unrotatedRect.height/2)
.rotate(angle)
.add(knownPoint);
console.log(knownPoint.rotate(-angle, pivot));
The original X is exactly as far from the axis as the transposed ("rotated") Y is, and vice versa, the original Y is as far as the transposed X is from the axis.
So:
origX = axisX - (axisY - transY)
origY = axisY - (axisX - transX)

Developing an Algorithm to Transform Four Cartesian Coordinates Into Square Coordinates

I am working on a project where four randomly placed robots each have unique Cartesian coordinates. I need to find a way to transform these coordinates into the coordinates of a square with side length defined by the user of the program.
For example, let's say I have four coordinates (5,13), (8,17), (13,2), and (6,24) that represent the coordinates of four robots. I need to find a square's coordinates such that the four robots are closest to these coordinates.
Thanks in advance.
As far as I understand your question you are looking for the centroid of the four points, the point which has equal — and thus minimal — distance to all points. It is calculated as the average for each coordinate:
The square's edge length is irrelevant to the position, though.
Update
If you additionally want to minimize the square corners' distance to a robot position, you can do the following:
Calculate the centroid c like described above and place the square there.
Imagine a circle with center at c and diameter of the square's edge length.
For each robot position calculate the point on the circle with shortest distance to the robot and use that as a corner of the square.
It looks as if the original poster is not coming back to share his solution here, so I'll post what I was working on.
Finding the center point of the four robots and then drawing the square around this point is indeed a good way to start, but it doesn't necessarily give the optimal result. For the example given in the question, the center point is (8,14) and the total distance is 22.688 (assuming a square size of 10).
When you draw the vector from a corner of the square to the closest robot, this vector shows you in which direction the square should move to reduce the distance from that corner to its closest robot. If you calculate the sum of the direction of these four vectors (by changing the vectors to size 1 before adding them up) then moving the square in the resulting direction will reduce the total distance.
I dreaded venturing into differential equation territory here, so I devised a simple algorithm which repeatedly calculates the direction to move in, and moves the square in ever decreasing steps, until a certain precision is reached.
For the example in the question, the optimal location it finds is (10,18), and the total distance is 21.814, which is an improvement of 0.874 over the center position (assuming a square size of 10).
Press "run code snippet" to see the algorithm in action with randomly generated positions. The scattered green dots are the center points that are considered while searching the optimal location for the square.
function positionSquare(points, size) {
var center = {x: 0, y:0};
for (var i in points) {
center.x += points[i].x / points.length;
center.y += points[i].y / points.length;
}
paintSquare(canvas, square(center), 1, "#D0D0D0");
order(points);
textOutput("<P>center position: " + center.x.toFixed(3) + "," + center.y.toFixed(3) + "<BR>total distance: " + distance(center, points).toFixed(3) + "</P>");
for (var step = 1; step > 0.0001; step /= 2)
{
var point = center;
var shortest, dist = distance(center, points);
do
{
center = point;
shortest = dist;
var dir = direction();
paintDot(canvas, center.x, center.y, 1, "green");
point.x = center.x + Math.cos(dir) * step;
point.y = center.y + Math.sin(dir) * step;
dist = distance(point, points);
}
while (dist < shortest)
}
textOutput("<P>optimal position: " + center.x.toFixed(3) + "," + center.y.toFixed(3) + "<BR>total distance: " + distance(point, points).toFixed(3) + "</P>");
return square(center);
function order(points) {
var clone = [], best = 0;
for (var i = 0; i < 2; i++) {
clone[i] = points.slice();
for (var j in clone[i]) clone[i][j].n = j;
if (i) {
clone[i].sort(function(a, b) {return b.y - a.y});
if (clone[i][0].x > clone[i][1].x) swap(clone[i], 0, 1);
if (clone[i][2].x < clone[i][3].x) swap(clone[i], 2, 3);
} else {
clone[i].sort(function(a, b) {return a.x - b.x});
swap(clone[i], 1, 3);
if (clone[i][0].y < clone[i][3].y) swap(clone[i], 0, 3);
if (clone[i][1].y < clone[i][2].y) swap(clone[i], 1, 2);
}
}
if (distance(center, clone[0]) > distance(center, clone[1])) best = 1;
for (var i in points) points[i] = {x: clone[best][i].x, y: clone[best][i].y};
function swap(a, i, j) {
var temp = a[i]; a[i] = a[j]; a[j] = temp;
}
}
function direction() {
var d, dx = 0, dy = 0, corners = square(center);
for (var i in points) {
d = Math.atan2(points[i].y - corners[i].y, points[i].x - corners[i].x);
dx += Math.cos(d);
dy += Math.sin(d);
}
return Math.atan2(dy, dx);
}
function distance(center, points) {
var d = 0, corners = square(center);
for (var i in points) {
var dx = points[i].x - corners[i].x;
var dy = points[i].y - corners[i].y;
d += Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
}
return d;
}
function square(center) {
return [{x: center.x - size / 2, y: center.y + size / 2},
{x: center.x + size / 2, y: center.y + size / 2},
{x: center.x + size / 2, y: center.y - size / 2},
{x: center.x - size / 2, y: center.y - size / 2}];
}
}
// PREPARE CANVAS
var canvas = document.getElementById("canvas");
canvas.width = 200; canvas.height = 200;
canvas = canvas.getContext("2d");
// GENERATE TEST DATA AND RUN FUNCTION
var points = [{x:5, y:13}, {x:8, y:17}, {x:13, y:2}, {x:6, y:24}];
for (var i = 0; i < 4; i++) {
points[i].x = 1 + 23 * Math.random(); points[i].y = 1 + 23 * Math.random();
}
for (var i in points) textOutput("point: " + points[i].x.toFixed(3) + "," + points[i].y.toFixed(3) + "<BR>");
var size = 10;
var square = positionSquare(points, size);
// SHOW RESULT ON CANVAS
for (var i in points) {
paintDot(canvas, points[i].x, points[i].y, 5, "red");
paintLine(canvas, points[i].x, points[i].y, square[i].x, square[i].y, 1, "blue");
}
paintSquare(canvas, square, 1, "green");
function paintDot(canvas, x, y, size, color) {
canvas.beginPath();
canvas.arc(8 * x, 200 - 8 * y, size, 0, 6.2831853);
canvas.closePath();
canvas.fillStyle = color;
canvas.fill();
}
function paintLine(canvas, x1, y1, x2, y2, width, color) {
canvas.beginPath();
canvas.moveTo(8 * x1, 200 - 8 * y1);
canvas.lineTo(8 * x2, 200 - 8 * y2);
canvas.strokeStyle = color;
canvas.stroke();
}
function paintSquare(canvas, square, width, color) {
canvas.rect(8 * square[0].x , 200 - 8 * square[0].y, 8 * size, 8 * size);
canvas.strokeStyle = color;
canvas.stroke();
}
// TEXT OUTPUT
function textOutput(t) {
var output = document.getElementById("output");
output.innerHTML += t;
}
<BODY STYLE="margin: 0; border: 0; padding: 0;">
<CANVAS ID="canvas" STYLE="width: 200px; height: 200px; float: left; background-color: #F8F8F8;"></CANVAS>
<DIV ID="output" STYLE="width: 400px; height: 200px; float: left; margin-left: 10px;"></DIV>
</BODY>
Further improvements: I haven't yet taken into account what happens when a corner and a robot are in the same spot, but the overall position isn't optimal. Since the direction from the corner to the robot is undefined, it should probably be taken out of the equation temporarily.

circle rotated rectangle collision detection

I am trying to implement the collision detection between rotated rectangle and circle by following this http://www.migapro.com/circle-and-rotated-rectangle-collision-detection/
I have added the code in jsfiddle here http://jsfiddle.net/Z6KSX/2/.
What am i missing here ?
function check_coll ( circle_x,circle_y, rect_x, rect_y, rect_width, rect_height, rect_angle)
{
// Rotate circle's center point back
var rect_centerX = rect_x /2 ;
var rect_centerY = rect_y /2 ;
var cx = (Math.cos(rect_angle) * (circle_x - rect_centerX)) - (Math.sin(rect_angle) * (circle_y - rect_centerY)) + rect_centerX;
var cy = (Math.sin(rect_angle) * (circle_x - rect_centerX)) + (Math.cos(rect_angle) * (circle_y - rect_centerY)) + rect_centerY;
// Closest point
var x, y;
// Find the unrotated closest x point from center of unrotated circle
if (cx < rect_x) {
x = rect_x;
}
else if (cx > rect_x + rect_width){
x = rect_x + rect_width;
}
else{
x = cx;
}
// Find the unrotated closest y point from center of unrotated circle
if (cy < rect_y){
y = rect_y;
}
else if (cy > rect_y + rect_height) {
y = rect_y + rect_height;
}
else {
y = cy;
}
// Determine collision
var collision = false;
var c_radius = 5;
var distance = findDistance(cx, cy, x, y);
if (distance < c_radius) {
collision = true; // Collision
}
else {
collision = false;
}
return collision;
}
function findDistance (x1, y1, x2, y2) {
var a = Math.abs(x1 - x2);
var b = Math.abs(y1 - y2);
var c = Math.sqrt((a * a) + (b * b));
return c;
}
Hehe, I find this amusing as I somewhat recently solved this for myself after spending a large amount of time going down the wrong path.
Eventually I figured out a way:
1.) Simply rotate the point of the center of the circle by the Negative amount the rectangle has been rotated by. Now the point is 'aligned' with the rectangle (in the rectangles relative coordinate space).
2.) Solve for circle vs. AABB. The way I solved it gave me a point on the rectangle that is closest to the circle's center.
3.) Rotate the resulting point from by the Positive amount the rectangle has been rotated by. Continue solving as usual (checking if the distance between that point and the circle center is within the circle's radius)
From a very quick glance at your code, it seems like maybe you are doing the same thing, but missing the last step? I suggest drawing out your point on the rectangle from step 2 to see exactly where it is to help debug.
I was able to figure this out . The issue in the code was, I was using the wrong radius and had missed the center of rect_x and rect_y
var rect_centerX = rect_x + (rect_width / 2);
var rect_centerY = rect_y + (rect_height /2);
When dealing with rotation on the canvas we will need to add the translate values to the corresponding x and y values used in createrect.
I also use this code for my project and it's working. The only thing you need to do is use -angle instead of the angle.
Here is my code link
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const rectX = 100;
const rectY = 100;
const rectWidth = 200;
const rectHeight = 100;
const circleRadius = 2;
const rectMidPointX = rectX + rectWidth / 2;
const rectMidPointY = rectY + rectHeight / 2;
const angle = Math.PI / 4;
let circleX;
let circleY;
canvas.addEventListener('mousemove', (e) => {
circleX = e.clientX;
circleY = e.clientY;
ctx.save();
ctx.beginPath();
ctx.fillStyle = '#fff';
ctx.arc(circleX, circleY, circleRadius, 0, 2 * Math.PI);
ctx.fill();
ctx.stroke();
ctx.restore();
calculateIntersection();
})
ctx.save();
//ctx.fillRect(100, 100, 100, 100);
ctx.strokeStyle = 'black';
ctx.translate(rectMidPointX, rectMidPointY);
ctx.rotate(angle);
ctx.translate(-rectMidPointX, -rectMidPointY);
ctx.strokeRect(rectX, rectY, rectWidth, rectHeight);
ctx.restore();
// Determine collision
let collision = false;
const findDistance = (fromX, fromY, toX, toY) => {
const a = Math.abs(fromX - toX);
const b = Math.abs(fromY - toY);
return Math.sqrt((a * a) + (b * b));
};
function calculateIntersection() {
// Rotate circle's center point back
const unrotatedCircleX = Math.cos(-angle) * (circleX - rectMidPointX) -
Math.sin(-angle) * (circleY - rectMidPointY) + rectMidPointX;
const unrotatedCircleY = Math.sin(-angle) * (circleX - rectMidPointX) +
Math.cos(-angle) * (circleY - rectMidPointY) + rectMidPointY;
// Closest point in the rectangle to the center of circle rotated backwards(unrotated)
let closestX, closestY;
// Find the unrotated closest x point from center of unrotated circle
if (unrotatedCircleX < rectX)
closestX = rectX;
else if (unrotatedCircleX > rectX + rectWidth)
closestX = rectX + rectWidth;
else
closestX = unrotatedCircleX;
// Find the unrotated closest y point from center of unrotated circle
if (unrotatedCircleY < rectY)
closestY = rectY;
else if (unrotatedCircleY > rectY + rectHeight)
closestY = rectY + rectHeight;
else
closestY = unrotatedCircleY;
const distance = findDistance(unrotatedCircleX, unrotatedCircleY, closestX, closestY);
if (distance < circleRadius)
collision = true; // Collision
else
collision = false;
console.log('collision', collision);
}
<canvas id="canvas" width="400px" height="400px" />

Resources