Convex hull of 4 points using gift wraping algorithm
gift wrapping is inefficient in the general case, but it is easy to code and with only 4 points the order of the algorithm is irrelevant.
HTML
<p>You can drag points around with the mouse.<br />They will snap to neighbours to allow easy check of co-incident points</p>
<p>The convex hull is in blue, the outline of the four points in green</p>
<canvas id='canvas' width=200 height=200></canvas>
<p id='comment'></p>
CSS
canvas {
background : #aaa;
}
JavaScript
function Point (x, y)
{
this.x = x;
this.y = y;
}
Point.prototype.equals = function (p)
{
return this.x == p.x && this.y == p.y;
};
Point.prototype.distance = function (p)
{
return Math.sqrt (Math.pow (this.x-p.x, 2)
+ Math.pow (this.y-p.y, 2));
};
function convex_hull (points)
{
function left_oriented (p1, p2, candidate)
{
var det = (p2.x - p1.x) * (candidate.y - p1.y)
- (candidate.x - p1.x) * (p2.y - p1.y);
if (det > 0) return true; // left-oriented
if (det < 0) return false; // right oriented
// select the farthest point in case of colinearity
return p1.distance (candidate) > p1.distance (p2);
}
var N = points.length;
var hull = [];
// get leftmost point
var min = 0;
for (var i = 1; i != N; i++)
{
if (points[i].y < points[min].y) min = i;
}
hull_point = points[min];
// walk the hull
do
{
hull.push(hull_point);
var end_point = points[0];
for (var i = 1; i != N; i++)
{
if ( hull_point.equals (end_point)
|| left_oriented (hull_point,
end_point,
points[i]))
{
end_point = points[i];
}
}
hull_point = end_point;
}
/*
* must compare coordinates values (and not simply objects)
* for the case of 4 co-incident points
*/
while (!end_point.equals (hull[0]));
return hull;
}
// --------------------------------------------------------
// demo code
// --------------------------------------------------------
function Demo (canvas, points)
{
this.drawPoly = function (points)
{
this.draw.beginPath();
this.draw.moveTo (points[0].x, points[0].y);
for (var i = 1 ; i != points.length ; i++)
{
var p = points[i];
this.draw.lineTo (p.x, p.y);
}
this.draw.closePath();
}
function getCursorPosition(e)
{
var x, y;
if (e.pageX != undefined && e.pageY != undefined)
{
x = e.pageX;
y = e.pageY;
}
else
{
x = e.clientX + document.body.scrollLeft...