Adding Points to Ripple

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.

ripples_2019Jun04b2.gh (36.6 KB) (revised)


2 Likes

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.

Thanks

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.

ripples_2019Jun04c.gh (41.0 KB)


Higher resolution is better when the Graph Mapper is adjusted for higher frequency ripples.

ripples_2019Jun04d.gh (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.
3DMurals.gh (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:
https://www.grasshopper3d.com/forum/topics/damped-sine-wave-formula

First to get this simple demo: damped_sine_crv_2019Jun05a.gh (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:

ripples_2019Jun05a

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)
ripples_2019Jun05b1
ripples_2019Jun05b1a

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.

ripples_2019Jun05c.gh (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.

ripples_2019Jun06a.gh (46.6 KB)
ripples_2019Jun06b.gh (47.4 KB) (ptsPerUnit = 7)



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?

ripples_2019Jun07a.gh (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.

ripples_2019Jun07b.gh (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 !!!"):

2 Likes

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:

ripples_2019Jun08b.gh (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:

3 Likes

“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”.

ripples_2019Jun08d.gh (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.

5 Likes

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!

Cool, glad you are enjoying this and following along. More changes…
ripples_2019Jun010a.gh (74.6 KB)

“radial rectangles” has been replaced by the more general “rectangles on curve”, a circle being just one possible curve. So there are now four ways to define the list of rectangles used by the model, one of them with three example curves, all moved “above the fold” since the model doesn’t care how the rectangles are created.


Added displays for “grid points”, “Expression kOps” and a “fuse” feature in the "“Ripple Points” group, ‘Max_kOps’ (red slider), to throttle the maximum number of slow Expression evaluations.

As explained in the model:

=== NOTES ===
The “fuse” feature in the ““Ripple Points” group, ‘Max_kOps’ (red slider),
works best when the slow grid points ‘Expression’ and ‘Dist’ components
(red group) are disabled (”!!! SLOW AT HI-RES !!!").

The displays for “grid points” and “Expression kOps”, the “Caliper” and
“Ripple Preview” features still work at high resolution.

(optional) Reduce delay in Data Dam preceding it from 10 secs. to “Always”.

Also note that a Repeat data component has been inserted in the lime green group. This is done so that if there are more ripple points than wave forms defined, the whole set will be reused instead of repeating the last waveform. Note that the ‘Scale’ group now has a “Steps” slider instead of using the number of ripple points, as before.

The composite rippled surface is finished at SrfGrid in the gold group. The green “base” group adds sides and a bottom to make a “Closed Brep” solid from each rectangular surface (the green Join to be baked).

Exaggerated amplitude can be useful for Caliper tool with red ”!!! SLOW AT HI-RES !!!" group disabled:


12 ripple points, 6 wave forms, 21 rectangles (3" X 16"), 11 ‘ptsPerUnit’ resolution, 126,378 grid points, 1,517 “Expression kOps” (1,517,000 Expression ops!), ~2 minutes:

1 Like

This (above) was the primary point of yesterday’s update to the GH model, and today’s as well.

To review briefly, the primary inputs for this ripple model are:

  1. a list of rectangles
  2. a list of “ripple points”
  3. a list of “wave forms” consisting of three parameters: Wavelength, Amplitude and Damping

Until yesterday, if you used the “Scale” option, the number of wave forms was guaranteed to be the same as the number of ripple points, evenly distributed by Range components. Now the “Steps” slider determines how many wave forms will emerge from the “Scale” group. It was always possible (and still is) using the “Config” group to define fewer wave forms than there are ripple points. Now it can be done with “Scale” as well.

Repeat Data (yesterday) is one way to handle that. Another way is to specify which of the available wave forms you want to apply.for each point. The updated lime green group in today’s code does that, with options to:

  • use either “Series” (like Repeat Data) or “List” (defined in a ‘idx_Wave’ text Panel in this example).
  • add random Jitter to the lists of wave form values.

This is like defining a list of stone sizes (wave forms) available to drop into the pond, creating as many ripple points as you like with them, anywhere you want, provided you have adequate CPU power for your required resolution.

ripples_2019Jun011a.gh (77.4 KB)

P.S. I have not yet tried to explore what happens if you define more wave forms than ripple points…?

1 Like

Impressive advancements from the original code!

I had a hard time with the Data Dam being set to always I did try that along with keeping the resolution <5 that was probably a bad idea so I switched back to 10 seconds.

You beat me to it with the idea of having more wave forms emerge from scale while keeping the ripple points at 5.

Radial exploration isn’t something I wouldn’t be using at the moment maybe in the future but its super fun to play with and explore new forms. I’m going to start experimenting with having more waves than ripple points that sounds very interesting. Thanks for all the knowledge Joseph.

Both components in the red group (!!! SLOW AT HI-RES !!!) should be disabled when reducing the Data Dam delay.

Just the opposite. It makes sense to have more “ripple points” (X/Y coordinates) than wave forms (pebble sizes). So you effectively re-use the pebble sizes. Having more wave forms defined than physical points doesn’t make sense* so I didn’t test/fix the code to handle that.

Have fun. Creating the tool is only part of the art project. Please post your results here. Cheers.

P.S. OK, sorry, I see how that* could make sense! :wink: When using the ‘List’ option, you can avoid using all of the wave forms defined. I think of it more the other way, that I can have many points defined using only a handful of wave forms (pebble sizes).

I spent a few minutes exploring this condition and found that the only way to create a problem is using the ‘List’ option instead of ‘Series’:

ripples_2019Jun14a2

Using only three “Ripple Points”, the ‘Series’ option guarantees that the number of wave forms will equal the number of points, but using ‘List’, twelve wave forms get generated, ten of them combined on the last point of three. This is bad! Ugly, unwanted, subtle if you don’t understand it. Warning, don’t do that! I could have fixed the code to prevent it from happening but didn’t.

Clean (below, easy to avoid… would be better if code protected against this condition)

ripples_2019Jun14a3

Later… A fix was simple, I talked myself into it. Adding List Item after ‘idx_Wave’ Panel driven by the existing Series component does it. It also appears to gracefully handle the condition when ‘List’ contains fewer wave form indexes than “Ripple Points”.
Re-wired the end of the “base” group to get around a tree mis-match problem that, in some cases, prevented “Closed Brep” results.

ripples_2019Jun014a.gh (78.9 KB)

Notice that when multiple rectangles are used, the “base” of each one is no thicker than its deepest wave trough, plus the ‘Base Thickness’ slider. So they may all be different… Might want to change that? Or take advantage of the fact that you only need a thick base in areas with deep craters.

Jospeh,

I did use list item and that’s how I started to learn grasshopper is through list rather than the geometry that affects that list such as pebble sizes as many other points, but didn’t have much success in a geometry that I liked I agree it is Ugly and not realistic for what I am doing it could become useful in later projects. I should’ve thought about the existing series component when testing this rather than recreating it.

I think it is best to consider a thick base for areas with deep craters.

Here is the form that I have found best for my project. Had to keep the height less than 15/16" while creating wave forms that you could actuality see if fabricated that decay. I also tried to keep amplitudes low so I don’t get a volcano like crater. Here are my results!topview_from5

topview_form5