ICE: Removing duplicates from arrays

Here’s an ICE tree that removes all duplicate elements from an array. It uses Generate Sample Set, so there’s no repeat nodes. But it relies on the fact that you can feed in an array of indices into Remove from Array, and Remove from Array doesn’t care if that array of indices itself contains duplicate. So, if you plug the array [1,1,1,2,2,2,3,3,3] in the Index port, Remove from Array will nicely remove elements 1, 2, and 3 with no complaints.


Unlike some other methods, this works with scalars too:


Using Generate Sample Set to avoid the Repeat node

Hat tip to Oleg who posted this tip on the mailing list some time ago.

The basic ideas is that instead of looping over an array with a Repeat with Counter, you use Generate Sample Set to get a data set, and you do everything in a per-generated element context.


As an example, let’s revisit the problem of taking one array and creating a new array where each element is the sum of the elements before it.


The old way, with a Repeat with Counter node, looks like this:

Using Generate Sample Set, you can work with a data set and use that to access the array elements:

Generate Sample Set is set up to give an exact number of samples:

ICE powers of 10 array

In ICE, how would you generate an array like [1, 10, 100, 1000, 10000, 100000, …] without using a Repeat node ?

It might help to look at it this way:


Once you recognize that you are looking at powers of 10, and recall that the basic Math nodes can handle arrays just as well as single values, the rest follows easily:

Evenly distributing points on a sphere with the golden section spiral

This post is based on the recent xsibase thread Golden Section Spiral in ICE, which in turn is based on Patrick Boucher’s 2006 article Points on a sphere.

So…here’s an ICE version of the Golden section spiral algorithm for evenly distributing points on a sphere. It’s a typical example of basic “thinking in ICE”: when you see a for loop in the alogrithm/pseudocode, you should see “in ICE” an array (or data set) flowing through a graph.

Here’s my GoldenSectionSpiral compound (although if you’ve never converted a scripted alogithm to ICE, you should do it yourself just for the exercise 😉 I thought the spiral effect was interesting, so I put in an option to not convert radians to degrees (which is necessary to get the real evenly distributed points).

Simple example of a parametric point cloud

Here’s a simple parametric point cloud that shows the two techniques for using arrays instead of Repeats that I blogged about earlier:

Using arrays to avoid Repeat part I
Using arrays to avoid Repeat part II

I used this set of parametric equations to get a cylinder point cloud:

x = sin(u)
y = cos(u)
z = v


0 <= u <= 2*PI
-2 <= v <= 2

For this exercise, I simply used Build Interpolated Array to build arrays of U and V values, but I probably should use something like the XYZ_Grid_Generator technique described by Daniel Brassard on si-community.

Here’s a version of the ICE tree with some Show Values.

I use the Modulo technique to build an array of the XY values for all points in the cloud.

Then I use the Divide by Scalar technique (the integer result is truncated) to build an array of the Z values.

Finally, I add XY vectors to the Z vectors to get the final point positions.

Using arrays to avoid Repeat part II

Part I is here

Another building block for using arrays instead of Repeat loops: an array that looks like [0,0,0,0, 1,1,1,1, 2,2,2,2, …].

Again, the trick is to use this array as the indices for Select in Array.

Here’s how to build this kind of array:

Here’s a simple example. I get the positions of the objects in a group, and then use those positions to add points in a point cloud. Basically, I have a group of objects, and an array of vectors (the interpolated array). When I add a point, I take an object position and add a vector to it to get the point position.

In pseudo-code:

For each object in group
      for each vector in array
             Add Point
             Point Position = vector + object position 

If that ICE tree is hard to follow, then it may help to use some attributes to store intermediate values(arrays). That way you can separate out some branches of the tree: