Rhinoscript, Voronoi diagram

Bookmark and Share

First, This code is based in an algorithm described in a David Rutten paper I read in 2006-07. I couldn’t resolve mathematically the intersection of the bisectors. Therefore I use the Curve Boolean Command in Rhino. To use the code and generate your VD, needs to select some points and a closed curve around the points. The code is quite spectacular because is flashing when the lines are selected.

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
Option Explicit
 
Call VoronoiTiles()
Sub VoronoiTiles()
 
	Dim ptCloud, BBox, i
 
	'input nube de puntos
	ptCloud = Rhino.GetPointCoordinates()
	If IsNull(ptCloud) Then Exit Sub
 
	BBox = Rhino.GetObject("sel the boundary of the building", 4) '//select the boundaries of the building...
	If IsNull(Rhino.IsPolyline(BBox)) Then Exit Sub
 
	For i = 0 To UBound(ptCloud)
 
		'call the function Voronoi
		Call VoronoiPolygon(i, PtCloud, BBox) 
 
	Next
 
End Sub
 
 
'voronoi function         i  the points bounding box
Function VoronoiPolygon(index, datSet, BBox)
 
	'this is not necessary, is in case the function failed...
	VoronoiPolygon = Null
 
	Dim midPt
	Dim ChordLength, Border
	Dim brdLines(), i, N
	Dim Ovec, PerpVec, Ovec2, PerpVec2, Sp, Ep
	ReDim brdLines(UBound(datSet)-1)
 
	Dim pts :  pts = Rhino.PolylineVertices(BBox)
	ChordLength = Rhino.Distance(pts(0), pts(2)) * 0.6
	N = 0
 
	Call Rhino.EnableRedraw(False)
 
	'i will run for each point in the datSet, previously called ptCloud...
	For i = 0 To UBound(datSet)
 
		'If i is not equal to the index, preiviously called also i. then...
		If i <> index Then
 
			'calc the mid point...out of the function Voronoi...
			midPt = CalcMidPt(datSet(i), datSet(index))
 
			Ovec = Rhino.VectorCreate(datSet(i), datSet(index)) 'here create from the "point" to the other points a vector.
			PerpVec = rhino.VectorCrossProduct(Ovec, Array(0, 0, 1)) 'here we calculate a perpendicular vector from the original vector.
			
			Ovec2 = Rhino.VectorCreate(datSet(index), datSet(i)) 'the same to the other direction
			PerpVec2 = rhino.VectorCrossProduct(Ovec2, Array(0, 0, 1)) 
 
			PerpVec = Rhino.VectorUnitize(PerpVec) 'here we unitize the vectors, now the vectors has length 1
			PerpVec2 = Rhino.VectorUnitize(perpVec2)
 
			'here we scale the vectors for the distance of the points multiplicated for the size of the BBox
			PerpVec = Rhino.VectorScale(PerpVec, Rhino.Distance(datSet(i), datSet(index)) * ChordLength) 
			PerpVec2 = Rhino.VectorScale(perpVec2, Rhino.Distance(datSet(i), datSet(index)) * ChordLength)
 
			Sp = Rhino.PointAdd(midPt, PerpVec) 'create a point in the end of the vector.
			Ep = Rhino.PointAdd(midPt, PerpVec2)
 
			'here we store each line inside of array
			brdLines(N) = Rhino.AddLine(Sp, Ep)
			N = N + 1
 
		End If
	Next
	Call Rhino.EnableRedraw(True)
 
	Call Rhino.UnselectAllObjects()
	Call Rhino.SelectObjects(brdLines)
	Call Rhino.SelectObject(BBox)
 
	Rhino.Command "-_CurveBoolean _DeleteInput=Yes _CombineRegions=No " & Rhino.Pt2Str(Array(datSet(index)(0), datSet(index)(1), datSet(index)(2))) & " _Enter", vbFalse
 
	'//delete extra lines and borders...
	Call Rhino.DeleteObjects(brdLines) 
	Rhino.Command " -ClearUndo "
 
End Function
 
Function CalcMidPt(a, b)
	CalcMidPt = Array((a(0) + b(0)) / 2, (a(1) + b(1)) / 2, 0)
End Function

Leave a Reply