Vector Field with Progressive Random Noise – Example 6.5
Example 6.5 looked at adding random values to rotate the vectors within a range. This script takes the idea of adding random rotation (or noise) to a higher level, and will be important for a future script looking at agent based fields. While the results of the script in and of themselves may not be the most impressive, one we apply agents it will give some quite nice results…but that is for later!
The basic idea here will be that the rotation of each vector will be progressive through the field. Let me set up a very simple field of four values, a linear series of vectors: vA – vB – vC – vD. For this example, my “noise” value, or random rotation value, is +/-10° Lets say vA has an angle of 0°. The next vector after this can rotate up to 10° from his neighbors, so the angle of vB could be anywhere from -10° to +10°. The next vector, vC, can also be rotated up to 10° from his neighbors, so if vA was rotated 10°, vC could be anywhere from 0° to 20°. The theoretical range of vC is actually -20° to +20°, and the theoretical range of vD is -30° to 30°. Got it? I thought so. Well, it should start to make sense (hopefully!) once we start trying it out in grasshopper!
This exercise will look a lot at data structures (again!) We will be creating our own structure, flipping it, and later matching one structure to another. Fun! So hopefully you have a fairly good grasp of this concept. If not, please at least read Exercise 1.1 again!
Step One – Setup Grid of Points
Here I am using a square curve drawn in Rhino, referenced into Grasshopper to set up my boundaries. I use a typical pattern of “Divide Domain2” with “Isotrim” to find the centers. You will notice once I get the centers from this method using the “Area” component, the points are all in one list. I actually need these to be in columns and rows, similar to the data structure I would get from a grid. I can give these points a structure using the “Partition List” component. I feed the points in, and I say how many branches I want by using the “V” value from my “Divide Domain2” process. Now my data is nicely structured to allow me to work with the rows and columns.
Notice I also want to extract four values from Step One to use in upcoming steps. The maximum cell dimension (which I get using the “Dimensions” component along with the “Maximum” component, as well as a “List Item”), my Start Points, which I just structured, as well as the Number of Rows and the number of columns. I put these into purple containers, which are labeled in the image.
Step Two – Set an Initial Vector
I want to be able to change the overall average starting vector of my fields. This is not completely necessary but gives an added level of control over the output. Regardless, i need to set up my starting vectors, which I do by “Moving” my points in the X Axis an amount equal to a percentage of the “Maximum Cell Size” determined in the previous step. This is so If I change the U and the V at the beginning, my geometry will scale along with it. I then use “Rotate vector” to get my starting condition.
Step Three – First Vector Rotation – Rows
This step and the next one are the core logic of this script, so pay attention! In the introduction, I explained we wanted each vector to rotate +/- our noise value in regards to its neighbor. Since we are working in 2 dimensions, we will need to do this twice. One for the rows (the first dimension), and again for the columns (the second dimension). This is also why it was essential to give our data a structure in the first step, so we could work with these rows and columns.
In this example, the amount of possible rotation in each step is +/- 18° from the neighboring row. I generated a list of random numbers, based on the “Number of Rows” in my script (using list length). You can see these values spit out by the generator. To make these rotations progressive, however, we are going to use a “Mass Addition” component. Mass addition is typically used to sum a big series of numbers, and its first output will give you exactly this value. But the second output is equally handy…this gives you the “partial” result after each step. I have attached a panel to both the “Random” number generator, as well as the “Mass Addition” component to clearly show what is going on. The first number is -1.45. This is the rotation which will be applied to Every Item 0 – the first row of items. The next random number is 16.39. But we don’t want to rotate the second row of items this amount. We use the partial result from mass addition which gives us (16.39 + -1.45 = 14.93)… and so on. and so forth. The image shows the amount each vector is rotated in relation to a dashed grey line, indicating its original position. You will notice in this particular series, the final vector is rotated -37.24 from the initial vector. Theoretically, this vector with a +/- 18° rotation at each step could have a total range of +/-180° assuming 10 rows. 20 rows would give a potential range of +/- 360°, although in both cases, laws of probability make this extremely improbable.
Step Four – Second Vector Rotation – Columns
The logic to this step is nearly identical to the first step. We now want to do the same thing, but this time to the second dimension, the columns. Before I can do this though, I need to “Flip” my data structure which reorganizes the logic of the lists. I do the exact same procedure. I will need to make sure my list length is using the variable for “columns” instead of rows. In this case, they are the same, but later you may want these to be different.
Notice this time field is a bit more fluid, since we had already rotated everything once, but if you look carefully, you will notice that the amount of vector rotation in each column is equal. I put the results of the last step as grey dashed lines for reference. The cumulative affect of the two rotations, however, means each vector will have a unique rotation, which is no more than his immediate neighbor either up and down, or left and right, in the matrix. Actually, it could be slightly more, if the vector was rotated -18° in both steps it would now have an angle of -36°. So the actual theoretical range for a value of 18 is actually twice that, but lets not get stuck on details 😉
One last thing, notice you need to “Flip” the matrix back after this step otherwise you will run into problems. For example, if you tried to use the “Display Vectors” component using the flipped vector matrix, along with the original Center Point matrix, your results will not be correct (unless you flip the center point matrix as well).
Step Five – Create Rectangles
I am now going to use my vectors to create rectangles using the SDL line component. This should be a pretty straightforward step by now.
Step Six- Assign color to rectangles
We’ve used the gradient tool quite a bit. Usually to assign a color based on an area, etc. Here I want the color to be based on the amount of rotation from the initial value. I can measure this using the “Angle” component to measure the angle between the list of initial vectors, and the list of Final vectors. (I could also add the results of the two phases together). The angle, converted to degrees, will serve as the “t” value for the gradient tool, with the L0 and L1 being 0 to 180 (all of my angle measurements will be positive and between 0 and 180°). I could alternately set L1 as the “Maximum” value from the angle measurements, but I am keeping it like this so you can see the effects of increasing rotation better across multiple examples later.
Two other things to note. Before I can apply the color to my rectangles, I need to make sure the data structure of my angle measurements matches the structure of my rectangles (they currently don’t…the rectangles are in a “grafted” list after their creation). First I flatten the list of rectangles, and then I use the “Unflatten” component. This asks you to provide a model according to which you will structure the data. I use the structure of my vectors (either one will do) to serve as the model.
Once everything is working, you can increase the field density in Step one. These variations are all with a 20×20 starting grid. Notice with more columns and rows the total amount of theoretical rotation also increases. That’s about it! We will come back to this when we start looking at agents and the results will be a little more interesting!