An interactive demonstration of d3-voronoi rendered to SVG. Compare to Canvas.
forked from mbostock's block: Voronoi Tessellation
license: gpl-3.0 |
An interactive demonstration of d3-voronoi rendered to SVG. Compare to Canvas.
forked from mbostock's block: Voronoi Tessellation
!function(a,b){"function"==typeof define&&define.amd?define(function(){return a.DoublyLinkedList=b()}):"object"==typeof exports?module.exports=b():a.DoublyLinkedList=b()}(this,function(){function a(a){this.data=a,this.previous=null,this.next=null}function b(){this._head=null,this._tail=null,this._length=0,this._isCircular=!1}var c={},d=Math.floor,e=Math.random;return a.prototype={constructor:a,hasPrevious:function(){return null!==this.previous},hasNext:function(){return null!==this.next}},b.VERSION="0.1.6",b.forge=function(){return new this},b.forgeCircular=function(){return this.forge().makeCircular()},b.prototype={constructor:b,makeCircular:function(){return this.isEmpty()||(this._head.previous=this._tail,this._tail.next=this._head),this._isCircular=!0,this},makeLinear:function(){return this.isEmpty()||(this._head.previous=null,this._tail.next=null),this._isCircular=!1,this},add:function(b){var c=new a(b),d=this._tail;return this.isEmpty()?(this._head=c,this._tail=c):(d.next=c,c.previous=d,this._tail=c),this._length+=1,this._isCircular&&this.makeCircular(),this},getAt:function(a){var b=this._getAt(a);return null!==b?b.data:null},getFirst:function(){var a=this._head;return null!==a?a.data:null},getPrevious:function(a){var b=this._getAdjacent(a,!1);return null!==b?b.data:null},getNext:function(a){var b=this._getAdjacent(a);return null!==b?b.data:null},getLast:function(){var a=this._tail;return null!==a?a.data:null},getRandom:function(){var a=0,b=this.getLength(),c=d(e()*(b-a))+a;return this.getAt(c)},getIndexOf:function(a){var b=0,d=-1;return this._traverse(function(e){return e.data===a?(d=b,c):void(b+=1)}),d},getLastIndexOf:function(a){var b=this._length-1,d=-1;return this._traverse(function(e){return e.data===a?(d=b,c):void(b-=1)},this._tail,!1),d},some:function(a,b,d){var e=this._get(b),f=!1;return this._traverse(function(b){return f=a.call(d,b.data),f?c:void 0},e),f},every:function(a,b,d){var e=this._get(b),f=!0;return this._traverse(function(b){return f=a.call(d,b.data),f?void 0:c},e),f},forEach:function(a,b,c){var d=this._get(b);this._traverse(function(b){a.call(c,b.data)},d)},forEachReverse:function(a,b,c){var d=this._get(b);this._traverse(function(b){a.call(c,b.data)},d,!1)},removeAt:function(a){var b=this._getAt(a),c=this._isHead(b),d=this._isTail(b);return null!==b?(c&&(this._head=b.next),d&&(this._tail=b.previous),b.hasNext()&&(b.next.previous=b.previous),b.hasPrevious()&&(b.previous.next=b.next),this._length-=1,(c||d||this._isCircular)&&this.makeCircular(),b.data):null},toArray:function(){for(var a=[],b=this._head;null!==b;)a.push(b.data),b=b.next;return a},toString:function(){return this.toArray().toString()},getLength:function(){return this._length},isEmpty:function(){return 0===this._length},isCircular:function(){return this._isCircular},_get:function(a){var b=null;return this._traverse(function(d){return d.data===a?(b=d,c):void 0}),b},_getAt:function(a){var b,c;if(a>-1&&a<this._length){for(b=this._head,c=0;a>c;)b=b.next,c+=1;return b}return null},_getAdjacent:function(a,b){b="boolean"==typeof b?b:!0;var d=b?"next":"previous",e=null;return this._traverse(function(b){return b.data===a?(e=b,c):void 0}),null!==e?e[d]:null},_traverse:function(a,b,d,e){b=b||this._head,d="boolean"==typeof d?d:!0;var f,g=b,h=this._length,i=d?"next":"previous";for(f=0;h>f;f+=1){if(null===g||a.call(e,g,this)===c)return;g=g[i]}},_isHead:function(a){return a===this._head},_isTail:function(a){return a===this._tail}},b}); |
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<style> | |
.links { | |
stroke: #000; | |
stroke-opacity: 0.2; | |
} | |
.polygons { | |
fill: none; | |
stroke: #000; | |
} | |
.polygons :first-child { | |
fill: #f00; | |
} | |
.sites { | |
fill: #000; | |
stroke: #fff; | |
} | |
.sites :first-child { | |
fill: #fff; | |
} | |
</style> | |
<svg width="400" height="200"></svg> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/buckets/1.90.0/buckets.js"></script> | |
<script> | |
var svg = d3.select("svg"), | |
width = +svg.attr("width"), | |
height = +svg.attr("height"); | |
svg.append("g") | |
.attr("class", "sitesL"); | |
svg.append("g") | |
.attr("class", "sitesR"); | |
var sites = d3.range(6) | |
.map(function(d) { return [Math.random() * width, Math.random() * height]; }); | |
// var polygon = svg.append("g") | |
// .attr("class", "polygons") | |
// .selectAll("path") | |
// .data(voronoi.polygons(sites)) | |
// .enter().append("path") | |
// .call(redrawPolygon); | |
// var link = svg.append("g") | |
// .attr("class", "links") | |
// .selectAll("line") | |
// .data(voronoi.links(sites)) | |
// .enter().append("line") | |
// .call(redrawLink); | |
var sites = sites.sort((a,b) => a[0] - b[0]) | |
var siteL = sites.splice(0, sites.length/2).reverse(); | |
var siteR = sites.splice(sites.length/2 - 1); | |
var site = d3.select(".sitesL").selectAll("circle") | |
.data(siteL).enter().append("circle") | |
.attr("r", 2.5) | |
.attr("cx", (d) => { | |
return d[0]}) | |
.attr("cy", (d) => d[1]) | |
var site = d3.select(".sitesR") | |
.selectAll("circle") | |
.data(siteR).enter().append("circle") | |
.attr("r", 2.5) | |
.attr("cx", (d) => d[0]) | |
.attr("cy", (d) => d[1]) | |
.attr("fill", "red") | |
var lastL = siteL[0] | |
var firstR = siteR[0] | |
svg.append("line") // attach a line | |
.attr("id", "line") | |
.style("stroke", "black") // colour the line | |
.attr("x1", lastL[0]) // x position of the first end of the line | |
.attr("y1", lastL[1]) // y position of the first end of the line | |
.attr("x2", firstR[0]) // x position of the second end of the line | |
.attr("y2", firstR[1]); // y position of the second end of the line | |
var getSlope = function(p2,p1){ | |
return (200-p2[1] - (200 - p1[1])) / (p2[0] - p1[0]) | |
} | |
var i = 0; | |
var j = 0; | |
var slope = getSlope(siteR[0], siteL[0]) | |
var n = true | |
while (n) { | |
n = false | |
while (siteL[i + 1] && getSlope(siteR[j], siteL[i+1]) > slope) { | |
n = true | |
console.log('i',slope, i , siteL[i][0], siteR[j][0]) | |
slope = getSlope(siteR[j], siteL[i + 1]) | |
d3.select("svg").append('line') | |
.attr("x1", siteL[i+1][0]) | |
.attr("y1", siteL[i+1][1]) | |
.attr("x2", siteR[j][0]) | |
.attr("y2", siteR[j][1]) | |
.attr("stroke", "red") | |
i++; | |
} | |
while (siteR[j + 1] && getSlope(siteR[j + 1], siteL[i]) < slope) { | |
n = true | |
console.log('j',slope, j , siteL[i][0], siteR[j][0]) | |
slope = getSlope(siteR[j + 1], siteL[i]) | |
d3.select("svg").append('line') | |
.attr("x1", siteL[i][0]) // x position of the first end of the line | |
.attr("y1", siteL[i][1]) | |
.attr("x2", siteR[j+1][0]) | |
.attr("y2", siteR[j+1][1]). | |
attr("stroke", "blue") | |
j++; | |
} | |
} | |
console.log("break") | |
</script> |
�PNG | |