or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

animation.mdcolor-management.mdcommunication.mdconfiguration.mdindex.mdvisual-display.mdvscode-integration.md

animation.mddocs/

0

# Animation System

1

2

Animation framework for creating animated sequences of CAD assemblies with timeline-based keyframe animation. The system enables smooth movement, rotation, and transformation of CAD objects over time using three.js animation tracks.

3

4

## Capabilities

5

6

### Animation Class

7

8

Main class for creating and managing animations of CAD assemblies.

9

10

```python { .api }

11

class Animation:

12

"""

13

Create animations for CAD assemblies with support for both CadQuery and build123d assemblies.

14

15

The Animation class manages multiple animation tracks that can be applied to different

16

objects within an assembly, allowing complex coordinated movements.

17

"""

18

19

def __init__(self, assembly):

20

"""

21

Initialize animation for a CAD assembly.

22

23

Parameters:

24

assembly: CAD assembly object (CadQuery Assembly or build123d Assembly)

25

The assembly must contain named objects that can be referenced

26

by path strings in animation tracks.

27

28

Attributes:

29

tracks (list): List of animation tracks added to the animation

30

is_cadquery (bool): True if assembly is CadQuery-based

31

is_build123d (bool): True if assembly is build123d-based

32

paths (list): Available object paths within the assembly

33

"""

34

```

35

36

**Usage Examples:**

37

38

```python

39

import cadquery as cq

40

from cadquery import Assembly

41

from ocp_vscode import Animation, show

42

43

# Create CadQuery assembly

44

base = cq.Workplane().box(50, 50, 10)

45

arm = cq.Workplane().box(5, 30, 5).translate((0, 15, 7.5))

46

joint = cq.Workplane().cylinder(3, 8).translate((0, 30, 7.5))

47

48

assembly = Assembly()

49

assembly.add(base, name="base", color=cq.Color("gray"))

50

assembly.add(arm, name="arm", color=cq.Color("blue"))

51

assembly.add(joint, name="joint", color=cq.Color("red"))

52

53

# Create animation

54

anim = Animation(assembly)

55

56

# Show assembly first

57

show(assembly)

58

```

59

60

### Animation Track Management

61

62

Methods for adding and configuring animation tracks for individual objects.

63

64

```python { .api }

65

def add_track(self, path, action, times, values):

66

"""

67

Add an animation track for a specific object in the assembly.

68

69

Parameters:

70

path (str): Path or ID of the CAD object to animate.

71

For CadQuery: object name from assembly

72

For build123d: hierarchical path like "/top-level/sublevel/object"

73

74

action (str): Type of animation action to perform:

75

- "t": Position vector (3-dim array)

76

- "tx": Translation along x-axis (float distance)

77

- "ty": Translation along y-axis (float distance)

78

- "tz": Translation along z-axis (float distance)

79

- "q": Quaternion rotation (x,y,z,w tuple)

80

- "rx": Rotation around x-axis (degrees)

81

- "ry": Rotation around y-axis (degrees)

82

- "rz": Rotation around z-axis (degrees)

83

84

times (list): Array of time points (in seconds) when the object

85

should reach the corresponding values. Must be same

86

length as values array.

87

88

values (list): Array of target values corresponding to each time point.

89

Format depends on action type:

90

- "t": List of 3-tuples [(x,y,z), (x,y,z), ...]

91

- "tx"/"ty"/"tz": List of float distances [d1, d2, ...]

92

- "q": List of 4-tuples [(x,y,z,w), (x,y,z,w), ...]

93

- "rx"/"ry"/"rz": List of angles in degrees [a1, a2, ...]

94

95

Raises:

96

ValueError: If times and values have different lengths, or if path

97

doesn't exist in the assembly.

98

"""

99

100

def animate(self, speed):

101

"""

102

Send animation to viewer and start playback.

103

104

Parameters:

105

speed (float): Animation playback speed multiplier.

106

1.0 = normal speed, 2.0 = double speed, 0.5 = half speed

107

108

Note:

109

All tracks added via add_track() will be played simultaneously.

110

The viewer will interpolate between keyframes for smooth motion.

111

"""

112

```

113

114

**Usage Examples:**

115

116

```python

117

from ocp_vscode import Animation, show

118

import math

119

120

# Create assembly (using previous example)

121

anim = Animation(assembly)

122

123

# Rotating joint animation

124

rotation_times = [0.0, 1.0, 2.0, 3.0, 4.0]

125

rotation_angles = [0, 90, 180, 270, 360] # Full rotation over 4 seconds

126

127

anim.add_track("joint", "rz", rotation_times, rotation_angles)

128

129

# Arm swinging motion

130

swing_times = [0.0, 1.0, 2.0, 3.0, 4.0]

131

swing_angles = [0, 30, 0, -30, 0] # Swing back and forth

132

133

anim.add_track("arm", "ry", swing_times, swing_angles)

134

135

# Position translation of entire arm

136

move_times = [0.0, 2.0, 4.0]

137

positions = [

138

(0, 0, 0), # Start position

139

(20, 0, 10), # Move up and forward

140

(0, 0, 0) # Return to start

141

]

142

143

anim.add_track("arm", "t", move_times, positions)

144

145

# Start animation at normal speed

146

anim.animate(speed=1.0)

147

```

148

149

### Advanced Animation Patterns

150

151

Complex animation sequences can be created by combining multiple tracks and timing patterns.

152

153

```python

154

from ocp_vscode import Animation

155

import numpy as np

156

157

def create_sinusoidal_motion(duration=5.0, frequency=1.0, amplitude=10.0):

158

"""Create smooth sinusoidal motion pattern"""

159

160

# Generate time points (30 FPS equivalent)

161

times = np.linspace(0, duration, int(duration * 30))

162

163

# Calculate sinusoidal positions

164

positions = []

165

for t in times:

166

x = amplitude * np.sin(2 * np.pi * frequency * t)

167

y = amplitude * np.cos(2 * np.pi * frequency * t)

168

z = 5 * np.sin(4 * np.pi * frequency * t) # Vertical oscillation

169

positions.append((x, y, z))

170

171

return times.tolist(), positions

172

173

def create_orbital_motion(radius=20, height=0, duration=4.0):

174

"""Create circular orbital motion"""

175

176

times = np.linspace(0, duration, 60)

177

positions = []

178

179

for t in times:

180

angle = 2 * np.pi * t / duration

181

x = radius * np.cos(angle)

182

y = radius * np.sin(angle)

183

z = height

184

positions.append((x, y, z))

185

186

return times.tolist(), positions

187

188

# Usage with complex assembly

189

anim = Animation(mechanical_assembly)

190

191

# Planet-like orbital motion for satellite components

192

orbit_times, orbit_positions = create_orbital_motion(radius=30, duration=6.0)

193

anim.add_track("satellite", "t", orbit_times, orbit_positions)

194

195

# Sinusoidal oscillation for vibrating parts

196

sine_times, sine_positions = create_sinusoidal_motion(duration=6.0, frequency=2.0)

197

anim.add_track("vibrator", "t", sine_times, sine_positions)

198

199

# Synchronized rotation

200

rotation_times = np.linspace(0, 6.0, 60).tolist()

201

rotation_angles = [360 * t / 6.0 for t in rotation_times] # One full rotation

202

anim.add_track("main_shaft", "rz", rotation_times, rotation_angles)

203

204

anim.animate(speed=1.0)

205

```

206

207

### Assembly Path Resolution

208

209

Different assembly types use different path formats for object identification.

210

211

```python

212

# CadQuery Assembly paths

213

# Objects are referenced by their assigned names

214

assembly = Assembly()

215

assembly.add(part1, name="base")

216

assembly.add(part2, name="arm")

217

assembly.add(part3, name="joint")

218

219

anim = Animation(assembly)

220

anim.add_track("base", "rz", times, angles) # Reference by name

221

anim.add_track("arm", "t", times, positions) # Reference by name

222

223

# build123d Assembly paths

224

# Objects use hierarchical paths

225

anim.add_track("/main/arm/joint", "rx", times, angles) # Hierarchical path

226

anim.add_track("/base/motor/shaft", "rz", times, rotations) # Nested path

227

```

228

229

### Animation Timing and Interpolation

230

231

The animation system uses three.js keyframe interpolation for smooth motion between defined points.

232

233

```python

234

# Linear interpolation between keyframes

235

times = [0.0, 1.0, 2.0]

236

positions = [(0, 0, 0), (10, 0, 0), (10, 10, 0)]

237

# Object moves linearly: (0,0,0) -> (10,0,0) -> (10,10,0)

238

239

# Easing effects through keyframe density

240

# Dense keyframes at start/end = slow motion

241

# Sparse keyframes in middle = fast motion

242

ease_times = [0.0, 0.1, 0.2, 0.5, 1.8, 1.9, 2.0]

243

ease_angles = [0, 5, 15, 90, 345, 355, 360]

244

# Slow start, fast middle, slow end rotation

245

246

# Synchronization across multiple objects

247

sync_times = [0.0, 1.0, 2.0, 3.0]

248

249

# All objects move together

250

anim.add_track("part1", "tx", sync_times, [0, 10, 20, 30])

251

anim.add_track("part2", "ty", sync_times, [0, 5, 10, 15])

252

anim.add_track("part3", "rz", sync_times, [0, 90, 180, 270])

253

```

254

255

### Performance Considerations

256

257

Optimize animations for smooth playback and reasonable file sizes.

258

259

```python

260

# Optimal keyframe density

261

# Too few keyframes = jerky motion

262

# Too many keyframes = large data, possible lag

263

264

# Good: 30-60 keyframes for 5 second animation

265

duration = 5.0

266

frame_rate = 30 # FPS equivalent

267

times = np.linspace(0, duration, duration * frame_rate).tolist()

268

269

# Avoid: Excessive keyframe density

270

# bad_times = np.linspace(0, 5.0, 1000).tolist() # Overkill for 5 seconds

271

272

# Efficient value calculation

273

# Pre-calculate complex mathematical functions

274

angles = [360 * t / duration for t in times] # Pre-calculated rotation

275

positions = [(math.sin(t), math.cos(t), 0) for t in times] # Pre-calculated positions

276

277

# Memory-efficient track building

278

for i, (time, angle, pos) in enumerate(zip(times, angles, positions)):

279

if i == 0: # First track

280

anim.add_track("rotor", "rz", [time], [angle])

281

anim.add_track("slider", "t", [time], [pos])

282

else: # Extend existing tracks

283

# Note: This is conceptual - actual implementation adds complete tracks

284

pass

285

```

286

287

### Error Handling and Validation

288

289

The animation system validates track parameters and provides helpful error messages.

290

291

```python

292

from ocp_vscode import Animation

293

294

anim = Animation(assembly)

295

296

# Validation errors

297

try:

298

# Mismatched array lengths

299

anim.add_track("part", "tx", [0, 1, 2], [0, 10]) # Error: different lengths

300

except ValueError as e:

301

print(f"Track error: {e}")

302

303

try:

304

# Invalid path

305

anim.add_track("nonexistent_part", "rz", [0, 1], [0, 90]) # Error: path not found

306

except ValueError as e:

307

print(f"Path error: {e}")

308

309

# Valid track addition

310

anim.add_track("existing_part", "ry", [0.0, 1.0, 2.0], [0, 45, 90]) # Success

311

```