Discrete Laplacian

Hi Daniel. Can you post the files for this? Thanks!

Hi David,

I posted the definition from above, and further explorations, in this thread:

Thanks for all this work, Daniel. The Heat Method definitions from the above page are incredibly useful in so many different ways.

I was also really impressed by the ‘Contour’ part that turns UV texture coordinates into Line geometry.

I wanted to follow this up here as I was trying to search for an implementation of the Stripe Patterns paper shared above. It creates really beautiful detail and Crane’s implementation is completely independent from the mesh resolution, which allows one to create very large pattern detail without compromising the shape. The actual pattern is encoded in texture coordinates again.

From running the executable from the website I generated this mesh and used your contouring routine to see if I could generate the line pattern from the texture coordinates and it almost works.

20200804 Stripe Pattern Bunny Contours.gh (472.6 KB)

Here is the texture file

Hi Mathias,
Yes - the stripe patterns paper is nice too.
It’s been a while since I read it properly, and I just skimmed through it again now, but I believe the reason simple contouring doesn’t work is that it isn’t a single consistent scalar field, but rather a double-cover.

For each pair of adjacent triangles, the directions of the field given by their texture coordinates are either parallel or anti-parallel. If you use a texture which isn’t the same when you rotate it half a turn (like the one you use is), this is shown clearly - the direction of colour change aligns, but flips between positive and negative arbitrarily across edges:

The contouring would have to be adapted to take account of this - the paper does go into this, but I’d need to read it more thoroughly.
I think it’s something fairly simple though - even just taking contours at 0 and 1 seems to get a lot closer:


StripePatternContours.gh (462.9 KB)
The triangles containing singular points of the field also need a special treatment.

(note there’s no need for all that extraction and reassigning of values to texture coordinates you had in that definition - my contouring script is already using the texture coordinates as the scalar values, just that I’d been assigning them in the Y component, while that file had them stored in the X, so I just switched it)

I’m actually also working on some new stuff with my own code making use of branched double covers. Will update more on that soon.

2 Likes

Stunning!

These iso values are even more complete and almost make the junctions work…

1 Like

Ah, it seems the values just need to be in steps of 1/n and symmetric about zero
StripePatternContours2.gh (467.9 KB)

3 Likes

I am new to programming in C#, Is there a way to have dynamic assembly access to Plankton.dll and Plankton.gha for these these scripts?

I have used the os.abspath.join… filepath, etc in Python scripts to have dynamic file access for different users, but I’m unsure how to do this in C#.

Any Guidance is appreciated.

Hi @Hamilton_Forsythe

To use libraries in the C# script component there are 2 steps-

Right-click the component and choose ‘Manage Assemblies’, then add the chosen dll/gha files.

In the script component, add a ‘using’ statement in the top section below the default ones like

using Grasshopper.Kernel;
using Grasshopper.Kernel.Data;
using Grasshopper.Kernel.Types;

using PlanktonGh.dll;

Hi @DanielPiker ,

thanks for the speedy reply. Ive been messing around with the cotan weighting script for a different application and was not able to get it working with trees (multiple meshes each with unique values and fix point boolean lists)

the error i am getting is:

  1. One or more errors occurred. (Index was out of range. Must be non-negative and less than the size of the collection.
    Parameter name: index) (Index was out of range. Must be non-negative and less than the size of the collection.
    Parameter name: index) (Index was out of range. Must be non-negative and less than the size of the collection.
    Parameter name: index) (Index was out of range. Must be non-negative and less than the size of the collection.
    Parameter name: index) (line: 0)

More interestingly, with two branches in my tree. I am getting proper outputs for my second branch but “null” in my first branch.

I have uploaded this example file:
COTAN_trees.gh (329.4 KB)

Hi @Hamilton_Forsythe

In the C# component, if variables are declared outside the RunScript method, under the line that says //<Custom additional code> then they persist between Grasshopper solver updates. This is what allows this smoothing script I wrote to run iteratively and show the iterations.

However, when you have a script component with an input with an input of type list, and you give it a tree (or of type item and you give it a list), then Grasshopper will run the RunScript method for each branch of that tree, or for each item of that list.
This won’t work if the script is written expecting to operate on the values from the previous smoothing iteration, because instead of the previous iteration data for that mesh, it will be getting the data from the previously processed branch, which here is a different mesh with a different vertex count and topology, so it won’t work.

So you have a few options-

If you just have 2 meshes you want to process independently, then the simplest way would be to just to copy paste the script component on the canvas, and not worry about paths at all. Of course this isn’t practical if you want to do this for 1000 meshes simultaneously.

Another easy option would be to join the meshes. Note that a mesh can be disjoint - it can have multiple parts which do not share any vertices and are not connected to each other by edges, but still be treated as a single mesh (this is true for both Rhino and Plankton meshes).

If you don’t need to see intermediate iterations, you could move everything inside the RunScript method, so it processes each mesh in full for some number of iterations and outputs the final result. Then it will work with tree input without trouble.

Finally, you could set the input types to Tree, and deal with the trees inside the script. So you’d need to declare and update one mesh and set of values for each branch. This is usually a bit of a hassle, and I’d recommend avoiding this if you can!

Hi @DanielPiker
I’m playing with some script about diffuse reaction on a non-uniform mesh, thus where the cotan weighting comes to help.


I see circular shapes in both halves of the mesh (even though the triangulated quads are 1:2 ratio on left and 2:1 on right)… so I guess I decently replicated the cotan method you explained… maybe :sweat_smile:

But the sizes are different!
“Chemicals” are flowing uniformly direction-wise, but faster where the triangle size is bigger…

In your video at post 4 the black circle grow the same size on both sides… I could replicate that visually if I made the smoothing of values really slow, but not if it is fast.
But, even a slow diffuse reaction will show different sizes…

Do you think this is expected or not?