RhinoScript – Attractors

hexattract

Example 01: Attractor Based Vector Transformations

 
Option Explicit
'Script written by www.supermanoeuvre.com
'Inputs can be either curves, or 3 or 

Call vectorGradientTransform()
 
Sub vectorGradientTransform()
 
	'-----------------------------------------------------------------------
	' USER INPUTS
	
	' ask user for object to transform
	Dim strObjs : strObjs = rhino.getObjects("gimme OBJECTS to transform", 4+8)
	If isNull(strObjs) Then Exit Sub
	' ask user for attractors
	Dim strAtts : strAtts = rhino.getObjects("gimme attracotr POINTS", 1)
	If isNull(strAtts) Then Exit Sub
 
	' change this to effect result!
	Dim dblScale : dblScale = 9500
 
	'-----------------------------------------------------------------------
	' SCRIPT BODY
	Dim i, j
	Dim gripNewLoc, arrGripLocs, strAttClosest, arrVec2Att, dblDistChk
 
	rhino.print "!!! SCRIPT HAS STARTED !!!"
	rhino.enableRedraw False
 
	For i = 0 To ubound(strObjs)
 
		' turn on object grips
		Rhino.EnableObjectGrips strObjs(i), True
		arrGripLocs = Rhino.ObjectGripLocations( strObjs(i) )
 
		' loop through grips & shift based of attractor
		For j = 0 To ubound(arrGripLocs)
			' call custom function
			strAttClosest = getClosestAttractor( arrGripLocs(j), strAtts )
			' make a vector to the closest attractor
			arrVec2Att = rhino.VectorCreate( strAttClosest(1), arrGripLocs(j) )			
			' create a falloff - math opertion to make a gradient of effect
			Dim vecScale : vecScale   = dblScale * ( strAttClosest(2) / ((strAttClosest(2)*strAttClosest(2))))
			arrVec2Att = Rhino.VectorUnitize (arrVec2Att)
			arrVec2Att = Rhino.VectorScale (arrVec2Att, vecScale )
			gripNewLoc = Rhino.PointAdd (arrGripLocs(j), arrVec2Att)
 
			' check that result point is not further than attractor otherwise it is wierd!
			dblDistChk = rhino.Distance( arrGripLocs(j), gripNewLoc )			
			If dblDistChk > strAttClosest(2) Then
				gripNewLoc = strAttClosest(1)
			End If
 
			' move object grip to new location
			Rhino.ObjectGripLocation strObjs(i), j, gripNewLoc
 
		Next
 
		' turn off grip
		Rhino.EnableObjectGrips strObjs(i), False
 
 
		rhino.print CInt( (i/ubound(strObjs)) * 100 ) & "% objects completed"
 
	Next
 
	rhino.enableRedraw True
	rhino.print "!!! SCRIPT HAS COMPLETED !!!"
 
 
End Sub
 
Function getClosestAttractor( PT, OBJS )
 
	getClosestAttractor = Null
 
	' Declare / Create a static array with 3 slots of information
	Dim arrAttInfo(2) 
	' arrAttInfo(0) = strName of the Attractor
	' arrAttInfo(1) = coordinate of the attractor
	' arrAttInfo(2) = distance to the attractor
	
	Dim i
	Dim arrPtTest, dblDistTest, dblDistClosest, intIndex
	' intIndex will keep track of the closest attractor ---- OBJS(intIndex)
	intIndex = 0
	dblDistClosest = 999999999
 
	For i = 0 To ubound(OBJS)
		arrPtTest   = rhino.pointCoordinates( OBJS(i) )
		dblDistTest = rhino.Distance( PT, arrPtTest )
		If dblDistTest < dblDistClosest Then
			dblDistClosest = dblDistTest
			intIndex = i
		End If		
	Next
 
	arrAttInfo(0) = OBJS(intIndex)
	arrAttInfo(1) = rhino.pointCoordinates( OBJS(intIndex) ) 
	arrAttInfo(2) = dblDistClosest
 
	getClosestAttractor = arrAttInfo
 
End Function

attracted

Example 02: Attractor Based Scale Operations

 
Option Explicit
 
' script written by www.supermanoeuvre.com

Call Main
 
Sub Main()
 
        'declarations
	Dim intXSize_, intYSize_, intZSize_, strObject, strObject2, dblScaleFactor
 
        'user input
	intXSize_ = Rhino.GetInteger("Input the number of copies in X, please",5,2,50)
	If IsNull(intXSize_) Then Exit Sub
 
	intYSize_ = Rhino.GetInteger("Input the number of copies in Y, please",5,2,50)
	If IsNull(intYSize_) Then Exit Sub
 
	intZSize_ = Rhino.GetInteger("Input the number of copies in Z, please",5,2,50)
	If IsNull(intZSize_) Then Exit Sub
 
	dblScaleFactor = Rhino.GetReal("Input global scale factor, please",.1)
	If IsNull(dblScaleFactor) Then Exit Sub
 
	strObject  = Rhino.GetObject("give me an object to copy around")
	If IsNull(strObject) 	Then Exit Sub
 
        'call custom sub
	Call makeCopiesXYZ(intXSize_,intYSize_,intZSize_,strObject, dblScaleFactor)
 
End Sub
 
Sub makeCopiesXYZ(intXSize, intYSize, intZSize, strObject, dblScaleFactor)
 
	Dim strMessage, i, j, k, arrEnd, strCopiedObject, arrCenter, dblShortestDistance
        Dim dblScale, arrScale
 
	rhino.Print strObject
 
	'loop for x-dimension
	For i = 0 To intXSize - 1
 
                'loop for y-dimension
		For j = 0 To intYSize - 1
 
                        'loop for z-dimension
			For k = 0 To intZSize - 1
 
				Dim arrStart : arrStart = array(-1,-1,-1)
				arrEnd     = array(i,j,k)
 
				strCopiedObject = rhino.CopyObject(strObject,arrStart,arrEnd)
 
				'call custom function
				arrCenter = getBBoxCentroid(strCopiedObject)
 
				'call custom function
				dblShortestDistance = getDistance2ClosestPt(arrCenter)
 
                               dblScale = dblShortestDistance*dblScaleFactor
 
                               arrScale = array(dblScale, dblScale, dblScale)
 
				Call Rhino.ScaleObject(strCopiedObject, arrCenter, arrScale)
 
				'Call Rhino.AddTextDot(arrCenter(0) & "," & arrCenter(1) & "," & arrCenter(2),arrCenter)
				
			Next 'end the k loop	
			
		Next 'end the j loop

	Next 'end the i loop

End Sub
 
Function getBBoxCentroid(strObject)
 
	getBBoxCentroid = Null
 
	Dim arrBoundingBox, x, y, z
 
	arrBoundingBox = Rhino.BoundingBox (strObject)
 
        'find the center of the bounding box by averaging the positions of two diagonal corners
	x = (arrBoundingBox(0)(0) + arrBoundingBox(6)(0))/2
	y = (arrBoundingBox(0)(1) + arrBoundingBox(6)(1))/2
	z = (arrBoundingBox(0)(2) + arrBoundingBox(6)(2))/2
 
	getBBoxCentroid = array(x,y,z)
 
End Function
 
Function getDistance2ClosestPt(arrCenter)
 
	getDistance2ClosestPt = Null
 
	Dim arrPointIDs, arrPointPosition, dblDistance, dblShortestDistance, i
 
	'get a list of all the points
	arrPointIDs = Rhino.ObjectsByType(1)
 
	'make the shortest distance massive to ensure the first sampled point is closer
	dblShortestDistance = 9999999999999999999999
 
	'loop through the points one at a time
	For i = 0 To Ubound(arrPointIDs)
 
		'get the position (x,y,z)
		arrPointPosition = Rhino.PointCoordinates(arrPointIDs(i))
 
		'find the current distance and store it
		dblDistance = Rhino.Distance(arrCenter,arrPointPosition)
 
		'test IF it is the closest so far
		If (dblDistance < dblShortestDistance) Then
 
			'if it is then store it as the closest
			dblShortestDistance = dblDistance
 
		End If
 
		'go to the next point

	Next
 
	'once i have done all points return the closest distance
	
	getDistance2ClosestPt = dblShortestDistance
 
End Function

GO BACK TO CODESHARE PAGE


About this entry