# Geometry Nodes set subset scale and interpolate others

I'm new to blender and am wondering how I can have n cube geometry nodes in a line where a random subset of x of them are given a random z scale and all others not in that subset have their z scale interpolated based on their neighbors.

I've played around with this for several hours but I have no idea how to only set the z scale on a random subset of x geometry nodes. And from there, I'm not sure how to interpolate others' z scales.

This is what I have so far. Right now, all Geometry Nodes have a random z scale:

Which looks like this:

Are there any specific editor nodes I should be aware of that would help in doing this? I've searched around but haven't found anything useful.

I'm familiar with Python scripting and this seems like it would be easy to do there, so if you have any ideas on how to do this, that would help too. I'm not even sure how to get the references to each node in Python.

EDIT

Ok, so I figured out how to set the scale of a random subset of instances. (I can control the probability of an instance being in this subset, but I couldn't figure out how to get exactly x instances but whatever)

But I still have no idea how to interpolate the scale of the instances between the blue ones. The accumulate field node looks interesting but I'm not having any luck. Any ideas?

Since calculating the heights seems easier in Python, let's combine their strengths by doing that in Python and passing the result as an input to the Geometry Nodes.

The plan:

1. Use Python to create the grid of points with an attribute representing the desired height.
2. Use Geometry Nodes to instantiate a cube at each point on the grid, reading the attribute for the instance scale.

### Creating the grid

Most of this code is doing the interpolation. You can replace that part with anything you want of course.

import bpy

#### CALCULATE HEIGHTS ####
###########################

def interpolate_list(key_points):
"""
Create a list by lerping between key points.

Each keypoint should be a pair (x,y) giving the value y of
the list at index x. The values at other indices will be
lerped from the two nearest keypoints.

The first keypoint must be at x=0. The list will be just
long enough to fit the last keypoint.

Keypoints must be sorted by x.
"""
assert len(key_points) > 0, "Must have at least one keypoint"
assert key_points[0][0] == 0, "First keypoint must be at zero"

result = [0] * (key_points[-1][0] + 1)

# Assign key points
for key_pt in key_points:
x, y = key_pt
result[x] = y

# Lerp between key points
for i in range(len(key_points) - 1):
xa, ya = key_points[i]
xb, yb = key_points[i + 1]

for x in range(xa + 1, xb):
dist = (x - xa) / (xb - xa)
result[x] = ya + (yb - ya) * dist

return result

# Replace this with randomly generated points if you like
key_points = [
(0, 1.0),
(14, 7.3),
(35, 5.0),
(44, 3.3),
(71, 9.1),
(89, 2.9),
(100, 4.0),
]

heights = interpolate_list(key_points)

#### CREATE MESH ####
#####################

def create_line_of_points_mesh(name, num_points, stride):
"""
Create a mesh object with a line of points along the X axis.
"""
mesh = bpy.data.meshes.new(name)
verts = [(stride * i, 0, 0) for i in range(num_points)]
mesh.from_pydata(verts, [], [])

ob = bpy.data.objects.new(mesh.name, mesh)

# Make new object active and selected
ob.select_set(True)
bpy.context.view_layer.objects.active = ob

return ob

ob = create_line_of_points_mesh(
name="Mesh",
num_points=len(heights),
stride=1,
)

#### ADD HEIGHT ATTRIBUTE ####
##############################

attr = ob.data.attributes.new("height", 'FLOAT', 'POINT')
attr.data.foreach_set("value", heights)


### Geometry Nodes

The Geometry Node setup is simple:

And the result: