Rhinoscript, Sphere packing

This code generates a Sphere packing, I full commented so you can follow the data flow of the code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
Call Main()
Sub Main()
	Dim Pt, R
 
	'aqui creamos nuestra primera sfera
	Pt = Array(Rnd * 300, Rnd * 50, Rnd * 100)
 
	'nos devuelve un array donde viene la superficie y el centro de la esfera.
	R = FuncCir(Pt, 20)
	Call Rhino.EnableRedraw(False)
	Call Pack(R)
	Call Rhino.EnableRedraw(True)
End Sub
 
Function Pack(R)
	Dim Pt, i, count
 
	'el script se para y pregunta, cuantas iteraciones
	count = Rhino.GetInteger(" number of Iterations ", 50, 2, 3000)
	If IsNull(count) Then Exit Function
 
	'creamos un array dinamico para comenzar a almacenar los centros de las esferas
	'y sus superficies
	Dim ArrData()
 
	'este loop corre por cada una de las iteraciones y 
	'va incrementando en 1 cada vez
	For i = 0 To count
 
		'redim preserve vamos almacenando datos cada vez
		'el primer dato en almacenar es el centro y la superficie de la esfera.
		ReDim Preserve ArrData(i)
		ArrData(i) = R
 
		'construimos un punto
		Randomize
		Pt = Array(Rnd * 300, Rnd * 50, Rnd * 100)
 
		'te lo usamos para contar
		Dim j
		Dim t: t = 0
 
		'este loop es para testear si el punto está dentro de una de las esferas
		For j = 0 To UBound(ArrData)
 
			'aqui buscamos el punto más cercano al centro de la superficie
			Dim uvPt: uvPt = Rhino.SurfaceClosestPoint(ArrData(j)(0), ArrData(j)(1))
 
			'aqui transformamos ese punto encontrado al espacio 3R para poder calcular su distancia
			Dim TPoint: Tpoint = Rhino.EvaluateSurface(ArrData(j)(0), uvPt)
 
			'aqui calculamos la distancia de este punto al centro de la sfera
			Dim DistSpe: DistSpe = Rhino.Distance(Tpoint, Arrdata(j)(1))
 
			'si el radio de la esfera es menor a la distancia entre el punto recien creado
			'quiere decir que el punto está dentro de la esfera, de lo contrario está fuera.
			If  DistSpe > Rhino.Distance(ArrData(j)(1), Pt)Then
				Call Rhino.print(" point In Sphere ")
				t = t + 1
 
			End If
		Next
 
		'si el punto no se ha encontrado dentro de ninguna esfera quiere decir que está libre
		'y se puede continuar.
		If (t = 0) Then
 
			'creamos un Array para almacenar todas las lineas y encontrar la esfera más cercana
			ReDim ArrLine(UBound(ArrData))
			Dim k, line
 
			'este array va recorriendo cada una de las esferas.
			'y haciendo una linea del pt testeado al centro de cada una de las esferas.
			For K = 0 To UBound(ArrData)
				line = Rhino.AddLine(Pt, ArrData(k)(1))
				ArrLine(k) = Line
			Next
 
			'llamamos a la función dist
			Dim d, d2, l
			'           punto la esfera    la primera linea
			d = funcDist(Pt, ArrData(0)(0), ArrLine(0))
 
			For l = 0 To UBound(ArrLine)
 
				d2 = funcDist(Pt, ArrData(l)(0), ArrLine(l))
 
				If d < d2 Then
					'Call Rhino.Print (”Nothing”)

				Else
					d = d2
 
				End If
			Next
 
			R = FuncCir(Pt, d)
			Call Rhino.DeleteObjects(ArrLine)
 
		End If
	Next
End Function
 
Function FuncCir(p, D)
 
	If  D >= 20 Then
		D = 20
	End If
 
	'aqui construimos la esfera
	Dim R(1)
	Dim sphere
	sphere = Rhino.AddSphere(p, D)
 
	'y los datos que estamos sacando fuera son la superficie
	'de la esfera y el centro de ella
	R(0) = Sphere
	R(1) = p
 
	'intIndex = Rhino.AddMaterialToObject(strObject)
	
 
	FuncCir = R
End Function
 
Function funcDist(Pt, surfaceP, Line)
	Dim Ap, j, d
 
	AP = Rhino.CurveSurfaceIntersection(Line, surfaceP) 
 
	For j = 0 To UBound(Ap)
		d = Rhino.Distance(Pt, Ap(j, 3))
	Next
 
	funcDist = d
End Function

Leave a Reply