I’m trying to simulate magnets in grasshopper using kangaroo. I found that magnetic snap is not suitable for my need because it does not work in real time. For example I’ve two points and I need them to act like ‘like poles’. Using magnetic snap(with negative strength) and bouncy solver, the simulation only runs once and the points reach their equilibrium state. Now, if I move one of the points closer to the other, there is no effect of the repulsion. I have to reset the simulation to see any effect. Is it possible to simulate my requirement in kangaroo?(real time magnetic attraction/repulsion)
Here’s an example of an attraction/repulsion goal.
PLaw_example.gh (14.8 KB)
(you’ll need to set the referenced assembly location of KangarooSolver.dll when you open it - usually this will be in
C:\Program Files\Rhino 6\Plug-ins\Grasshopper\Components
if you are on 6, or
C:\Program Files\Rhino WIP\Plug-ins\Grasshopper\Components
if you are using the WIP)
You can make it negative for repulsion or positive for attraction.
The exponent controls how quickly the force falls off with distance.
Did you try the file in the first link? (PLaw_example.gh)
That is a goal that lets you set the interaction between pairs of particles.
Thanks a lot Daniel! After a few modifications the first link was really helpful.
Btw, just started using Rhino, grasshopper and kangaroo and I feel its a great piece of software, kudos for that!
Hi Daniel! I downloaded your script and found it incredibly useful for simulating magnetic forces in Rhino. However, I was hoping to modify it so that it would be able to account for individual charges being positive and negative as opposed to the bulk attraction / repulsion that the current “charge strength” parameter allows for right now.
Reading through your script, I get that I should be modifying the Strength variable, but I am not sure what is going on with the Rhino vector operations. It seems that making certain objects have a positive charge and others have a negative charge might introduce more complexity than I expect–unless there is a simpler solution.
Do you have any tips / recommendations for modifying your script to implement what I am talking about? Any help is appreciated.
Here’s a modification where like charges repel, and opposites attract. It’s quite fun to see it form crystals!
PLaw_polarities.gh (20.8 KB)
Thank you so much Daniel that was super helpful. We managed to make this work in 3D as well which is very exciting. One issue that we’ve been running into with this type of simulation work is performance related–perhaps you might have useful input on scaling up simulations optimally.
Generally, when we have multiple features turned on (i.e. gravity, collisions between objects, and magnetic attraction) performance drops drastically and some of the goals stop being carried out. We are testing how disabling goals one at a time can help. Do you think that this magnet physics is contributing to this performance issue significantly, and is there any way to make the code more efficient?
Hi @antonyawad
Glad it was helpful.
This custom attraction/repulsion goal will be the reason your simulation is slowing down so much.
It currently calculates the interaction of all points with all other points, so the number of interactions quickly gets huge as you increase the number of points.
I can think of some ways to speed it up, but it would be helpful to understand more about the application.
I think the biggest relatively easy improvement would be to have a distance above which the repulsion/attraction forces cut off.
Since they are based on negative powers of distance, the influence between far apart points becomes extremely small, and treating them as zero beyond some cut-off distance can skip lots of calculation without any noticeable change in behaviour.
Further to this, but a bit more involved, you can also do some sorting of all the points first, such as sweep-and-prune, or an RTree, which lets you quickly rule out many distant interaction pairs without actually calculating the distances (as used in some of the collision goals).
Also, if you don’t need to be able to adjust the exponent for the attraction/repulsion during runtime and it is an integer, I think using eg d*d*d
instead of Math.Pow(d,3)
can be quicker.
There’s more that could be done, such as as changing the method of parallelization, or a big one would be to implement something like Barnes-Hut, which partitions the points and lets it treat distant groups of particles as one big one. That would be a bigger project though.
Like I say though, understanding how you want to use it would help.
Here’s a version with some of the improvements mentioned above
polarity.gh (12.7 KB)
The patterns that can emerge can vary a lot from just small changes to the parameters, such as the strengths and exponents of the attraction/repulsion.
Hello! Is there a way to change the radius and asign a different value to each?
Hi @DanielPiker , is this for Rhino 8?
The file above works in Rhino 7 if the referenced dll location is changed to the one in the Rhino 7 folder.
I did create that file in 8, but there’s nothing referenced there that is unique to 8.
Hi Daniel,
I’m loving these self-assembling videos! I’m wondering if it would be possible to apply this attraction/repulsion goal to rigid bodies, to create different types of lattices? I came across this thread on using kangaroo to pack 3D prints and it got me thinking it would be fun to combine this to create magnetic toy simulations.
I tried combining collisions with your custom goal and then adding a magnetic snap within a certain range but I am getting pretty chaotic results…
I’m trying to see if I could make something that with enough time would assemble into this.
My best guess is that the collider component is creating a rounded end around my attraction/repulsion points and preventing the ends of each node to get within snapping distance of one another. In which case can you think of a way to create a cylinder collider with flat instead of round caps? I’m probably also missing something with your custom goal. Does range refer to the distance at which each point samples its neighbors and radius the distance that the points will snap into one another’s orbit?
nodePolarity_simple.gh (38.3 KB)
Anyways thanks as always for the fun example files.
Hi @augbot
Nice idea.
The closest thing I remember doing was this:
I need to go back to some old drives to find it, but as I recall it was using rigid bodies and an early version of the Concentric and AlignFaces goals.
It looks like it also had a setting to only activate these goals when the relevant points come within a certain proximity, which didn’t make it into the released component.
So we might want a slightly customised goal to bring back this proximity setting, and also perhaps a polarity setting, so that like charges repel.
An alternative and maybe easier way to approach this could be a triangle of 3 points on the end of each arm, using the goal from the polarity example above. This also has the effect of constraining also the rotation about the axis, while the first approach lets them swivel.
Here’s a first go at this:
snaptoy.gh (36.4 KB)
That requires separate components for each unit though - to make it more usable with many, it would need changing to reference them as groups, or to create them parametrically from the start.
Here’s a better version that lets you create many units without having separate components for each. I also noticed one set of magnets needed rotating 60° from my first def if you want them to assemble into a diamond lattice like in your second video.
snaptoy2.gh (28.6 KB)
It could probably still use some collision to stop them joining the wrong way (I think even just a single sphere at the center of each unit could work)
Also, I’m not sure how you’d prevent the situation where 2 triangles snap together along an edge with the other point on the wrong side, like 0:08 to 0:11 in the video (either in the simulation or in real life).
This is nice.
It would be cool if an object or a group of objects could be locked temporarily.
Hi Daniel,
Thanks for the reply. Yes I think the triangular endpoints is the simpler approach to achieve the diamond lattice, however it locks them into a single outcome. I think most of the magic (like your crystallization videos) comes from when there is a little bit of play in the system (swivel, or slight bend), which can lead to unexpected results. Like if you put them in a virtual container and shook them could a dodeca pop out? (i know that the angles would have to distort slightly)
It seems to get something like this I should probably look closer at the align faces goal and maybe work in wireframes over mesh collisions for the moment. Do you have any example files for the align faces from the first video you shared?
Yeah, I think this could be really useful for a bunch of things. Like if you want to simulate something where you are adding particles or forces as you go but you only need to consider some of the more “active” particles for the next step in the solver…