Adding Points to Ripple

Hello Forum,

I am trying to add additional points/ripples to this definition that was created a while back by @Joseph_Oster I am assuming that the points dictate the center of the drop.
Link to his version:

My version is similar to his I only tried to copy the points meaning the MD sliders and MDp clusters, but why doesn’t this create additional ripples? I have posted the edited definition below in hopes that someone can help me out.

Multiple Points (28.7 KB)

I haven’t touched Grasshopper in a long time… Did you find that code in this thread?

It wasn’t designed well for additional points, due to the individual damping factor for each point. Fixed in attached version (R5), yellow group: (35.5 KB)


Thanks Joseph I really appreciate the quick response.

To answer your question yes the definition was downloaded from your post on that thread.

I am going to spend time understanding your logic within the new file posted above. Thanks again for your time.

there are also some approaches described here that might be of interest.

1 Like

I will give this a look thanks!

More like a scale factor than damping factor, actually. The idea was for the points to represent different sized stones and pebbles, so to speak.

In addition to the X/Y position for each point, the scale needs to be set for each one too. It could have been written differently, I can see several flaws and ways to improve it. Found and fixed an error just now regarding the ‘U’ input to ‘SrfGrid’.

This version (attached) uses ‘Random’ for location of points and their scale factors: (43.5 KB)

The previously used manual inputs for X, Y and Scale are disconnected and left in the GH file since, for the artist, they can give more specific results.


Joseph I see what your saying, however I like having both controls of the ripples such that I can place it where I would like using the X/Y position. I also like having them decay as they go outward. Due to the scale of my model being 4’x4’ I would like to have them decay much faster rather than having a large surface for this effect to take place.

Great second solution though I will need something like this in the future where the points are random and not controlled. It’s like you read my mind :joy:

Yeah, manual control is better for artistic effect. Would be better yet for each point to have a different frequency as well as “scale” (initial amplitude). You can play with the Graph Mapper controls to shape the damped sine curve but flexibility is limited, it’s not parametric and as written, applies to all points equally. Much room for improvement on this, probably been done many times, but it’s fun. (36.6 KB) (revised)


WOW Joseph once again I really appreciate the quick response and time taken to solve this.

I’m going to take some time to look at the last .gh file posted to really understand whats going on thanks for the solution. I will also look into the amplitude for each point and see where that gets me.


This one demonstrates two things:

  1. resolution can be increased from 100 X 100 “pixels” (10,000 points) shaping the rippled surface, to considerably more without a severe performance hit. The two slider inputs to ‘MPlane’ (white group) can now go to 300 X 300 for a smoother surface.

  2. The manual inputs for X/Y and “Scale” are reorganized so that any of the six sets of controls can be disabled, removing those points from the model. “pt 3” and “pt 5” are shown disabled, leaving four points creating ripples. (41.0 KB)

Higher resolution is better when the Graph Mapper is adjusted for higher frequency ripples. (38.8 KB)

I like the solution there’s way more control over the points, but I agree with you that having the ripples decay quickly can’t be parametrically done. I have tried playing with these files I think my next step is to take this into another script to control the decay better with the use of an image sampler.

Option: Make a rendering of the ripples (top view) then take that image into Photoshop edit out what I don’t want and then plug it into this definition (posted below). The end goal is to try and come up with something similar to the picture attached. I would delete everything outside of the yellow area then plug that image into this definition. I will post my results later once I come up with a solution unless you have a better idea. (369.7 KB)

I’ve played with Image Sampler to get a boat wake surface, with good success, though can’t find it on the forum at the moment.

I said it couldn’t be done using Graph Mapper. It can be done. I modified code from @DavidRutten found here:

First to get this simple demo: (5.5 KB)

Then adapted it to code posted here, with other changes including:

  • Scale appropriate for unit inches.
  • Fixed the way the bottom of the “Closed Brep” solid is created below the rippled surface to handle an extreme case like this:


At first, I wired it with three separate controls for each point (besides location):

  • Wavelength
  • Amplitude
  • Damping

(The yellow group is disconnected and does nothing, explained below)

But it gets tiresome exploring parameter settings when it takes so long to respond with a new surface (quicker at low resolution!), so I wrote the yellow “Scale” group to define ranges for each of the three parameters, split evenly among the points (0…N) using the Range component. Used instead of the sliders for each point, not ideal as these may not be linear relationships, but it’s fewer adjustments to explore the scale of things. (44.1 KB) (revised)
(manual config of each point’s wave params disabled)

1 Like

I miss understood the statement about the graph mapper I knew it controlled the intensity depending on how you set it but didn’t know it had a correlation to the decay of the ripples I knew a set scale had to be configured but didn’t know the correct way. This is exactly what I was looking for. I also agree with you manipulating the yellow group in your first iteration was not quick enough to see the result.

I like the final iteration a lot THANKS Joseph!

“Final iteration”? Software is never final. :slight_smile:

Today’s changes don’t touch the basic algorithm but offer some usability improvements.

First, in the white group you can define a rectangle, not just a square. Also, resolution is specified as ‘ptsPerUnit’ (Points Per Unit, or per inch in this case) and applied to both X and Y dimensions. As noted in the code:

NOTE: For maximum performance, use lowest possible
resolution (1) while experimenting, then raise it for final.

This is worth explaining. Using the example of a 48 inch/unit square, at the lowest resolution of “ptsPerUnit = 1”, there will be 2,401 grid points defining the surface (49 X 49). For each grid point, the distance and damped sine function must be computed for each of the six ripple points. In this case, that’s 2,401 X 6 = 14,406 times through the Expression component, less than a second.

If you use short wavelengths (less than ~2 inches/units in this case), low amplitude ripples will be invisible without going to higher resolution. At least 4 and ideally 7 or 8 ‘ptsPerUnit’. When ‘ptsPerUnit = 7’, the number of grid points jumps from 2,401 to 113,569! Multiply by six ripple points and that’s 681,414 times through the Expression component! 48.2 secs. on an old laptop.

In the process of experimenting, I defined a rectangle smaller than the points and it still worked fine, as expected. No reason to confine ripple points to the “canvas” so I dropped the MD Sliders (XY widgets) and replaced them with X and Y sliders.

Rearranged slightly so the ‘Points’ can be supplied either manually (top left orange group) or from other means, such as the two examples of internalized points, ‘Pts_internal’ and ‘Pts_Rhino’. One of the best ways I found for locating ripple points is baking them in Rhino, importing them to GH, then selecting and moving them in Rhino. (remember to internalize them!)

Added a “switch” (see red arrow) between yellow “Scale” group and cyan “Config” group. And a pair of ten second Data Dam components to delay the heavy crunch after changing parameters. (46.6 KB) (47.4 KB) (ptsPerUnit = 7)

1 Like

Experimenting further, I cautiously stepped up the ptsPerUnit resolution to 16 (1/16th inches in this 48 X 48 inch example). Compute time wasn’t bad at all, considering:

  • 591,361 grid points.
  • Multiplied by 6 "ripple points = 3,548,166 times through the Expression component.
  • Elapsed Time: 4.4 mins. on Expression, 11.3 sec. on Dist.

This is surprisingly reasonable, considering how useful high resolution is for precision at this scale. The ripples in the first example I posted yesterday are so subtle they are almost like embossing. Less than 1/4" deep at most (0.2 inches deep at centers).

Just for fun and visualization, I added a “Caliper” group to the bottom of the code that creates a high precision curve for each of the six ripple point wave forms and tracks them where they intersect at an XY point defined with an MD Slider. As you move the point around, the value for that point is displayed in blue for positive, red for negative, along with a colored arrow (vector) pointing up or down. Goofy but interesting? (49.3 KB)

1 Like

Added a “Ripple Preview” feature that, one point at a time, shows a high resolution (20 ‘ptsPerUnit’) revolved surface with ripples that respond quickly to ‘Config’ changes (Wavelength, Amplitude and Damping). It is disabled by default and works best by disabling the slow Expression component that handles grid points. (55.6 KB)

Both the “Caliper” and “Ripple Preview” features can work at high resolution with the slow grid points Expression component disabled ("!!! SLOW AT HI-RES !!!"):


I’m going to need some time to really learn this wow I’m still on the previous definition :sweat_smile:

I’ll reply with a better response once I get a better understanding of these two.

The core algorithm hasn’t changed since I introduced the damped sine (actually cosine) Expression component, just making it better. :wink:

Wouldn’t it be nice if it worked with multiple rectangles? Took a few little tweaks to get the code in proper Grasshopper fashion, but it does now. Dimensions are obtained from the rectangles, which may be supplied by any means and need not touch each other. To demonstrate, there is a white “two rectangles” group that creates two side by side: (61.2 KB)

Or you can use the internalized “3 rectangles”, imported from Rhino:

Baked and rendered as reflective copper material in Neon, R5:

Rhino file raytraced in R6:


“radial rectangles” - Again, no change to the core algorithm, just a different way of generating rectangles arrayed in a circle, to use as input for the rippled surface/solid “machine”. (62.2 KB)

Same code, different list of rectangles (below) from “radial rectangles” group. These are ~3" X 16" along an arc of radius 36", using the same ripple points and wave forms as before.

Since this model relies on the SrfGrid component, it can only produce rectangular surfaces.


I should’ve been more clear I aim to try and add text for what is happening within the script so I can better understand someones logic and thinking, rather than just playing with sliders.

I understand the script pretty well now and the only part that confuses me is the slow expression Exp(-xd)aCos(2π*x/w) I get what its doing just wish I could apply the math to the logic. Other than that I am able to follow your thinking. I know its exploding the data from the scale group then inputting it into the base group.

As far as ditching the graph mappers that was a really good idea I like having the X,Y sliders better. The resolution group is extremely successful I started at 4 and slowly bumped it up to 5 or 6 and got some really good results I also like how you can now scale the model which corresponds to the base group. It was smart to include the data dam for when there are drastic changes while leaving the resolution at 5 and often times it would still work for me (I would forget to bring this back down to 1 :sweat_smile:)

I agree with the version with the ‘caliper’ group it helps me track the heights for fabrication I would say its more interesting than goofy.

Now I am getting my toes wet with radial rectangles I really enjoy the control and endless possibilities with this idea definitely will be playing around with this one for awhile :scream:

Thank you so much for explaining what you were executing this really helped me learn an abundance more within grasshopper and be able to follow your definition a lot better!