Computers & Mobile Education Science
The Batman Equation

Reportedly, the equation above plots as the figure below, which is…familiar from somewhere. Can’t quite put my finger on it. [via Boing Boing]

More:

64 thoughts on “The Batman Equation

  1. The graph cheats. It only uses cherry picked real roots. It would look very different if all roots were graphed

    1. yeah, first thing i noticed was a number of |x|- or -|x| in denominators.  where are the bits of the graph where x == ?  ah well, next up: parametric quintic spline …possibly on a Riemannian sphere

    2. It’s not a cheat. All extra roots are killed away by the sqrt parts. Here is my matlab code to plot it:

      %% define the batman equationBatmanEq = @(x,y) ……((x/7)^2*sqrt(abs(abs(x)-3)/(abs(x)-3)) + (y/3)^2*sqrt(abs(y+3*sqrt(33)/7)/(y+3*sqrt(33)/7))-1) ……* (abs(x/2)-((3*sqrt(33)-7)/112)*x^2 -3 +sqrt(1-(abs(abs(x)-2)-1)^2) -y) ……* (9*sqrt(abs((abs(x)-1)*(abs(x)-0.75))/((1-abs(x))*(abs(x)-0.75))) -8*abs(x) -y) ……* (3*abs(x) + 0.75*sqrt(abs((abs(x)-0.75)*(abs(x)-0.5))/((0.75-abs(x))*(abs(x)-0.5))) -y) ……* (2.25*sqrt(abs((x-0.5)*(x+0.5))/((0.5-x)*(0.5+x))) -y) ……* (6*sqrt(10)/7 + (1.5-0.5*abs(x))*sqrt(abs(abs(x)-1)/(abs(x)-1)) -6*sqrt(10)/14*sqrt(4-(abs(x)-1)^2) -y);%% Calculate X- and Y-array defining the Batman logo% set x-pointsxx = (-7.1:0.01:7.1);% init y line arraysyy_pos = nan(size(xx));yy_neg = nan(size(xx));% set the range of y values to scan for the liney_scan = 0:0.01:3;% init Batman equation value arraysEqValue = zeros(size(y_scan));% Find y-values for each x-pointfor ii = 1:length(xx)% POSITIVE Y VALUES: ii = 1:length(xx)% POSITIVE Y VALUES:% POSITIVE Y VALUES:% calculate equation values for a vertical line of (x,y)-coordinates% calculate equation values for a vertical line of (x,y)-coordinates% Note that EqValues have also imaginary part!% Note that EqValues have also imaginary part!for jj = 1:length(y_scan)EqValue(jj) = BatmanEq(xx(ii), y_scan(jj));endfor jj = 1:length(y_scan)EqValue(jj) = BatmanEq(xx(ii), y_scan(jj));endend% Find y-coordinate around which the abs(EqValue) minimizes. % Find y-coordinate around which the abs(EqValue) minimizes. [~, mini] = min(abs(EqValue));% list indices around that minimum% list indices around that minimumind = max(mini-2, 1):min(mini+2,length(y_scan));% Although the batman logo “looks” continuous, it has breaks where it is% Although the batman logo “looks” continuous, it has breaks where it is% not defined (0 over 0 e.g. at x==3). We cannot interpolate in those% not defined (0 over 0 e.g. at x==3). We cannot interpolate in those% places.% places.if any(isnan(EqValue(ind)))yy_pos(ii) = nan;elseif any(isnan(EqValue(ind)))yy_pos(ii) = nan;elseelse% Use interpolation to find the Eq==0 point more accurately.% Use interpolation to find the Eq==0 point more accurately.% Spline interpolation works best here:% Spline interpolation works best here:% Spline interpolation likely finds also the points where eq gets% Spline interpolation likely finds also the points where eq gets% values [+,0,+] or [-,0,-] (as oppose to only [-,0,+] or [+,0,-]% values [+,0,+] or [-,0,-] (as oppose to only [-,0,+] or [+,0,-]% found by the other methods). However, spline does not perform% found by the other methods). However, spline does not perform% well with sharp corners. Thus interp of abs(EqValue) will not% well with sharp corners. Thus interp of abs(EqValue) will not% work as most zero points are in sharp corners thus using% work as most zero points are in sharp corners thus using% real(EqValue) is preferred. % real(EqValue) is preferred. yy_pos(ii) = interp1(real(EqValue(ind)), y_scan(ind), 0, ‘spline’);% Interpolation using only real part of the eq value, may lead to’spline’);% Interpolation using only real part of the eq value, may lead to% Interpolation using only real part of the eq value, may lead to% totally false values in some circumstances. Thus we must make sure% totally false values in some circumstances. Thus we must make sure% that absolute value of the Eq value is lower than treshold.% that absolute value of the Eq value is lower than treshold.if abs(BatmanEq(xx(ii), yy_pos(ii))) > 1 yy_pos(ii) = nan;endif abs(BatmanEq(xx(ii), yy_pos(ii))) > 1 yy_pos(ii) = nan;endendendend% NEGATIVE Y VALUES:% NEGATIVE Y VALUES:% Exactly same as with positive but: % Exactly same as with positive but: % ‘y_scan’ -> ‘-y_scan’)% ‘y_scan’ -> ‘-y_scan’)% ‘yy_pos’ -> ‘yy_neg’)% ‘yy_pos’ -> ‘yy_neg’)for jj = 1:length(y_scan)EqValue(jj) = BatmanEq(xx(ii), -y_scan(jj));endfor jj = 1:length(y_scan)EqValue(jj) = BatmanEq(xx(ii), -y_scan(jj));endend[~, mini] = min(abs(EqValue));ind = max(mini-2, 1):min(mini+2,length(y_scan));if any(isnan(EqValue(ind)))yy_neg(ii) = nan;elseif any(isnan(EqValue(ind)))yy_neg(ii) = nan;elseelseyy_neg(ii) = interp1(real(EqValue(ind)), -y_scan(ind), 0, ‘spline’);if abs(BatmanEq(xx(ii), yy_neg(ii))) > 1yy_neg(ii) = nan;end’spline’);if abs(BatmanEq(xx(ii), yy_neg(ii))) > 1yy_neg(ii) = nan;endif abs(BatmanEq(xx(ii), yy_neg(ii))) > 1yy_neg(ii) = nan;endendendendend% build plot arrays and ignore nan valuesnan_filter_pos = find(~isnan(yy_pos));nan_filter_neg = find(~isnan(yy_neg));xx_plot = [xx(nan_filter_pos), xx(nan_filter_neg(end:(-1):1))];yy_plot = [yy_pos(nan_filter_pos), yy_neg(nan_filter_neg(end:(-1):1))];%% plot Batman logo% init figureclfaxis equalequal% set background to yellowset(gca, ‘Color’, ‘y’)’Color’, ‘y’)% patch the Batman logopatch(xx_plot, yy_plot, [0,0,0], ……’EdgeColor’, ‘r’, …’EdgeColor’, ‘r’, …’LineWidth’, 4, …’LineWidth’, 4, …’LineStyle’, ‘:’)’LineStyle’, ‘:’)

  2. The graph cheats. It only uses cherry picked real roots. It would look very different if all roots were graphed

  3. Yeah I saw it a few days ago, put it into Matlab, and it turns out, it doesn’t work.
    The only way to MAKE it work is by graphing each term (the stuff within the brackets) separately within the boundaries that make up the shape.

    This doesn’t work:
    f = ‘((x/7)^2*sqrt(abs(abs(x)-​3)/(abs(x)-3))+(y/3)^2*sqr​t(abs(y+(3*sqrt(33))/7)/(y​+(3*sqrt(33))/7))-1)*(abs(​x/2)-((3*sqrt(33)-7)/112)*​x^2-3+sqrt(1-(abs(abs(x)-2​)-1)^2)-y)*(9*sqrt(abs((ab​s(x) – 1)*(abs(x)-3/4))/((1-abs(x​))*(abs(x)-3/4)))-8*abs(x)​-y)*(3*abs(x)+3/4*sqrt(abs​((abs(x) – 3/4)*(abs(x) – 1/2))/((3/4 – abs(x))*(abs(x) – 1/2))) – y)*(9/4*sqrt(abs((x-1/2)*(​x + 1/2))/((1/2-x)*(1/2+x))) – y)*((6*sqrt(10))/7+ (3/2-abs(x)/2)*sqrt(abs(ab​s(x)-1)/(abs(x)-1))-(6*sqr​t(10))/14*sqrt(4-(abs(x)-1​)^2)-y) = 0’;

    This does:
    hold on
    f1 = ‘(x/7)^2 * sqrt(abs(abs(x)-3)/(abs(x)​-3)) + (y/3)^2 * sqrt(abs(y + 3/7*sqrt(33))/(y + 3/7*sqrt(33))) – 1’;
    ezplot(f1,[-8 8 -3*sqrt(33)/7 6-4*sqrt(33)/7]);
    f2 = ‘abs(x/2)-(3*sqrt(33)-7) * x^2/112 – 3 + sqrt(1-(abs(abs(x)-2)-1)^2​) – y’;
    ezplot(f2,[-4 4]);
    f3 = ‘9 * sqrt(abs((1-abs(x))*(abs(x​)-0.75)) / ((1-abs(x))*(abs(x)-0.75))​) – 8*abs(x) – y’;
    ezplot(f3,[-1 -0.75 -5 5]);
    ezplot(f3,[ 0.75 1 -5 5]);
    f4 = ‘3*abs(x) + 0.75*sqrt(abs((0.75-abs(x)​)*(abs(x)-.5)) / ((.75-abs(x))*(abs(x)-.5))​) – y’;
    ezplot(f4,[-0.75 0.75 2.25 5]);
    f5 = ‘2.25*sqrt(abs(((0.5-x)*(0​.5+x))/((0.5-x)*(0.5+x))))​ – y’;
    ezplot(f5,[-0.5 0.5 -5 5]);
    f6 = ‘6*sqrt(10)/7 + (1.5-0.5*abs(x)) * sqrt(abs(abs(x)-1) / (abs(x)-1)) – 6*sqrt(10)/14 * sqrt(4-(abs(x)-1)^2) – y’;
    ezplot(f6,[-3 -1 -5 5]);
    ezplot(f6,[ 1 3 -5 5]);

    WolframAlpha won’t do, by the way… 

  4. This will work on Wolfram if you do the following:

    1. Graph each term separately
    2. Don’t type f(x)-y=0. Just type f(x).
    3. It may speed it up to do x=0 to 7.
    4. Don’t bother with abs(x). Just do x instead. You’ll only get one side of the equation, and then reflect it.

    First one’s a bit trickier. Recognize that it’s an oval: (x/7)^2 + (y/3)^3 = 1. Those funny square roots just assure that |x| is not less than 3, and that y is not less than -3root33/7. Then they just reduce to 1. Otherwise, they are undefined.

  5. This will work on Wolfram if you do the following:

    1. Graph each term separately
    2. Don’t type f(x)-y=0. Just type f(x).
    3. It may speed it up to do x=0 to 7.
    4. Don’t bother with abs(x). Just do x instead. You’ll only get one side of the equation, and then reflect it.

    First one’s a bit trickier. Recognize that it’s an oval: (x/7)^2 + (y/3)^3 = 1. Those funny square roots just assure that |x| is not less than 3, and that y is not less than -3root33/7. Then they just reduce to 1. Otherwise, they are undefined.

    1. That explains the first term. (outside of wing – big oval)
      2nd term is a bit tricky.
      3rd, 4th, and 5th terms:Again, forget |x|. Just think about x and reflect it. Ignoring the funny square roots we simply have:y= -8x + 9
      y= 3x + .75 and
      y = 2.25

      These are simple linear equations you should be able to graph yourself.
      They funny square roots are there to assure that x falls within some region. Try thinking about what happens to them when x is greater than 1 or less than .75, in the case of the first term, or greater than .75 or less than .5 in the case of the second term, or greater than .5 in the case of the third term. than insures that what’s under the square roots either reduce to 1, or are negative, the top being positive and the bottom being negative.

      Those 3 terms give you the head and ears.

  6. the equation above relies on an artifact of the plotting software used which blithely ignores the fact that the value sqrt(|x|/x) is undefined when x=0. indeed, since we’re dealing with real numbers, this value is really only defined when x>0. it seems a little ‘sneaky’ to rely on the solver to ignore complex values and also to conveniently ignore undefined values.

    a nicer solution would be one that is unequivocally defined everywhere (in the real, as opposed to complex, world). furthermore, a nice solution would be ‘robust’ in that small variations (such as those arising from, say, roundoff) would perturb the solution slightly (as opposed to eliminating large chunks).

    try the following in maxima (actually wxmaxima) which is free. the resulting plot is not quite as nice as the plot above (the lines around the head don’t have that nice ‘straight line’ look), but seems more ‘legitimate’ to me (in that any reasonable solver should plot a similar shape). please excuse the mess.

    load(draw)
    f(a,b,x,y):=a*x^2+b*y^2;
    c1:sqrt(26);
    draw2d(implicit(
    f(1/36,1/9,x,y)
    +max(0,2-f(1.5,1,x+3,y+2.7))
    +max(0,2-f(1.5,1,x-3,y+2.7))
    +max(0,2-f(1.9,1/1.7,(5*(x+1)+(y+3.5))/c1,(-(x+1)+5*(y+3.5))/c1))
    +max(0,2-f(1.9,1/1.7,(5*(x-1)-(y+3.5))/c1,((x-1)+5*(y+3.5))/c1))
    +max(0,2-((1.1*(x-2))^4-(y-2.1)))
    +max(0,2-((1.1*(x+2))^4-(y-2.1)))
    +max(0,2-((1.5*x)^8-(y-3.5)))
    -1,
    x,-6,6,y,-4,4))

    -joe

Comments are closed.

Tagged

I am descended from 5,000 generations of tool-using primates. Also, I went to college and stuff. I am a long-time contributor to MAKE magazine and makezine.com. My work has also appeared in ReadyMade, c't – Magazin für Computertechnik, and The Wall Street Journal.

View more articles by Sean Michael Ragan