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.
xxxxxxxxxx
<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="https://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(α) = (1+cos(nα))</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;
}
}
});
//https://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>
Modified http://d3js.org/d3.v3.min.js to a secure url
https://d3js.org/d3.v3.min.js