From 5a8800501d86f8d0873f25b05d0c185ebc5cdfcf Mon Sep 17 00:00:00 2001 From: Greg Smith Date: Sun, 9 Mar 2014 03:04:18 -0500 Subject: [PATCH] d3.js definitions: added a more complex Voronoi diagram test case, and updated definitions to pass --- d3/d3-tests.ts | 118 ++++++++++++++++++++++++++++++++++++++++++++++++- d3/d3.d.ts | 56 ++++++++++++++++------- 2 files changed, 156 insertions(+), 18 deletions(-) diff --git a/d3/d3-tests.ts b/d3/d3-tests.ts index 362f31ea06..aab65c06c0 100644 --- a/d3/d3-tests.ts +++ b/d3/d3-tests.ts @@ -1160,7 +1160,7 @@ function azimuthalEquidistant() { } //Example from http://bl.ocks.org/mbostock/4060366 -function voroniTesselation() { +function voronoiTesselation() { var width = 960, height = 500; @@ -1195,6 +1195,122 @@ function voroniTesselation() { } } +// Example from https://gist.github.com/christophermanning/1734663 +function forceDirectedVoronoi() { + var w = window.innerWidth > 960 ? 960 : (window.innerWidth || 960), + h = window.innerHeight > 500 ? 500 : (window.innerHeight || 500), + radius = 5.25, + links = [], + simulate = true, + zoomToAdd = true, + color = d3.scale.quantize().domain([10000, 7250]).range(["#dadaeb","#bcbddc","#9e9ac8","#807dba","#6a51a3","#54278f","#3f007d"]) + + var numVertices = (w*h) / 3000; + var vertices = d3.range(numVertices).map(function(i) { + var angle = radius * (i+10); + return {x: angle*Math.cos(angle)+(w/2), y: angle*Math.sin(angle)+(h/2)}; + }); + var d3_geom_voronoi = d3.geom.voronoi() + .x(function(d) { return d.x; }) + .y(function(d) { return d.y; }) + var prevEventScale = 1; + var zoom = d3.behavior.zoom().on("zoom", function(d,i) { + if (zoomToAdd){ + if (d3.event.scale > prevEventScale) { + var angle = radius * vertices.length; + vertices.push({x: angle*Math.cos(angle)+(w/2), y: angle*Math.sin(angle)+(h/2)}) + } else if (vertices.length > 2 && d3.event.scale != prevEventScale) { + vertices.pop(); + } + force.nodes(vertices).start() + } else { + if (d3.event.scale > prevEventScale) { + radius+= .01 + } else { + radius -= .01 + } + vertices.forEach(function(d, i) { + var angle = radius * (i+10); + vertices[i] = {x: angle*Math.cos(angle)+(w/2), y: angle*Math.sin(angle)+(h/2)}; + }); + force.nodes(vertices).start() + } + prevEventScale = d3.event.scale; + }); + + d3.select(window) + .on("keydown", function() { + // shift + if(d3.event.keyCode == 16) { + zoomToAdd = false + } + + // s + if(d3.event.keyCode == 83) { + simulate = !simulate + if(simulate) { + force.start() + } else { + force.stop() + } + } + }) + .on("keyup", function() { + zoomToAdd = true + }) + + var svg = d3.select("#chart") + .append("svg") + .attr("width", w) + .attr("height", h) + .call(zoom) + + var force = d3.layout.force() + .charge(-300) + .size([w, h]) + .on("tick", update); + + force.nodes(vertices).start(); + + var circle = svg.selectAll("circle"); + var path = svg.selectAll("path"); + var link = svg.selectAll("line"); + + function update() { + path = path.data(d3_geom_voronoi(vertices)); + path.enter().append("path") + // drag node by dragging cell + .call(d3.behavior.drag() + .on("drag", function(d, i) { + vertices[i] = {x: vertices[i].x + d3.event.dx, y: vertices[i].y + d3.event.dy} + }) + ) + .style("fill", function(d, i) { return color(0) }) + path.attr("d", function(d) { return "M" + d.join("L") + "Z"; }) + .transition().duration(150).style("fill", function(d, i) { return color(d3.geom.polygon(d).area()) }) + path.exit().remove(); + + circle = circle.data(vertices) + circle.enter().append("circle") + .attr("r", 0) + .transition().duration(1000).attr("r", 5); + circle.attr("cx", function(d) { return d.x; }) + .attr("cy", function(d) { return d.y; }); + circle.exit().transition().attr("r", 0).remove(); + + link = link.data(d3_geom_voronoi.links(vertices)) + link.enter().append("line") + link.attr("x1", function(d) { return d.source.x; }) + .attr("y1", function(d) { return d.source.y; }) + .attr("x2", function(d) { return d.target.x; }) + .attr("y2", function(d) { return d.target.y; }) + + link.exit().remove() + + if(!simulate) force.stop() + } +} + //Example from http://bl.ocks.org/mbostock/4341156 function delaunayTesselation() { var width = 960, diff --git a/d3/d3.d.ts b/d3/d3.d.ts index 9f6965cfaf..0b3f7e0b3b 100644 --- a/d3/d3.d.ts +++ b/d3/d3.d.ts @@ -3211,11 +3211,11 @@ declare module D3 { // Geometry export module Geom { export interface Geom { - voronoi(): Voronoi; + voronoi(): Voronoi; /** * compute the Voronoi diagram for the specified points. */ - voronoi(vertices?: Array): Array; + voronoi(vertices: Array): Array; /** * compute the Delaunay triangulation for the specified points. */ @@ -3296,48 +3296,58 @@ declare module D3 { y: number; } - export interface Voronoi { + export interface Voronoi { /** - * compute the Voronoi diagram for the specified points. + * Compute the Voronoi diagram for the specified data. */ - (vertices?: Array): Array; + (data: Array): Array; + /** + * Compute the graph links for the Voronoi diagram for the specified data. + */ + links(data: Array): Array; + /** + * Compute the triangles for the Voronoi diagram for the specified data. + */ + triangles(data: Array): Array>; x: { /** * Get the x-coordinate accessor. */ - (): (data: any, index ?: number) => number; + (): (data: T, index ?: number) => number; + /** * Set the x-coordinate accessor. * * @param accessor The new accessor function */ - (accessor: (data: any) => number): Voronoi; - (accessor: (data: any, index: number) => number): Voronoi; + (accessor: (data: T, index: number) => number): Voronoi; + /** * Set the x-coordinate to a constant. * - * @param cnst The new constant value. + * @param constant The new constant value. */ - (cnst: number): Voronoi; + (constant: number): Voronoi; } y: { /** * Get the y-coordinate accessor. */ - (): (data: any, index ?: number) => number; + (): (data: T, index ?: number) => number; + /** * Set the y-coordinate accessor. * - * @param accessor The new accessor function. + * @param accessor The new accessor function */ - (accessor: (data: any) => number): Voronoi; - (accessor: (data: any, index: number) => number): Voronoi; + (accessor: (data: T, index: number) => number): Voronoi; + /** * Set the y-coordinate to a constant. * - * @param cnst The new constant value. + * @param constant The new constant value. */ - (cnst: number): Voronoi; + (constant: number): Voronoi; } clipExtent: { /** @@ -3349,7 +3359,19 @@ declare module D3 { * * @param extent The new clip extent. */ - (extent: Array>): Voronoi; + (extent: Array>): Voronoi; + } + size: { + /** + * Get the size. + */ + (): Array; + /** + * Set the size, equivalent to a clip extent starting from (0,0). + * + * @param size The new size. + */ + (size: Array): Voronoi; } }