-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLorentzattractor.py
150 lines (120 loc) · 4.94 KB
/
Lorentzattractor.py
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
import bpy
import math
import numpy as np
def get_grease_pencil(gpencil_obj_name='GPencil') -> bpy.types.GreasePencil:
"""
Return the grease-pencil object with the given name. Initialize one if not already present.
:param gpencil_obj_name: name/key of the grease pencil object in the scene
"""
# If not present already, create grease pencil object
if gpencil_obj_name not in bpy.context.scene.objects:
bpy.ops.object.gpencil_add(location=(0, 0, 0), type='EMPTY')
# rename grease pencil
bpy.context.scene.objects[-1].name = gpencil_obj_name
# Get grease pencil object
gpencil = bpy.context.scene.objects[gpencil_obj_name]
return gpencil
def get_grease_pencil_layer(gpencil: bpy.types.GreasePencil, gpencil_layer_name='GP_Layer',
clear_layer=False) -> bpy.types.GPencilLayer:
"""
Return the grease-pencil layer with the given name. Create one if not already present.
:param gpencil: grease-pencil object for the layer data
:param gpencil_layer_name: name/key of the grease pencil layer
:param clear_layer: whether to clear all previous layer data
"""
# Get grease pencil layer or create one if none exists
if gpencil.data.layers and gpencil_layer_name in gpencil.data.layers:
gpencil_layer = gpencil.data.layers[gpencil_layer_name]
else:
gpencil_layer = gpencil.data.layers.new(gpencil_layer_name, set_active=True)
if clear_layer:
gpencil_layer.clear() # clear all previous layer data
# bpy.ops.gpencil.paintmode_toggle() # need to trigger otherwise there is no frame
return gpencil_layer
# Util for default behavior merging previous two methods
def init_grease_pencil(gpencil_obj_name='GPencil', gpencil_layer_name='GP_Layer',
clear_layer=True) -> bpy.types.GPencilLayer:
gpencil = get_grease_pencil(gpencil_obj_name)
gpencil_layer = get_grease_pencil_layer(gpencil, gpencil_layer_name, clear_layer=clear_layer)
return gpencil_layer
def draw_line(gp_frame, p0: tuple, p1: tuple):
# Init new stroke
gp_stroke = gp_frame.strokes.new()
gp_stroke.display_mode = '3DSPACE' # allows for editing
# Define stroke geometry
gp_stroke.points.add(count=2)
gp_stroke.points[0].co = p0
gp_stroke.points[1].co = p1
return gp_stroke
def draw_circle(gp_frame, center: tuple, radius: float, segments: int):
# Init new stroke
gp_stroke = gp_frame.strokes.new()
gp_stroke.display_mode = '3DSPACE' # allows for editing
gp_stroke.draw_cyclic = True # closes the stroke
#gp_stroke.line_width = 100
#gp_stroke.material_index = 1
# Define stroke geometry
angle = 2*math.pi/segments # angle in radians
gp_stroke.points.add(count=segments)
for i in range(segments):
x = center[0] + radius*math.cos(angle*i)
y = center[1] + radius*math.sin(angle*i)
z = center[2]
gp_stroke.points[i].co = (x, y, z)
return gp_stroke
def rotate_stroke(stroke, angle, axis='z'):
# Define rotation matrix based on axis
if axis.lower() == 'x':
transform_matrix = np.array([[1, 0, 0],
[0, math.cos(angle), -math.sin(angle)],
[0, math.sin(angle), math.cos(angle)]])
elif axis.lower() == 'y':
transform_matrix = np.array([[math.cos(angle), 0, -math.sin(angle)],
[0, 1, 0],
[math.sin(angle), 0, math.cos(angle)]])
# default on z
else:
transform_matrix = np.array([[cos(angle), -math.sin(angle), 0],
[sin(angle), math.cos(angle), 0],
[0, 0, 1]])
# Apply rotation matrix to each point
for i, p in enumerate(stroke.points):
p.co = transform_matrix @ np.array(p.co).reshape(3, 1)
def draw_sphere(gp_frame, center: tuple, radius: int, circles: int):
angle = math.pi / circles
for i in range(circles):
circle = draw_circle(gp_frame, center, radius, 32)
rotate_stroke(circle, angle*i, 'x')
print(angle * i)
gp_layer = init_grease_pencil()
sigma = 10
beta = 8/3
ro = 28
#init coords
x = 1
y = 1
z = 1
dt = 0.01
prevpos = [(x,y,z),]
def lorrentz(x,y,z,dt):
dx = (sigma*(y-x))*dt
dy = (x*(ro - z) - y)*dt
dz = (x*y - beta*z)*dt
return (dx,dy,dz)
for frama in range(0,1000):
gp_frame = gp_layer.frames.new(frama)
dxyz = lorrentz(x,y,z,dt)
newcoords = (x+dxyz[0],y+dxyz[1],z+dxyz[2])
if(np.linalg.norm(np.array((x,y,z)) - np.array(newcoords)) < 0.1):
pass
else:
prevpos.append(newcoords)
gp_stroke = gp_frame.strokes.new()
gp_stroke.display_mode = '3DSPACE' # allows for editing
gp_stroke.line_width = 200
gp_stroke.material_index = 1
for cpos in range(1,len(prevpos)-1):
draw_line(gp_frame,prevpos[cpos-1],prevpos[cpos])
x+=dxyz[0]
y+=dxyz[1]
z+=dxyz[2]