Now we may want to add a surface defined by the Points. But in order to do so we need to store the Points in a nested List rather than making them all children of the same Point in a one dimensional List. This will make it easier to work with the Points as Lists of spirals as they were defined.

Remember a List of Lists is essentially a List which contains another List in each position, which in turn contains the actual objects, in this case the Point objects. This is a 2D data structure similar to a row and column table. To create this List structure we start out with an empty List using the {} to do define an empty List and then fill that list again empty Lists. Inside these inner Lists we will store our Points one by one. In the end we will return the nested List structure in the function which will make it accessible as a 2D List to other Features such as for a BSplineSurface or PolygonGrid.

Adjusting the data structure to reflect the nested loops with a nested List of Points

Let’s start by defining our pt01 variable as an empty List in the beginning of the script.

Point pt01 = {};

This creates the outer List, now we have to add an empty List inside of this List each time we run the spNum loop to create a List to store the actual spiral Points in, each set in their own List.

To do so we add the line pt[j] = {} in the first line of the first Loop. The [j] specifies the position in the outer List we are placing the new List, remember we need one List each for each of the set of Spiral Points.

To actually store the Point in the nested List structure we need to index into the List with j and i, j for the number of the spiral and i for the point number in that spiral, which looks like this

pt01[j][i] = new Point();

We need to remove the this keyword in order to not create a single list again. We will parent the 2D List by using the return statement at the end of the function instead. This will preserve the nested List of our Point data structure. If we add a return statement we also need to declare the return Type of our function by adding the Type in front of the function declaration. We will have to use Point as the type and add [][] to indicate that it is a two dimensional List of Points.

Now we are storing the Points in a 2D nested List structure that is formatted correctly to reflect the structure of the Point spirals and parent it correctly to the point01 Feature by using the return statement. The resulting Points look no different to the previous one but if we hover over the Points in the geometry window we see that the have two indices now, which means they are part of a two dimensional data structure as desired.

We now can use this Data structure as an input to a Polygon ByPointGrid for instance to create a faceted surface.

Adding a Polygon Grid to the Point data structure

We can now use a conventional Feature like the Polygon with the Points created by the script.

Now we notice that the way we created our Points creates a gap when using them as the definition of the Polygon Grid, both at the top and between the last and first spiral. We can adjust the loops to create a duplicate set of Points and an additional set at the top – to do so we can simply add 1 to the num and spNum value in the for loops – the script then looks like this:

Or alternatively we could use a BSplineSurface, then we would not want to adjust the spNum loop but instead make the surface periodic in the spNum direction it would then look like this before making it periodic:

And after making the BSplineSurface.ByPoles periodic in the V direction by setting Vclosed to true:

Using the same script structure but a different set of equations one can generate different tower outlines, in this case using a cubic function. The difference here is that the height of the spiral is defined by the function and the radius is defined by the even increments. This is necessary in order to flip the x and y axis to fit the tower. It also is mirrored to not stand upside down and shifted to start at the z=0 level.

Point [][] function (CoordinateSystem cs, int num, int spNum)

{

Point pt01 = {};

for (int j = 0; j < spNum+1; ++j)

{

pt01[j] = {};

for (int i = 0; i < num; ++i)

{

double radius = i;

double shift = 360/spNum*j;

double hShift = ((1.0/num)*(Pow((num-1),3))*0.2);

double height = ((-1.0/num) * (Pow(i,3))*0.2)+ hShift;

double xPos = Cos((360/num * i) + shift)*radius;

double yPos = Sin((360/num * i) + shift)*radius;

pt01[j][i] = new Point();

pt01[j][i].ByCartesianCoordinates(cs, xPos, yPos, height);

}

}

return pt01;

}

The generation of the Surface or the Polygon could also be integrated into the function itself but then the parent Feature would have to be of the Type of the final outcome and the Point would become an internal Feature that is not drawn. The script would adapt like this for the last tower case, using a Polygon.ByFunction method (because the Feature that is supposed to be drawn and seen is a Polygon not the Point and one should not mix Feature Types usually for children.

One removes the return type and instead creates a Polygon variable called poly here and makes it a child of the Polygon created ByFunction method using the this keyword as in the beginning of the Point function example. The Points are not parented to anything but only passed into the Polygon.ByPointGrid method and therefore are not displayed in the final result.

Remember this script has to be placed inside Polygon.ByFunction method not as in the previous example in the Point.ByFunction method because we are making the Polygon a child of the parent Polygon here.

function (CoordinateSystem cs, int num, int spNum)

{

Point pt01 = {};

for (int j = 0; j < spNum+1; ++j)

{

pt01[j] = {};

for (int i = 0; i < num; ++i)

{

double radius = i;

double shift = 360/spNum*j;

double hShift = ((1.0/num)*(Pow((num-1),3))*0.2);

double height = ((-1.0/num) * (Pow(i,3))*0.2)+ hShift;

double xPos = Cos((360/num*i) + shift)*radius;

double yPos = Sin((360/num*i) + shift)*radius;

pt01[j][i] = new Point();

pt01[j][i].ByCartesianCoordinates(cs, xPos, yPos, height);

}

}

Polygon poly = new Polygon(this);

poly.ByPointGrid(pt01);

}

The Polygon.ByFunction version where the Points are only internally created and do not show up in the final geometry.