Skip to content

Instantly share code, notes, and snippets.

@ixtli
Created September 13, 2012 00:52
Show Gist options
  • Save ixtli/3711079 to your computer and use it in GitHub Desktop.
Save ixtli/3711079 to your computer and use it in GitHub Desktop.
Circle vs Rect intersection volume in 2D
canvas {
background-color: rgba(0,0,0,.1);
}
<!doctype html public "✰">
<!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="en"> <![endif]-->
<!--[if IE 7]> <html class="no-js ie7 oldie" lang="en"> <![endif]-->
<!--[if IE 8]> <html class="no-js ie8 oldie" lang="en"> <![endif]-->
<!-- Consider adding a manifest.appcache: h5bp.com/d/Offline -->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<title>Test Space</title>
<meta name="description" content="WeTopia Data Editor">
<meta name="author" content="Chris Galardi">
<!-- Mobile viewport optimized: j.mp/bplateviewport -->
<meta name="viewport" content="width=device-width,initial-scale=1">
<!-- CSS concatenated and minified via ant build script-->
<link rel="stylesheet" href="test.css">
</head>
<body>
<canvas id="can"></canvas>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="test.js"></script>
<!-- Prompt IE 6 users to install Chrome Frame. Remove this if you want to support IE 6.
chromium.org/developers/how-tos/chrome-frame-getting-started -->
<!--[if lt IE 7 ]>
<script src="//ajax.googleapis.com/ajax/libs/chrome-frame/1.0.3/CFInstall.min.js"></script>
<script>window.attachEvent('onload',function(){CFInstall.check({mode:'overlay'})})</script>
<![endif]-->
</body>
</html>
function CanvasTest ()
{
this.canvas = null;
this.ctx = null;
this.rect = {
x : 0, y : 0, width : 0, height : 0,
};
this.circle = {
x : 0, y : 0, radius : 0,
};
};
CanvasTest.prototype =
{
canvasWidth : 500,
canvasHeight : 500,
init: function ()
{
this.canvas = $('canvas#can');
this.ctx = this.canvas[0].getContext('2d');
this.canvas.width(this.canvasWidth);
this.canvas.height(this.canvasHeight);
this.canvas[0].width = this.canvas.width();
this.canvas[0].height = this.canvas.height();
this.canvas.on('mousemove', $.proxy(this.mouseMove, this));
this.rect.x = 175;
this.rect.y = 175;
this.rect.width = 150;
this.rect.height = 150;
this.circle.radius = 20;
this.update();
},
mouseMove: function (evt)
{
this.circle.x = evt.offsetX;
this.circle.y = evt.offsetY;
this.update();
},
getIntersectionRect: function ()
{
var rect = this.rect;
var circle = this.circle;
var retRect = {};
var rectBottom = rect.y + rect.height;
var rectRight = rect.x + rect.width;
var circleBottom = circle.y + circle.radius;
var circleRight = circle.x + circle.radius;
var circleX = circle.x - circle.radius;
var circleY = circle.y - circle.radius;
var diameter = circle.radius * 2;
if (circleX < rect.x)
{
retRect.width = diameter - (rect.x - circleX);
retRect.x = rect.x;
} else if (circleRight > rectRight) {
retRect.width = diameter - (circleRight - rectRight);
retRect.x = circleX;
} else {
retRect.width = diameter;
retRect.x = circleX;
}
if (circleY < rect.y)
{
retRect.height = diameter - (rect.y - circleY);
retRect.y = rect.y;
} else if (circleBottom > rectBottom) {
retRect.height = diameter - (circleBottom - rectBottom);
retRect.y = circleY
} else {
retRect.height = diameter;
retRect.y = circleY;
}
return retRect;
},
update: function ()
{
var ctx = this.ctx;
var iRect = this.getIntersectionRect();
// clear
this.canvas[0].width = this.canvasWidth;
// draw rect
ctx.fillStyle = "rgba(0,0,220,.5)";
ctx.fillRect(this.rect.x, this.rect.y, this.rect.width, this.rect.height);
// draw sphere
ctx.fillStyle = "rgba(220,0,0,.5)";
ctx.beginPath();
ctx.arc(this.circle.x, this.circle.y, this.circle.radius, 0, 2 * Math.PI, false);
ctx.fill();
if (!iRect) return;
// draw intersection rect
ctx.fillStyle = "rgba(0, 220, 0, .5)";
ctx.fillRect(iRect.x, iRect.y, iRect.width, iRect.height);
},
};
var ct = new CanvasTest();
$(window).ready(function () {ct.init();});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment