Step 1: Find center of polygon using average position of points
This function will find the center given all the points in the drawing, independent of order:
function findCenter(points) {
var x = 0, y = 0, i, len = points.length;
for (i = 0; i < len; i++) {
x += points[i].x;
y += points[i].y;
}
return {x: x / len, y: y / len}; // return average position
}
Demo showing center point in polygon
/**
* Created by knguyen on 4/13/2015.
*/
var pointsArray = [];
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
function Point(x, y) {
this.x = x;
this.y = y;
}
function drawDot(e) {
var position = getMousePosition(canvas, e);
posx = position.x;
posy = position.y;
storeCoordinate(posx, posy);
context.fillStyle = "#F00";
context.fillRect(posx, posy, 6, 6);
}
function getMousePosition(c, e) {
var rect = canvas.getBoundingClientRect();
return {x: e.clientX - rect.left, y: e.clientY - rect.top}
}
function storeCoordinate(xVal, yVal) {pointsArray.push(new Point(xVal, yVal))}
$("#solve").click(
function() {
var p = findCenter(pointsArray);
context.fillStyle = "green";
context.fillRect(p.x, p.y, 4, 4);
}
);
function findCenter(points) {
var x = 0, y = 0, i, len = points.length;
for (i = 0; i < len; i++) {
x += points[i].x;
y += points[i].y;
}
return {x: x / len, y: y / len}; // return average position
}
#myCanvas {border: 1px solid #000}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="myCanvas" width="400" height="300" onclick="drawDot(event)"></canvas>
<div>
<button type="button" class="btn btn-default" id="solve">Show center point</button>
</div>
Step 2: Sort points based on angle
- Extend the point object to also take an angle argument.
- Iterate trough the point array
- Calculate the angle relative to the center point
- Sort array based on angle
To find the angles just calculate the angle relative to the center point.
Here is how:
function findAngles(c, points) {
var i, len = points.length, p, dx, dy;
for (i = 0; i < len; i++) {
p = points[i];
dx = p.x - c.x;
dy = p.y - c.y;
p.angle = Math.atan2(dy, dx);
}
}
Then you have to sort the points based on angle using a custom sort function. Just use the standard sort()
method on the array and supply your own function which will use the angle property of the point object:
pointsArray.sort(function(a, b) {
if (a.angle > b.angle) return 1;
else if (a.angle < b.angle) return -1;
return 0;
});
Then draw a line between all the points.
Working Demo
var pointsArray = [];
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
function Point(x, y) {
this.x = x;
this.y = y;
this.angle = 0;
}
canvas.onclick = drawDot;
function drawDot(e) {
var position = getMousePosition(canvas, e);
posx = position.x;
posy = position.y;
storeCoordinate(posx, posy);
context.fillStyle = "#F00";
context.fillRect(posx-3, posy-3, 6, 6);
}
function getMousePosition(c, e) {
var rect = canvas.getBoundingClientRect();
return {x: e.clientX - rect.left, y: e.clientY - rect.top}
}
function storeCoordinate(xVal, yVal) {pointsArray.push(new Point(xVal, yVal))}
$("#solve").click(
function() {
// find center
var cent = findCenter(pointsArray);
context.fillStyle = "green";
context.fillRect(cent.x-3, cent.y-3, 6, 6);
// find angles
findAngles(cent, pointsArray);
// sort based on angle using custom sort
pointsArray.sort(function(a, b) {
return (a.angle >= b.angle) ? 1 : -1
});
// draw lines
context.beginPath();
context.moveTo(pointsArray[0].x, pointsArray[0].y);
for(var i = 0; i < pointsArray.length; i++) {
context.lineTo(pointsArray[i].x, pointsArray[i].y);
}
context.strokeStyle = "#00f";
context.closePath();
context.stroke();
}
);
function findCenter(points) {
var x = 0, y = 0, i, len = points.length;
for (i = 0; i < len; i++) {
x += points[i].x;
y += points[i].y;
}
return {x: x / len, y: y / len}; // return average position
}
function findAngles(c, points) {
var i, len = points.length, p, dx, dy;
for (i = 0; i < len; i++) {
p = points[i];
dx = p.x - c.x;
dy = p.y - c.y;
p.angle = Math.atan2(dy, dx);
}
}
$("#reset").click(
function() {
context.clearRect(0, 0, canvas.width, canvas.height); //clear the canvas
pointsArray = []; //clear the array
}
);
#myCanvas {border: 1px solid #000}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="myCanvas" width="400" height="300"></canvas>
<div><button id="solve">Draw Polygon</button><button id="reset">Reset</button></div>