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; }