Signed Distance Node

john's Avatar

john

16 May, 2024 01:58 AM

Attached is a node, signed_dist, that computes the minimum signed distance from points to a shape boundary. Distances outside the shape are postiive; distances inside are negative. Thanks to Jussi Jokinen for spurring my interest in signed distances.

Signed_dist takes five parameters:

  • Points. A grid of points (typically used to form a canvas of pixels)
  • Shape. A path or geometry, normally closed
  • Normalize. If checked, distances will be normalized (-1 to 1) based on the maximum exterior and interior distances
  • Exterior Focus. Changes the distribution of distance values for points outside shapes. A positive focus will make the values more quickly approach the maximum, negative will do the reverse. The effect can be better understood when distance values are used to drive pixel colors. Values can range from -99 to +99.
  • interior Focus. Does the same thing but for points inside shapes.

NOTE: for the purposed of this function, points that land exactly on the boundary of the shape are considered to be outside. I made a much more complex version of this node that counted boundary points as being inside (as is the normal practice), but it ran twice as slowly, so I went with the simpler, faster version.

Signed distance functions (SDFs) are primarily used to handle challenging real time animation like flickering flames. Flames represented as multiple vector paths with complex geometries which change second by second and merge and separate in near-infinite ways can be hard to compute at scale. SDFs provide a way of representing shapes not as distinct splines, but as emergent properties of a field of pixels, where each position in the field (each pixel) is given a number which can then code for color. More about SDFs here:

https://en.wikipedia.org/wiki/Signed_distance_function

Nodebox is nowhere near fast enough to animate flames in real time. But, as Jussi has demonstrated, signed distances can be used in all sorts of generative art projects. Jussi used signed distances as a displacement or terrain map, which he then used to draw lines which he fed to a plotter. I can see many other possibilities.

If you use signed_dist to color "pixels" (a grid of squares), you will have to be content with a relatively low resolution. Even a 100 x 100 pixel grid will require firing the node 10,000 times. I worked to make this node as efficient as I could. The time required to calculate 10,000 distance will depend on how complex the shape is. On my MacBook Pro:

  • a simple 400 diameter circle at 100 x 100 took under 1 second
  • a 1500 point TimesNewRoman lower case at 100 x 100 took 2 seconds
  • the inkblot monster shown in the screenshot at 100 x 100 took 12 seconds

Those numbers are just for the distances; more time will be required to draw and color the "pixels". I find I can produce 200 x 200 PNGs (40,000 pixels) without too much waiting; going higher than about 320 x 320 (100,000+ pixels) may cause "out of memory" errors.

I have attached the node with a demo (see screenshot).

The demo allows you to try three different shapes:

  • an overlapping ball and star
  • a lower case a
  • an inkblot monster (roughly similar to what Jussi described making)

The display_grid subnetwork lets you optionally display the distance numbers for each pixel and/or overlay an outline of the shape.

You can also easily change the canvas size and resolution using the make_grid subnetwork. Set the resolution to a low number, like 25, with the show numbers option on, and a simple shape to more easily see the distance numbers and the effect of changing focus. Choose normalize to see the distances displayed on a scale from -100 to 100 (multiplied by 100 for ease of use). Drag the exterior and interior focus up and down to see how this affects the distances, and thus the colors.

NOTE: when using display_grid, negative focuses will not show correctly unless you have normalized the distances. In order to display negatively focused distances, you need to know the maximum distance when unfocused, which display_grid has no way of knowing based only on unnormalized distances. If you are using your own code to display images, this will not be an issue (and it's now easy to normalize in any event).

I've had a lot of fun making this node, and am eager to see what people do with it. Enjoy!

Reply to this discussion

Internal reply

Formatting help / Preview (switch to plain text) No formatting (switch to Markdown)

Attaching KB article:

»

Already uploaded files

  • signed_distance_screenshot.png 1.93 MB
  • signed_dist_demo.ndbx.zip 25.2 KB

Attached Files

You can attach files up to 10MB

If you don't have an account yet, we need to confirm you're human and not a machine trying to post spam.

Keyboard shortcuts

Generic

? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac

Recent Discussions

16 May, 2024 02:11 AM
16 May, 2024 01:58 AM
14 May, 2024 01:29 AM
13 May, 2024 12:36 AM
12 May, 2024 07:46 PM

 

05 May, 2024 04:38 PM
03 May, 2024 06:50 AM
03 May, 2024 12:30 AM
03 May, 2024 12:09 AM
19 Apr, 2024 04:41 AM
16 Apr, 2024 06:18 PM