<p>You should separate your line drawing logic from your calculation logic.<br>
In general you should try to have a generic line drawing function that would accept any number of points and draw a line from one point to the next.<br>
The simplest implementation for this would be to have dense points and draw a circle at each point.</p>

<p>If you however absolutely have to calculate the color of a pixel as a function of the X coordinate you'll have to calculate the value multiple times.<br>
Lets say you want thickness of 3 pixels, you will have to calculate this for [X-1, X, X+1] and then check if the current pixel is close to any of the values.<br>
A big downside to this is that you have many duplicate calculations.</p>

CC BY-SA 4.0
2020-04-18T14:23:45.060Z
2020-04-18T14:23:45.060Z
zoran404
<p>I have written a very minimal plotting code which take a function <span class="math-container">$f$</span> and a domain <span class="math-container">$[a,b]$</span> and plots its graph. (It's <a href="https://github.com/NAThompson/graphics" rel="nofollow noreferrer">here</a>, if relevant.)</p>

<p>Now, I query <span class="math-container">$f$</span> at the sides of each pixel, and then every vertical pixel in the line gets marked. But this makes an incredibly thin graph unless the pixel density is low. So I want to support variable line thickness.</p>

<p>When the function is constant, this is easy: Just add the requisite number of pixels above and below the correct pixel. However, as <span class="math-container">$f'(x) \to \infty$</span>, that gets weird. You still mark above and below the correct pixel, but then the graph appears thin. Here's an example, which I've made comically thick for emphasis:</p>

<p><a href="https://i.sstatic.net/Uws93.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/Uws93.png" alt="enter image description here"></a></p>

<p>The function <span class="math-container">$\sin(x)$</span> is pretty much uniformly thick, but <span class="math-container">$1/x$</span> gets really thin as <span class="math-container">$x\to 0$</span>, and so does <span class="math-container">$\sin(1/x)$</span>.</p>

<p>What can I do to get these graphs uniformly thick?</p>

<p>If I assume I can use automatic differentiation on <span class="math-container">$f$</span>, does the problem have a more interesting solution?</p>

<p><em>Note</em>: I tried setting the line thickness at point <span class="math-container">$x$</span> to
<span class="math-container">$$
t(x) = t_{\mathrm{user}}\max(1, |f'(x)|)
$$</span>
where <span class="math-container">$ t_{\mathrm{user}}$</span> is the user requested thickness.
But of course <span class="math-container">$|f'|$</span> can diverge, so this did horrible things to the graph. So I did:
<span class="math-container">$$
t(x) = t_{\mathrm{user}}\min(\max(1, |f'(x)|), 8)
$$</span>
which also looked terrible, though admittedly less terrible than before. But it's just too arbitrary, so asking the hive-mind it is.</p>

<p><em>Edit</em>: I'm now thinking that the width should be marked along the normal to the tangent, i.e. the line
<span class="math-container">$$
y - f(x_i) = -\frac{1}{f'(x_i)} (x-x_i),
$$</span>
not along a vertical. So automatic differentiation is required?</p>

<p><em>Edit 2</em>: You can get the derivative in pixel space via finite differences; that's just fine, and I image cheaper. Then it's Bresenham's line algorithm + some alpha decay with distance from the curve?</p>

CC BY-SA 4.0
2020-04-18T14:18:15.847Z
`The function sin(x) is pretty much uniformly thick` it's not uniform at all, you would notice this better if you used a higher frequency
zoran404
CC BY-SA 4.0
2020-04-18T14:39:49.103Z
If I used a higher frequency, I would amplify the derivative, which is precisely the point of the question.
user14717
CC BY-SA 4.0
2020-04-18T15:07:56.793Z
I was talking about `sin(x)` in your screenshot, it's not uniform. The thickness around 0 is around 25% thinner.
zoran404
<line-drawing>
Uniform line thickness in plot
user14717
# Uniform line thickness in plot

(Asked by: username_0 on 2020-04-18)

I have written a very minimal plotting code which take a function $f$ and a domain $[a,b]$ and plots its graph. (It's [here](https://github.com/NAThompson/graphics), if relevant.)

Now, I query $f$ at the sides of each pixel, and then every vertical pixel in the line gets marked. But this makes an incredibly thin graph unless the pixel density is low. So I want to support variable line thickness.

When the function is constant, this is easy: Just add the requisite number of pixels above and below the correct pixel. However, as $f'(x) \to \infty$, that gets weird. You still mark above and below the correct pixel, but then the graph appears thin. Here's an example, which I've made comically thick for emphasis:

[![enter image description here](https://i.sstatic.net/Uws93.png)](https://i.sstatic.net/Uws93.png)

The function $\sin(x)$ is pretty much uniformly thick, but $1/x$ gets really thin as $x\to 0$, and so does $\sin(1/x)$.

What can I do to get these graphs uniformly thick?

If I assume I can use automatic differentiation on $f$, does the problem have a more interesting solution?

*Note*: I tried setting the line thickness at point $x$ to
$$
t(x) = t\_{\mathrm{user}}\max(1, |f'(x)|)
$$
where $ t\_{\mathrm{user}}$ is the user requested thickness.
But of course $|f'|$ can diverge, so this did horrible things to the graph. So I did:
$$
t(x) = t\_{\mathrm{user}}\min(\max(1, |f'(x)|), 8)
$$
which also looked terrible, though admittedly less terrible than before. But it's just too arbitrary, so asking the hive-mind it is.

*Edit*: I'm now thinking that the width should be marked along the normal to the tangent, i.e. the line
$$
y - f(x\_i) = -\frac{1}{f'(x\_i)} (x-x\_i),
$$
not along a vertical. So automatic differentiation is required?

*Edit 2*: You can get the derivative in pixel space via finite differences; that's just fine, and I image cheaper. Then it's Bresenham's line algorithm + some alpha decay with distance from the curve?

**Tags:** line-drawing

> **Comments:**
> **username_1**: `The function sin(x) is pretty much uniformly thick` it's not uniform at all, you would notice this better if you used a higher frequency  
> **username_0**: If I used a higher frequency, I would amplify the derivative, which is precisely the point of the question.  
> **username_1**: I was talking about `sin(x)` in your screenshot, it's not uniform. The thickness around 0 is around 25% thinner.  

---

## 1 answers

### Answer by username_1 on 2020-04-18. Score: 2

You should separate your line drawing logic from your calculation logic.  
In general you should try to have a generic line drawing function that would accept any number of points and draw a line from one point to the next.  
The simplest implementation for this would be to have dense points and draw a circle at each point.

If you however absolutely have to calculate the color of a pixel as a function of the X coordinate you'll have to calculate the value multiple times.  
Lets say you want thickness of 3 pixels, you will have to calculate this for [X-1, X, X+1] and then check if the current pixel is close to any of the values.  
A big downside to this is that you have many duplicate calculations.


---

