1
$\begingroup$

The goal is to generate a picture like this:

ellipse with gradient

A symmetric color gradient around an ellipse which is rotated by $\theta$, has $(x_\circ,y_\circ)$ as center and and major and an minor axis $a,b$.
The total line width should be invariant to changes in those parameters.

It was done by using the implicit ellipse equation with different axis offsets $h$ from $-d$ to $d$ with step size of 1 pixel. So total line width is $2d$.

$$L_{h} = A_{h}x^2 + B_{h}xy + C_{h}y^2 + D_{h}x + E_{h}y + F_{h} = 0$$

with $$ A_{h} = (a+h)^2 \sin^2\theta + (b+h)^2 \cos^2\theta $$ $$ B_{h} = 2\left((b+h)^2 - (a+h)^2\right) \sin\theta \cos\theta $$ $$ C_{h} = (a+h)^2 \cos^2\theta + (b+h)^2 \sin^2\theta $$ $$ D_{h} = -2A_{h} x_\circ - B_{h} y_\circ $$ $$ E_{h} = - B_{h} x_\circ - 2C_{h} y_\circ $$ $$ F_{h} = A_{h} x_\circ^2 + B_{h} x_\circ y_\circ + C_{h} y_\circ^2 - (a+h)^2 (b+h)^2 $$

We first check if $L_0$ is below (means inside the ellipse) or greater (means outside the ellipse) than $0$. If greater we check if $L_d$ is greater or smaller $0$. If smaller we check it with $h = \frac{d}{2}$. If it is smaller than this we check it for $h = \frac{d}{4}$. If bigger we check for $h = \frac{d}{2} + \frac{d}{4}$. And so on.

With this we can compute an approximation of the distance with the step size as unit. (note: this is not the shortest point to ellipse edge distance even for very small steps but it's very close to)
This requires $O(\log_2(d))$ checks per pixel.

Calculating the real distance seems to be require an equation solver for each pixel or solving a quatric equation (degree of 4) with results of thousands of operations.


Can we do any quicker?
For example applying a filter on a ellipse without gradient. How would the math about it look like?
Or can we approximate the distance?
Or something else?


More details:
Will be used for many ellipses with different arbitrary parameter $\theta, (x_\circ,y_\circ), a ,b$.
My related math stack threads: about inner and outer boundary, about distance point to ellipse, about quick calculation of gradient

$\endgroup$

1 Answer 1

3
$\begingroup$

You can exactly find the distance to a 2D ellipse using the signed distance function of an ellipse. Here is one by iq on shadertoy:

https://www.shadertoy.com/view/4sS3zz

Then a scale invariant way of generating the gradient can be achieved by adding before the last fragColor statement in mainImage():

col = vec3(0.0);
float gradientWidth = 0.1;
if(abs(d) < gradientWidth) {
    //col = vec3(1.0) * (1.0 - smoothstep(0.0, 1.0, abs(d) / gradientWidth)); //use this for smooth gradient
    col = vec3(1.0) * (1.0 - (abs(d) / gradientWidth));
}
$\endgroup$
1
  • $\begingroup$ wow, what a nice page. And wow that there is actually an analytic solution. Thousand times faster to solutions I found but still using some slow trigonometry and root functions. However there are also links to approximative solutions not using any trigonometry. (Points need to be rotated by $\theta$ and translated by $x_\circ,y_\circ$). Will need to test which is actually the fastest. Will mark this as answer. Thank you! If someone posts some faster/better way (e.g. some filter?) I can change it again. $\endgroup$
    – UncleBob
    May 7 at 15:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.