Skip to content

Instantly share code, notes, and snippets.

@nanu146
Last active December 30, 2016 17:38
Show Gist options
  • Save nanu146/64a48f0d931804593fb9984132d9dca9 to your computer and use it in GitHub Desktop.
Save nanu146/64a48f0d931804593fb9984132d9dca9 to your computer and use it in GitHub Desktop.
Convex Hull Recursive Graham scan using d3.js
license: gpl-3.0
height: 700
border: no
function radiansToDegrees(radians){
return (radians*360)/(2*Math.PI);
}
function degreesToRadians(degrees){
return (degrees/360)*2*Math.PI;
}
function triangleSignedArea(a,b,c){
return b.x*(c.y-a.y) +a.x*(b.y-c.y)+c.x*(a.y-b.y);
}
function sortByPolarAngle(a,b)
{
a.origin=origin;
b.origin=origin;
return a.polarAngle()-b.polarAngle();
}
function diagonalCreator(arr)
{
diagonals=[];
for (var i = 1; i <= arr.length; i++) {
var temp=[];
temp.push(arr[i-1]);
temp.push(arr[i]||arr[0])
diagonals.push(temp);
}
return diagonals;
}
<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
.line
{
stroke:black;
stroke-width:2px;
fill:none;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.js"></script>
<script src="particle.js"></script>
<script src="geom_utils.js"></script>
<script >
margin={top:50,bottom:100,left:50,right:50}
width=700;
height=500;
var origin;
var particleHolder=[];
var line = d3.svg.line()
.x(function(d) { return x(d.getX()/2000); })
.y(function(d) { return y(d.getY()/2000); });
var diagonal = d3.svg.diagonal()
.source(function(d) { return {"x":d[0].getX(), "y":d[0].getY()}; })
.target(function(d) { return {"x":d[1].getX(), "y":d[1].getY()}; })
var x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([0, height]);
for (var i = 0; i < 100; i++) {
a=particle.create();
a.height=height;
a.setX(Math.random()*(width-100) +1);
a.setY(Math.random()*(height-100) +1);
particleHolder.push(a);
}
canvas=document.getElementById("canvas");
window.onload=function(){
svg=d3.select("body")
.append("svg")
.style({"width":width+"px","height":height+"px"});
svg.selectAll("points").data(particleHolder).enter().append("circle").attr("cx",function(d){return d.getX()})
.attr("cy",function(d){return d.getY()})
.attr("r",2).style("fill","black")
.on('click',function(d){console.log(d.name+" x "+d.x+" y "+d.y+" ty "+ d.getY())});
particleHolder.sort(function(a,b){return a.y-b.y})
//particle.prototype.origin={x:particleHolder[0].x,y:particleHolder[0].y}
origin={x:particleHolder[0].x,y:particleHolder[0].y}
particleHolder.sort(function(a,b){return a.polarAngle()-b.polarAngle()})
particleHolder.sort(sortByPolarAngle)
stack=new Array();
stack.push(particleHolder.splice(0,1)[0]);
stack.push(particleHolder.splice(0,1)[0]);
for(i=2;i<particleHolder.length;i++){
stack.push()
}
recursiveHullCreator(particleHolder,stack);
links=diagonalCreator(stack);
/*svg.selectAll(".link")
.data(links)
.enter().append("path")
.attr("class", "line")
.transition().delay(function(d,i){return i*200})
.attr("d", diagonal);
*/
svg.selectAll(".links").data(links)
.enter().append("line")
.style({"stroke":"black","stroke-width":"2px"})
.transition().delay(function(d,i){return i*200})
.attr("x1",function(d){return d[0].getX()})
.attr("y1",function(d){return d[0].getY()})
.attr("x2",function(d){return d[1].getX()})
.attr("y2",function(d){return d[1].getY()})
/*
function recursiveHullCreator(points,stack)
{
newNode=points.splice(0,1);
while(triangleSignedArea(points[points.length-2],points[points.length-1], newNode)
{
stack.pop();
}
stack.push(newNode);
}
*/
function recursiveHullCreator(points,stack)
{
if(points.length>0)
{
newNode=points[0];
if(triangleSignedArea(stack[stack.length-2],stack[stack.length-1], newNode)<0)
{
stack.pop();
recursiveHullCreator(points,stack);
}
else{
stack.push(points.splice(0,1)[0]);
recursiveHullCreator(points,stack);
}
}
else{
return;
}
}
}
</script>
</head>
<body>
</body>
</html>
var particle={
x:0,
y:0,
height:0,
origin:{},
// dummy constructor
create:function(){
var obj;
obj=Object.create(this);
return obj;
},
setX:function(x){
this.x=x;
},
setY:function(y){
this.y= y
},
getX:function(){
return this.x;
},
getY:function(){
return this.height-this.y;
},
polarAngle:function(){
if(!this.equals(this.origin)){
return Math.atan2((this.y-this.origin.y),(this.x-this.origin.x));
}
else
{
return null;
}
},
equals:function(obj){
return this.x==obj.x&& this.y==obj.y? true: false;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment