Skip to content

Instantly share code, notes, and snippets.

@rgov
Created April 18, 2013 20:22
Show Gist options
  • Save rgov/5415912 to your computer and use it in GitHub Desktop.
Save rgov/5415912 to your computer and use it in GitHub Desktop.
Building a curve for @mdznr
Let's widen the circle to have a radius of 1.
Solve x^2 + (y - 1)^2 = 1, you get
y = 1 +/- Sqrt[1 - x^2]
Focus on the bottom-right part of the circle first, from x = 0 to 1:
y = 1 - Sqrt[1 - x^2]
Let's make the right half of this curve repeat. Instead of using x, we'll use
a sawtooth curve with period 1, which looks like:
y = x - Floor[x]
Then we get
y = 1 - Sqrt[1 - (x - Floor[x])^2]
which is the buttom-right of the circle repeating horizontally. Let's make it
step up a little bit each time, according to
y = Floor[x]
then we get
y = (1 - Sqrt[1 - (x - Floor[x])^2]) + Floor[x]
Now switch to the top-left of the circle.
y = 1 + Sqrt[1 - x^2]
Lets slide this over so it's in the same position as the bottom-right was:
y = Sqrt[1 - (x - 1)^2]
So that gives us these two for our quarter-circles.
y = Sqrt[1 - (x - 1)^2]
y = 1 - Sqrt[1 - x^2]
We want one equation which we can toggle between based on f[x]. For instance,
to toggle between
y = 0 + x
y = 1 - x
we can use
y = (-1)^f[x] * x + ((-1)^f[x] - 1) / -2
which evaluates to the first if f[x] is 0, and the second if f[x] is 1.
We do the same trick to toggle between
y = x - 1
y = x - 0
yielding
y = x - ((-1)^f[x] + 1) / 2
Then we can put these two together to combine our two quarter-circles:
y = (-1)^f[x] * Sqrt[1 - (x - ((-1)^f[x] + 1) / 2)^2] + ((-1)^f[x] - 1) / -2
Now we get the top-left when f[x] is 0, and the bottom-right when f[x] is 1.
Actually, this is dependent on whether f[x] is even or odd.
Let's also combine this with our two earlier findings. Our first was to use the
sawtooth curve for x (we don't care about where it appears in f[x]).
y = (-1)^f[x] * Sqrt[1 - ((x - Floor[x]) - ((-1)^f[x] + 1) / 2)^2] + ((-1)^f[x] - 1) / -2
And add our step-up:
y = (-1)^f[x] * Sqrt[1 - ((x - Floor[x]) - ((-1)^f[x] + 1) / 2)^2] + ((-1)^f[x] - 1) / -2 + Floor[x]
All that remains is picking f[x] so that it switches appropriately. We need a
stepwise function that switches between even and odd, at an interval of 1. We
have this already:
f[x] = Floor[x]
y = (-1)^Floor[x] * Sqrt[1 - ((x - Floor[x]) - ((-1)^Floor[x] + 1) / 2)^2] + ((-1)^Floor[x] - 1) / -2 + Floor[x]
which is the desired curve.
@rgov
Copy link
Author

rgov commented Apr 18, 2013

I think I swapped the ordering of the two curves when I was building up the f[x] toggle. I also might be missing some coefficients to change the phase from 2 to 1.

This could probably be done much better using an S-shaped trigonometric function. If you find a suitable one, F[x], then you can re-use the sawtooth and step up tricks: F[x] becomes F[x - Floor[x]] + Floor[x].

For instance, y = 1/2 (tanh[4x - 2] + 1) is pretty close, and gets pretty close. Compare:

http://www.wolframalpha.com/input/?i=y+%3D+tanh%5B2x+-+2%5D+%2B+1%2C+%28-1%29%5EFloor%5Bx+-+1%5D+*+Sqrt%5B1+-+%28%28x+-+1+-+Floor%5Bx+-+1%5D%29+-+%28%28-1%29%5EFloor%5Bx+-+1%5D+%2B+1%29+%2F+2%29%5E2%5D+%2B+%28%28-1%29%5EFloor%5Bx+-+1%5D+-+1%29+%2F+-2+%2B+Floor%5Bx%5D+from+x+%3D+0+to+2

@hortont424 points out you could use the sigmoid function instead of tanh for an easier-to-compute approximation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment