-
Notifications
You must be signed in to change notification settings - Fork 26
Expand file tree
/
Copy pathshell_sort_scale.py
More file actions
168 lines (127 loc) · 6.08 KB
/
shell_sort_scale.py
File metadata and controls
168 lines (127 loc) · 6.08 KB
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
import bpy
import random
from mathutils import Vector, Matrix
############################################################
# Shell Sort Algorithm
############################################################
def shellSort(arr, n, arrayCounter, comparisonCounter):
global iframe
gap=n//2
while gap>0:
j=gap
# Check the array in from left to right
# Till the last possible index of j
while j<n:
i=j-gap # This will keep help in maintain gap value
while i>=0:
for cube in arr:
cube.keyframe_insert(data_path="location", frame= iframe)
#add 1 to comparison counter
comparisonCounter.inputs[0].default_value += 1
comparisonCounter.inputs[0].keyframe_insert(data_path='default_value', frame=iframe)
#add 2 to array counter
arrayCounter.inputs[0].default_value += 2
arrayCounter.inputs[0].keyframe_insert(data_path='default_value', frame=iframe)
# If value on right side is already greater than left side value
# We don't do swap else we swap
if arr[i+gap].scale.z > arr[i].scale.z:
break
else:
arr[i+gap].location.x = i
arr[i].location.x = i + gap
arr[i+gap].keyframe_insert(data_path="location", frame= iframe)
arr[i].keyframe_insert(data_path="location", frame= iframe)
iframe += 1
arr[i+gap],arr[i] = arr[i],arr[i+gap]
#add 4 to array counter
arrayCounter.inputs[0].default_value += 4
arrayCounter.inputs[0].keyframe_insert(data_path='default_value', frame=iframe)
i=i-gap # To check left side also
# If the element present is greater than current element
j+=1
gap=gap//2
############################################################
# Setup Random Cubes + Array to be sorted
############################################################
def setup_array(count):
#initialize array
cubes=[]
#delete every existing node_group
for grp in bpy.data.node_groups:
bpy.data.node_groups.remove(grp)
#delete every existing object
for ob in bpy.data.objects:
bpy.data.objects.remove(ob)
#add counter object, set position of counter object below other cube
bpy.ops.mesh.primitive_cube_add(location = (-2.5, 0, -3.375))
bpy.context.active_object.name = 'Counter'
#add geometry node modifier
bpy.ops.object.modifier_add(type='NODES')
#get and clear node_group
node_grp = bpy.data.node_groups[-1]
node_grp.nodes.clear()
#add nodes
stringToCurves = node_grp.nodes.new("GeometryNodeStringToCurves")
fillCurve = node_grp.nodes.new("GeometryNodeFillCurve")
transform = node_grp.nodes.new("GeometryNodeTransform")
joinStrings = node_grp.nodes.new("GeometryNodeStringJoin")
comparisonString = node_grp.nodes.new("FunctionNodeInputString")
comparisonCounter = node_grp.nodes.new("FunctionNodeValueToString")
arrayString = node_grp.nodes.new("FunctionNodeInputString")
arrayCounter = node_grp.nodes.new("FunctionNodeValueToString")
groupOutput = node_grp.nodes.new('NodeGroupOutput')
#90 degree rotation of the transform node of counter object
transform.inputs[2].default_value[0] = 1.5708
#set default values of some nodes
comparisonString.string = "Comparisons:"
arrayString.string = "Array Accesses:"
stringToCurves.inputs[1].default_value = 2
joinStrings.inputs[0].default_value = " "
#connect nodes to eachother
node_grp.links.new(fillCurve.outputs[0], groupOutput.inputs[0])
node_grp.links.new(transform.outputs[0], fillCurve.inputs[0])
node_grp.links.new(stringToCurves.outputs[0], transform.inputs[0])
node_grp.links.new(joinStrings.outputs[0], stringToCurves.inputs[0])
node_grp.links.new(comparisonCounter.outputs[0], joinStrings.inputs[1])
node_grp.links.new(comparisonString.outputs[0], joinStrings.inputs[1])
node_grp.links.new(arrayCounter.outputs[0], joinStrings.inputs[1])
node_grp.links.new(arrayString.outputs[0], joinStrings.inputs[1])
#add keyframe on frame 0 for comparison and array counter
comparisonCounter.inputs[0].keyframe_insert(data_path='default_value', frame=0)
arrayCounter.inputs[0].keyframe_insert(data_path='default_value', frame=0)
#fill arrays with numbers between 1 & count
ran = list(range(0,count-1))
#randomize array order
random.shuffle(ran)
#sets origin of cube to bottom of mesh
def origin_to_bottom(ob, matrix=Matrix()):
me = ob.data
mw = ob.matrix_world
local_verts = [matrix @ Vector(v[:]) for v in ob.bound_box]
o = sum(local_verts, Vector()) / 8
o.z = min(v.z for v in local_verts)
o = matrix.inverted() @ o
me.transform(Matrix.Translation(-o))
mw.translation = mw @ o
#create cubes with random location
for i in range(count-1):
bpy.ops.mesh.primitive_cube_add(location=(ran[i], 0, 0), scale=(0.25, 0.25, 0.25))
#shuffle array
random.shuffle(ran)
#assign random scale to all cubes and add them to array
s = 0
for ob in bpy.data.objects:
if ob.type == 'MESH' and ob.name != "Counter":
origin_to_bottom(ob)
ob.scale.z = ran[s]+1
cubes.append(ob)
s += 1
#sort array based on location.x
cubes.sort(key = lambda obj: obj.location.x)
return (cubes, arrayCounter, comparisonCounter)
############################################################
# Call Functions
############################################################
cubes, arrayCounter, comparisonCounter = setup_array(50)
iframe = 1
shellSort(cubes, len(cubes), arrayCounter, comparisonCounter)