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.

GenerateSampleSet_Remove_Duplicates

Unlike some other methods, this works with scalars too:

GenerateSampleSet_Remove_Duplicates_Scalar

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.

GenerateSampleSEt_vs_Repeat

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.

Array_accumulation

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

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

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

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:

1
10
100
1000
10000
100000

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

where

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: