wiki.ksteinfe.net
Personal tools
 

Rhinoscript:two dimensional arrays

From ksteinfeWiki

Contents

Overview

In concept and practice, Two-dimensional arrays work much the same as one-dimensional arrays. They're both collections of variables. They both have fixed carrying capacities which must be defined in advance, and they both must be handled carefully so that one doesn't exceed this carrying capacity, or accidentally end up with empty values. The main difference, of course, is that where one-dimensional arrays are something like a list of variables stretching off in one dimension, two-dimensional arrays are something like a table of variables extending out in two-dimensions.

There are two types of two-dimensional arrays in rhinoscript: the 'rectangular' type, and the 'jagged' type. Both have their uses, but for the beginning scripter, I would recommend sticking with the 'jagged' type, as it's the more general case.

Rectangular vs Jagged Arrays

Shown below are diagrams representing two different ways to store a table of values. A rectangular array on the left, and a jagged array on the right. Both store grids of numbers, but in slightly different ways.

2239304207_2d930c61bf_o.png

The first, on the left, is pretty much a grid, something like an excel sheet. We can address each "cell" by saying which row we want, then which column we want, and then pull out the corresponding number. For example, if we wanted the number 6.6, we would find it in row 1, column 3.

The second, on the right, is less of a grid and more of a bunch of nested arrays, something like a list of lists. We can address each value we might want in a similar way: first saying which list we want to choose from, then which item in that list we want. For example, if we wanted the number 6.6, we would find it in list 1, item 3.

So, saying "row 1, column 3" and "list 1, item 3" is pretty much the same thing - both require 2 variables to locate a single piece of information. The critical difference here is that while the rectangular array must always have the same number of columns in each row (maintaining its rectangleness), the jagged array may have different amounts of items in each list (giving it a jagged-looking edge).

2d Rectangular Arrays

TODO: describe

2232931527_955168b801_o.png


Declaration, Assignment, and Retrieval

TODO

2d Rectangular Array Declaration

TODO

2d Rectangular Array Assignment

TODO

2d Rectangular Array Retrieval

TODO

UBound in 2d Rectangular Arrays

TODO

Resizing 2d Rectangular Arrays

TODO

2d Jagged Arrays

Jagged arrays, as opposed to rectangular arrays, are best thought of as lists of lists, or arrays of arrays rather than grids. Each item in the top-most array, is itself an array and must be declared and addressed as such.

Imagine creating an array, as we did in the one-dimensional array page, and rather than populating it with numbers, populating it with other arrays. We might end up with something like this:

2232929325_69e0cedf3b_o.png

Declaration, Assignment, and Retrieval

2d Jagged Array Declaration

Declaring 2d Jagged arrays is a bit tricky, and is necessarily mixed in with the business of assigning values. The reason for this stems from the very nature of the jagged array - its jaggedness. Because each top-level item in a jagged array is an array itself, each must be declared and assigned to individually. So, while we can declare the top-level dimension of our jagged array (how many arrays will be in our array), there's no way to declare the size of each sub-array all at once.

Understanding this, we may declare a 2d jagged array, and define how many top-level items are in it with the code below.

ReDim arrjagNumbers(3)

You might notice that this is exactly the same syntax as declaring a 1d array - this is because 2d jagged arrays are simply 1d arrays filled up with other 1d arrays. You can see this in resulting diagram below (I'll draw it a bit differently in anticipation of filling it up as a 2d array).

2239530121_a8bddd0b16_o.png

So, now we have an array with four slots for more arrays to go into, but none are there just yet. We can't go any further than this, and cannot define the size of each sub-array, until we get down to the business of assigning values.

2d Jagged Array Assignment

Once you've declared a 2d jagged array, and defined how many slots are available at the top-level (how many lists of lists you're working with), you can get to work assigning values. This would almost always involve a loop of some kind, but we'll go through it manually this first time around.

For each of the four rows above, we need to declare a 1d array, populate it with values, and then assign it to the proper row in our 2d array. This could be quite a few steps to go through for each row, but luckily we've got a quick syntax at our disposal for declaring and populating 1d arrays.

Using this syntax, filling up one row of our 2d array is fairly painless:

arrjagNumbers(0) = array( 5.0 , 5.1 , 5.2 , 5.4 , 5.6 )

2240322262_3000fb374f_o.png

Which results in a 2d array, with one row filled up. Now, if we were working with a loop, this could have gone quicker... but since we're not, we've got to assign each subsequent row one-at-a-time.

arrjagNumbers(1) = array( 6.0 , 6.1 , 6.2 , 6.4 , 6.6 , 6.8 )
arrjagNumbers(2) = array( 7.0 , 7.1 , 7.2 , 7.4 , 7.6 , 7.8 )
arrjagNumbers(3) = array( 8.0 , 8.1 , 8.2 , 8.4 )

2240317136_f7348a8a16_o.png


Heteromorphism

As an aside, you should be aware that rhinoscript will be perfectly happy to let you do the wrong thing - which may lead to results that you don't like. Just like 1d arrays, 2d arrays need not be made up of all the same type of objects. You might, for example, fill up your 2d jagged array with both 1d arrays, and the occasional single value or two. While the language complier itself will be perfectly fine with this, it's not a recommended practice, as it's very easy to get confused about what to expect as you retrieve information from your arrays.

For example, we might have populated our array above like this:

ReDim arrjagNumbers(3)
arrjagNumbers(0) = array( 5.0 , 5.1 , 5.2 , 5.4 , 5.6 )
arrjagNumbers(1) = array( 6.0 , 6.1 , 6.2 , 6.4 , 6.6 , 6.8 )
arrjagNumbers(2) = array( 7.0 , 7.1 , 7.2 , 7.4 , 7.6 , 7.8 )
arrjagNumbers(3) = 10.1
'' WRONG!! BAD FORM!!

2239528685_83553628f9_o.png

We can see right away from our diagram that something ain't kosher. If we were to look inside arrjagNumbers(0), we would find another array, so asking for something like arrjagNumbers(0)(2) would be perfectly fine. However, when we look inside arrjagNumbers(3), we simply find a number. So, asking for arrjagNumbers(3)(2) would produce an error.

This kind of thing is strongly frowned upon by the nerd community.

2d Jagged Array Retrieval

Retrieving single values from a 2d jagged array is fairly straightforward, and closely resembles the syntax of 1d array retrieval, with the addition of an extra index.

Dim x
x = arrjagNumbers(2)(1)
'' x is now equal to 7.2
x = arrjagNumbers(1)(1)
'' x is now equal to 6.2

Rhino.Print( arrjagNumbers(1)(2) )
''prints 6.4 to the console

You can also retrieve whole arrays (rows) from a 2d jagged array with much the same syntax. In this following example, we define a list of points (each 'point' simply an array of three values) and retrieve them one-at-a-time to create points in rhino. Remember, the Rhino.AddPoint function requires an array of three numbers.

Check out the sweet For loop structure, which allows us to quickly fill up a large array. Also, notice the use of the UBound() function.

'' first, declare and fill up a 2d jagged array of 40 points
ReDim arrPoints(39)
Dim i
For i=0 To 39
     arrPoints(i) = array(0,0,i/2)
Next

'' now, loop through this array and plot out each point
Dim j
For j=0 To UBound(arrPoints)
     Call Rhino.AddPoint(arrPoints(j))
Next


If you attempt to retrieve a value from a 2d array at an index which doesn't exist, or if you think you've retrieved a single value but actually have an array on your hands, you'll get an error. Using our arrjagNumbers example from above:

[ERROR] "Subscript out of range:[number: 6]"
Print( arrjagNumbers(0)(6) )
'' here, we're trying to retrieve a value from an index which doesn't exist


[ERROR] "Type mismatch in parameter. String required"
Print( arrjagNumbers(2) )
'' here, we're trying to pass an Array to the Rhino.Print function.
'' a string, number, or boolean is required

UBound in 2d Jagged Arrays

UBound is short for "Upper bound", which is the terminology used to indicate the highest possible index of an array. For a discussion of this function applied to 1d arrays, see the 1d Arrays page .

UBound works much the same way when applied to a 2d jagged array, except we have to pay attention to which dimension of the array we're referring to. Again using the arrjagNumbers example coded above (and diagrammed below), UBound will behave in the following way:

2240317136_f7348a8a16_o.png

Print( UBound(arrjagNumbers) )
'' prints "3" to the console, referring to highest index availbale
'' at the top-level of the array

Print( UBound(arrjagNumbers(1)) )
'' prints "4" to the console, referring to highest index availbale
'' at index 1

Print( UBound(arrjagNumbers(3)) )
'' prints "2" to the console, referring to highest index availbale
'' at index 3

Resizing 2d Jagged Arrays

TODO