Skip to content

Instantly share code, notes, and snippets.

@chabb
Last active May 13, 2022 08:24
Show Gist options
  • Save chabb/423835fd6705787e4ab3 to your computer and use it in GitHub Desktop.
Save chabb/423835fd6705787e4ab3 to your computer and use it in GitHub Desktop.
Générateur de rosaces

Les différentes formes qui peuvent être générées par les fonctions trigonométriques ont quelque chose de fascinant. En tombant sur ce site, je me demandais s'il était possible de reconstruire un générateur reproduisant ces formes, avec les formules correspondantes, à l'aide de d3.js. Eh oui, d3 est un outil capable de se plier à tous les usages qu'on voudra bien en faire.

Changez les valeurs et cliquez sur le bouton pour redessiner la rosace.

<!DOCTYPE html>
<meta charset="utf-8">
<style>
.frame {
fill: none;
stroke: #000;
}
.axis text {
font: 10px sans-serif;
}
#params {
font:35px "Helvetica Neue";
}
.axis line,
.axis circle {
fill: none;
stroke: #777;
stroke-dasharray: 1,4;
}
.axis :last-of-type circle {
stroke: #333;
stroke-dasharray: none;
}
.line {
fill: none;
stroke: red;
stroke-width: 1.5px;
}
input {
vertical-align: middle;
font:20px "Helvetica Neue";
}
#sub {
font:35px "Helvetica Neue";
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<div id="params" style="position:absolute;">
<form name="main" onsubmit="return update()" action="" method="get">
N : <input id="na" size="1" type="number" min="0" max="10" value="5" step="1"> /
<input id="nb" size="1" type="number" min="1" max="10" value="2" step="1">
<br>
E : <input id="e" type="number" min="0" max="5" value="2.9" step="0.1">
<br>
<input type="submit" id="sub" value="Redraw">
</form>
<span style="font-size:25px">f(&#x3b1;) = (1+cos(n&#x3b1;))</span>
</div>
<script>
d3.interpolators.push(function(a,b){
if (Array.isArray(a[0]) && Array.isArray(b[0])) {
var x = [],
c = [],
na = a.length,
nb = b.length,
n0 = Math.min(a.length, b.length),
i,
delta = b.length - a.length,
newSize;
for (i=0; i < na; ++i) c[i] = b[i];
newSize;
return function(t) {
newSize = a.length + delta*t;
//console.log(newSize,c.length,t,delta);
if (newSize>c.length){
for (i=c.length;i<newSize;i++) c.push(b[i]);
}
return c;
}
}
});
//http://www.mathcurve.com/courbes2d/conchoidderosace/conchoidderosace.shtmlv
var n = 5/2
var factor = 2.9;
var data = d3.range(-16*Math.PI, 16*Math.PI, .01).map(function(t) {
return [t, (1+factor*Math.cos((n)*t))/(1+factor)];
});
var empty = d3.range(0, 2*Math.PI, .01).map(function(t) {
return [0,0];
});
var margin = 30;
// radius is the minimal dimension, minus the margin
var width = 960,
height = 500,
radius = Math.min(width, height) / 2 - margin;
var r = d3.scale.linear()
.domain([0, 1])
.range([0, radius]);
//default accessor [[x1,y1]] => radian and angle
var line = d3.svg.line.radial()
.radius(function(d){; return (r(d[1])); }) // will change between -1 and 1
.angle(function(d) { ;return d[0];});
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
// radius axis
// cheat with CSS
var gr = svg.append("g")
.attr("class", "r axis")
.selectAll("g")
.data(r.ticks(10).slice(0))
.enter().append("g");
gr.append("circle")
.attr("r", function(d,i){console.log("=>",d,i,r(d));return r(d)});
gr.append("text")
.attr("y", function(d) { return -r(d) - 4; })
.attr("transform", "rotate(50)")
.style("text-anchor", "middle")
.text(function(d) { return d; });
var ga = svg.append("g")
.attr("class", "a axis")
.selectAll("g")
.data(d3.range(0, 360, 15))
.enter().append("g")
.attr("transform", function(d) { return "rotate(" + (d-90) + ")"; });
ga.append("line")
.attr("x2", radius);
ga.append("text")
.attr("x", radius + 6)
.attr("dy", ".35em")
.style("text-anchor", function(d) { return d < 270 && d > 90 ? "end" : null; })
.attr("transform", function(d) { return d < 270 && d > 90 ? "rotate(180 " + (radius + 6) + ",0)" : null; })
.text(function(d) { return d + "°"; });
// a bit cheating
var path =
svg.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line);
var totalLength = path.node().getTotalLength();
path.transition().duration(1000).attrTween("d",function(d){
console.log(empty,d);
var interpolate = d3.interpolate( [[0,0]],d);
return function(t) { return line(interpolate(t))};
})
function update() {
var nfa = parseFloat(document.getElementById("na").value);
var nfb = parseFloat(document.getElementById("nb").value);
var e = parseFloat(document.getElementById("e").value);
console.log(nfa,nfb,e);
var _n = nfa/nfb;
var _factor = e;
var _data = d3.range(-16*Math.PI, 16*Math.PI, .01).map(function(t) {
return [t, ( 1+_factor*Math.cos((_n)*t))/(1+_factor)];
});
path.datum(_data).transition(2000).attr("d",line);
return false;
}
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment