Last active
December 20, 2015 03:49
-
-
Save KKostya/6066548 to your computer and use it in GitHub Desktop.
More fun with Joukowski
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function dist(z0,z,z1) | |
{ | |
var dx10 = z1.re-z0.re, dy10 = z1.im-z0.im; | |
var dx0 = z.re-z0.re, dy0 = z.im-z0.im; | |
return Math.pow(dx10*dy0-dy10*dx0,2)/(dx0*dx0+dy0*dy0); | |
} | |
function resampleLoop(f,ps,eps) | |
{ | |
var ds = ps.map(f); | |
function refStep(params,data) | |
{ | |
for(var i = 0; i < params.length; i++) | |
{ | |
var ni = i+1<params.length?i+1:0; | |
var p0 = params[i], p1 = params[ni]; | |
var newp = (p0+p1)/2; | |
if( p1-p0 >= Math.PI || p1-p0 <= -Math.PI ) newp += Math.PI; | |
var newf = f(newp); | |
if(dist(data[i],newf,data[ni]) > eps) | |
{ params.splice(++i,0,newp); data.splice(i,0,newf); } | |
} | |
} | |
refStep(ps,ds); | |
refStep(ps,ds); | |
refStep(ps,ds); | |
refStep(ps,ds); | |
refStep(ps,ds); | |
return ds; | |
} | |
function resampleLine(f,ps,eps) | |
{ | |
var ds = ps.map(f); | |
function refStep(params,data) | |
{ | |
for(var i = 0; i < params.length-1; i++) | |
{ | |
var p0 = params[i], p1 = params[i+1]; | |
var newp = (p0+p1)/2; | |
var newf = f(newp); | |
if(dist(data[i],newf,data[i+1]) > eps) | |
{ params.splice(++i,0,newp); data.splice(i,0,newf); } | |
} | |
} | |
refStep(ps,ds); | |
refStep(ps,ds); | |
refStep(ps,ds); | |
refStep(ps,ds); | |
refStep(ps,ds); | |
return ds; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<style> | |
svg { font: 10px sans-serif; } | |
.brsh .extent { fill: steelblue; stroke: grey; stroke-width: 0.5px; fill-opacity: .125;} | |
.brsh .back { fill: none; stroke: black; stroke-width: 1px;} | |
.line { fill: none; stroke: black; stroke-width: 1px; } | |
.force .line { fill: none; stroke: red; stroke-width: 1.5px; } | |
.poten .line { fill: none; stroke: blue; stroke-width: 1.5px; } | |
.axis { fill: none; stroke: black; } | |
</style> | |
<body> | |
<form> | |
<label><input type="radio" name="mode" value="rctng"> Rectangular</label> | |
<label><input type="radio" name="mode" value="crclr" checked> Circular</label> | |
</form> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<script src="confmap.js"></script> | |
<script> | |
function Complex(re, im) { this.re = re; this.im = im; }; | |
Complex.prototype.clone = function(){ return new Complex(this.re,this.im); }; | |
Complex.prototype.add = function(z) { this.re += z.re; this.im += z.im; return this; }; | |
Complex.prototype.sub = function(z) { this.re -= z.re; this.im -= z.im; return this; }; | |
Complex.prototype.mul = function(z) | |
{ | |
var tmp = this.re; | |
this.re = this.re*z.re - this.im*z.im; | |
this.im = tmp*z.im + this.im*z.re; | |
return this; | |
}; | |
Complex.prototype.div = function(z) | |
{ | |
var tmp = this.re, | |
n = z.re*z.re + z.im*z.im; | |
this.re = (this.re*z.re + this.im*z.im)/n; | |
this.im = ( -tmp*z.im + this.im*z.re)/n; | |
return this; | |
}; | |
var width = 960, height = 500; | |
var svg = d3.select("body") | |
.append("svg") | |
.attr("width", width) | |
.attr("height", height); | |
svg.append("clipPath") | |
.attr("id","clip") | |
.append("rect") | |
.attr("x",0).attr("y",0) | |
.attr("width",width/2).attr("height",height); | |
var mapd = svg.append("g").attr("class","mapd").attr("clip-path","url(#clip)"); | |
var brsh = svg.append("g").attr("class","brsh") | |
.attr("transform","translate("+width/2+")"); | |
var brsR = brsh.append("g").attr("class", "poten"); | |
var brsP = brsh.append("g").attr("class", "force"); | |
var mapR = mapd.append("g").attr("class", "poten"); | |
var mapP = mapd.append("g").attr("class", "force"); | |
var x1 = d3.scale.linear().range([0, width/2]).domain([-5, 5]); | |
var y1 = d3.scale.linear().range([ height, 0]).domain([-5, 5]); | |
var x2 = d3.scale.linear().range([0, width/2]).domain([-3, 3]); | |
var y2 = d3.scale.linear().range([ height, 0]).domain([-3, 3]); | |
mapd.append("g").attr("class","axis") | |
.attr("transform","translate(0,"+height/2+")") | |
.call(d3.svg.axis().scale(x1).orient("bottom")); | |
mapd.append("g").attr("class","axis") | |
.attr("transform","translate("+width/4+")") | |
.call(d3.svg.axis().scale(y1).orient("left")); | |
brsh.append("g").attr("class","axis") | |
.attr("transform","translate(0,"+height/2+")") | |
.call(d3.svg.axis().scale(x2).orient("bottom")); | |
brsh.append("g").attr("class","axis") | |
.attr("transform","translate("+width/4+")") | |
.call(d3.svg.axis().scale(y2).orient("left")); | |
var line1 = d3.svg.line() | |
.x(function(d) { return x1(d.re); }) | |
.y(function(d) { return y1(d.im); }); | |
var line2 = d3.svg.line() | |
.x(function(d) { return x2(d.re); }) | |
.y(function(d) { return y2(d.im); }); | |
var brush = d3.svg.brush().x(x2).y(y2).on("brush", plotC); | |
brsh.append("rect").attr("class","back") | |
.attr("width",width/2) | |
.attr("height",height); | |
brsh.call(brush); | |
function plines(sel,data, f) | |
{ | |
var paths = sel.selectAll('.line').data(data); | |
paths.enter().append('path').attr('class','line'); | |
paths.attr('d',f); | |
paths.exit().remove(); | |
} | |
d3.selectAll("input").on("change", function(){ | |
if(this.value==="crclr") brush.on("brush",plotC); | |
else brush.on("brush",plotR); | |
brush.on("brush")(); }); | |
function f(z) { return z.add((new Complex(1,0)).div(z)) } | |
function plotC() | |
{ | |
if(brush.empty()) return; | |
ext = brush.extent(); | |
var rads = d3.range(0,1,1/10); | |
var phis = d3.range(-Math.PI,Math.PI,Math.PI/10); | |
var x0 = (ext[1][0] + ext[0][0])/2; | |
var y0 = (ext[1][1] + ext[0][1])/2; | |
var dx = (ext[1][0] - ext[0][0])/2; | |
var dy = (ext[1][1] - ext[0][1])/2; | |
var Ppars = rads.map(function(r){return function(t){return new Complex(x0+r*dx*Math.cos(t),y0+r*dy*Math.sin(t));};}); | |
var Rpars = phis.map(function(p){return function(t){return new Complex(x0+t*dx*Math.cos(p),y0+t*dy*Math.sin(p));};}); | |
plines(brsR, Ppars.map(function(par){return phis.map(par);}), function(d){return line2(d)+'Z';}); | |
plines(brsP, Rpars.map(function(par){return rads.map(par);}), function(d){return line2(d);}); | |
var PparsF = Ppars.map(function(par){return function(t){return f(par(t)); };}); | |
var RparsF = Rpars.map(function(par){return function(t){return f(par(t)); };}); | |
plines(mapR,PparsF.map(function(par){return resampleLoop(par,phis,0.0001);}),function(d){return line1(d)+'Z';}); | |
plines(mapP,RparsF.map(function(par){return resampleLine(par,rads,0.0001);}),function(d){return line1(d);}); | |
} | |
function plotR() | |
{ | |
if(brush.empty()) return; | |
ext = brush.extent(); | |
var x1 = ext[1][0], x0 = ext[0][0] | |
var y1 = ext[1][1], y0 = ext[0][1] | |
var dx = ext[1][0] - ext[0][0]; | |
var dy = ext[1][1] - ext[0][1]; | |
var xs = d3.range(0,1.01,1/10); | |
var ys = d3.range(0,1.01,1/10); | |
var Xpars = xs.map(function(x){return function(t){return new Complex(x0+x*dx,y0+t*dy);};}); | |
var Ypars = ys.map(function(y){return function(t){return new Complex(x0+t*dx,y0+y*dy);};}); | |
plines(brsR, Xpars.map(function(par){return ys.map(par);}), function(d){return line2(d);}); | |
plines(brsP, Ypars.map(function(par){return xs.map(par);}), function(d){return line2(d);}); | |
var XparsF = Xpars.map(function(par){return function(t){return f(par(t)); };}); | |
var YparsF = Ypars.map(function(par){return function(t){return f(par(t)); };}); | |
plines(mapR,XparsF.map(function(par){return resampleLine(par,ys,0.0001);}),function(d){return line1(d);}); | |
plines(mapP,YparsF.map(function(par){return resampleLine(par,xs,0.0001);}),function(d){return line1(d);}); | |
} | |
</script> | |
</body> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment