The Socialhacker http://socialhacker.com/index.xml Content on The Socialhacker Hugo -- gohugo.io en-us anton@socialhacker.com (Anton Staaf) anton@socialhacker.com (Anton Staaf) Copyright &copy; Anton Staaf.&nbsp;<a href="http://socialhacker.com/copyright/">Some rights reserved</a>. Mon, 01 May 2017 00:00:00 +0000 Interactive Explosions using Exponential Decay http://socialhacker.com/posts/breaker/interactive_explosions/ Mon, 06 Mar 2017 00:00:00 +0000 anton@socialhacker.com (Anton Staaf) http://socialhacker.com/posts/breaker/interactive_explosions/ <p>I have been working on a game recently, and I ran into some interesting math along the way. I wanted an explosion animation that started out fast, and as it got larger it would get slower. Below you can click, drag or swipe to create the explosions I ended up building.</p> <div class="viewport shock-wave-view" id=""></div> <p>For simplicity, I am rendering the explosion as a ring, with expanding inner and outer radii. I wanted the rate of expansion of the two radii to start fast and end slow, but this could just as easily be applied to a collection of particles. One possible formula for velocity would be a linear ramp, changing from the initial to the final velocity in equal steps over the animation. That is, a constant change in velocity.</p> <p><span class="math">$\frac{dV(t)}{dt} = \frac{V_T - V_0}{T}$</span></p> <p>But that didn't have the effect I was looking for; I wanted the leading edge of the ring to be moving really quickly and to slow down really quickly. And as it was near the end of the animation, moving more slowly, I wanted it to be slowing down more slowly as well. I wanted the change in velocity to be proportional to the current velocity.</p> <p><span class="math">$$$\label{eqn:exponential_decay} \frac{dV(t)}{dt} = -\lambda V(t)$$$</span></p> <p>This differential equation, known as an <a href="https://en.wikipedia.org/wiki/Exponential_decay">Exponential Decay</a>, is conventionally written with a negative sign so that the proportionality constant, <span class="math">$$\lambda$$</span>, will be positive. When <span class="math">$$\lambda$$</span> is positive it continually subtracts a proportion of the velocity from itself, so when the velocity is large, the portion subtracted will be large, and when the velocity is small, the portion subtracted will be small. For completeness we'll also need a differential equation that relates position and velocity.</p> <p><span class="math">$$$\label{eqn:position_diffeq} \frac{dX(t)}{dt} = V(t)$$$</span></p> <p>The combination of <span class="math">$$\eqref{eqn:exponential_decay}$$</span> and <span class="math">$$\eqref{eqn:position_diffeq}$$</span> is a system of differential equations; it says that the change in something's velocity (in our case the two ring radii) at some time will be proportional to the thing's velocity at that time. It also says that the change in the thing's position at some time is the thing's velocity. You can use these equations exactly as they are, via numeric integration. You iteratively update the velocity and position of the value you are simulating. The simplest way to do the update would be with the <a href="https://en.wikipedia.org/wiki/Euler_method">Euler method</a>. You would select a small increment in time (a timestep) and move the simulation forward by that amount of time over and over again. For every timestep you update velocity by evaluating <span class="math">$$\eqref{eqn:exponential_decay}$$</span>, and then position by evaluating <span class="math">$$\eqref{eqn:position_diffeq}$$</span>. But if you want to know the position or velocity at a specific time you'll need to rerun the simulation from the beginning to get it, which could be very costly if you have selected a small timestep, which you would have to do to ensure an accurate simulation. Alternatively you could store all previous steps of the simulation, which would take a lot of memory. Either way, what values should you use for <span class="math">$$\lambda$$</span> and the initial position and velocity? A better approach (at least for my needs) is to solve this differential equation analytically, and use the result to pick initial values and to evaluate position and velocity at arbitrary times.</p> <p>Here is another version of the same expanding ring, rendered using the awesome online calculator <a href="https://www.desmos.com/">Desmos</a>. You can manually control the time slider (if you can grab it) to get a feel for how the two exponentials control the inner and outer radii of the ring.</p> <iframe src = "https://www.desmos.com/calculator/xm4ltfryqz?embed" id = "" class = "desmos-iframe"> </iframe> <p>So where's the interesting math? It turns out that picking the initial position, velocity, and <span class="math">$$\lambda$$</span> values to get a good-looking explosion takes some care. For one thing, I wanted to make the final positions of the two exponenitals that control the inner and outer radii equal. I could have done that by trial an error, maybe, but there's a better way. In this post I'll go through solving <span class="math">$$\eqref{eqn:exponential_decay}$$</span> and <span class="math">$$\eqref{eqn:position_diffeq}$$</span> for a number of different parameters. We'll want an equation that can tell us the radius at a given time in the simulation. We'll also want to be able to compute initial velocity given some more intuitive parameters that make specifying the explosion simpler. In this case, it turns out to be easier to specify the final velocity, duration of explosion, and amount that the ring should expand. Given these, the initial velocity and <span class="math">$$\lambda$$</span> are completely defined.</p> <h2 id="velocity">Velocity</h2> <p>The first step will be to solve <span class="math">$$\eqref{eqn:exponential_decay}$$</span> so that we have an equation for velocity at an arbitrary time. This is a pretty simple differential equation, and we can solve it directly by integration.</p> <button data-open = Hide&#32;derivation data-closed = Show&#32;derivation class = "hidden-shortcode-button"> Show derivation </button> </section> <section class="content hidden-shortcode-wrapper start-closed "> <div class="hidden-shortcode-content" style="overflow: auto"> <p>First multiply both sides of <span class="math">$$\eqref{eqn:exponential_decay}$$</span> by <span class="math">$$dt$$</span> and divide by <span class="math">$$V(t)$$</span>.</p> <p><span class="math">$\frac{1}{V(t)} dV(t) = -\lambda dt$</span></p> <p>Integrate both sides and collect the integration constants on the right. The integral of <span class="math">$$\frac{1}{u}du$$</span> is <span class="math">$$log(u) + C$$</span>, and the integral of <span class="math">$$a du$$</span> is <span class="math">$$a u + C$$</span>.</p> <p><span class="math">$log(V(t)) = -\lambda t + C$</span></p> <p>We want to get an equation for <span class="math">$$V(t)$$</span> so we need to get it out of the logarithm on the left; exponentiate both sides.</p> <p><span class="math">$V(t) = e^{-\lambda t + C}$</span></p> <p>We just have one step left; we need to determine what <span class="math">$$C$$</span> is. To find out what <span class="math">$$C$$</span> is we compute the velocity at time zero (<span class="math">$$V_0$$</span>).</p> <p><span class="math">$V_0 := V(0) = e^C$</span></p> <p>So we can break the exponential up into two factors, and replace the second factor (<span class="math">$$e^C$$</span>) with <span class="math">$$V_0$$</span>. We can see that <span class="math">$$C$$</span> was just the logarithm of our initial velocity (<span class="math">$$V_0$$</span>).</p> </div> </section> <section class="content"> <p>The result is the solution for velocity at any time <span class="math">$$t$$</span>.</p> <p><span class="math">$$$\label{eqn:velocity} V(t) = V_0 e^{-\lambda t}$$$</span></p> <p>Nothing too surprising here; this tells us how a value changes over time if it is continually being acted on in proportion to itself. Here is the same function written in Dart<sup class="footnote-ref" id="fnref:1"><a class="footnote" href="#fn:1">1</a></sup>. This is one method from a class called <a href="http://socialhacker.com/source/breaker/web/exponential_rate_source/">ExponentialRate</a> that I am using to model this system of differential equations in the game. The complete source for <a href="http://socialhacker.com/source/breaker/web/exponential_rate_source/">ExponentialRate</a> can be found <a href="http://socialhacker.com/source/breaker/web/exponential_rate_source/">here</a>.</p> <pre><code class="language-dart">/// /// Return the rate of change of the value at a given time. /// /// Time can be negative, positive, or zero, it should also be able to be /// positive or negative infinity, but I haven&#39;t verified that Dart&#39;s exp /// function correctly handles those cases. /// double rate(double time) =&gt; initial_rate * exp(-lambda * time);</code></pre> <h2 id="position">Position</h2> <p>Next we want to know about the position over time, both so that we can query it for animations and so that we can solve the equation for our initial velocity. Now that we have <span class="math">$$\eqref{eqn:velocity}$$</span>, which is an equation for <span class="math">$$V(t)$$</span>, we can substitute it into <span class="math">$$\eqref{eqn:position_diffeq}$$</span>, our definition of position. This gives us a differential equation that we can solve.</p> <button data-open = Hide&#32;derivation data-closed = Show&#32;derivation class = "hidden-shortcode-button"> Show derivation </button> </section> <section class="content hidden-shortcode-wrapper start-closed "> <div class="hidden-shortcode-content" style="overflow: auto"> <p><span class="math">$$$\label{eqn:exponential_position_diffeq} \frac{dX(t)}{dt} = V_0 e^{-\lambda t}$$$</span></p> <p>Again, this is a pretty simple differential equation; the only thing that we have to remember is</p> <p><span class="math">$\int e^u du = e^u + C.$</span></p> <p>But to apply this integral we need to make sure that <span class="math">$$du$$</span> really is the derivative of <span class="math">$$u$$</span>. In our case;</p> <p><span class="math">$u = -\lambda t$</span></p> <p>Differentiate this with respect to <span class="math">$$t$$</span> and we get</p> <p><span class="math">$\frac{du}{dt} = -\lambda$</span></p> <p>or</p> <p><span class="math">$du = -\lambda dt.$</span></p> <p>This means that</p> <p><span class="math">$$$\label{eqn:exponential_integral} \int -\lambda e^{-\lambda t} dt = e^{-\lambda t} + C.$$$</span></p> <p>We want to manipulate <span class="math">$$\eqref{eqn:exponential_position_diffeq}$$</span> until we can apply this integral to the right side. First multiply <span class="math">$$\eqref{eqn:exponential_position_diffeq}$$</span> by <span class="math">$$dt$$</span>.</p> <p><span class="math">$dX(t) = V_0 e^{-\lambda t} dt$</span></p> <p>The right hand side is missing a <span class="math">$$-\lambda$$</span> term, we can introduce one by multiplying the right hand side by <span class="math">$$\frac{-\lambda}{-\lambda} = 1$$</span>.</p> <p><span class="math">$dX(t) = \frac{V_0}{-\lambda} -\lambda e^{-\lambda t} dt$</span></p> <p>At this point we can integrate both sides.</p> <p><span class="math">$\int dX(t) = \int \frac{V_0}{-\lambda} -\lambda e^{-\lambda t} dt$</span></p> <p>The left hand side is simply the integral of the derivative of <span class="math">$$X(t)$$</span>. That will be <span class="math">$$X(t) + C_0$$</span>, where <span class="math">$$C_0$$</span> is an arbitrary constant that was lost by the differentiation. On the right hand side we can move the constant <span class="math">$$\frac{V_0}{-\lambda}$$</span> out of the integral.</p> <p><span class="math">$X(t) + C_0 = \frac{V_0}{-\lambda} \int -\lambda e^{-\lambda t} dt$</span></p> <p>The integral now matches <span class="math">$$\eqref{eqn:exponential_integral}$$</span>.</p> <p><span class="math">$X(t) + C_0 = \frac{V_0}{-\lambda} (e^{-\lambda t} + C_1)$</span></p> <p>Expand the product on the right, and move all of the terms that depend on our unknown integration constants to the right.</p> <p><span class="math">$X(t) = \frac{V_0}{-\lambda} e^{-\lambda t} + (\frac{V_0}{-\lambda} C_1 - C_0)$</span></p> <p>We can replace <span class="math">$$\frac{V_0}{-\lambda} C_1 - C_0$$</span> with a new constant <span class="math">$$C$$</span>.</p> <p><span class="math">$X(t) = \frac{V_0}{-\lambda} e^{-\lambda t} + C$</span></p> <p>To find the combined integration constant solve for initial position <span class="math">$$X_0$$</span>.</p> <p><span class="math">\begin{align*} X_0 :&= X(0)\\ &= \frac{V_0}{-\lambda} e^0 + C\\ &= \frac{V_0}{-\lambda} + C \end{align*}</span></p> <p>So our integration constant is</p> <p><span class="math">$C = X_0 - \frac{V_0}{-\lambda}.$</span></p> <p>And the final solution for our position over time is</p> <p><span class="math">$X(t) = \frac{V_0}{-\lambda} e^{-\lambda t} + X_0 - \frac{V_0}{-\lambda}.$</span></p> <p>This can be simplified by factoring out <span class="math">$$\frac{1}{-\lambda}$$</span>.</p> </div> </section> <section class="content"> <p>The result is an explicit equation for <span class="math">$$X(t)$$</span>.</p> <p><span class="math">$$$\label{eqn:position} X(t) = X_0 + \frac{1}{-\lambda} (V_0 e^{-\lambda t} - V_0)$$$</span></p> <p>Below you can experiment with <span class="math">$$\eqref{eqn:velocity}$$</span> and <span class="math">$$\eqref{eqn:position}$$</span>, try changing <span class="math">$$X_0$$</span>, <span class="math">$$V_0$$</span>, <span class="math">$$\lambda$$</span>, and the total time of the simulation. <span class="math">$$V_0$$</span> is controlled by manipulating the tangent line to the graph at the origin.</p> <iframe src = "https://www.desmos.com/calculator/f1c9s0eity?embed" id = "" class = "desmos-iframe"> </iframe> <p>I noticed that the first term (<span class="math">$$V_0 e^{-\lambda t}$$</span>) is just <span class="math">$$\eqref{eqn:velocity}$$</span>, so I used that in its place.</p> <p><span class="math">$$$\label{eqn:position_from_rate} X(t) = X_0 + \frac{1}{-\lambda}(V(t) - V_0)$$$</span></p> <p>There is something very pleasing about this equation; the change in position is proportional to the change in velocity. But this form of the equation has some issues. One thing to note about this solution is that it doesn't work if <span class="math">$$\lambda$$</span> is equal to zero. Fortunately <span class="math">$$\eqref{eqn:exponential_decay}$$</span> then becomes trivial (<span class="math">$$\frac{dV(t)}{dt} = 0$$</span>), and the solutions are <span class="math">$$V(t) = V_0$$</span> and <span class="math">$$X(t) = X_0 + V_0 t$$</span>. However, when I thought about this more, I realized that this substitution of <span class="math">$$\eqref{eqn:velocity}$$</span> had hidden a numerical issue in the implementation as well. If we start back with <span class="math">$$\eqref{eqn:position}$$</span> and rearrange a little by factoring out <span class="math">$$V_0$$</span> and moving <span class="math">$$\frac{1}{-\lambda}$$</span> in we can see more clearly what the problem is.</p> <p><span class="math">$X(t) = X_0 + V_0 \frac{e^{-\lambda t} - 1}{-\lambda}$</span></p> <p>The right term numerator is <span class="math">$$e^{-\lambda t} - 1$$</span>, which, for values of <span class="math">$$-\lambda t$$</span> close to zero, can lead to <a href="https://en.wikipedia.org/wiki/Loss_of_significance">Loss of Significance</a> because we are subtracting two numbers that are nearly identical (<span class="math">$$e^0 = 1$$</span>). It wasn't clear at first to me how to handle this; in C/C++ I would have used <a href="http://man7.org/linux/man-pages/man3/expm1.3.html">expm1</a> and then used the trivial solutions for <span class="math">$$\eqref{eqn:exponential_decay}$$</span> and <span class="math">$$\eqref{eqn:position_diffeq}$$</span> when <span class="math">$$\lambda$$</span> was zero, but there would still be a possible problem with the division when <span class="math">$$\lambda$$</span> is very close to zero because both numerator and denominator would be approaching zero. In hopes that I could come up with an alternate representation that would work for all values of <span class="math">$$\lambda$$</span> and <span class="math">$$t$$</span>, I started to work with the infinite sum representation of the exponential function.</p> <p><span class="math">$\def\exp_sum#1#2{\sum_{k=#1}^{\infty} \frac{#2^k}{k!}}$</span></p> <p><span class="math">$e^x = \exp_sum{0}{x}$</span></p> <p>I used this sum in place of the exponential in <span class="math">$$\eqref{eqn:position}$$</span>.</p> <p><span class="math">$X(t) = X_0 + \frac{V_0}{-\lambda} (\exp_sum{0}{(-\lambda t)} - 1)$</span></p> <p>The first term in the sum is just one.</p> <p><span class="math">$e^{-\lambda t} = 1 + \exp_sum{1}{(-\lambda t)}$</span></p> <p>That one cancels out the subtraction by one, leaving all of the remaining terms from <span class="math">$$\numrange{1}{\infty}$$</span>. All of those terms have at least one <span class="math">$$-\lambda$$</span> in them, so I was able to divide the sum by <span class="math">$$-\lambda$$</span>, canceling out one of the <span class="math">$$-\lambda$$</span> factors in each term. The result had no divisions by <span class="math">$$-\lambda$$</span>. Nice.</p> <p><span class="math">$X(t) = X_0 + V_0 (\sum_{k=1}^{\infty} \frac{-\lambda^{k-1} t^k}{k!})$</span></p> <p>Then I saw that I could pull a <span class="math">$$t$$</span> out of the sum as well. And I could shift the sum index (<span class="math">$$k$$</span>) by one, so that the sum started at zero again.</p> <p><span class="math">$X(t) = X_0 + V_0 t (\sum_{k=0}^{\infty} \frac{(-\lambda t)^k}{(k + 1)!})$</span></p> <p>The sum now looked so much like an exponential by itself that I was distracted into thinking that I could do something to recover a simple exponential form, with some additional damping factor (accounting for the <span class="math">$$+1$$</span> in the factorial), that didn't have the division by zero problem that the original version had. Eventually I realized that the pulling out of <span class="math">$$t$$</span> was the crucial piece that I had missed at first. I went back to <span class="math">$$\eqref{eqn:position}$$</span> to see what would happen when I took a <span class="math">$$t$$</span> out of the second factor.</p> <p><span class="math">$$$\label{eqn:position_with_hex} X(t) = X_0 + V_0 t \frac{e^{-\lambda t} - 1}{-\lambda t}$$$</span></p> <p>I had to put a <span class="math">$$t$$</span> in the denominator, which nicely turns the problematic portion into a one variable problem. No longer did I have to treat <span class="math">$$-\lambda$$</span> and <span class="math">$$t$$</span> as separate variables; I could just lump them together and work on solving <span class="math">$$\frac{e^x-1}{x}$$</span>, which at this point I feel like needs a name. If anyone knows of a name for this particular function<sup class="footnote-ref" id="fnref:2"><a class="footnote" href="#fn:2">2</a></sup> I would be interested, for now I'm calling it a hexponential, or <span class="math">$$hex(x)$$</span>, short for &quot;half exponential&quot; because the derivative at zero is one half instead of one, but otherwise it looks like an exponential.</p> <iframe src = "https://www.desmos.com/calculator/6qdzpcumvk?embed" id = "" class = "desmos-iframe"> </iframe> <p><span class="math">$hex(x) := \frac{e^x - 1}{x} = \sum_{k=0}^{\infty} \frac{x^k}{(k + 1)!}$</span></p> <p>Hex is well behaved at the origin, even with the division by zero, because the division is in some sense just an artifact of writing the function down in a <a href="https://en.wikipedia.org/wiki/Closed-form_expression">Closed Form</a>. We can use the sum representation to compute it around zero nicely. We can also see this by using <a href="https://en.wikipedia.org/wiki/L%27H%C3%B4pital%27s_rule">L'HÃ´pital's rule</a> to compute the limit of the closed form of hex. Here is the resulting version of <span class="math">$$\eqref{eqn:position_with_hex}$$</span> written in Dart.</p> <pre><code class="language-dart">/// /// Return the value at a given time. /// /// Time can be negative, positive, or zero, it should also be able to be /// positive or negative infinity, but I haven&#39;t verified that Dart&#39;s exp /// function correctly handles those cases. /// double value(double time) { // // This version of hex maintains about 14 digits of precision, not full // machine precision (~16 digits for doubles). // double hex(double x) { // // A threshold of 10^-2 seems like a good compromise. The smaller // the threshold is, the fewer terms we need to use to accurately // evaluate hex. But smaller thresholds increase the loss of // significance when using the exponential form below. The // truncation error introduced by a threshold of 10^-2 is O(x^6), // or on the order of 1e-12. In fact, the first term that we lose // from the sum is x^6/6!, or 10^-12/720, or 1.38e-15, so our // truncation error is closer to 1e-15. // if (x.abs() &lt; 1e-2) return 1 &#43; (1 &#43; (1 &#43; (1 &#43; x / 5) * x / 4) * x / 3) * x / 2; // // The worst case loss of significance from the subtraction below // will be when x = 10^-2. // // log2(1-(1/e^(10^-2))) ~ -6.6 // // So we can expect to loose 7 bits of precision, from our doubles // 53 bit mantissa. Or ~2 digits from our ~16 digits of precision. // return (exp(x) - 1) / x; } return initial_value &#43; initial_rate * time * hex(-lambda * time); }</code></pre> <h2 id="lambda">Lambda</h2> <p>We now have our solutions for <span class="math">$$\eqref{eqn:exponential_decay}$$</span> and <span class="math">$$\eqref{eqn:position_diffeq}$$</span>, but we're still stuck specifying <span class="math">$$X_0$$</span>, <span class="math">$$V_0$$</span>, <span class="math">$$\lambda$$</span>, and <span class="math">$$T$$</span> (the total time of the simulation). Instead, we would like to be specifying <span class="math">$$X_0$$</span>, <span class="math">$$X_T$$</span>, <span class="math">$$V_T$$</span>, and <span class="math">$$T$$</span>, where</p> <p><span class="math">\begin{align*} X_T &:= X(T)\\ V_T &:= V(T). \end{align*}</span></p> <p>In other words, we need to come up with equations that give us <span class="math">$$V_0$$</span> and <span class="math">$$\lambda$$</span> in terms of <span class="math">$$X_0$$</span>, <span class="math">$$X_T$$</span>, <span class="math">$$V_T$$</span>, and <span class="math">$$T$$</span>.</p> <p>We can use <span class="math">$$\eqref{eqn:velocity}$$</span>, the solution for our velocity at a given time, to compute <span class="math">$$\lambda$$</span> if we know <span class="math">$$V_0$$</span>, <span class="math">$$V_T$$</span>, and <span class="math">$$T$$</span>. This can then be substituted into <span class="math">$$\eqref{eqn:position}$$</span> which gives us an equation relating <span class="math">$$X_0$$</span>, <span class="math">$$X_T$$</span>, <span class="math">$$V_0$$</span>, <span class="math">$$V_T$$</span>, and <span class="math">$$T$$</span>. We can then solve that equation for <span class="math">$$V_0$$</span>.</p> <button data-open = Hide&#32;derivation data-closed = Show&#32;derivation class = "hidden-shortcode-button"> Show derivation </button> </section> <section class="content hidden-shortcode-wrapper start-closed "> <div class="hidden-shortcode-content" style="overflow: auto"> <p>We want to solve <span class="math">$$\eqref{eqn:velocity}$$</span> for <span class="math">$$\lambda$$</span>, which we can do if we can take the log of the exponential.</p> <p><span class="math">$V(t) = V_0 e^{-\lambda t}$</span></p> <p>Divide both sides by <span class="math">$$V_0$$</span> and then take the log of both sides.</p> <p><span class="math">$log(\frac{V_T}{V_0}) = -\lambda T$</span></p> <p>Divide both sides by <span class="math">$$-T$$</span> to get our final equation for <span class="math">$$\lambda$$</span>.</p> </div> </section> <section class="content"> <p><span class="math">$$$\label{eqn:lambda} \lambda = -\frac{log(\frac{V_T}{V_0})}{T}$$$</span></p> <p>We will need to use this equation once we've solved <span class="math">$$\eqref{eqn:position}$$</span> for <span class="math">$$V_0$$</span> to compute <span class="math">$$\lambda$$</span>. Again, we can write <span class="math">$$\eqref{eqn:lambda}$$</span> in Dart.</p> <pre><code class="language-dart">/// /// Compute the proportionality coefficient lambda given the start and end /// rates as well as total time taken. /// static double _lambda(double final_rate, double initial_rate, double total_time) { // // If final_rate, or initial_rate is zero then the other must also be // zero. This is because the only way to actually get to zero with an // exponential is to already be there. And if you&#39;re there, there is // no way to leave. In this case lambda should be zero, because our // rate is not changing. // assert((final_rate == 0.0) == (initial_rate == 0.0)); if (final_rate == 0.0) return 0.0; // // Lambda is not a complex number, we are only interested in solving // for real values. So final_rate and initial_rate must also have the // same sign. // assert((final_rate &gt; 0.0) == (initial_rate &gt; 0.0)); return -log(final_rate / initial_rate) / total_time; }</code></pre> <p>We can now substitute <span class="math">$$\eqref{eqn:lambda}$$</span> into <span class="math">$$\eqref{eqn:position}$$</span>, giving us an equation for position that is parameterized by <span class="math">$$X_0$$</span>, <span class="math">$$V_0$$</span>, <span class="math">$$V_T$$</span>, and <span class="math">$$T$$</span>.</p> <p><span class="math">$$$\label{eqn:position_no_lambda} X(t) = X_0 + \frac{T}{log(\frac{V_T}{V_0})} (V_0 e^{\frac{log(\frac{V_T}{V_0})}{T} t} - V_0)$$$</span></p> <p>We can play with this function in Desmos as well, but we still don't get to specify the final position of the animation (<span class="math">$$X_T$$</span>).</p> <iframe src = "https://www.desmos.com/calculator/thwcw9lw0q?embed" id = "" class = "desmos-iframe"> </iframe> <p>You'll probably notice that <span class="math">$$V_0$$</span> and <span class="math">$$V_T$$</span> have to have the same sign. If they do not then desmos doesn't show a graph at all. This is because <span class="math">$$\eqref{eqn:lambda}$$</span> takes the logarithm of their ratio, and as long as <span class="math">$$V_0$$</span> and <span class="math">$$V_T$$</span> have the same sign their ratio is positive. The logarithm for real numbers is not defined for negative numbers. So Desmos (and the Dart implementation above) give up. But if we were to use the complex exponential and logarithm then there is actually a solution when <span class="math">$$V_0$$</span> and <span class="math">$$V_T$$</span> have different signs. The solution ends up being a combination of sine, cosine and exponential functions. The sine and cosine allow for the change in sign of the rate. I touched on this briefly at the end of my <a href="http://socialhacker.com/posts/2d_rotation/#exponential-map">2D Rotation</a> post. It is never the case in the game I'm writing that I want the initial and final velocities to have different signs, so I opted to keep the solution real. I could imagine an explosion animation that contracts at the end, but that wasn't what I was going for visually.</p> <h2 id="initial-velocity">Initial Velocity</h2> <p>We now have <span class="math">$$\eqref{eqn:position}$$</span> that tells us <span class="math">$$X_T$$</span> given <span class="math">$$X_0$$</span>, <span class="math">$$V_0$$</span>, <span class="math">$$\lambda$$</span>, and <span class="math">$$T$$</span>. And we just found <span class="math">$$\eqref{eqn:lambda}$$</span>, an equation for <span class="math">$$\lambda$$</span>. Then we substituted <span class="math">$$\eqref{eqn:lambda}$$</span> into <span class="math">$$\eqref{eqn:position}$$</span> to get <span class="math">$$\eqref{eqn:position_no_lambda}$$</span>. Now we'll solve the result for <span class="math">$$V_0$$</span>. This is where the math got interesting; I had never encountered the <a href="https://en.wikipedia.org/wiki/Lambert_W_function">Lambert W function</a> before. And it turns out that solving for <span class="math">$$V_0$$</span> will need it. To apply it we need to get one side of this equation to look like <span class="math">$$f(V_0) e^{f(V_0)}$$</span>, and the other side to not have <span class="math">$$V_0$$</span> in it. Because it will make the remaining math easier to follow I'm going define <span class="math">$$\Delta X$$</span> here.</p> <p><span class="math">$\Delta X := X_T - X_0$</span></p> <button data-open = Hide&#32;derivation data-closed = Show&#32;derivation class = "hidden-shortcode-button"> Show derivation </button> </section> <section class="content hidden-shortcode-wrapper start-closed "> <div class="hidden-shortcode-content" style="overflow: auto"> <p>If we evaluate <span class="math">$$\eqref{eqn:position_no_lambda}$$</span> at <span class="math">$$T$$</span>, our final time, we will have an equation that relates <span class="math">$$X_0$$</span>, <span class="math">$$X_T$$</span>, <span class="math">$$V_0$$</span>, <span class="math">$$V_T$$</span>, and <span class="math">$$T$$</span>. With the addition of <span class="math">$$\Delta X$$</span> the result looks like</p> <p><span class="math">$\Delta X = \frac{T}{log(\frac{V_T}{V_0})} (V_0 e^{\frac{log(\frac{V_T}{V_0})}{T} T} - V_0).$</span></p> <p>We can immediately cancel the two <span class="math">$$T$$</span> factors in the exponent and then simplify the exponent of the log of <span class="math">$$V_T$$</span> divided by <span class="math">$$V_0$$</span>, and finally cancel the <span class="math">$$V_0$$</span> factors. The result is that the first term in the parentheses just becomes <span class="math">$$V_T$$</span>. This makes sense given the substitution I considered in <span class="math">$$\eqref{eqn:position_from_rate}$$</span>.</p> <p><span class="math">$\Delta X = \frac{T}{log(\frac{V_T}{V_0})}(V_T - V_0)$</span></p> <p>Multiply both sides by <span class="math">$$log(V_T) - log(V_0) = log(\frac{V_T}{V_0})$$</span>.</p> <p><span class="math">$\Delta X log(V_T) - \Delta X log(V_0) = V_T T - V_0 T$</span></p> <p>Divide by <span class="math">$$\Delta X$$</span> and move all the terms with <span class="math">$$V_0$$</span> to one side, and all the remaining terms (those with <span class="math">$$V_T$$</span>) to the other side.</p> <p><span class="math">$log(V_T) - T\frac{V_T}{\Delta X} = log(V_0) - T\frac{V_0}{\Delta X}$</span></p> <p>We're getting close; exponentiate each side.</p> <p><span class="math">$V_T e^{-T\frac{V_T}{\Delta X}} = V_0 e^{-T\frac{V_0}{\Delta X}}$</span></p> <p>Now all we need to do is make the right hand side look like <span class="math">$$f(V_0) e^{f(V_0)}$$</span>. We can do that by multiplying both sides by <span class="math">$$-\frac{T}{\Delta X}$$</span>.</p> </div> </section> <section class="content"> <p>We now have an equation that relates all of our coefficients (<span class="math">$$X_0, X_T, V_0, V_T$$</span>, and <span class="math">$$T$$</span>); We just have to solve it for <span class="math">$$V_0$$</span>.</p> <p><span class="math">$$$\label{eqn:initial_velocity_symetric} -T \frac{V_T}{\Delta X} e^{-T \frac{V_T}{\Delta X}} = -T \frac{V_0}{\Delta X} e^{-T \frac{V_0}{\Delta X}}$$$</span></p> <p>Now that the right hand side is in the correct form <span class="math">$$f(V_0) = -T \frac{V_0}{\Delta X}$$</span>, we can apply W to both sides. You might notice that the left hand side is also in the same form, it is <span class="math">$$f(V_T) = -T \frac{V_T}{\Delta X}$$</span>. More about that later.</p> <p><span class="math">$W(-T \frac{V_T}{\Delta X} e^{-T \frac{V_T}{\Delta X}}) = -T \frac{V_0}{\Delta X}$</span></p> <p>And finally, multiply both sides by <span class="math">$$-\frac{\Delta X}{T}$$</span> to solve for <span class="math">$$V_0$$</span>.</p> <p><span class="math">$V_0 = -W(-T \frac{V_T}{\Delta X} e^{-T \frac{V_T}{\Delta X}}) \frac{\Delta X}{T}$</span></p> <p>This is a lot to look at, but it has some repetition that we can factor out, making it easier to understand; substitute <span class="math">$$A = -T \frac{V_T}{\Delta X}$$</span>.</p> <p><span class="math">$$$\label{eqn:initial_velocity} V_0 = V_T \frac{W(A e^A)}{A}$$$</span></p> <p>I wanted to add a Desmos graph here where you could play with the new set of parameters, but Desmos doesn't currently support the Lambert W function, which makes it pretty hard to evaluate the above equation. It could be approximated with a lot of work, but this post has taken long enough to write already.</p> <p>But we can get an idea for the sort of solutions that the Lambert W function would return. Below is a graph of <span class="math">$$f(x) = xe^x$$</span> that shows that for any value of <span class="math">$$x_1 < 0$$</span> other than <span class="math">$$x_1 = -1$$</span> there is another value <span class="math">$$x_2 \neq x_1$$</span> such that <span class="math">$$f(x_1) = f(x_2)$$</span>. In other words, if <span class="math">$$x$$</span> is less than zero, and not equal to negative one, then the inverse of <span class="math">$$f(x)$$</span> has two values. That other value can be computed using one of the two branches of the Lambert W function.</p> <iframe src = "https://www.desmos.com/calculator/obnlc5a5un?embed" id = "" class = "desmos-iframe"> </iframe> <p>I'd like to return briefly to the interesting symmetry of <span class="math">$$\eqref{eqn:initial_velocity_symetric}$$</span>, it was of the form:</p> <p><span class="math">$X e^X = Y e^Y$</span></p> <p>where</p> <p><span class="math">\begin{align*} X &:= f(V_T) = -T \frac{V_T}{\Delta X}\\ Y &:= f(V_0) = -T \frac{V_0}{\Delta X}. \end{align*}</span></p> <p>Our problem was that we were given <span class="math">$$Y$$</span> and we needed to compute <span class="math">$$X$$</span>, more or less. It's probably obvious that there's a trivial solution to this problem; <span class="math">$$X = Y$$</span>. That makes both sides identical, and so obviously it's a solution to <span class="math">$$\eqref{eqn:initial_velocity_symetric}$$</span>, but we arrived at <span class="math">$$\eqref{eqn:initial_velocity_symetric}$$</span> by manipulating <span class="math">$$\eqref{eqn:position}$$</span>. And <span class="math">$$\eqref{eqn:position}$$</span> is not valid when <span class="math">$$V_T = V_0$$</span> (because then <span class="math">$$\lambda$$</span> is zero), and since <span class="math">$$X$$</span> and <span class="math">$$Y$$</span> are just <span class="math">$$f(V_T)$$</span> and <span class="math">$$f(V_0)$$</span>, <span class="math">$$X = Y$$</span> can't be a solution we're actually looking for. Fortunately, there is a second solution for all values of <span class="math">$$A$$</span> other than <span class="math">$$-1$$</span>. When <span class="math">$$A = -1$$</span> the initial rate is just the final rate.</p> <pre><code class="language-dart">/// /// Return the initial rate that will result in the given change in value /// and rate, over the specified total time. /// /// delta_value in [ 0 .. infinity) /// final_rate in (-infinity .. infinity) /// total_time in [ 0 .. infinity) /// static double _initial_rate(double delta_value, double final_rate, double total_time) { /// /// If delta_value is zero, then final_rate must also be zero. It is /// not possible to have zero change in value with a non-zero /// final_rate because the exponential is monotonic. /// assert(delta_value != 0.0 || final_rate == 0.0); /// /// Since we&#39;re not expected to change the value at all, and final_rate /// is zero, _initial_rate should also be zero. /// if (delta_value == 0.0) return 0.0; /// /// If total_time is zero, then delta_value must also be zero. If /// delta_value were not zero we would have to somehow give two /// different values for the same instant in time. /// assert(total_time != 0.0 || delta_value == 0.0); /// /// If total_time is zero then _initial_rate will match final_rate. /// if (total_time == 0.0) return final_rate; final double A = -total_time * final_rate / delta_value; if (A &gt; -1.0) return W_negative_one(A * exp(A)) * final_rate / A; if (A &lt; -1.0) return W_zero(A * exp(A)) * final_rate / A; return final_rate; }</code></pre> <p>To evaluate the Lambert W function I wrote a version of the approximations found in <a href="https://arxiv.org/abs/1003.1628">Having Fun with Lambert W(x) Function</a>. A post about that implementation might be a good idea. For now, the source can be found <a href="http://socialhacker.com/source/breaker/web/lambert_w_function_source/">here</a>.</p> <h2 id="dimensional-analysis">Dimensional Analysis</h2> <p>It's a good idea to double check our work and make sure that the resulting equations make sense from a units perspective. Let's add units. First we'll figure out the units of <span class="math">$$\lambda$$</span>. We start with <span class="math">$$\eqref{eqn:lambda}$$</span> and add units to the right side.</p> <p><span class="math">$\lambda = -\frac{log(\frac{V(t) \si{m s^{-1}}}{V_0 \si{m s^{-1}}})}{t \si{s}}$</span></p> <p>The units of velocity (<span class="math">$$\si{m s^{-1}}$$</span>) cancel, leaving the numerator unitless. The denominator still has units of seconds, so lambda has units of inverse seconds, also known as Hertz, a unit of frequency.</p> <p>The units for <span class="math">$$\eqref{eqn:velocity}$$</span> are also simple.</p> <p><span class="math">$V(t) = V_0 \si{m s^{-1}} e^{-\lambda \si{s^{-1}} t \si{s}}$</span></p> <p>The units of <span class="math">$$\lambda$$</span> and <span class="math">$$t$$</span> in the exponential cancel, leaving that unitless. The only remaining units are from <span class="math">$$V_0$$</span>, so <span class="math">$$V(t)$$</span> has the same units, those of velocity.</p> <p>Next we can check the units for <span class="math">$$\eqref{eqn:position_from_rate}$$</span>.</p> <p><span class="math">$X(t) \si{m} - X_0 \si{m} = \frac{1}{-\lambda \si{s^{-1}}} (V(t) \si{m s^{-1}} - V_0\si{m s^{-1}})$</span></p> <p>We can cancel <span class="math">$$\si{s^{-1}}$$</span> from numerator and denominator, leaving meters on both sides, giving the correct units for position.</p> <p>Finally let's check <span class="math">$$\eqref{eqn:initial_velocity}$$</span> - to do that we just have to show that <span class="math">$$A(t)$$</span> is unitless.</p> <p><span class="math">$A(t) = -t \si{s} \frac{V(t) \si{m s^{-1}}}{X(t) \si{m}}$</span></p> <p>Pretty easy to see that seconds and meters cancel out completely.</p> <div class="footnotes"> <hr> <ol> <li id="fn:1"><p>Why Dart? you're probably asking right now. Well, I wanted to write a web game, and I got about one git commit into doing it in Javascript when I remembered that Javascript doesn't have operator overloading. For me, operator overloading is a language requirement; without it you just can't write much math beyond scalar algebra. I also like that Dart has some static typing abilities. I know that operator overloading, as well as static vs. dynamic typing, are contentious topics for a lot of people, but I'm not going to say much more about them in this post, perhaps later. I will say that I'm very much looking forward to using something compiled to WebAssembly instead.</p> <a class="footnote-return" href="#fnref:1"><sup>[return]</sup></a></li> <li id="fn:2"><p>My brother in law, <a href="http://home.sandiego.edu/~shulman/">Michael Shulman</a>, pointed out that what I've called the Hexponential can also be viewed as the <a href="https://en.wikipedia.org/wiki/Difference_quotient">Difference Quotient</a> of <span class="math">$$e^x$$</span> at zero. And that the general operation on an infinite series of subtracting the first term and dividing by the argument produces a difference quotient for the function at zero.</p> <a class="footnote-return" href="#fnref:2"><sup>[return]</sup></a></li> </ol> </div> 2D Rotation http://socialhacker.com/posts/2d_rotation/ Thu, 05 Sep 2013 21:55:00 -0800 anton@socialhacker.com (Anton Staaf) http://socialhacker.com/posts/2d_rotation/ <p>I'm hoping with this post to show one way that complex numbers come about and how they are a natural way of representing rotations in 2D. To do this I will introduce a small amount of Clifford algebra and some infinite series expansions. A benefit of understanding rotations in this way will be that it generalizes to arbitrary dimensions, though you probably only care about the two and three dimensional cases.</p> <p>A friend of mine recently asked me about 2D rotations. He had started with a <a href="http://en.wikipedia.org/wiki/Rotation_matrix">2x2 rotation matrix</a>:</p> <p><span class="math">$\left( \begin{array}{cr} cos(\theta) & -sin(\theta)\\ sin(\theta) & cos(\theta)\\ \end{array} \right) \left( \begin{array}{c} x\\ y\\ \end{array} \right) = \left( \begin{array}{c} cos(\theta) x - sin(\theta) y\\ sin(\theta) x + cos(\theta) y\\ \end{array} \right)$</span></p> <p>After playing with it for a while he concluded that the second row of the matrix was redundant and you could just store the first row, or really any row or column. This reminded him of something I had said a while back about using complex numbers to represent rotations. This prompted me to write a first version of this post as an email in response. Then he wrote again saying that it seemed like the two component thing was the result of <span class="math">$$e^{i\theta}$$</span>. So I have added a section on the exponential map and Taylor series.</p> <h2 id="complex-numbers">Complex Numbers</h2> <p>First let's start with a bit of a review of complex numbers. You've probably been introduced to them at some point as a number with two components, a real portion and an imaginary portion, where the imaginary portion is signified by having a lower case <span class="math">$$i$$</span> associated with it.</p> <p><span class="math">$(a + b i)$</span></p> <p>And they were probably being used to fill in a gap when someone tried to take the square root of a negative number. Probably it was right around when you learned the quadratic formula. Some people are introduced to complex numbers when they start playing with fractals; the Mandelbrot set, Julia sets, and others are defined in the complex plane. The complex plane is what you get if you treat the real and imaginary parts of a complex number as the <span class="math">$$x$$</span> and <span class="math">$$y$$</span> components of a 2D vector. A lot of neat results come from that mapping. Later I'll show a different way to associate the components of a complex number with the <span class="math">$$x$$</span> and <span class="math">$$y$$</span> components of a 2D vector, but first, let's remember what happens when you multiply two complex numbers together.</p> <p><span class="math">$(a_1 + b_1 i) (a_2 + b_2 i)$</span></p> <p>You probably remember FOIL (First Outer Inner Last) which tells you how to go about doing this multiplication. First multiple the a's together, then the outer elements <span class="math">$$(a_1 \text{and} b_2 i)$$</span>, then the inner elements <span class="math">$$(b_1 i \text{and} a_2)$$</span>, and finally the last elements, the b's.</p> <p><span class="math">$(a_1 a_2) + (a_1 b_2 i) + (b_1 i a_2) + (b_1 i b_2 i)$</span></p> <p>With complex numbers we're free to move the i's around inside each product, so we'll move them to the end of each one, and outside of the parentheses.</p> <p><span class="math">$(a_1 a_2) + (a_1 b_2) i + (b_1 a_2) i + (b_1 b_2) i i$</span></p> <p>The <span class="math">$$i i$$</span> that we get from the multiplication of the two imaginary components <span class="math">$$(b_1 \text{and} b_2)$$</span> of the two complex numbers could also be written <span class="math">$$i^2$$</span>. The whole reason for inventing <span class="math">$$i$$</span> was to provide an answer to the question of what <span class="math">$$x$$</span> is in the following.</p> <p><span class="math">$x = \sqrt{-1}$</span></p> <p>So, <span class="math">$$i^2 = -1$$</span>, and thus the result of multiplying two imaginary components of a complex number together is a real number, just one that has the opposite sign than it would otherwise. So, taking this into account and merging the two terms in the middle that each have a single <span class="math">$$i$$</span> in them we can simplify the result of multiplying two complex numbers down to the following.</p> <p><span class="math">$(a_1 a_2) + (a_1 b_2 + b_1 a_2) i - (b_1 b_2)$</span></p> <p>Finally, moving the imaginary portion to the end we get:</p> <p><span class="math">$(a_1 a_2 - b_1 b_2) + (a_1 b_2 + b_1 a_2) i$</span></p> <p>Which is another complex number <span class="math">$$(a_3 + b_3 i)$$</span> where <span class="math">$$a_3$$</span> and <span class="math">$$b_3$$</span> are defined as:</p> <p><span class="math">\begin{align*} a_3 &= a_1 a_2 - b_1 b_2 \\ b_3 &= a_1 b_2 + b_1 b_2 \end{align*}</span></p> <p>With that basic review of complex numbers, let's move on to talk about the Clifford algebra.</p> <h2 id="clifford-algebra">Clifford Algebra</h2> <p>Above we had said that you could make a 2D plane by associating the real and imaginary components of a complex number with the <span class="math">$$x$$</span> and <span class="math">$$y$$</span> elements of a 2D vector. But we didn't really talk about what that meant or how you could distinguish an <span class="math">$$x$$</span> component from a <span class="math">$$y$$</span> component. There has been an enormous amount written about this subject, and I highly recommend Geometrical Vectors by Gabriel Weinreich. But for now, I'm going to introduce two new things, sort of like <span class="math">$$i$$</span> from the complex numbers, called <span class="math">$$\mathbf{e_1}$$</span> and <span class="math">$$\mathbf{e_2}$$</span>. And we will use them to distinguish between the two components of a 2D vector. So, our vectors will look like this. <span class="math">$$(x \mathbf{e_1} + y \mathbf{e_2})$$</span> These things, we'll call them bases, have a few properties: a base times itself equals one, and swapping the position of two bases in a term negates the term.</p> <p><span class="math">$\mathbf{e_i e_i} = 1\\ \mathbf{e_i e_j} = - \mathbf{e_j e_i}$</span></p> <p>These vectors behave just like you would expect a vector to behave. You can add and subtract them.</p> <p><span class="math">$(x_1 \mathbf{e_1} + y_1 \mathbf{e_2}) + (x_2 \mathbf{e_1} + y_2 \mathbf{e_2}) = ((x_1 + x_2) \mathbf{e_1} + (y_1 + y_2) \mathbf{e_2})$</span></p> <p>And you can multiply them by scalars.</p> <p><span class="math">$c (x_1 \mathbf{e_1} + y_1 \mathbf{e_2}) = (c x_1 \mathbf{e_1} + c y_1 \mathbf{e_2})$</span></p> <p>But they also have another interesting trick, if we multiply two of these vectors together we get an interesting new object.</p> <p><span class="math">$(x_1 \mathbf{e_1} + y_1 \mathbf{e_2}) (x_2 \mathbf{e_1} + y_2 \mathbf{e_2})$</span></p> <p>using FOIL you get</p> <p><span class="math">$(x_1 x_2) \mathbf{e_1 e_1} + (x_1 y_2) \mathbf{e_1 e_2} + (y_1 x_2) \mathbf{e_2 e_1} + (y_1 y_2) \mathbf{e_2 e_2}$</span></p> <p>Since <span class="math">$$\mathbf{e_1 e_1} = 1$$</span> and <span class="math">$$\mathbf{e_2 e_2} = 1$$</span> the first and last terms turn into scalars and you get</p> <p><span class="math">$(x_1 x_2) + (x_1 y_2) \mathbf{e_1 e_2} + (y_1 x_2) \mathbf{e_2 e_1} + (y_1 y_2)$</span></p> <p>Now, the middle two terms can be combined by swapping the <span class="math">$$\mathbf{e_2 e_1}$$</span> in the second term to be <span class="math">$$\mathbf{e_1 e_2}$$</span> and negating the whole term. So the result is</p> <p><span class="math">$(x_1 x_2) + (x_1 y_2 - y_1 x_2) \mathbf{e_1 e_2} + (y_1 y_2)$</span></p> <p>Finally, grouping the first and last term together you get</p> <p><span class="math">$(x_1 x_2 + y_1 y_2) + (x_1 y_2 - y_1 x_2) \mathbf{e_1 e_2}$</span></p> <p>We see that the first term is just the dot product of the two vectors, and the second term is just the 2D cross product <sup class="footnote-ref" id="fnref:1"><a class="footnote" href="#fn:1">1</a></sup> times something weird, this <span class="math">$$\mathbf{e_1 e_2}$$</span> term. So we've got some new odd object here: a scalar plus a scalar times a strange pair of bases. If we replace the dot and cross product values with the letters <span class="math">$$a$$</span> and <span class="math">$$b$$</span> we have <span class="math">$$a + b \mathbf{e_1 e_2}$$</span>.</p> <p>As you may know, the dot product of two vectors is equal to the cosine of the angle between them times the length of each vector. Similarly, the length of the cross product of two vectors is equal to the sine of the angle between them times the length of each vector. These sines and cosines allow us to get back to rotation.</p> <h2 id="2d-rotation-revisited">2D Rotation Revisited</h2> <p>Now what happens if we multiply one of our original vectors times one of these?</p> <p><span class="math">$(x \mathbf{e_1} + y \mathbf{e_2}) (a + b \mathbf{e_1 e_2})$</span></p> <p>We get:</p> <p><span class="math">$(a x) \mathbf{e_1} + (b x) \mathbf{e_1 e_1 e_2} + (a y) \mathbf{e_2} + (b y) \mathbf{e_2 e_1 e_2}$</span></p> <p>Which after simplification is:</p> <p><span class="math">$(a x - b y) \mathbf{e_1} + (b x + a y) \mathbf{e_2}$</span></p> <p>Which looks a lot like a rotation matrix application. <sup class="footnote-ref" id="fnref:2"><a class="footnote" href="#fn:2">2</a></sup> Especially when you remember that if the two vectors we started with are unit length then a and b are equal to the cos and sin of the angles between the two vectors. In which case we have:</p> <p><span class="math">$a = cos(\theta)\\ b = sin(\theta)$</span></p> <p>and after substitution:</p> <p><span class="math">\begin{align*} &(cos(\theta) x - sin(\theta) y) \mathbf{e_1} +\\ &(sin(\theta) x + cos(\theta) y) \mathbf{e_2} \end{align*}</span></p> <h2 id="complex-numbers-revisited">Complex Numbers Revisited</h2> <p>You can probably see where this is going. Let's try multiplying two of these 'scalar plus scalar times base pairs' together.</p> <p><span class="math">$(a_1 + b_1 \mathbf{e_1 e_2}) (a_2 + b_2 \mathbf{e_1 e_2})$</span></p> <p>Again, using FOIL we get:</p> <p><span class="math">$(a_1 a_2) + (a_1 b_2) \mathbf{e_1 e_2} + b_1 \mathbf{e_1 e_2} a_2 + b_1 \mathbf{e_1 e_2} b_2 \mathbf{e_1 e_2}$</span></p> <p>It is fine to move the scalars around, so let's clean this up:</p> <p><span class="math">$(a_1 a_2) + (a_1 b_2) \mathbf{e_1 e_2} + (a_2 b_1) \mathbf{e_1 e_2} + (b_1 b_2) \mathbf{e_1 e_2 e_1 e_2}$</span></p> <p>We can combine the two <span class="math">$$\mathbf{e_1 e_2}$$</span> terms:</p> <p><span class="math">$(a_1 a_2) + (a_1 b_2 + a_2 b_1) \mathbf{e_1 e_2} + (b_1 b_2) \mathbf{e_1 e_2 e_1 e_2}$</span></p> <p>Next we deal with the <span class="math">$$\mathbf{e_1 e_2 e_1 e_2}$$</span> term. If we swap the middle <span class="math">$$\mathbf{e_2 e_1}$$</span> into <span class="math">$$\mathbf{e_1 e_2}$$</span> and negate the whole thing we get <span class="math">$$-\mathbf{e_1 e_1 e_2 e_2}$$</span>. And since a base times itself is <span class="math">$$1$$</span> we have <span class="math">$$-1 * 1$$</span> or <span class="math">$$-1$$</span>. So, the last term can be replaced with <span class="math">$$-(b_1 b_2)$$</span>, causing the entire thing to turn into:</p> <p><span class="math">\begin{align*} &(a_1 a_2 - b_1 b_2) +\\ &(a_1 b_2 + a_2 b_1) \mathbf{e_1 e_2} \end{align*}</span></p> <p>And poof, we have another one of these scalar plus scalar times <span class="math">$$\mathbf{e_1 e_2}$$</span> things. The fact that <span class="math">$$\mathbf{e_1 e_2 e_1 e_2} = -1$$</span> should have given it away: <span class="math">$$\mathbf{e_1 e_2}$$</span> could also be called <span class="math">$$i$$</span> and these are complex numbers (or at least they behave like them, which in some sense means that they are them).</p> <p>If complex numbers really do represent rotations in 2D then we would expect that there would be a way to combine two rotations that are represented by complex numbers, resulting in a single complex number that represents the combined rotation. And you are probably not surprised to learn that there is, and it is just complex multiplication (which we worked out above). To show this let's assume that <span class="math">$$(a_1 + b_1 \mathbf{e_1 e_2})$$</span> represents a rotation by <span class="math">$$\theta$$</span> radians and <span class="math">$$(a_2 + b_2 \mathbf{e_1 e_2})$$</span> represents a rotation by <span class="math">$$\phi$$</span> radians. So:</p> <p><span class="math">$a_1 = cos(\theta)\\ b_1 = sin(\theta)\\ a_2 = cos(\phi)\\ b_2 = sin(\phi)$</span></p> <p>If we rewrite the result of multiplying two complex numbers together and substitute these cosines and sines in we get:</p> <p><span class="math">\begin{align*} &(cos(\theta) cos(\phi) - sin(\theta) sin(\phi)) +\\ &(cos(\theta) sin(\phi) + cos(\phi) sin(\theta)) \mathbf{e_1 e_2} \end{align*}</span></p> <p>Now we have to remember (or re-derive, but this post is getting too long as it is) the sin and cos of the sum of angles formulas. They are, probably not surprisingly:</p> <p><span class="math">\begin{align*} cos(\theta + \phi) &= cos(\theta) cos(\phi) - sin(\theta) sin(\phi)\\ sin(\theta + \phi) &= cos(\theta) sin(\phi) + cos(\phi) sin(\theta)\\ \end{align*}</span></p> <p>And thus, we can rewrite the product of two complex numbers that represent rotations as:</p> <p><span class="math">$cos(\theta + \phi) + sin(\theta + \phi) \mathbf{e_1 e_2}$</span></p> <p>And indeed, the product of two complex numbers that represent rotations, is itself a rotation, one that is the sum of the two independent rotations.</p> <h2 id="exponential-map">Exponential Map</h2> <p>The exponential map is a special function that is its own derivative. It is fascinating, and I recommend reading more about it. Here I'm just going to quickly show one fantastic result. I'll need to use the words Taylor Series and infinity, but I'm not going to justify them much. It can be thought of as an infinite sum of terms, or as the exponentiation <span class="math">$$e^x$$</span>.</p> <p><span class="math">$exp(x) = e^x = \sum_{k=0}^{\infty} \frac{x^k}{k!}$</span></p> <p>This function is valid for all complex numbers, but we will limit the input to just the imaginary numbers (the imaginary portion of a complex number). To make the notation a little simpler I'll use <span class="math">$$i$$</span> instead of <span class="math">$$\mathbf{e_1 e_2}$$</span>. I'll show that by doing this we effectively map an infinite line to the circle of radius one centered at the origin of the complex plane. Points on the line can be thought of as representing angles in radians. And every time we move <span class="math">$$2 \pi$$</span> along the line we make one full loop around the circle. So, there are many points on the line that map to the same point on the circle. These all represent the same rotation.</p> <p><span class="math">$exp(x i) = e^{x i} = \sum_{k=0}^{\infty} \frac{(x i)^k}{k!}$</span></p> <p>First, let's look at the <span class="math">$$(x i)^k$$</span> term. The first few terms in the infinite sum and the generalization for an arbitrary value of <span class="math">$$k$$</span> are:</p> <p><span class="math">\begin{align*} (x i)^0 &= x^0 = 1\\ (x i)^1 &= x^1 i = x i\\ (x i)^2 &= x^2 i i = -1 x^2\\ (x i)^3 &= x^3 i i i = -1 x^3 i\\ &\vdots\\ (x i)^k &= x^k i^k = \begin{cases} -1^{\frac{k}{2}} x^k & k\;\text{is even} \\[1ex] -1^{\frac{k-1}{2}} x^k i & k\;\text{is odd} \end{cases}\\ \end{align*}</span></p> <p>If we group all of the even and all of the odd terms together we get:</p> <p><span class="math">$e^{x i} = \sum_{k=0,2,4...}^{\infty} \frac{-1^{\frac{k}{2}} x^k}{k!} + \sum_{k=1,3,5...}^{\infty} \frac{-1^{\frac{k-1}{2}} x^k}{k!}i$</span></p> <p>We can turn the sums back into simple sums from zero to infinity by transforming <span class="math">$$k$$</span> in each of them. In the first one we can replace <span class="math">$$k$$</span> with <span class="math">$$2k$$</span>, and in the second we can replace <span class="math">$$k$$</span> with <span class="math">$$2k+1$$</span>. The result is:</p> <p><span class="math">$e^{x i} = \sum_{k=0}^{\infty} \frac{-1^k x^{2k}}{(2k)!} + \sum_{k=0}^{\infty} \frac{-1^k x^{2k+1}}{(2k+1)!}i$</span></p> <p>It turns out that the first sum is actually the Taylor series expansion for <span class="math">$$cos(x)$$</span> and the second sum is the Taylor series expansion for <span class="math">$$sin(x)$$</span>. So this can be rewritten as:</p> <p><span class="math">$e^{x i} = cos(x) + sin(x) i$</span></p> <p>This beautiful result is known as <a href="http://en.wikipedia.org/wiki/Euler's_formula">Euler's formula</a>.</p> <h2 id="further-reading">Further Reading</h2> <ul> <li><a href="https://en.wikipedia.org/wiki/Universal_geometric_algebra">Universal Geometric Algebra</a></li> </ul> <div class="footnotes"> <hr> <ol> <li id="fn:1"><p>In 2D the cross product as we normally think of it doesn't exist, but the value above can be thought of as the Z component of a 3D cross product of two vectors that lie in the XY plane. Since the two vectors have zero Z components, the X and Y components of their cross product is zero, so the overall cross product length is just the length of the Z portion.</p> <a class="footnote-return" href="#fnref:1"><sup>[return]</sup></a></li> <li id="fn:2"><p>There is a bit more subtlety to this, the actual group action we care about is ATA* <sup class="footnote-ref" id="fnref:3"><a class="footnote" href="#fn:3">3</a></sup> where A is a complex number, T is a vector and A* is the conjugate of the complex number. That action works even if the complex number isn't unit, and it generalizes up to higher dimensions (TA, what we did here, doesn't).</p> <a class="footnote-return" href="#fnref:2"><sup>[return]</sup></a></li> <li id="fn:3"><p>The construction of a complex number as a multiplication of two vectors using the odd base combination rules gives a cool way to ask for a rotation between two vectors. If you use the full ATA* group operation the rotation is twice the angle between the two vectors though. This turns out to be important in higher dimensions.</p> <a class="footnote-return" href="#fnref:3"><sup>[return]</sup></a></li> </ol> </div> Mandelbrot http://socialhacker.com/posts/fractals/mandelbrot/ Wed, 16 May 2012 00:00:00 +0000 anton@socialhacker.com (Anton Staaf) http://socialhacker.com/posts/fractals/mandelbrot/ <p><a href="http://socialhacker.com/applications/mandelbrot/mandelbrot.html">Mandelbrot</a> is a javascript implementation of a simple mandelbrot set calculator.</p> <p></p> <pre><code class="language-javascript">// // Set the pixel at location &lt;x,y&gt; in the image data to &lt;r,g,b,a&gt;. The r, g, // and b elements are the red, green, and blue color components. The a element // is the alpha, or transparency value. The r, g, b, and a values can range // from 0 to 255. // function set_pixel(image_data, x, y, r, g, b, a) { // Compute the index into the pixel data. Each pixel is represented by four // sequential values in the image_data.data array. index = (x &#43; y * image_data.width) * 4; image_data.data[index &#43; 0] = r; image_data.data[index &#43; 1] = g; image_data.data[index &#43; 2] = b; image_data.data[index &#43; 3] = a; } // // Compute the number of iterations required for a single orbit of the // mandelbrot equation to escape from a circle of radius 2 centered at the // origin of the complex plane. // function compute_escape_time(c_r, c_i, maximum_iterations) { z_r = 0.0; z_i = 0.0; for (i = 0; i &lt; maximum_iterations; i&#43;&#43;) { // // Compute a single iteration of Z^2 &#43; C. Complex numbers are of the // form &#34;real &#43; imaginary * i&#34;, so to square them you end up computing: // // (real &#43; imaginary * i) * (real &#43; imaginary * i) // = // real * real &#43; imaginary * imaginary * i^2 &#43; 2 * real * imaginary * i // = // real * real - imaginary * imaginary &#43; 2 * real * imaginary * i // // So the new real value is (real * real - imaginary * imaginary) // And the new imaginary value is (2 * real * imaginary) // // The reason the first &#43; turns into a - is because i^2 is defined to be // equal to -1, that&#39;s what makes the numbers imaginary. // temp = (z_r * z_r) - (z_i * z_i) &#43; c_r; z_i = (2.0 * z_r * z_i) &#43; c_i; z_r = temp; // Check to see if the magnitude of the complex number is larger than // 2. We check whether the squared magnitude is greater than 4 here to // avoid taking a square root, because square roots are slow. if (((z_r * z_r) &#43; (z_i * z_i)) &gt; 4.0) return i; } // Return the maximum iterations value if we never escaped. return maximum_iterations; } // // Draw a Mandelbrot set filling in a canvas specified by element_id. // function draw_mandelbrot(element_id) { // Lookup the canvas and get a 2D rendering context from it. element = document.getElementById(element_id); context = element.getContext(&#34;2d&#34;); // // Construct an image data object to hold the pixels before they are // drawn to the screen. // image_data = context.createImageData(element.width, element.height); // // Iterate over every pixel in the canvas and compute the escape time for // the corresponding point in the complex plane. // for (y = 0; y &lt; image_data.height; y&#43;&#43;) { for (x = 0; x &lt; image_data.width; x&#43;&#43;) { // // This scales the &lt;x, y&gt; values into a smaller range of the // complex plane. But it doesn&#39;t take into account the size of the // canvas element. So if the canvas element changes size, this will // need to change as well. This can be made automatic, but it would // obcure the meaning for this example. It would be a good // experiment to change these values and try and make the result // general. // iterations = compute_escape_time((x - 350.0) / 200.0, (y - 250.0) / 200.0, 100); // // This is a simple use of the iteration count. We are only looking // at the bottom bit of the resulting escape time iterations. This // results in the zebra striping look. // if (iterations &amp; 1) r = g = b = 255; else r = g = b = 0; // // Write the computed color value to the image_data at the current // location. // set_pixel(image_data, x, y, r, g, b, 255); } } // Finally, copy the resulting image to the canvas for display. context.putImageData(image_data, 0, 0); } </code></pre> <p>Syntax highlighted with <a href="http://prismjs.com">Prism</a>.</p> Git Filter Branch http://socialhacker.com/posts/git_filter_branch/ Sun, 25 Mar 2012 03:14:00 -0800 anton@socialhacker.com (Anton Staaf) http://socialhacker.com/posts/git_filter_branch/ <p>This HOWTO describes the steps required to extract a portion of a large git repository into it's own separate repository.</p> <p>I have found this useful numerous times because when I first started to use git I created a single repository for all of my personal projects. Since then I've come to appreciate having many smaller repositories. So whenever I want to open up some new chunk of code I use these steps to extract the history for just that chunk into a new repository and then publish that.</p> <h2 id="setup">Setup</h2> <p>I always start by doing a fresh clone of the repository that I want to extract from, so that I know I'm not messing with my primary development environment. This has the added advantage that as long as you don't clone with --recursive, you won't have any submodules checked out. If you have submodules then the filter branch can get into trouble trouble.</p> <pre><code class="language-bash">git clone git://source.socialhacker.com/... temp_clone </code></pre> <p>Then just to make sure I'm not going to do something stupid, I remove the remote from the newly cloned repository.</p> <pre><code class="language-bash">cd temp_clone git remote rm origin </code></pre> <p>Now we're ready to run git filter-branch. In particular, I run the subdirectory filter which replays all of your commits, only keeping changes to a given subdirectory. You need to add the --prune-empty option to cause filter-branch to not include empty commits.</p> <pre><code class="language-bash">git filter-branch \ --prune-empty \ --subdirectory-filter &amp;lt;directory&amp;gt; \ -- \ --all </code></pre> <p>Now, at this point I like to fix up the history a little. In particular I fix up the commit messages with the name and email address I've decided on. For a while I hadn't set these correctly and my early commits have something pretty useless. This will only work if you're the only committer to your repository. If you have multiple people committing, then this will wipe out their author names and email addresses from their commits.</p> <pre><code class="language-bash">git filter-branch \ -f \ --env-filter &quot;export GIT_AUTHOR_NAME='Anton Staaf'; export GIT_AUTHOR_EMAIL='anton@socialhacker.com';&quot; \ HEAD git filter-branch \ -f \ --env-filter &quot;export GIT_COMMITTER_NAME='Anton Staaf'; export GIT_COMMITTER_EMAIL='anton@socialhacker.com';&quot; \ HEAD </code></pre> <p>The final step before you can push your new repository is to remove all of the old information about the commits that you no longer want to be visible. The first line below clears out the reflog, so that it doesn't maintain references to the old state of the repository. The second line does a garbage collection run on the repository. This will remove any objects that are no longer referenced.</p> <pre><code class="language-bash">git reflog expire --expire=now --all git gc --aggressive --prune=now </code></pre> <p>At this point you can add a new remote and push your repository.</p> Diet Planner http://socialhacker.com/posts/diet_planner/ Sat, 17 Mar 2012 00:00:00 +0000 anton@socialhacker.com (Anton Staaf) http://socialhacker.com/posts/diet_planner/ <p>The <a href="http://socialhacker.com/applications/diet_planner/diet_planner.html">Diet Planner</a> is a simple javascript application that can calculate grams of fat, protien, and carbohydrates needed to gain or lose weight given various body metrics.</p> Brute Force SSH Attack Protection http://socialhacker.com/posts/ssh_protection/ Tue, 12 Oct 2010 05:19:37 -0800 anton@socialhacker.com (Anton Staaf) http://socialhacker.com/posts/ssh_protection/ <p>This HOWTO describes a couple things that you can do to secure your SSH server on a Linux machine (Ubuntu, RedHat, Suse...).</p> <p>This is useful because there are script kiddies all around trying to break into computers. And I imagine that botnets writers will take more interest in Linux as it's market share increases.</p> <p>The pattern that I have seen is of many many requests from the same IP address trying to guess users and passwords. Most of the requests are trying to guess the root password.</p> <p>There are a couple things we can do to slow these attackers. The most obvious is to configure ssh to only allow logins from a couple select users. And to disallow remote login by the root user. We can also use IPTables to only allow a limited number of connections per minute. And finaly, we can move the SSH server to a different port on the machine. I don't know if this actually causes the attackers any pause however. They may just be trying all of the open ports.</p> <p>There are more complex solutions to the problem. Port knocking or log parsing come to mind. But I've opted for the simplest solution that doesn't impact usability in my case.</p> <p>The use of IPTables to limit repeated connections is based on work by Kevin van Zonneveld. You can see his approach on <a href="http://kevin.vanzonneveld.net/techblog/article/block_brute_force_attacks_with_iptables/">his blog</a></p> <h2 id="what-is-iptables">What is IPTables</h2> <p>IPTables is part of the kernels network stack (I think). It is a user configurable state machine that can be used to filter packets as they are received, before they are forwarded or before they are transmitted.</p> <p>Our configuration will drop incoming packets that meet a specific set of rules.</p> <h2 id="sshd-configuration">SSHD configuration</h2> <p>The file /etc/ssh/sshd_config is used to configure the ssh server on your linux machine. The changes I made to mine were to change &quot;Port 22&quot; to &quot;Port xxxx&quot; and to add &quot;AllowUsers yyyy zzzz wwww&quot; where xxxx is the new port you want SSH to listen to. yyyy, zzzz and wwww are the users that you want to have remove access. I also made sure that the line &quot;PermitRootLogin no&quot; existed and was not commented out.</p> <h2 id="ssh-configuration">SSH configuration</h2> <p>If you have changed the port that sshd listens to then you will probably want to configure your ssh clients on any machine that you would like to access your server from. In your home directory on each of these machines you should find &quot;~/.ssh/&quot;. In that directory you can create a config file. It's just called config. Put the following in that file. Again, xxxx is the new port that your ssh server is listening to.</p> <pre><code class="language-ssh_config">Host your.server.name Port xxxx </code></pre> <h2 id="network-scripts">Network scripts</h2> <p>In Ubuntu there are directories that contain scripts to run when an interface comes up or goes down. These are convenient places to put the IPTables commands needed to drop attackers packets. The directory for scripts to run when a network interface comes up is /etc/network/if-up.d. And the directory for scripts to run when a network interface goes down is /etc/network/if-down.d. We will create one file in the if-up.d directory and a symlink in the if-down.d directory. We do this to consolidate the logic in a single location. We can use the MODE variable to determine if the interface is coming up or going down.</p> <p>In /etc/network/if-up.d/ssh-protection put the following.</p> <pre><code class="language-bash">#!/bin/bash SSH_IFACE=&quot;eth1&quot; SSH_PORT=xxxx # This should be the port you've moved your ssh server to, or 22 if you haven't moved it. SSH_PERIOD=60 SSH_COUNT=8 # # Only add the rules to the interface that SSH is actually listening on. # if [ &quot;$IFACE&quot; != &quot;$SSH_IFACE&quot; ]; then exit 0 fi case &quot;$MODE&quot; in start) IPTABLES_ACTION=&quot;-A&quot; ;; stop) IPTABLES_ACTION=&quot;-D&quot; ;; esac /sbin/iptables$IPTABLES_ACTION INPUT \ -i $IFACE \ -p tcp \ --dport$SSH_PORT \ -m state \ --state NEW \ -m recent \ --set \ --name SSH /sbin/iptables $IPTABLES_ACTION INPUT \ -i$IFACE \ -p tcp \ --dport $SSH_PORT \ -m state \ --state NEW \ -m recent \ --update \ --seconds$SSH_PERIOD \ --hitcount $SSH_COUNT \ --rttl \ --name SSH \ -j DROP </code></pre> <p>This file needs to be executable by root. You can use the following command line to make it so.</p> <pre><code class="language-bash">chmod u+x /etc/network/if-up.d/ssh-protection </code></pre> <p>And in /etc/network/if-down.d create a symlink to the ssh-protection file in if-up.d using the following command line. This command line assumes you're in the if-down.d directory.</p> <pre><code class="language-bash">ln -s ../if-up.d/ssh-protection </code></pre> Port Forwarding http://socialhacker.com/posts/port_forwarding/ Wed, 20 May 2009 23:10:10 -0800 anton@socialhacker.com (Anton Staaf) http://socialhacker.com/posts/port_forwarding/ <p>This HOWTO describes the steps required to setup your RedHat (well any Linux distro) firewall to forward the port used by gtk-gnutella to a machine on your internal network. This is useful because it allows your gtk-gnutella client to behave in a non firewalled mode and thus more of the gnutella network is available to you. In particular, other machines that are behind firewalls that can handle push requests will become available to you.</p> <h2 id="what-is-port-forwarding">What is Port Forwarding?</h2> <p>Port forwarding is a feature of the IPTables system. It allows one computer to forward connections made to it so that another computer can actually process the request. If you want a very simple metaphor you can think of it as mail forwarding. Each computer has a number of addresses called ports, and IPTables allows (among other things) connections to these ports to be sent to another computer. The most common use of port forwarding that I am aware of is allowing servers to run on machines that would normally be hidden behind a firewall.</p> <h2 id="firewall-script">Firewall script</h2> <p>I am going to assume that you are using the default firewall script that comes with RedHat or whatever distribution you are running. My system is currently running RedHat 8.0 (heh, not anymore). And I am using a firewall script called rc.firewall-2.4. You should be able to find it in your /etc/rc.d directory. If you don't find it it may be that I had to install it and just don't remember. :) You can search for rc.firewall-2.4 on Google and find many copies.</p> <h2 id="setup">Setup</h2> <p>My goal was to make gtk-gnutella work in a non-firewalled mode from within my firewalled LAN. To do this people suggested a line of the form:</p> <pre><code class="language-bash">$IPTABLES -t nat -I PREROUTING -p tcp -i $EXTIF --dport 6346 -j DNAT --to 192.168.0.2:6346 </code></pre> <p>Where$IPTABLES is the iptables executable, $EXTIF is the external ethernet interface (I use two ethernet cards in my firewall), port 6346 is the gtk-gnutella port and 192.168.0.2 is the machine on my internal network on which I wished to run gtk-gnutella.</p> <p>With the rc.firewall-2.4 script this doesn't quite work. The reason is that by default any connection that would open a new session from the outside world is dropped. This is done with the line:</p> <pre><code class="language-bash">$IPTABLES -P FORWARD DROP </code></pre> <p>The solution is to add a rule into the FORWARD chain that causes connections from the outside world to port 6346 to not be dropped, but instead to be accepted. Then the PREROUTING rule above will be encountered and the connection will be forwarded to the internal machine as desired. The line to accomplish this is:</p> <pre><code class="language-bash">$IPTABLES -A FORWARD -i$EXTIF -o $INTIF -p tcp --dport 6346 -j ACCEPT </code></pre> <p>I placed this right before the line:</p> <pre><code class="language-bash">$IPTABLES -A FORWARD -j LOG </code></pre> <p>I did this because this line will will add a rule that causes all rules added after it to not be checked.</p> Virtual Hosting and SSL http://socialhacker.com/posts/socialhacker/virtual_hosting_and_ssl/ Tue, 05 May 2009 00:28:33 -0800 anton@socialhacker.com (Anton Staaf) http://socialhacker.com/posts/socialhacker/virtual_hosting_and_ssl/ <p>All right, now that we have some blogs up. We will want to enable SSL/TLS security, also known as https. The reason you want this may be obvious to some. But to spell it out for you, if you don&rsquo;t use https to connect to your administrative pages in Movable Type while you&rsquo;re sipping on your latte, then everyone else that&rsquo;s on that wireless network can see you type your password in, plain as day. And by &ldquo;can&rdquo;, I mean there is nothing preventing them from watching your traffic. Most likely, no one is, but you never know.</p> <p>There are a couple of complications that we will need to work through though. Firstly, SSL and name based virtual hosting are mostly incompatible. And secondly, unless you get a Certificate Authority, such as Verisign, to sign your SSL key you and your security conscious visitors will be presented with an ugly message from the browser saying that your site is trying to identify itself with an invalid security certificate.</p> <p>So, why are SSL and name based virtual hosting mostly incompatible? Well, it turns out that the way name based virtual hosting works is for the browser to send to your web server the name of the server it&rsquo;s trying to connect to. And then your web server uses that information to look through the list of virtually hosted domains until it finds a match. Then the page the browser wants is sent from the server to the browser. But if you have connected to the web server using an https connection then the communication channel needs to be encrypted. So the server needs to send the browser the public key of the domain the browser is trying to connect to. But the server doesn&rsquo;t yet know what domain the browser is trying to connect to, because that information is part of what will eventually be encrypted and sent by the browser. Apache will just serve the first certificate it finds in this case. So all but the first domain in your list of virtually hosted domains will cause the browser to issue an additional warning, that the certificate is for the wrong domain. This isn&rsquo;t a big problem for large hosting companies or business, they can just assign a separate IP address to each domain. And then use that extra information to configure the web server, allowing it to pass the correct domain specific key back to the browser. For us little guys, that&rsquo;s not really a suitable approach. You can do something similar by having your web server listen on a bunch of different ports, one for each domains SSL connection. But then your URLs will have to have the port number in them as well. Not a really classy solution. There is a solution to this problem in the works. It&rsquo;s called &ldquo;Server Name Indication&rdquo; or SNI, and it&rsquo;s part of the TLS protocol. Unfortunately it&rsquo;s still not readily available (see <a href="http://www.alexanderkiel.net/2008/04/22/status-of-tls-sni/">this</a> page). So, what&rsquo;s the solution? It&rsquo;s pretty simple actually, just use one certificate for all of your domains. There is an extension that allows for multiple domain names to be associated with a single certificate. When a browser receives such a certificate, it looks at all of the domain names and if any of them match it is satisfied. There seem to be some security issues with this feature (see <a href="http://nils.toedtmann.net/pub/subjectAltName.txt">this</a> page). But since we are mainly interested in using it to authenticate ourselves with our own server, it&rsquo;s not a big deal, I think. And that brings us to our second issue. We can pay Verisign to generate a certificate for us, or we can sign it ourself. If you pay Verisign (or other Certificate Authority) then anyone that browses your web site with a secure https connection will feel right at home, secure even. If you sign the certificate yourself, then viewers will be presented with a nastygram from their browser. Since I am mainly interested in being able to securely access my servers from insecure networks, I&rsquo;m happy to sign the certificates myself.</p> <p>First you need to enable SSL in your Apache configuration. In the Apache2 configuration for Ubuntu these files are located in /etc/apache2. You&rsquo;ll need to make sure that your ports.conf file contains something like the following:</p> <pre><code class="language-apache_config">Listen 80 &lt;IfModule mod_ssl.c&gt; Listen 443 &lt;/IfModule&gt; </code></pre> <p>This causes Apache to listen on port 443 for connections as well as port 80. Port 443 is the https port. And your conf.d/namevirtualhosts file should look something like:</p> <pre><code class="language-apache_config">NameVirtualHost *:80 NameVirtualHost *:443 </code></pre> <p>This tells Apache to look up virtual hosts by name for traffic coming in on either port. Next you need to make sure that your conf.d/ssl_certificate file looks something like:</p> <pre><code class="language-apache_config">SSLCertificateFile /etc/apache2/ssl/serverwide.crt SSLCertificateKeyFile /etc/apache2/ssl/serverwide.key </code></pre> <p>You can see that I&rsquo;ve called my certificate and key files serverwide to make it obvious that they are used by all domains served by this server. It is very important that these files have their permissions set so that only root can read them. You&rsquo;ll also need to make symlinks from the ssl.conf and ssl.load files in your mods-available directory to your mods-enabled directory.</p> <p>Now we&rsquo;re ready to generate and sign our key and certificate. Once you have generated the certificate you can inspect it&rsquo;s contents with this command.</p> <pre><code class="language-bash">openssl x509 -in serverwide.crt -noout -text </code></pre> <p>To generate a key use the following command. You will be asked for a pass phrase. It is important that you remember this pass phrase or your key will be lost to you forever. Or at least until computers are powerful enough to brute force crack your key.</p> <pre><code class="language-bash">openssl genrsa -des3 -rand /dev/urandom -out serverwide.key 1024 </code></pre> <p>Once you have a key you can create and sign a certificate with the following command. You will be asked for the pass phrase you entered above. This is because the key is protected by that pass phrase and can&rsquo;t be used without it. This certificate will be valid for one year.</p> <pre><code class="language-bash">openssl req -config server.config -new -key serverwide.key -out serverwide.crt -x509 -days 365 </code></pre> <p>Most of the options we need to pass to OpenSSL to create and sign the certificate can be passed in a configuration file. The command line above assumes the configuration file is called server.config. Below is an example server.config file, the main lines of interest are in the alt_names section. The alt_names section is where you can put all of the virtually hosted domains on your server. The browser will look for a match with any of those domains when the server passes it the certificate we have just generated. I also found that subjectAltName had to be in both the v3_req and v3_ca sections.</p> <pre><code class="language-openssl_config">[ req ] default_bits = 1024 default_md = sha1 distinguished_name = req_distinguished_name prompt = no string_mask = nombstr req_extensions = v3_req x509_extensions = v3_ca [ req_distinguished_name ] countryName = &amp;lt;country code&amp;gt; stateOrProvinceName = &amp;lt;state&amp;gt; localityName = &amp;lt;city&amp;gt; organizationName = &amp;lt;whatever, could be your name&amp;gt; organizationalUnitName = &amp;lt;again, whatever&amp;gt; commonName = www.domain1.com emailAddress = webmaster@domain1.com [ v3_req ] basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment subjectAltName = @alt_names [ v3_ca ] subjectAltName = @alt_names [ alt_names ] DNS.1 = www.domain1.com DNS.2 = www.domain2.com DNS.3 = www.domain3.com </code></pre> <p>The key that we have generated will have a pass phrase associated with it (the one you entered when you generated the key). This pass phrase will need to be entered every time you restart your apache server. There are ways of removing this extra security, but if you want to do that I&rsquo;ll let you look that one up elsewhere. For me with a server running on a UPS, I reboot or restart apache a couple of times a year at most. The added security is well woth it. If your server get&rsquo;s compromised, and it will eventually, then your security key will be coppied. And that is as they say, a bad thing.</p> <p>And finally, in your site configuration file, probably in /etc/apache2/sites-available, you will need to add the following:</p> <pre><code class="language-apache_config">&lt;VirtualHost *:443&gt; ServerName www.domain1.com ServerAlias domain1.com *.domain1.com DocumentRoot /var/www/domain1 SSLEngine On &lt;/VirtualHost&gt; </code></pre> <p>This is the Virtual host configuration file for your secured site. You&rsquo;ll want to add any additional configurations to it from your normal *:80 configuration section.</p> Virtual Hosting and Movable Type http://socialhacker.com/posts/socialhacker/virtual_hosting_and_mt/ Sat, 02 May 2009 11:33:15 -0800 anton@socialhacker.com (Anton Staaf) http://socialhacker.com/posts/socialhacker/virtual_hosting_and_mt/ <p>It was a lot harder than I anticipated to get Movable Type to run from a single global install on all of my virtually hosted domains. So in the spirit of sharing, here&rsquo;s how I did it.</p> <p>First, install movable type into a directory at the root of your web servers directory structure. I put mine in /var/www/shared/. The resulting directory structure contained:</p> <dl> <dt>/var/www/shared/cgi-bin/mt</dt> <dd>This directory contains pretty much everything in the Movable Type tarball.</dd> <dt>/var/www/shared/mt-static</dt> <dd>This directory is the mt-static directory from the Movable Type tarball. I moved it out to the top level of the shared directory because I have Apache configured to not serve documents from the cgi-bin directory.</dd> <dt>/var/www/shared/conf</dt> <dd>This directory will contain the configuration files for all of the sites you will be virtually hosting.</dd> </dl> <p>Next configure apache for each of your virtually hosted domains. I assume you already have virtual hosting up and running. The configuration file for socialhacker.com looks like this:</p> <pre><code class="language-apache_config">&lt;VirtualHost *:80&gt; ServerName www.socialhacker.com ServerAlias socialhacker.com *.socialhacker.com DocumentRoot /var/www/socialhacker AddHandler cgi-script .cgi SetEnv MT_HOME /var/www/shared/cgi-bin/mt SetEnv MT_CONFIG /var/www/shared/conf/socialhacker.cgi ScriptAlias /cgi-bin/ /var/www/shared/cgi-bin/ Alias /mt-static/ /var/www/shared/mt-static/ &lt;/VirtualHost&gt; </code></pre> <p>The important bits here are how you set up the alias&rsquo; and the environment variables. And all of this is covered in <a href="http://www.movabletype.org/documentation/enterprise/managing-multiple-instances-of.html">this article</a>.</p> <p>Finally, you need to create a configuration file in the shared/conf directry for your site. I did this by hand, which you&rsquo;ll need to do as well since Movable Type won&rsquo;t set most of these options in the configuration file it generates.</p> <pre><code class="language-movable_type_config">CGIPath /cgi-bin/mt/ StaticWebPath /mt-static/ StaticFilePath /var/www/shared/mt-static/ PluginPath /var/www/shared/cgi-bin/mt/plugins/ TemplatePath /var/www/shared/cgi-bin/mt/tmpl/ WeblogTemplatesPath /var/www/shared/cgi-bin/mt/default_templates/ ObjectDriver DBI::mysql Database &lt;your database name&gt; DBUser &lt;your database user&gt; DBPassword &lt;your database password&gt; DBHost localhost MailTransfer smtp SMTPServer smtp.&lt;your provider&gt;.com _(probably)_ </code></pre> <p>And there&rsquo;s the real magic. You have to specify paths to the Static content as well as both Template directories, and the Plugin directory. If you forget the first template directory you won&rsquo;t get very far as the administrative pages won&rsquo;t load. But if you forget the second template path you&rsquo;ll get all the way to making a post and find that all of the files in your blog directory are zero length. If you forget the Plugin path you&rsquo;ll be missing all of your plugins.</p> <p>Hopefully you&rsquo;ve found this useful in setting up your own Movable Type blogs.</p>