Yet another quick test for a geometry function:
Click, drag, and release to draw a line. A point will be drawn at the intersections if there are any. Hit ‘S’ to toggle between treating the drawn segment as a line segments or a line.
The demo uses some basic Phaser features for the interaction and drawing. The Javascript code is:
var game = new Phaser.Game(530, 300, Phaser.CANVAS, 'container',
{ create: create, update: update, render: render });
var line;
var setting;
var result1;
var result2;
var circle;
var segment = true;
function create() {
line = new Phaser.Line(game.world.width/4, game.world.height/4,
3*game.world.width/4, 3*game.world.height/4);
circle = new Phaser.Circle(game.world.width/2, game.world.height/2,
Math.min(game.world.height, game.world.width)/2);
game.input.onDown.add(click, this);
setting = false;
result1 = new Phaser.Point();
result2 = new Phaser.Point();
game.input.keyboard.addKey(Phaser.Keyboard.S)
.onDown.add(function() {
segment = !segment;
}, this);
}
function update() {
if (setting) {
line.end.set(game.input.activePointer.x,
game.input.activePointer.y);
if (!game.input.activePointer.isDown) {
setting = false;
}
}
}
function click(pointer) {
setting = true;
line.start.set(pointer.x, pointer.y);
}
function render() {
game.debug.geom(line);
game.debug.geom(circle, '#00ff00', false, 2);
var res = intersection(line, circle, result1, result2, segment);
if (res) {
result1.x--;
result1.y--;
result2.x--;
result2.y--;
game.debug.geom(result1, '#ff0000');
if (res == INTERSECTION)
game.debug.geom(result2, '#ff0000');
}
}
var NO_INTERSECTION = 0;
var INTERSECTION = 1;
var SINGLE_INTERSECTION = 2;
var TANGENT = 3;
function intersection(line, circle, result1, result2, segment) {
var lx = line.end.x - line.start.x;
var ly = line.end.y - line.start.y;
var len = Math.sqrt(lx*lx + ly*ly);
var dx = lx / len;
var dy = ly / len;
var t = dx*(circle.x-line.start.x) + dy*(circle.y-line.start.y);
var ex = t * dx + line.start.x;
var ey = t * dy + line.start.y;
var lec = Math.sqrt((ex-circle.x)*(ex-circle.x) +
(ey-circle.y)*(ey-circle.y));
if (lec < circle.radius) {
var dt = Math.sqrt(circle.radius*circle.radius - lec*lec);
var te = dx*(line.end.x-line.start.x) + dy*(line.end.y-line.start.y);
if (segment) {
if ((t-dt < 0 || t-dt > te) &&
(t+dt < 0 || t+dt > te)) {
return NO_INTERSECTION;
} else if (t-dt < 0 || t-dt > te) {
result1.x = (t+dt)*dx + line.start.x;
result1.y = (t+dt)*dy + line.start.y;
return SINGLE_INTERSECTION;
} else if (t+dt < 0 || t+dt > te) {
result1.x = (t-dt)*dx + line.start.x;
result1.y = (t-dt)*dy + line.start.y;
return SINGLE_INTERSECTION;
}
}
result1.x = (t-dt)*dx + line.start.x;
result1.y = (t-dt)*dy + line.start.y;
result2.x = (t+dt)*dx + line.start.x;
result2.y = (t+dt)*dy + line.start.y;
return INTERSECTION;
} else if (lec == circle.radius) {
result1.x = ex;
result1.y = ey;
result2.x = ex;
result2.y = ey;
return TANGENT;
}
return NO_INTERSECTION;
}