Checking the Boundaries of a Quadratic Curve in JavaScript
Remember that any quadratic equation always have two roots for any
value of y (except at it's maximum or minimum point).
All we need to do is use these two roots (x values) as boundaries
for our check.
y = ax2 + bx + c
ax2 + bx + (c-y) = 0
x = |
-b ± √(b2 - 4a(c-y)) |
2a |
Our range will then be:
-b - √(b2 - 4a(c-y)) |
≤ x ≤ |
-b + √(b2 - 4a(c-y)) |
2a |
2a |
where a, b, and c
are constants.
We will reuse the moving ball graphic and check for when
it enters the region of our curve.
Code to Detect Entrance into Quadratic Region in JavaScript
To check for when our ball enters the quadratic curve,
we will continually check the x position
of the ball against the x position gotten using the
quadratic equation at the same y position
as that of the ball.
We'll designate the coordinates of the ball as
(xb, yb), and those of
the curve as (xq, yq).
Create 2 new files; On Notepad++: File, New.
Call them quadratic_region.html and quadratic_region.js.
Type out the adjoining JavaScript code for detecting the instance a travelling
body crosses the boundary of a quadratic curve.
quadratic_region.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Quadratic Region</title>
</head>
<body>
<h3>Detect a Second Body entering a Quadratic Region</h3>
<canvas id="quad_region" width="600" height="450" style="border: 1px solid #000000;">
Your browser (version) does not support canvas object; Time to update!
</canvas>
<button onclick="doGlide()">Glide</button>
<button onclick="clearTimeout(clr_obj)">Stop</button>
<script src="QuadraticRegion.js"></script>
</body>
</html>
JavaScript code for quadratic_region.js
var canvas = document.getElementById("quad_region");
var context = canvas.getContext("2d");
context.fillStyle = "#888888";
var x_ball = 50;
var y_ball = 150;
var radius = 40;
context.beginPath();
context.arc(x_ball, y_ball, radius, 0, 2 * Math.PI);
context.fill();
var xq_start = 200;
var yq_start = 50;
var xq_min = 350;
var yq_min = 300;
var xq_stop = 500;
var a = (yq_start - yq_min) / Math.pow((xq_start - xq_min), 2);
var b = -2 * a * xq_min;
var c = yq_min + a * Math.pow(xq_min, 2);
var x = xq_start;
var y = yq_start;
for (; x < xq_stop; x += 1) {
y = a * x * x + b * x + c;
context.beginPath();
context.arc(x, y, 1, 0, 2 * Math.PI);
context.fill();
}
var discriminant = Math.sqrt(b * b - 4 * a * (c - y_ball));
var xq_lb;
var xq_ub;
if (a < 0) {
xq_lb = (-b + discriminant) / (2 * a);
xq_ub = (-b - discriminant) / (2 * a);
} else {
xq_lb = (-b - discriminant) / (2 * a);
xq_ub = (-b + discriminant) / (2 * a);
}
var clr_obj;
function doGlide() {
if (x_ball <= 540) {
context.clearRect(x_ball - radius - 10, y_ball - radius, 80, 80);
if ((x_ball - radius <= xq_lb && x_ball + radius >= xq_lb)
|| (x_ball - radius <= xq_ub && x_ball + radius >= xq_ub)) {
context.fillStyle = "#ff0000";
} else if (x_ball - radius >= xq_lb && x_ball + radius <= xq_ub) {
context.fillStyle = "#00ff00";
} else {
context.fillStyle = "#888888";
}
context.beginPath();
context.arc(x_ball, y_ball, radius, 0, 2 * Math.PI);
context.fill();
x_ball += 10;
clr_obj = setTimeout(function () { doGlide(); }, 100);
}
}