Jun 242014
 

Everything that we have covered so far could have been achieved, with perhaps a little more hard work and head-scratching, using grasshopper without scripting. However there are certain kinds of algorithm that cannot be achieved within native grasshopper without the use of scripting or specialist plug-ins.

Perhaps the most prominent category of these algorithms are those which rely on recursion in order to generate forms with self-similarity such as fractals, L-systems and so on.

In computer science, ‘recursion’ is a term used to refer to functions whose definition includes a call to itself. For example:

C#5_1

(Whatever you do, don’t try to actually run this snippet – this is an example of infinite recursion and it will keep going ‘forever’ – until your computer runs out of memory and crashes!)

When a recursive function is called, it will perform a set of actions which includes calling itself – which will then perform a set of actions which includes calling itself – which will then perform a set of actions which includes calling itself and so on.

This probably seems like a very strange thing to want to do, but it is actually very useful for a large number of applications. For example, when the computer is parsing your code in the first place, it will recursively break each line down into smaller and smaller chunks until it reaches individual commands that it can then understand and execute.

Geometrically it is ideally suited to generative fractal patterns, where the overall pattern contains many smaller copies of itself. In this example we are going to use it to create a simple fractal branching pattern where a line sprouts two more lines from one end, each of which will then sprout two more lines, each of which will then sprout two more lines and so on.

C#5_2

To begin, create a new C# component as well as a line parameter component and three sliders. On the C# component, set up four inputs as follows: firstly an input called ‘ln’ with it’s type hint set to ‘Line’, which will be used to put in our starting line. Connect the line to this. Next, an input called ‘ang’, which will control the angle of our branches and an input called ‘fact’, which will control the length of our branches – both of these should be of type ‘double’ and should be controlled by two of the sliders. Finally, an input called ‘it’ which will control the number of times the fractal structure will branch. This should be an integer type – set the last slider up accordingly and connect it to the input.

C#5_3

Looking at the script, our RunScript function should now look something like this:

C#5_4

However to begin with we’re not going to touch RunScript. In order to use recursion we’re going to need to define our own function that we can later on call within itself. We’re also going to need somewhere to store our outputs that we can populate from that other function. So, in the white space below RunScript, write:

C#5_5

Here we are declaring two things: a list of lines called outList and a new subroutine called ‘Branch’. Because outList is not declared inside a function its scope is not limited to any one function – we can access it from anywhere inside this component.

The Branch subroutine has pretty much the same inputs as our component itself – a Line ln, two doubles called ang and fact and an integer called it.

Back in RunScript, let’s initialise our outList and set it up to be output to A and hook up our Branch subroutine to the component’s inputs:

C#5_6

Now, when our component starts, Branch() will be called. However, it won’t do anything yet – let’s change that.

Let’s begin by making Branch generate the new lines that branch out of the original. In your Branch function, write the following:

C#5_7

This is a multi-step process, but is really very simple. In order to determine the direction of our branches, we need to find the direction of our starting line. We do this by extracting the front and end points of our line – accessed through the ‘From’ and ‘To’ properties. We then subtract the start from the end point to get the vector that describes the direction and length of the line. Points and Vectors have overloaded operators, meaning that you can use certain mathematical symbols (+,-,* etc.) with them as if they were numbers, in this case to perform vector mathematics.

C#5_8

From this vector we can now calculate the vectors that will describe the path of our branching lines. We do this by first making a copy of vAB, then rotating it by our input angle ‘ang’ and then finally by scaling it by our scale factor ‘fact’. To rotate the vector we use the built-in Rotate() function. This takes in two parameters: the first of which is the angle and the second is the axis about which the rotation will take place. In this case we are only working on the XY plane so we can just rotate about the Z axis – if you wanted to create a 3d branching structure you could do so by replacing this with something else. To represent the Z axis, we create a new vector with components (0,0,1) – i.e. a unit vector pointing directly up along the Z axis.

C#5_9

Now that we have the vectors that provide the direction and size of our branching lines, all we need to do is find the end point of those branches by adding the vector to the end point of our initial line. We can then create a new line between the end point of the old line and the new end-point and we have got our branch. Now all we need to do is add it to our outList so that it will be output from the component.

C#5_10

If you close the script, you should see that from our initial line we have created a ‘Y’ shape. However it only branches once no matter what value we put into ‘it’ because we have not yet implemented the recursion.

C#5_11

Fortunately, recursion is much easier to implement than it is to understand. All we need to do is to add a call to our branch function at the end of the function itself, passing in our new branches instead of the starting line:

C#5_12

So, now each branch will generate two more branches, each of which will generate two more branches, each of which will generate two more branches… and so on. The problem that we have now is that this will continue infinitely – if you let this script run then it will keep going until you run out of memory and then it will crash your computer. To prevent this from happening we need to stop the recursion after a certain number of branches. Note that when we call Branch() in the sample above we are also passing in ‘it – 1’ rather than ‘it’ – so each time we branch ‘it’ in the new function will be one smaller than ‘it’ was in the parent function. We now just need to stop the function from executing once ‘it’ reaches zero by wrapping the whole thing in an if statement.

C#5_13

Now by adjusting the slider which controls it we can control the number of levels of recursion.

C#5_14

We can control the form of the resulting fractal by adjusting the scale factor and the branching angle to generate a range of different patterns.

C#5_15 C#5_16 C#5_17

Note that this is only one example of what is possible with recursion.  You could generate any fractal pattern you like using the same basic structure but changing the geometric operations being performed.  Recursion is also a useful tool whenever trying to program any system that needs to branch (whether geometrically or conceptually) – for example parsing text or mathematics, finding connecting paths through a network and so on.

The example file for this session can be downloaded here:

AADRL C# Example 5 – Fractal Branching

Nov 182013
 

Example 3A

In the last example, we used a Range component to gradually increase the rotation of a set of rectangular section curves as they moved along a shape, thus creating a twist.  In that case, we increased the rotation linearly (i.e. with the same step each time).  If we were to plot that onto a graph we would get some kind of straight line graph of the form y = mx.

We don’t always want to increase things linearly, however.  Say we want to define some other kind of relationship – how are we to do it?

One easy way of doing this graphically is with a Graph Mapper component (Params/Input).  Starting from Example 3, drop one onto the canvas and connect the R output of our Range component into the input nodule on the left.

We will use the graph mapper to change the size of the rectangle profile curves as they go along the curve.  Add a new Scale component (Transform/Affine) and insert it between the Rectangle component and the Rotate component such that the R output of the Rectangle component plugs into its G input and its G output plugs into the G input of the Rotate component.

Ex3A_1

The C input gives the centre of the scaling operation.  By default, this is set to (0,0,0) so all of those frames will be being scaled around the origin.  To scale them around their own centre plug the F output from the Perp Frames component in here.  Grasshopper will automatically convert the planes from this output into points, using the global origin of each plane (which in this case is the centroid of our Rectangles as well).

Finally, connect the output of the Graph Mapper to the F input to control the scaling factor.

The Scale component will probably now go red.  This is because we have not yet finshed setting up the Graph Mapper – it has no graph type specified.  Because of that it is simply outputting whatever we put into it unchanged.  Since the first value in the list coming out of our Range component is 0, that is being passed along and the Scale component is attempting to scale the first rectangle by a factor of 0 – resulting in a Null result.

Ex3A_2

To fix this, let’s set up a graph in the Graph Mapper so that this doesn’t happen.  Right click on the Graph Mapper and go down to ‘Graph types’ in the context menu.  Select ‘Linear’.  A straight line graph should now appear inside the Mapper.

Ex3A_3

What the Graph Mapper does is to take each of the values that are input into it, treat it as an x value and read off the equivalent y value from the graph.  The linear graph type defaults to y=x, so it is the same as not having done anything – however on that line you should see two little handles that you can drag around in order to change the graph curve.  Move them so that the line no longer passes through zero to fix the problem with the Scale component.
Move the handles around and note the effect this has on the shape of our twisted form.

Ex3A_4

Now try changing the graph type – experiment with the different kinds and see what results you get out.

Ex3A_5 Ex3A_6 Ex3A_7 Ex3A_8

Example 4

The Graph Mapper is a nice tool for getting graphical control over the progression of a particular variable, but it is limited to certain pre-set graph types and can be hard to get exact control over.  Sometimes you will want to get actual mathematical equations involved, and to do that we will now look at how to plot a mathematical function in Grasshopper.

Start a new definition and add a new Range component (Sets/Sequence).  Set up Number Sliders to control both the Domain and Step Number.

Ex4_1

Now add an Evaluate component from Maths/Script.  This component lets you apply your own mathematical formula to a set of inputs.  The number of these inputs is adjustable – if you zoom in on the component then you will see a set of small + and – symbols appear next to the x and y inputs.  These can be used to add or remove inputs from the component.  For the moment, we just want to take in a single input – x – so click on the small ‘-’ next to the y input to delete it.

Ex4_2

Now plug the output of our Range component into x.  We are going to take these x values, apply a function to them to get y and then plot x against y.  The next step is to define the function.  If you double-click on the Evaluate component an expression editor interface will pop up which displays a lot of the functions that it’s possible to use and also will perform basic error checking on the equation for you as you type.  Alternatively, you can input a formula as a text string into F, which is what we will do here, using a Panel (Params/Input) to type our equation into.  For starters, we’ll draw a straight line graph – add a Panel, plug its output into F and type in:

2*x

(The * is the sign we use for multiplication)

Ex4_4

Now we need to plot the points and draw the line.  To accomplish the former, add a Construct Point component to the document.  Pretty much identical to VectorXYZ, Construct Point lets you, well, construct a point by specifying its X, Y and Z coordinates.  Plug the output of our Range into X and the output of our Evaluate component into Y.  You should see a straight line of points appear.

Ex4_5

To actually draw the plotted curve itself we will use the Interpolate component (Curve/Spline).  This works similarly to the CurveThroughPt command in Rhino in that it takes in a set of points and creates a curve (with a given degree) that passes through all of them.  Plug the Pt output from our Construct Point component into the V input of an Interpolate component.

Ex4_6

Now we can experiment with different equations and see what they do.  Here are some of the operators and other functions that we can use:

+     Add
-     Subtract
*    Multiply
/    Divide
^   To the power of
%    Modulus (divide by a given number and return the remainder)

sqrt(x)     The square root of x
sin(x)       The sine of x
cos(x)       The cosine of x
tan(x)       The tangent of x
cot(x)       The cotangent of x
asin(x)     The arcsine of x (inverse sine)
acos(x)     The arccosine of x (inverse cosine)
atan(x)     The arctangent of x (inverse tan)

For a full list of all available functions, go into the expression designer and click the button on the top right.

Ex4_8 Ex4_7 Ex4_9 Ex4_10 Ex4_11

The complete example files for this session can be downloaded here:

AADRL 2013 Examples 3A & 4

Oct 172013
 

Rhino is a NURBS-based 3D CAD package produced by Robert McNeel and Associates.  It also plays host to the Grasshopper parametric design plug-in which will be the main focus of this course, however before we begin looking at that tool it is useful to understand the basics of Rhino itself.

 

Interface

After loading up Rhino and choosing a unit system (I like metres, myself), you should see something that looks a little bit like this (click for bigger):

Rhino Interface AnnotationMenu Bar:  All the things you might expect of a windows menu bar such as Save/Load etc.  Also contains menus of modelling tools categorised by type.

Command Prompt: Type here to make things happen.  Press enter or right-click without typing anything to repeat the last command.  See below for a list of useful commands.

Command History: A list of commands previously used as well as any other little messages Rhino may want to give you from time to time.

Toolbars: A set of buttons that give quick access to various tools.  Most tool buttons have different functions assigned to left and right mouse buttons – hover over them to see a tooltip that describes each function.  Holding down the left mouse button over a button for a second or so will bring up a sub-menu of related tools.

Properties Tab: Displays the properties (such as name, display colour and so on) of the currently selected item.

Layer Table Tab: Displays the current layer table.  Like most CAD packages, objects in Rhino all sit on a particular layer.  You can select, colour, hide and lock all entities on a layer quickly an easily, so they are a useful tool for organising your model and keeping it clean.  Newly created objects are (usually) added to the current layer (the one with the tick).  Double-left-click on a layer to make it the current one.

3D Viewports: Where the magic happens.  Provides you with a 3D view of your current model geometry.  By default is split into four separate views with the view name in the top left corner.  To make one view take up the whole screen, double-left-click on its name (and do the same again to make it return to the previous arrangement).  Right click on the name or left-click on the little drop down arrow to see a list of options for that viewport.  The most important option is probably the rendering style – this defaults to ‘Wireframe’, meaning that only points, curves and the edges of surfaces will be displayed.  Turn on ‘Shaded’ mode to see surfaces in all their glory.

In the viewport, left-click to select objects.  Hold and drag the right mouse button to navigate – in perspective mode this will rotate the view, in orthographic view modes (Top, Front, Right etc.) it will pan.  To pan in perspective mode, hold shift at the same time.

In each of the viewports you should see a grid (if you don’t see it, hit F7 to toggle its visibility) – this is the construction plane.  The construction plane is important because it is Rhino’s way of dealing with the problem of interacting with a 3D space through a 2D screen and input method.  When you pick points or do other operations in the 3d view, they will default to being projected onto the current construction plane, unless being overriden by…

Object Snap Toggles: VERY useful.  Use these to snap to different objects in the 3d view when picking points – vital when modelling to ensure that various things connect properly.  Turn on the ‘Project’ option to enforce projecting your input onto the current construction plane.  You may not be able to see these toggles when you first open Rhino – turn them on by clicking ‘Osnap’ on the…

Status Bar: Gives you various bits of useful information such as the current mouse position, layer and so on.  Also home to important toggles such as the aforementioned Osnap.

 

Useful Commands

Rhino contains hundreds if not thousands of different commands and I’m not going to cover them all.  Here is a list of some of the most useful/commonly used ones.  These can be used either by typing in the command name at the prompt or by clicking the equivalent button in the toolbars or menus.  Pay attention to the command prompt – it will guide you through the inputs needed for each command.  Note that often there are several ways of providing the input – for example with the Point command you can position the point either by clicking in the 3D view or by typing in the x,y,z coordinates of the new point.

Help – Access Rhino’s built-in help file.  Good for more detail on what all these commands do.
Options – Gives access to Rhino’s (many many) options, including useful things like the current document’s units and display options.
Point – Create a single point object
Line – Draw a straight line between two points
Polyline – Draw a set of joined straight lines through a set of points in sequence
Arc – Create a single-radius curve around a point
Curve – Draw a curve by manually specifying its control points
CurveThroughPt – Create a curve that passes through a selection of point objects.  Note that you’ll need to have created the point objects beforehand and that the order in which you select them is the order in which the curve will pass through them.
SrfPt – Create a quadrilateral surface by specifying it’s corner vertices
Loft – Create a surface that passes through a selection of curves.  The Surface equivalent of CurveThroughPt.
PlanarSrf – ‘Fill in’ a planar closed curve with a planar surface cut to the right shape.
Move – Move an object along a particular vector.  You can also move objects just by holding down the left mouse button on them and dragging, however it is usually preferable to use the Move command as it gives you more control, with the ability to make use of object snaps and numerical input.
Rotate – Rotate an object about a particular point with a particular angle.  By default, rotation is done on the current construction plane.
Copy – Create a copy of an object
Rebuild – Change the degree or number of control points of a curve or surface.
Join – Join several objects together into one larger object.  For this to work the ends (of curves) or edges (of surfaces) must be exactly touching – this is where object snaps are vital.
Explode – The anti-join.  Breaks joined objects up into their component parts.
Intersect – Create points and curves at the intersection between two (or more) objects.
Trim – Cut off a bit of one object using another as a cutting tool.  The cutting object must intersect the object to be trimmed.
Split – Like Trim, except you keep the offcut as a separate object.
CPlane – Allows you to reposition the construction plane of the current viewport in a number of different ways.
PointsOn – Turn on the control points for the selected surface or curve.  This lets you manually adjust the topology of these objects without having to create a new one.
PointsOff – Turn control points off again.  Until you do this you won’t be able to select the object itself.
EditPtOn – Turn on edit points for the selected curve.  Edit points can be used similarly to control points, however they lie on the line itself and thus can be a bit easier to use.
EditPtOff – Turn off edit points.
InsertEditPoint – Add a new edit point to a curve at the selected location.  Useful to get a bit more local control of a curve.
Blend – Smoothly join two curves
BlendSrf – Smoothly join two surfaces
Project – Project curves and points onto a surface.  Projections always happen ‘down’ onto the construction plane (i.e. in the direction of the current CPlane’s z-axis).  Useful when trimming a surface with a curve to make sure that the curve exactly intersects the surface.
ProjectToCPlane – Like project, only it projects everything onto the current construction plane.  Useful when you want to make a bunch of curves all occupy the same plane in a hurry.
Grasshopper – You’ll need this one next week.  If nothing happens then download and install grasshopper

 

NURBS Curves and Surfaces

To use Rhino (and also Grasshopper) well, it helps to know a little bit about the way that Rhino deals with its geometry ‘under the hood’.  Rhino is heavily focussed around NURBS, or Non-uniform Rational Basis Splines.  This is a way of mathematically representing curves and surfaces using one or more polynomial functions and a set of control points.  Compared to other ways of representing 3D geometry such as meshes they have a number of advantages in that they are more precise and far more scalable.  Meshes can only approximate curved geometry and if you zoom in or blow up the geometry the individual faces of the mesh soon become apparent.  NURBS, however, can represent a smooth curve exactly at whatever scale you need them to.  The main disadvantage of NURBS compared to meshes is that they can be a bit more difficult to work with since you do not have quite such a direct level of control over their shape.  They can also be a bit more computationally ‘heavy’ since they cannot be rendered directly and must be converted into a mesh before they can be drawn to the screen.

The two most important properties that define a NURBS curve in Rhino are its control points and its degree (there are also knots, but we’ll ignore those for now since you never really need to get directly involved with those in Rhino).  The control points act as attractors that ‘pull’ the curve towards them and define the general shape of the object.  The degree refers to the degree of the polynomial that defines the curve itself.  The degree also determines the number of control points that will influence any particular point along the curve.  A curve of degree 1 consists of straight lines between control points as the position of a point on the curve is only being determined by the position of the control point directly ahead and behind it.  Higher-degree curves will be also influenced by control points further down the chain and so will have a smoother appearance.

A degree 1 curve (a polyline) between control points

A degree 1 curve (a polyline) between control points

A degree 3 curve using the same control points

A degree 3 curve using the same control points

A degree 5 curve with the same control points

A degree 5 curve with the same control points

NURBS surfaces work in exactly the same way except rather than a single string of control points they have a two-directional grid.

A simple surface and its control points

A simple surface and its control points

It’s worth noting that all surfaces in Rhino need to have a full rectangular grid of control points.  All surfaces are therefore, behind the scenes, distorted rectangles.  Often you will wish to have a surface which does not have a rectangular boundary and so will apply a trim.  When trimming a surface, Rhino adds an additional layer of trim data to the object, which marks out certain areas of the surface as being, for most purposes, non-existant.  Note though that this does not affect the underlying NURBS definition of the surface – the full rectangular grid of control points will remain intact, even if some of those points only have influence over areas of the surface which do not appear to exist anymore.  This is important to bear in mind, as some Rhino commands and Grasshopper components will treat surfaces as being the full untrimmed distorted rectangle, so even trimmed parts of a surface can be important sometimes.

A trimmed surface, with its control points

A trimmed surface, with its control points

Tips

  • Often creating anything other than basic geometry in Rhino will be a multi-step process and you are likely to need to create plenty of temporary ‘construction’ geometry in order to position and trim things correctly.
  • In particular, most ways of creating surfaces will first require you to create a set of curve inputs to define the shape.
  • Use layers to group related parts of the model together and give them descriptive names – when you have 300 layers and can’t find the turned-off bit of the model that you want you’ll understand why.
  • Get into the habit of using object snaps, but turn off any you don’t currently need – it’s easy to accidentally snap to something that looks right in 2d, but ends up being miles in front of or behind the point you wanted when you look at it in 3d.
  • The help tab on the sidebar automatically displays the help documentation for the command you’re currently using.  Useful if it’s a command you’ve not used before.
  • The categorised commands on the menu bar can be a good way of browsing through commands and learning what’s available.
  • Objects that are locked (or on locked layers) cannot be selected but objects snaps will still use them – this can be useful to ‘trace over’ 3d geometry.

Obviously, this only gives you the bare bones of how to use Rhino – learning to use it properly will take practice!  Take a look here, here or search YouTube for tutorials.  If you find any good ones or have any other tips that you want to share then add them in the comments below.

Mar 212011
 

This week, we look at using Genetic Algorithms to solve geometric problems via Grasshopper’s built-in genetic algorithm engine, Galapagos.  Genetic algorithms attempt to mimic the way lifeforms evolve over time, on the basis that if it’s good enough for creating all life as we know it, it’s probably a fairly good tool for helping us develop design solutions.

There are two main things to consider when we are setting up a grasshopper model to use Galapagos.  The first are the input parameters that we are going to use as genomes.  Each genome is a value that controls certain aspects of the design – the height of a wall, for instance, the width of a window, the number of columns etc.  Galapagos will modify these values for us and attempt to find the ‘best’ solution.  At present, galapagos can only do this through modifying sliders, which places a slight limitation on the way we set up the grasshopper definition because it means that everything we want it to be possible to change has to be controlled via a slider.  We can still include other parameters (linked geometry, strings etc.) but galapagos will not be able to modify them for us.  At each generation, grasshopper will fiddle (technical term) with these values and come up with a variety of different combinations.  The best sets of values will pass on to the next generation (either directly or through ‘breeding’ with another value set) – the rest will be eliminated.  The idea is that the population at each generation will become more and more suitable to the task at hand and hence you will be given ever improving solutions to whatever problem you are trying to solve.

The second, possibly more difficult part, is coming up with a way of assessing your model and turning that assessment into a single numerical value that you can use to express the ‘fitness’ of a given design, i.e. giving it a score based on how ‘good’ it is.  This gets especially tricky if you need to consider more than one criteria that are not all of the same importance, since then you need to weight each criteria’s contribution to the final score.  This is mathematically quite easy (you just need to multiply it by a certain factor) but determining what these weightings should be in order to give the best results can take a bit of trial and error.  For some more on this I recommend this blog entry by the mighty David Rutten himself.

Indeed, if you’re thinking of using Galapagos you should probably leaf through the rest of David’s blog – he did write the thing, after all.

For my part, here are two annotated examples that use it:

The first (the idea for which I think I probably stole of of David anyway) uses galapagos to arrange a catenary so that it passes through (or at least, close to) a point, while (as a secondary consideration) minimising the length of the catenary.

Not breathtakingly useful, I know, but it should help to demonstrate the basics.  Get it here: Example6a.ghx (Right click, save target as)

The next one does something a little bit cleverer.  Given a certain set of points, we use metaballs (a form of implicit surface, although in grasshopper they only creates curves, which represent a 2D ‘slice’ through a metaball) to cover as many points as it can while also keeping the total covered area as small as possible.  In this abstract form again this is probably not particularly useful but hopefully it is easy to see how it might be modified for use in masterplanning, for example.

Get it here: Example6b.ghx (Right click, save blahdy blah)

As an optimisation tool, genetic algorithms leave something to be desired.  They need a large pool of test cases at each cycle and are highly random in the way that they work, meaning that they can take many many times longer than a more ‘straightforward’ optimisation routine would and may in the end not actually find the most optimum possible solution anyway.  For this reason, they tend to fall onto the ‘often discussed, rarely used’ pile.  However, they are also a lot more ‘creative’ – possibly throwing up solutions that you might never have considered otherwise.  Given that we are all evolved creatures ourselves, it could be argued that all ‘designs’ are really the product of a genetic algorithm that has been running for several billion years.

Mar 062011
 

This week, we create our own universe.  Specifically, we create a universe with two physical laws:

F = ma, or Newton’s second law of motion

F = G(m1*m2)/r^2, or Newton’s law of universal gravitation

Using those laws, we’re going to simulate a ‘solar system’ of different bodies and plot the paths they make moving under gravitation.  To do this we’re going to use an iterative algorithm; calculating the forces that the planets exert on each other, moving them a little bit, re-calculating the forces based on their new positions, moving them again and so on.

First up, we’re going to create a class to represent the ‘planets’ in our solar system.  We’re going to do this separately using Visual Studio, then compile it as a DLL, a library of code that does nothing on its own but that can be used freely by other bits of code.  There are a couple of advantages to doing it this way – we can re-use this bit of code easily if we need to and we can minimise our time spent using grasshopper’s horrible built-in script editor.

To create the dll, open up Visual Studio/Visual Basic Express and create a new ‘class library’ project.  DLLs are used a lot – RhinoCommon itself is stored in a DLL, and since we want to use some of the RhinoCommon types (points, vectors etc.) our first task is to reference that dll to let Visual Studio know where it is and that we want to use it.  To do this, go to Project->Properties->References and add one to RhinoCommon.dll (should be somewhere in your grasshopper install directory).  Then add this code:


'Before we can use anything from RhinoCommon, we need to reference the .dll
'You can do this in Project->Properties->References

'This imports the Rhino.Geometry namespace so we don't have to type it out every time we use something from there
Imports Rhino.Geometry

'This is the class we will use to represent each 'planet'
'This could be adapted to any kind of agent, however
Public Class Planet

'Each planet has three 'physical' properties
Public position As Point3d
Public velocity As Vector3d
Public mass As Double

'So we can plot the trail of the planet we store all of it's previous points
Public path As List(Of Point3d)

'Constructor:
Public Sub New(ByVal initialPosition As Point3d, ByVal initialVelocity As Vector3d, _
ByVal initialMass As Double)

position = initialPosition
velocity = initialVelocity
mass = initialMass

path = New List(Of Point3d)
path.Add(New Point3d(position.X, position.Y, position.Z))

End Sub

''' <summary>
''' This sub gets called iteratively to update the position of the planet
''' </summary>
''' <remarks></remarks>
Public Sub Move()
position += velocity
path.Add(New Point3d(position.X, position.Y, position.Z))
End Sub

''' <summary>
''' This converts a force into a change in velocity
''' </summary>
''' <param name="force"></param>
''' <remarks></remarks>
Public Sub ApplyForce(ByVal force As Vector3d)
velocity += force / mass
End Sub

End Class

Then hit ‘Build’ to create our actual .dll. VS will put it in the folder for your project under Bin/Release.

Now for our grasshopper part.  Create a script component, right click on it, go to ‘Referenced assemblies’ and use the pop-up form to add a reference to our newly-created .dll.  This will allow us to use our ‘Planet’ class within the scripting component.

Set up the component’s inputs to take a list of points, P, a list of vectors, V, a list of doubles, M, and an integer, T.  These represent, respectively, our planet’s starting positions, initial velocities, masses and the length of time we want to simulate.  Then add this code:

Private Sub RunScript(ByVal P As List(Of Point3d), ByVal V As List(Of Vector3d), ByVal M As List(Of Double), ByVal T As Integer, ByRef Path As Object)

Dim planets As New List(Of Planet)

'First of all, we create our 'planets'.
'Here we recreate the behaviour Of the 'longest list' data matching option
For i As Integer = 0 To P.Count - 1
Dim position As Point3d = P(i)
'If values exist for the other parameters here then we use them
'otherwise, we use the last value in the list
Dim velocity As vector3d = V(math.Min(i, V.Count - 1))
Dim mass As Double = M(math.Min(i, M.Count - 1))
Dim planet As New Planet(position, velocity, mass)
planets.Add(planet)
Next

'All our simulation is going to take place in this loop
'Each step through this loop represents a discrete amount of time
'To simplify things, we've assumed this is equal to 1 time unit
For time As Integer = 0 To T

'First, we check every planet against every other planet and work out the forces each
'pair is exerting on each other
For j As Integer = 0 To planets.Count - 2

Dim planetA As Planet = planets(j)

'By checking each planet only against the planets later in the list, we ensure that each
'pair is only going to be checked once
For k As Integer = j + 1 To planets.Count - 1

Dim planetB As Planet = planets(k)
Dim F As Double
'Here we calculate the force using the formula:
'Force = (mass1 * mass2)/distance^2
'i.e. Newton's law of universal gravitation
F = (planetA.mass * planetB.mass) / planetA.position.DistanceTo(planetB.position) ^ 2
Dim direction As Vector3d = planetB.position - planetA.position
direction.Unitize
direction *= F

planetA.ApplyForce(direction)
planetB.ApplyForce(-direction)
Next

Next

'Now that we have worked out how each planet will be moving, we update their positions
For Each planet As Planet In Planets
planet.Move()
Next

Next

'NOTE: This part *should* work, but doesn't always due to a bug in RhinoCommon:
'=========================================================================================
'Dim outList As New List(Of Curve)
'For Each planet As Planet In Planets
'  Dim crv As Curve = Curve.CreateInterpolatedCurve(planet.path, 3)
'  outList.Add(crv)
'Next

'Path = outList
'=========================================================================================

'Since the above won't work reliably, we instead create a data tree, with the points that
'describe each planet's path stored in a separate branch.  This means we can feed them into
'an 'interpolate curve' component and get a separate curve for each planet.
Dim Tree As New DataTree(Of Point3d)

For z As Integer = 0 To planets.Count - 1
'For each planet we create a new path:
Dim TreePath As New GH_Path(z)
For Each pt As point3d In planets(z).path
'We then add each point to the tree, stipulating the path to use to store them
Tree.Add(pt, TreePath)
Next

Next

'And finally, we output our tree:
Path = Tree

End Sub 

Now plug the output path points into an ‘interpolate curve’ component, stick in some initial variables and you should have some interesting results, or at least interesting messes.  Note that the algorithm is quite sensitive to scale – if you don’t see anything it may just be that your planets are too far apart to have any effect on each other.

You can download the complete example here: http://www.vitruality.com/Teaching/PhysicsExample.zip

I used a script like this when we were in the initial stages of designing the Orbit as a way of defining the centreline of the lattice.  In the end however, this approach proved a bit to difficult to control.  If you play around with it a bit you will notice that it is extremely sensitive to initial conditions.  Move one of the starting positions even slightly and it will totally change the result you get.  Since for the Orbit we needed to have finer control over the form in order to get something that was structurally feasible (we were going for visually unstable, but not actually unstable), in the end we abandoned that idea and went for something a bit more manual.

But, while this script might not be particularly useful for this reason, this basic structure could be modified for any sort of physical simulation or agent-based generation (dynamic relaxation, boids, pheremone-based stuff, etc.).  The only things that you’d need to change would be the controlling equations (in this case, the gravitation formula)…

Feb 062011
 

I didn’t actually know about this until I accidentally stumbled accross it in iplayer, but Cecil Balmond (my boss when I was in Arup’s AGU (Advanced Geometry Unit), until he went off to do his own thing) did a radio series for the BBC a little while ago about the evolution and use of mathematics in design.  As it turns out, they’re pretty good, and well worth a listen if you’re at all interested in anything ever.

You can listen to all three episodes here.

Episode 3 is where he gets into the sort of things that we actually do for a living, but episode 2 in particular is well worth listening to for the part where Cecil interviews the previously mentioned (and sadly recently deceased) Benoit Mandelbrot.  I geeked out a bit over that part and it sounds like Cecil did too.

Jan 222011
 

Last year, I gave a lecture at the AADRL about fractals and their implementation, as part of a course I was teaching on generative and parametric design using Rhino.  For anybody interested in RhinoScript, here is the example code that I gave in that class to generate a very simple fractal – the Sierpiński triangle:

http://www.vitruality.com/Teaching/sierpinski triangle.rvb

The way you generate a pattern like this is easy:  You take a starting triangle, then draw three smaller touching triangles inside it (à la the Triforce), then draw three smaller triangles within each of those and so on forever (or, in the script’s case, until you reach a suitably tiny scale).

And so on and so on and so on...

Like I say, this is pretty simple as fractals go, but the key idea behind implementing them all in code is exactly the same.  They all need to have some function which performs a particular geometric operation and then calls itself, using the outputs of that operation as the inputs for the next cycle.  You could modify the script above to create any fractal you want just by replacing the specific parts that deal with subdividing the triangle.  The geometrical mathematics might become more complicated but the basic framework will remain the same.

During that class, I made the rookie mistake of saying ‘…and expanding this to three dimensions is pretty simple.’, to which one of the students reasonably responded ‘well, can you show us that, then.’ to which I said ‘um’.  And then, after I’d thought about it a bit more, did so:

www.vitruality.com/Teaching/Sierpinski%20Pyramid.rvb

For brevity’s sake, I actually ‘cheated’ a little in that script, since I ask the user to input the vertices (if I’d had more time, this could have been extracted from the input geometry itself, although due to the way Rhino stores BReps, this is a non-trivial operation) and then simply scale about those points to create the subdivisions.  The benefit to this however is that you can now use the same script for more than just pyramids.   Anyway.

Fractals are quite interesting not just because they’re quite pretty but also because a lot of the natural forms that surround us exhibit fractal-like structure.  Fern leaves and snow flakes are the most frequently cited examples, but also clouds, mountain ranges, galaxies and even the distribution of blood vessels in our own bodies also have self-similarity at different scales.

Looking at these forms as fractals has some interesting implications.  For instance, the coastline of Britain, which King of Fractals Benoît Mandelbrot demonstrated had fractal characteristics, is (practically) infinitely long.   This probably seems a bit counter-intuitive, even if it does explain why this program felt like it went on forever.  Trace around Britain on a map and you’ll be able to get out a certain measurement, but go to the coast itself with a measuring tape and you’ll realise the problem.  Do you measure around every headland?  Do you measure around every rock?  Every grain of sand?  Every atom?  The greater the level of detail you decide to include, the longer and longer your measurement will get.

Natural forms display fractal properties simply because they are produced by physical processes, which are in turn governed by physical laws which apply at all scales.  The oceanic currents that shape continents are driven by the same forces as the vortices that carve out rockpools, so in a sense it should really come as no surprise that we find fractals all around us.  Of course these patterns do begin to change slightly as you go down in scale and this is due to the intrinsic imbalance between the fundamental forces of nature.  At large scales gravity dominates – even though it is substantially weaker than the other three fundamental interactions it has influence over much larger distances.  As you head down towards the atomic scale gravity becomes insignificant and the attraction and repulsion between particles becomes the primary driver behind form.  For this reason no natural fractal is ever perfect but it is these ‘imperfections’ that allow the universe as we know it to exist in the first place.

Fractals show us impossible universes without scale, without limits, without variation, without us.  Dead, but pretty with it.

http://www.bbc.co.uk/programmes/b006mvlc