Gradient Patterns
It’s been a while I’ve played with Grasshopper. It is getting to be more and more powerful. I think I will be exploring more in this world of Grasshopper + VB.NET and also IronPython included in the upcoming Rhino 5. This definition is super simple. It arrays / deforms a component that you define according to the two surfaces and their UV divisions.
In order to use the definition, first define a box, and some geometries within the box as your base component. Then, simply create two surfaces as references for organizing your components. Finally, control U/V divisions.
This is a rhinoscript where you can set various points where vectors flow out from according to a certain velocity. As these vectors travel, the flows are attracted to the various attractor points in different weights three dimensionally. It simulates a close logic to the emitted particles being attracted to newton forces in Maya.
—-
Option Explicit
‘Script written by Howard Jiho Kim / crtl-i.com
Call Main()
Sub Main()
Dim startPt, velocity
velocity = Array(10,0,0)
startPt = Rhino.GetObjects(“Select Start Points”,1)
‘Attractors / Distances
Dim no_attr, attr, attrStr, i
no_attr = Rhino.GetInteger(“How many attractors?”)
ReDim attr(no_attr-1), attrStr(no_attr-1)
For i=0 To no_attr-1
attr(i) = Rhino.GetObject(“Select Attractor ” & (i+1),1)
attrStr(i) = Rhino.GetReal(“Enter Strength for Attractor ” & (i+1))
Next
For i=0 To Ubound(startPt)
Flow velocity, startPt(i), no_attr, attr, attrStr, 35
Next
End Sub
Function Flow(velocity, startPt, no_attr, attr, attrStr, gens)
Dim vec1, vec0
vec1 = Rhino.VectorCreate(velocity, Array(0,0,0))
vec0 = Rhino.VectorCreate(Rhino.PointCoordinates(startPt), Array(0,0,0))
Dim totalDistance, distance, i
ReDim distance(no_attr-1)
Dim vec, finalVec, vec4, tagStop
tagStop = 0
ReDim vec(no_attr-1)
Dim newPt, newLine, endPt2
totalDistance=0
If gens>0 Then
For i=0 To no_attr-1
distance(i) = Rhino.Distance(Rhino.PointCoordinates(startPt), Rhino.PointCoordinates(attr(i)))
totalDistance = totalDistance + distance(i)
Rhino.Print distance(i)
Rhino.Print totalDistance
If distance(i) < 1 Then
gens = -1
End If
Next
‘Vectors
vec4 = vec1
For i=0 To no_attr-1
vec(i) = Rhino.VectorCreate(Rhino.PointCoordinates(attr(i)), Rhino.PointCoordinates(startPt))
vec(i) = Rhino.VectorUnitize(vec(i))
vec(i) = Rhino.VectorScale(vec(i), (attrStr(i)/distance(i))^2)
vec4 = Rhino.VectorAdd(vec4, vec(i))
Next
finalVec = Rhino.VectorUnitize(vec4)
finalVec = Rhino.VectorScale(finalVec, 1)
If tagStop = 0 Then
newPt = Rhino.AddPoint(finalVec)
newLine = Rhino.AddLine(Array(0,0,0), finalVec)
endPt2 = Rhino.MoveObject(newPt, vec0)
newLine = Rhino.MoveObject(newLine, vec0)
End If
Flow velocity, endPt2, no_attr, attr, attrStr, gens-1
End If
End Function
Some facade studies. All these patterns are made through a version of script that is very close to the 3D-pixelate code.

This is a script that pixelates point clouds into a user-defined 3-dimensional grid. It also arrays same size boxes to the pixelated points. If used wisely, it could become a good tool to rationalize a nurb surface into many small boxes.
![]()
It first pixelates the points into a wanted grid. Naturally, the geometry starts to lose its shape as the pixelating factor grows.

Then it populates the points with a box that you define.
—–
Option Explicit
‘Script written by Howard Jiho Kim / crtl-i.com
Sub Pixelate
Dim strObject, arrPoint, arrObjects, box_pt(7), box
arrObjects = Rhino.GetObjects(“Select points to pixelate”)
Dim multiplier_x, m1_x, m2_x, finalHeight_x, arrEnd(2)
multiplier_x = Rhino.GetReal(“Enter Pixelating Factor for X axis (0 for Non-Pixelation): “)
Dim multiplier_y, m1_y, m2_y, finalHeight_y
multiplier_y = Rhino.GetReal(“Enter Pixelating Factor for Y axis (0 for Non-Pixelation): “)
Dim multiplier_z, m1_z, m2_z, finalHeight_z
multiplier_z = Rhino.GetReal(“Enter Pixelating Factor for Z axis (0 for Non-Pixelation): “)
Dim box_yn
box_yn = Rhino.GetInteger(“Create boxes? (1-Yes, 2-No)”)
If box_yn = 1 Then
Dim box_x, box_y, box_z, box_mid_pt(2)
box_x = Rhino.GetReal(“Enter Box size-x: “)
box_y = Rhino.GetReal(“Enter Box size-y: “)
box_z = Rhino.GetReal(“Enter Box size-z: “)
box_pt(0) = Array(0,0,0)
box_pt(1) = Array(box_x,0,0)
box_pt(2) = Array(box_x,box_y,0)
box_pt(3) = Array(0,box_y,0)
box_pt(4) = Array(0,0,box_z)
box_pt(5) = Array(box_x,0,box_z)
box_pt(6) = Array(box_x,box_y,box_z)
box_pt(7) = Array(0,box_y,box_z)
box_mid_pt(0) = box_x/2
box_mid_pt(1) = box_y/2
box_mid_pt(2) = box_z/2
box = Rhino.AddBox(box_pt)
End If
If Not IsNull(arrObjects) Then
For Each strObject In arrObjects
arrPoint=Rhino.PointCoordinates(strObject)
Rhino.Print Rhino.Pt2Str(arrPoint, 3)
If multiplier_x > 0 Then
m1_x = arrPoint(0) / multiplier_x
m1_x = Rhino.Floor(m1_x)
m2_x = (arrPoint(0) – (m1_x*multiplier_x))*2
If m2_x > multiplier_x Then m1_x = m1_x+1
finalHeight_x = m1_x * multiplier_x
arrEnd(0) = finalHeight_x
ElseIf multiplier_x=0 Then
arrEnd(0) = arrPoint(0)
End If
If multiplier_y > 0 Then
m1_y = arrPoint(1) / multiplier_y
m1_y = Rhino.Floor(m1_y)
m2_y = (arrPoint(1) – (m1_y*multiplier_y))*2
If m2_y > multiplier_y Then m1_y = m1_y+1
finalHeight_y = m1_y * multiplier_y
arrEnd(1) = finalHeight_y
ElseIf multiplier_y=0 Then
arrEnd(1) = arrPoint(1)
End If
If multiplier_z > 0 Then
m1_z = arrPoint(2) / multiplier_z
m1_z = Rhino.Floor(m1_z)
m2_z = (arrPoint(2) – (m1_z*multiplier_z))*2
If m2_z > multiplier_z Then m1_z = m1_z+1
finalHeight_z = m1_z * multiplier_z
arrEnd(2) = finalHeight_z
ElseIf multiplier_z=0 Then
arrEnd(2) = arrPoint(2)
End If
Rhino.MoveObject strObject, arrPoint, arrEnd
If box_yn = 1 Then
Rhino.CopyObject box, box_mid_pt, arrEnd
End If
Next
If box_yn = 1 Then
Rhino.DeleteObject box
End If
End If
End Sub
Pixelate
I recently purchased a book which turned out to be one of the most amazing books I have ever come across: “A New Kind of Science” by Stephen Wolfram. The entire book is available online for viewing at: http://www.wolframscience.com/nksonline/toc.html
I have been reading a chapter on randomness, which is why I have been writing scripts that heavily depends on random number generator. These are the results of a growth algorithm that explores a territory that is somewhere in between being random and ordered.
A new script that I have been writing based on a script found in:
http://ncertainties3.wordpress.com/explicit-protocols/adam/181008_weldedwire/
The script diffuses any curve into smaller pieces of lines depending on a few parameters.
Merry Christmas, btw :)
Some tests:
This is still under a lot of progress. Just exploring ways to randomly populate a surface with mesh objects in this case with bikes and tanks.
Just a random study. Each cell is a a solid box carved by a sphere that is changing in shape performed by BooleanDifference in Rhino.
It’s been interesting to see how Korean students are almost always forced to memorize infinite amount of information as part of their education. If one fails to do so, unwanted consequences ranging from lower test scores to physical punishments follow. In efforts to compete and be successful in this system, the students often choose a path that maximizes their ability to memorize facts: learning through repetition. From this a type of art emerge, the process of learning is expressed through blank pieces of paper, ink, and time. The students refer to this as Ggamji meaning black paper.
It’s interesting to find that Koreans from few hundred years ago also had very similar ways of learning. These are scans of old books that you can easily buy all over Korea. These are traces of students from the past copying their textbooks over and over to memorize the contents. It’s a funny feeling buying thousands of hours of one’s effort to learn with just a few bucks.
Some images of an on-going facade design. Same-sized fins. Varied rotations.
Under progress, progress, and more progress.
I’ve been trying to explore more with Rhino Explicit History and also with RhinoScript. Here’s a simple one that arrays basic object onto a surface and orients them to a target surface. It doesn’t deform the base object in any ways. It could be a useful tool in trying to create gradient patterns using just rotations without changing the shape of the basic components (so the fabrication process is more efficient). RhinoScript is still quite new to me. I started with the Honeycomb script that Andrew Kudless wrote few years ago. The code still needs to be more optimized and cleaned up. But, the code works nonetheless.
—-
Option Explicit
‘by Andrew Kudless | andrew@materialsystems.org | april, 2005
‘Edited by Howard Jiho Kim | kimjiho@gmail.com | March, 2008
Sub OrientObjTwoSurfaces()
Dim orientObj
Dim orientPoint(2)
Dim sourceSurf, sourceSurf2
Dim uDiv, vDiv, maxDiv
Dim uArray, vArray
Dim i,j, index
‘surface 1 variables
Dim uMax, vMax
Dim uInc, vInc
Dim uStart, vStart
‘surface 2 variables
Dim u2Max, v2Max
Dim u2Inc, v2Inc
Dim u2Start, v2Start
‘surface points variables
Dim arrParam(1), arr2Param(1), arrPoint, arr2Point
Dim surface1Points(), surface2Points()
‘Rhino.EnableRedraw vbFalse
orientObj = Rhino.GetObject (“Select the Object to Orient”)
If IsNull(orientObj) Then Exit Sub
orientPoint(0) = Rhino.GetPoint(“Select Point 1 to Orient”)
If IsNull(orientPoint(0)) Then Exit Sub
orientPoint(1) = Rhino.GetPoint(“Select Point 2 to Orient”)
If IsNull(orientPoint(1)) Then Exit Sub
orientPoint(2) = Rhino.GetPoint(“Select Point 3 to Orient”)
If IsNull(orientPoint(2)) Then Exit Sub
uDiv = Rhino.GetInteger (“Enter the number of divisions in the U direction”)
If IsNull(uDiv) Then Exit Sub
vDiv = Rhino.GetInteger (“Enter the number of divisions in the V direction”)
If IsNull(vDiv) Then Exit Sub
‘Get inputs
sourceSurf = Rhino.GetObject (“Select the base Surface”, 8)
If IsNull(sourceSurf) Then Exit Sub
‘Get inputs
sourceSurf2 = Rhino.GetObject (“Select a target Surface”, 8)
If IsNull(sourceSurf2) Then Exit Sub
ReDim uVal(uDiv)
ReDim vVal(vDiv)
ReDim u2Val(uDiv)
ReDim v2Val(vDiv)
uMax = Rhino.SurfaceDomain (sourceSurf, 0)
vMax = Rhino.SurfaceDomain (sourceSurf, 1)
uInc = uMax(1)/uDiv
vInc = vMax(1)/vDiv
For i = 0 To uDiv
uVal(i) = i * uInc
Rhino.Print “uVal(” & i & “):” & uVal(i)
Next
For i = 0 To vDiv
vVal(i) = i * vInc
Rhino.Print “vVal(” & i & “):” & vVal(i)
Next
u2Max = Rhino.SurfaceDomain (sourceSurf2, 0)
v2Max = Rhino.SurfaceDomain (sourceSurf2, 1)
u2Inc = u2Max(1)/uDiv
v2Inc = v2Max(1)/vDiv
For i = 0 To uDiv
u2Val(i) = i * u2Inc
Rhino.Print “u2Val(” & i & “):” & u2Val(i)
Next
For i = 0 To vDiv
v2Val(i) = i * v2Inc
Rhino.Print “v2Val(” & i & “):” & v2Val(i)
Next
Rhino.Print “Calculating Array…”
‘Find which direction has more points
If uDiv >= vDiv Then
maxDiv = uDiv
Else
maxDiv = vDiv
End If
‘ARRAY POINS on SURFACE1
Dim targetPoint(2)
Dim p1, arrVector, NewLine, NewLine2, line1, line2, line3, arrXform
Dim arrPlane, arrRotated
For i=0 To uDiv
For j=0 To vDiv
arrParam(0) = uVal(i)
arrParam(1) = vVal(j)
arrPoint = Rhino.EvaluateSurface(sourceSurf, arrParam)
line1 = Rhino.AddPoint(arrPoint)
targetPoint(0) = Rhino.PointCoordinates(line1)
arr2Param(0) = uVal(i)
arr2Param(1) = vVal(j)
arr2Point = Rhino.EvaluateSurface(sourceSurf2, arr2Param)
line2 = Rhino.AddPoint(arr2Point)
targetPoint(2) = Rhino.PointCoordinates(line2)
NewLine = Rhino.AddLine (arrPoint, arr2Point)
arrVector = Rhino.VectorCreate(arr2Point, arrPoint)
Rhino.ViewCPlane , Rhino.PlaneFromNormal(arrPoint, arrVector)
arrPlane = ViewCPlane
arrRotated = RotatePlane(arrPlane, 90, arrPlane(1))
Rhino.ViewCPlane , arrRotated
arrPlane = ViewCPlane
NewLine2 = Rhino.RotateObject(NewLine, arrPlane(0), 90.0, ,True)
arrPoint = Rhino.CurveEndPoint(NewLine2)
line3 = Rhino.AddPoint(arrPoint)
targetPoint(1) = Rhino.PointCoordinates(line3)
If IsArray(orientPoint) Then
If IsArray(targetPoint) Then
Rhino.OrientObject orientObj, orientPoint, targetPoint, 1
End If
End If
Rhino.DeleteObject (line1)
Rhino.DeleteObject (line2)
Rhino.DeleteObject (line3)
‘Rhino.DeleteObject (NewLine)
Rhino.DeleteObject (NewLine2)
Next
Next
‘Rhino.EnableRedraw vbTrue
End Sub
OrientObjTwoSurfaces
Rhino.Print “Array Complete”