Create a gist now

Instantly share code, notes, and snippets.

@mbostock /.block
Last active Aug 23, 2017

What would you like to do?
Epicyclic Gearing
license: gpl-3.0

From Wikipedia:

Epicyclic gearing or planetary gearing is a gear system consisting of one or more outer gears, or planet gears, revolving about a central, or sun gear. … Epicyclic gearing systems also incorporate the use of an outer ring gear or annulus, which meshes with the planet gears.

Use the menu in the top-left to change the frame of reference, fixing the specified gear in-place.

<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
width: 960px;
height: 500px;
position: relative;
}
form {
position: absolute;
top: 1em;
left: 1em;
}
path {
fill-rule: evenodd;
stroke: #333;
stroke-width: 2px;
}
.sun path {
fill: #6baed6;
}
.planet path {
fill: #9ecae1;
}
.annulus path {
fill: #c6dbef;
}
</style>
<form>
<input type="radio" name="reference" id="ref-annulus">
<label for="ref-annulus">Annulus</label><br>
<input type="radio" name="reference" id="ref-planet" checked>
<label for="ref-planet">Planets</label><br>
<input type="radio" name="reference" id="ref-sun">
<label for="ref-sun">Sun</label>
</form>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var width = 960,
height = 500,
radius = 80,
x = Math.sin(2 * Math.PI / 3),
y = Math.cos(2 * Math.PI / 3);
var offset = 0,
speed = 4,
start = Date.now();
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")scale(.55)")
.append("g");
var frame = svg.append("g")
.datum({radius: Infinity});
frame.append("g")
.attr("class", "annulus")
.datum({teeth: 80, radius: -radius * 5, annulus: true})
.append("path")
.attr("d", gear);
frame.append("g")
.attr("class", "sun")
.datum({teeth: 16, radius: radius})
.append("path")
.attr("d", gear);
frame.append("g")
.attr("class", "planet")
.attr("transform", "translate(0,-" + radius * 3 + ")")
.datum({teeth: 32, radius: -radius * 2})
.append("path")
.attr("d", gear);
frame.append("g")
.attr("class", "planet")
.attr("transform", "translate(" + -radius * 3 * x + "," + -radius * 3 * y + ")")
.datum({teeth: 32, radius: -radius * 2})
.append("path")
.attr("d", gear);
frame.append("g")
.attr("class", "planet")
.attr("transform", "translate(" + radius * 3 * x + "," + -radius * 3 * y + ")")
.datum({teeth: 32, radius: -radius * 2})
.append("path")
.attr("d", gear);
d3.selectAll("input[name=reference]")
.data([radius * 5, Infinity, -radius])
.on("change", function(radius1) {
var radius0 = frame.datum().radius, angle = (Date.now() - start) * speed;
frame.datum({radius: radius1});
svg.attr("transform", "rotate(" + (offset += angle / radius0 - angle / radius1) + ")");
});
d3.selectAll("input[name=speed]")
.on("change", function() { speed = +this.value; });
function gear(d) {
var n = d.teeth,
r2 = Math.abs(d.radius),
r0 = r2 - 8,
r1 = r2 + 8,
r3 = d.annulus ? (r3 = r0, r0 = r1, r1 = r3, r2 + 20) : 20,
da = Math.PI / n,
a0 = -Math.PI / 2 + (d.annulus ? Math.PI / n : 0),
i = -1,
path = ["M", r0 * Math.cos(a0), ",", r0 * Math.sin(a0)];
while (++i < n) path.push(
"A", r0, ",", r0, " 0 0,1 ", r0 * Math.cos(a0 += da), ",", r0 * Math.sin(a0),
"L", r2 * Math.cos(a0), ",", r2 * Math.sin(a0),
"L", r1 * Math.cos(a0 += da / 3), ",", r1 * Math.sin(a0),
"A", r1, ",", r1, " 0 0,1 ", r1 * Math.cos(a0 += da / 3), ",", r1 * Math.sin(a0),
"L", r2 * Math.cos(a0 += da / 3), ",", r2 * Math.sin(a0),
"L", r0 * Math.cos(a0), ",", r0 * Math.sin(a0));
path.push("M0,", -r3, "A", r3, ",", r3, " 0 0,0 0,", r3, "A", r3, ",", r3, " 0 0,0 0,", -r3, "Z");
return path.join("");
}
d3.timer(function() {
var angle = (Date.now() - start) * speed,
transform = function(d) { return "rotate(" + angle / d.radius + ")"; };
frame.selectAll("path").attr("transform", transform);
frame.attr("transform", transform); // frame of reference
});
</script>

Pomax commented Sep 28, 2013

basedon the wiki quote, the sun and annulus radio buttons need their labels exchanged =)

This example is amazing indeed! :)

Hello sir i want to perform intersection with two geojson files with draw tool. I have tried with by using example https://bl.ocks.org/pgiraud/2ed05b0a9e394c5652b3. By using it i can able to perform intersection to one geojson with draw tool. Now my intension is to perform intersection to the two geojson files and then find intersection of the one geojson with other geojson, i have tried with the code like below for reference sir.

<title>Select features example</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/ol3/3.10.1/ol-debug.js"></script> <script src="ol.js"></script> <script src="jsts_geom_Polygon.js"></script> <script src="https://cdn.rawgit.com/bjornharrtell/jsts/gh-pages/lib/0.16.0/javascript.util.min.js"></script> <script src="https://cdn.rawgit.com/bjornharrtell/jsts/gh-pages/lib/0.16.0/jsts.min.js"></script> <script src="jsts_io_GeoJSONParser.js"></script> <style> html, body { padding: 0; margin: 0; } html, body, .map { height: 100%; width: 100%; } </style>

<script> var geojsonFormat = new ol.format.GeoJSON(); var style = new ol.style.Style({ fill: new ol.style.Fill({ color: 'rgba(255, 255, 255, 0.3)' }), stroke: new ol.style.Stroke({ color: 'rgba(255, 120, 0, 0.6)', width: 1 }) }); var styles = [style]; var highlightStyle = [ new ol.style.Style({ fill: new ol.style.Fill({ color: 'rgba(255, 120, 0, 0.3)' }), stroke: new ol.style.Stroke({ color: 'rgba(255, 120, 0, 0.6)', width: 1 }) }) ]; var vector3 = new ol.layer.Vector({ maxResolution: 0.8, source: new ol.source.Vector({ url: 'ap_taluk.geojson', format: new ol.format.GeoJSON({ defaultDataProjection:'EPSG:4326' }) }), style: styles }); var vector2 = new ol.layer.Vector({ maxResolution: 0.8, source: new ol.source.Vector({ url: 'flood.geojson', format: new ol.format.GeoJSON({ defaultDataProjection:'EPSG:4326' }) }), style: styles }); var layer1 = new ol.layer.Tile({ title: 'India', source: new ol.source.TileWMS({ url: '', params: {LAYERS: ''} }), transparent: false }); var dist = new ol.layer.Tile({ title: 'flood', source: new ol.source.TileWMS({ url: '', params: {LAYERS: ''} }) }); var distaluk = new ol.layer.Tile({ title: 'taluk', source: new ol.source.TileWMS({ url: '', params: {LAYERS: ''} }) }); intersectionLayer = new ol.layer.Vector({ source: new ol.source.Vector() }); var map = new ol.Map({ layers: [layer1,vector2,vector3,intersectionLayer,distaluk], target: 'map', view: new ol.View({ projection: 'EPSG:4326', center: [79.419,15.428], zoom: 8 }) }); var draw_inter = new ol.interaction.Draw({ type: 'Polygon' }); map.addInteraction(draw_inter); draw_inter.on('drawstart', function(evt) { intersectionLayer.getSource().clear(); }); var olParser = new jsts.io.olParser(); var geojsonParser = new jsts.io.GeoJSONParser(); draw_inter.on('drawend', function(evt) { var poly1 = olParser.read(evt.feature.getGeometry()); var extent1 = evt.feature.getGeometry().getExtent(); var source = vector2.getSource(); var source2 = vector3.getSource(); //var source4 = vector4.getSource(); var features = source.getFeatures(); var features2 = source2.getFeatures(); // var features4 = source4.getFeatures(); features.forEach(function(feature) { if (!ol.extent.intersects(extent1, feature.getGeometry().getExtent())) { return; } var poly2 = olParser.read(feature.getGeometry()); var intersection = poly1.intersection(poly2); //alert(intersection); intersection = geojsonParser.write(intersection); if(intersection.type === 'GeometryCollection' && intersection.geometries.length === 0) { return; } else { intersectionLayer.getSource().addFeature(geojsonFormat.readFeature({ type: 'Feature', properties: {}, geometry: intersection })); //alert("flood"+feature.get('geometry')); } }); features2.forEach(function(feature) { if (!ol.extent.intersects(extent1, feature.getGeometry().getExtent())) { return; } var poly3 = olParser.read(feature.getGeometry()); var intersection = poly1.intersection(poly3); //alert(intersection); intersection = geojsonParser.write(intersection); if(intersection.type === 'GeometryCollection' && intersection.geometries.length === 0) { return; } else { alert("village"+feature.get('taluk')); /*intersectionLayer.getSource().addFeature(geojsonFormat.readFeature({ type: 'Feature', properties: {}, geometry: intersection })); /*layersize = intersectionLayer.getSource().getFeatures().length; alert(" size"+layersize); for(i=0;i 10000) { output = (Math.round(totalarea / 1000000 * 100) / 100) + ' ' + 'km2'; } else { output = (Math.round(totalarea * 100) / 100) + ' ' + 'm2'; } alert(output); }); </script>

Kyeongan commented Sep 2, 2016

Amazing!

Hi, this question is actually relates to the D3 graph stated here http://bl.ocks.org/mbostock/7607535. I'm very interested in using this graph. However, could you suggest a bit on how to include "hover" behaviour for every node (include parent and children nodes) please?

Does anyone has the data called 'airport.csv' and 'flights.csv' because in the example :https://bl.ocks.org/mbostock/7608400 , these two files are used but there is no source, I want to figure out the format of these files and use my own data to replace them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment