droplets.gh (15.3 KB)

Here a small “simulator” using points as droplets.

Droplet fall speed is equal to wave propagation speed, so when a droplet is below Z=0 it is projected to XY plane and its Z value used as radius of the wave.

Waves keeps a constant volume (conservation of energy… ? maybe not…)

Used a c# script for most of the work, used Parallel.For for increased speed using multithreading.

Managing big lists of values is slow on grasshopper, doing everything inside a c# script let the simulation works realtime even with big meshes and high droplets count.

Added comments inside the c# script so anyone could reverse engineer it and maybe learn how to do stuff…

Cya boyz!

code:

```
using System.Threading;
using System.Threading.Tasks;
private void RunScript(Mesh M, List<Point3d> P, double Wp, double Wh, ref object A)
{
double pi = Math.PI;
// Finding droplets that are below Z=0 and putting them into a new list. Projecting them into XY plane.
// Saving the Z values into a separate list. Point depth is used as time factor (the further down, the earlier the droplet did hit the water surface).
List<Rhino.Geometry.Point3f> pts = new List<Rhino.Geometry.Point3f>();
List<double> t = new List<double>();
foreach(Rhino.Geometry.Point3d p in P){
if(p.Z < 0){
pts.Add(new Rhino.Geometry.Point3f((float) p.X, (float) p.Y, 0));
t.Add(-p.Z);
}
}
// The next 2 lines do the same thing: iterate through M.Vertices list.
Parallel.For(0, M.Vertices.Count, i => { // This is the parallel, multithreaded method. Faster.
// for(int i = 0;i < M.Vertices.Count;i++){ // This is the normal for loop method. Slower.
// Current vertex is M.Vertices[i] .
// This value will become later the Z movement of current vertex.
double m = 0;
// Now iterating to each Z<0 droplets; finding distance to current vertex and applying function to increment m.
for(int j = 0;j < pts.Count;j++){
double d = M.Vertices[i].DistanceTo(pts[j]); // distance
// Wave speed is same as droplet, so wave radius is equal to droplet value below Z=0;
if(!(d < t[j] - Wp / 2 || d > (t[j] + Wp / 2))){ // Applying function only to areas around the wave radius +/- half Wave pitch (Wp).
m += Wh * (1 - Math.Cos(pi + pi * (d - t[j]) / (0.5 * Wp))) / (d + 1);
}
}
// Moving vertex.
M.Vertices[i] = M.Vertices[i] + new Rhino.Geometry.Vector3f(0, 0, (float) m);
}); // End of parallel method.
// } // End of for loop method.
M.RebuildNormals();
A = M;
}
```