RhinoScript morphodynamic

From KokkugiaWiki

this tutorial covers the basics of a morphodynamic design strategy based on attractors. the first script demonstrates how a field of geometry can undergo simple transformations at a local level based on the proximity of a field of attractors. the second script looks at how more complex parametric transformations can be developed.

attractor tools scale

this script is used for scaling up or down fields of objects. however it is easy to modify the script to do more interesting things than scaling. in its current format it generates things like the following:

download this rhino file which contains the base geometry to operate on.

the pseudo-code for the script looks something like the following: 'define the variables

' user defined input

' loop through each object and get the closest attractor

' get object center point

' loop through attractors to find the distance to the closest attractor

' get distance from the object center point to the attractor

' is it closer then keep track of the distance and the attractor

' if the object is within the threshold then operate on it

Option Explicit

' script written by roland snooks 2007 www.kokkugia.com

Call attractorToolsScale

Sub attractorToolsScale

Dim i, j, arrObjects, arrAttract, thresholdDist, scaleFactor, arrBBox, arrCntrPt, counter, arrAttPt

Dim dblAttDistTest, dblClosestAttDist, dblClosestAtt, adjAmount

' input

arrObjects = Rhino.GetObjects("select objects")

arrAttract = Rhino.GetObjects("select point attractors", 0)

thresholdDist = Rhino.GetReal("distance threshold", 10, 0)

scaleFactor = Rhino.GetReal("scale factor", 1, 0)

' loop through each object and get the closest attractor

For i = 0 To UBound(arrObjects)

' get object bounding box centerpoint

arrBBox = Rhino.BoundingBox(arrObjects(i))

arrCntrPt = array((((arrBBox(2)(0)) + (arrBBox(0)(0))) / 2), (((arrBBox(2)(1)) + (arrBBox(0)(1))) / 2), (((arrBBox(0)(2)) + (arrBBox(4)(2))) / 2))

' loop through attractors to find the distance to the closest

counter = 0

For j = 0 To UBound(arrAttract)

arrAttPt = Rhino.PointCoordinates(arrAttract(j))

' get distance

dblAttDistTest = Rhino.Distance(arrAttPt, arrCntrPt)

' is it closer

If counter < 1 Then

dblClosestAttDist = dblAttDistTest

dblClosestAtt = counter

Else

If dblAttDistTest < thresholdDist Then

If dblAttDistTest < dblClosestAttDist Then

dblClosestAttDist = dblAttDistTest

dblClosestAtt = counter

End If

End If

End If

counter = counter + 1

Next

' if the object is within the threshold then operate on it

If dblClosestAttDist < thresholdDist Then

' caculate the adjustment amount

' decrease infinite amount

adjAmount = 1 - ((thresholdDist - dblClosestAttDist)/thresholdDist)

' increase by factor of up to 100% x scaleFactor

'adjAmount = ((thresholdDist - dblClosestAttDist)/thresholdDist) * scaleFactor + 1

' based on attractor proximity do something to the object (eg scale)

' scale

Rhino.ScaleObject arrObjects(i), arrCntrPt, array(adjAmount,adjAmount,adjAmount)

End If

Next

End Sub

in addition to scaling the objects we could also modify their color. this is best done with a separate function: Function at_ChangeColor(obj,tDist,aDist,sFactor)

Dim objColor, newColor

' caculate color

newColor = 255 - ((1 - ((tDist - aDist)/tDist)) * 255)

' change color

objColor = Rhino.ObjectColor(obj, newColor)

End Function

this function would need to be called in the same part of the script where we call the scale method. at_ChangeColor arrObjects(i),thresholdDist,dblClosestAttDist,scaleFactor

to use curves instead of points as attractors you could replace the following line of code: arrAttPt = Rhino.PointCoordinates(arrAttract(j))

this bit of code is effectively getting the parameter of the closest point on the attractor curve and then returning the coordinates of that point. dblParam = Rhino.CurveClosestPoint(arrAttract(j), arrCntrPt)

arrAttPt = Rhino.EvaluateCurve(arrAttract(j), dblParam)

attractor tools parametric

the following function is an example of how a parametric component can be instantiated on a surface using a predefined polyline substrate. this function can be called from the attractorTools script, instead of calling the scale method, consequently it instantiates a parametric component using the attractor information as the input to the component.

download this rhino file which contains the base geometry to operate on.

the following line needs to be called at the end of the outer loop: at_Component arrObjects(i), srf, adjAmount

the parametric component uses simple vector math to essentially scale the polyline and project it along the surface normal a certain distance before surfacing

the result. Option Explicit

' script written by roland snooks 2007 www.kokkugia.com

Call attractorToolsScale

Sub attractorToolsScale

Dim i, j, arrObjects, arrAttract, thresholdDist, scaleFactor, arrBBox, arrCntrPt, counter, arrAttPt

Dim dblAttDistTest, dblClosestAttDist, dblClosestAtt, adjAmount, srf

' input

arrObjects = Rhino.GetObjects("select polygon tesselations", 4)

srf = Rhino.GetObject("select base surface", 16)

arrAttract = Rhino.GetObjects("select point attractors", 1)

thresholdDist = Rhino.GetReal("distance threshold", 5, 0)

scaleFactor = Rhino.GetReal("scale factor", 2, 0)

' loop through each object and get the closest attractor

For i = 0 To UBound(arrObjects)

' get object bounding box centerpoint

arrBBox = Rhino.BoundingBox(arrObjects(i))

arrCntrPt = array((((arrBBox(2)(0)) + (arrBBox(0)(0))) / 2), (((arrBBox(2)(1)) + (arrBBox(0)(1))) / 2), (((arrBBox(0)(2)) + (arrBBox(4)(2))) / 2))

' loop through attractors to find the distance to the closest

counter = 0

For j = 0 To UBound(arrAttract)

arrAttPt = Rhino.PointCoordinates(arrAttract(j))

' get distance

dblAttDistTest = Rhino.Distance(arrAttPt, arrCntrPt)

' is it closer

If counter < 1 Then

dblClosestAttDist = dblAttDistTest

dblClosestAtt = counter

Else

If dblAttDistTest < thresholdDist Then

If dblAttDistTest < dblClosestAttDist Then

dblClosestAttDist = dblAttDistTest

dblClosestAtt = counter

End If

End If

End If

counter = counter + 1

Next

' if the object is within the threshold then operate on it

If dblClosestAttDist < thresholdDist Then

' caculate the adjustment amount

adjAmount = 1 - ((thresholdDist - dblClosestAttDist)/thresholdDist) ' decrease infinite amount

'adjAmount = ((thresholdDist - dblClosestAttDist)/thresholdDist) * scaleFactor + 1 ' increase by factor of up to 100% x scaleFactor

' based on attractor proximity do something to the object (eg scale)

' scale

'Rhino.ScaleObject arrObjects(i), arrCntrPt, array(adjAmount,adjAmount,adjAmount) ' scale

' instantiate parametric component

at_Component arrObjects(i), srf, adjAmount

' change color

at_ChangeColor arrObjects(i),thresholdDist,dblClosestAttDist,scaleFactor

End If

Next

End Sub

Function at_Component(obj, srf, adjAmount)

Dim pts, centerPt, i, x, y, z, newPts(), srfNormal, closestPt, arrVertices(), arrFaceVertices(), ptCount, ptVec, scaleVec

' get the obj's points

pts = Rhino.PolylineVertices(obj)

' calculate the centerPoint of the pts

ptCount = UBound(pts)

For i = 0 To ptCount

x = x + pts(i)(0)

y = y + pts(i)(1)

z = z + pts(i)(2)

Next

centerPt = Array(x/(ptCount+1), y/(ptCount+1), z/(ptCount+1))

ReDim newPts(0)

' offset points to the inside

For i = 0 To ptCount

' calculate vector from pt to centerPt

ptVec = Rhino.VectorCreate(centerPt, pts(i))

' scale that vector based on adjAmount

scaleVec = Rhino.VectorScale(ptVec, adjAmount*5)

' make a new pt and add it to an array

ReDim Preserve newPts(i)

newPts(i) = Rhino.VectorAdd(pts(i), scaleVec)

Next

' get pt on srf closest to pt

closestPt = Rhino.SurfaceClosestPoint(srf, centerPt)

' get normal

srfNormal = Rhino.SurfaceNormal(srf, closestPt)

' move points normal based on adjAmount

For i = 0 To ptCount

' move each point by a factor of the normal

newPts(i) = Rhino.VectorAdd(newPts(i), Rhino.VectorScale(srfNormal, adjAmount) )

Next

Dim arrVertTemp, arrFaceTemp

' loop through all pts to make mesh

For i = 0 To ptCount

If i = ptCount Then

ReDim Preserve arrVertices(i)

arrVertices(i) = array(pts(i), newPts(i), newPts(0), pts(0))

Else

ReDim Preserve arrVertices(i)

arrVertices(i) = array(pts(i), newPts(i), newPts(i+1), pts(i+1))

End If

Rhino.AddPolyline arrVertices(i)

Rhino.AddSrfPt arrVertices(i)

ReDim Preserve arrFaceVertices(i)

arrFaceVertices(i) = array(0,1,2,3,3)

Next

'Rhino.AddMesh arrVertices, arrFaceVertices

End Function

Subscribe to:
Post Comments (Atom)

## No comments:

Post a Comment