or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

3d-objects.mdadvanced-animations.mdanimation-system.mdboolean-operations.mdcoordinate-systems.mdindex.mdinteractive-controls.mdmathematical-objects.mdmatrix-visualization.mdprobability-stats.mdscene-framework.mdtext-and-latex.mdutilities-and-constants.mdvalue-tracking.mdvector-fields.md

boolean-operations.mddocs/

0

# Boolean Operations

1

2

ManimGL provides precise geometric boolean operations for 2D vectorized objects through integration with the Skia-Path Ops library. These operations enable complex shape construction, geometric analysis, and sophisticated mathematical visualizations by combining, subtracting, and analyzing the relationships between shapes.

3

4

## Capabilities

5

6

### Union Operations

7

8

Combine multiple shapes into a single unified shape containing all areas from the input objects.

9

10

```python { .api }

11

class Union(VMobject):

12

def __init__(self, *vmobjects: VMobject, **kwargs):

13

"""

14

Create the union (combined area) of two or more VMobjects.

15

16

Parameters:

17

- vmobjects: Variable number of VMobject instances (minimum 2 required)

18

- kwargs: Additional keyword arguments passed to VMobject constructor

19

20

Raises:

21

- ValueError: If fewer than 2 mobjects are provided

22

"""

23

```

24

25

### Difference Operations

26

27

Subtract one shape from another, creating the remaining area after removal.

28

29

```python { .api }

30

class Difference(VMobject):

31

def __init__(self, subject: VMobject, clip: VMobject, **kwargs):

32

"""

33

Create the difference between two VMobjects (subject minus clip).

34

35

Parameters:

36

- subject: The VMobject to subtract from

37

- clip: The VMobject to subtract

38

- kwargs: Additional keyword arguments passed to VMobject constructor

39

"""

40

```

41

42

### Intersection Operations

43

44

Find the overlapping area where two or more shapes intersect.

45

46

```python { .api }

47

class Intersection(VMobject):

48

def __init__(self, *vmobjects: VMobject, **kwargs):

49

"""

50

Create the intersection (overlapping area) of two or more VMobjects.

51

52

Parameters:

53

- vmobjects: Variable number of VMobject instances (minimum 2 required)

54

- kwargs: Additional keyword arguments passed to VMobject constructor

55

56

Raises:

57

- ValueError: If fewer than 2 mobjects are provided

58

"""

59

```

60

61

### Exclusion Operations

62

63

Create the exclusive or (XOR) of shapes, showing areas that belong to exactly one of the input objects.

64

65

```python { .api }

66

class Exclusion(VMobject):

67

def __init__(self, *vmobjects: VMobject, **kwargs):

68

"""

69

Create the exclusive or (XOR) of two or more VMobjects.

70

71

Parameters:

72

- vmobjects: Variable number of VMobject instances (minimum 2 required)

73

- kwargs: Additional keyword arguments passed to VMobject constructor

74

75

Raises:

76

- ValueError: If fewer than 2 mobjects are provided

77

"""

78

```

79

80

### Internal Path Conversion

81

82

Low-level functions for converting between ManimGL objects and Skia paths for boolean operations.

83

84

```python { .api }

85

def _convert_vmobject_to_skia_path(vmobject: VMobject) -> pathops.Path:

86

"""

87

Convert a ManimGL VMobject to a Skia path for boolean operations.

88

89

Parameters:

90

- vmobject: VMobject to convert

91

92

Returns:

93

pathops.Path object for use in boolean operations

94

"""

95

96

def _convert_skia_path_to_vmobject(path: pathops.Path, vmobject: VMobject) -> VMobject:

97

"""

98

Convert a Skia path back to a ManimGL VMobject.

99

100

Parameters:

101

- path: pathops.Path object from boolean operation

102

- vmobject: Template VMobject for style and properties

103

104

Returns:

105

VMobject with boolean operation result

106

"""

107

```

108

109

## Usage Examples

110

111

### Basic Boolean Operations

112

113

```python

114

from manimlib import *

115

116

class BooleanBasics(Scene):

117

def construct(self):

118

# Create base shapes

119

circle = Circle(radius=1.5, color=BLUE, fill_opacity=0.5)

120

square = Square(side_length=2.5, color=RED, fill_opacity=0.5)

121

122

# Position shapes for demonstration

123

circle.shift(LEFT * 0.5)

124

square.shift(RIGHT * 0.5)

125

126

# Show original shapes

127

self.play(ShowCreation(circle), ShowCreation(square))

128

self.wait()

129

130

# Union - combine both shapes

131

union_result = Union(circle, square)

132

union_result.set_fill(GREEN, opacity=0.7)

133

134

self.play(

135

Transform(VGroup(circle, square), union_result),

136

run_time=2

137

)

138

self.wait()

139

140

# Reset for next operation

141

circle = Circle(radius=1.5, color=BLUE, fill_opacity=0.5).shift(LEFT * 0.5)

142

square = Square(side_length=2.5, color=RED, fill_opacity=0.5).shift(RIGHT * 0.5)

143

144

# Intersection - only overlapping area

145

intersection_result = Intersection(circle, square)

146

intersection_result.set_fill(PURPLE, opacity=0.8)

147

148

self.play(Transform(union_result, VGroup(circle, square)))

149

self.wait()

150

self.play(Transform(VGroup(circle, square), intersection_result))

151

self.wait()

152

```

153

154

### Complex Shape Construction

155

156

```python

157

class ComplexShapes(Scene):

158

def construct(self):

159

# Create gear shape using boolean operations

160

base_circle = Circle(radius=2, fill_opacity=1, color=GREY)

161

inner_circle = Circle(radius=0.8, fill_opacity=1, color=BLACK)

162

163

# Create gear teeth

164

num_teeth = 12

165

teeth = VGroup()

166

for i in range(num_teeth):

167

angle = i * TAU / num_teeth

168

tooth = Rectangle(

169

width=0.4, height=0.6,

170

fill_opacity=1, color=GREY

171

)

172

tooth.move_to(2.3 * np.array([np.cos(angle), np.sin(angle), 0]))

173

tooth.rotate(angle)

174

teeth.add(tooth)

175

176

# Combine all teeth with base circle

177

gear_outline = Union(base_circle, *teeth)

178

179

# Subtract inner circle to create hole

180

gear = Difference(gear_outline, inner_circle)

181

gear.set_fill(YELLOW, opacity=0.8)

182

gear.set_stroke(YELLOW_D, width=2)

183

184

self.play(ShowCreation(gear), run_time=3)

185

186

# Add rotation animation

187

self.play(Rotate(gear, TAU, run_time=4, rate_func=linear))

188

```

189

190

### Mathematical Set Visualization

191

192

```python

193

class SetOperations(Scene):

194

def construct(self):

195

# Create Venn diagram

196

set_a = Circle(radius=1.2, color=BLUE, fill_opacity=0.3)

197

set_b = Circle(radius=1.2, color=RED, fill_opacity=0.3)

198

199

set_a.shift(LEFT * 0.8)

200

set_b.shift(RIGHT * 0.8)

201

202

# Labels

203

label_a = Text("A", font_size=48).move_to(set_a.get_center() + LEFT * 0.5)

204

label_b = Text("B", font_size=48).move_to(set_b.get_center() + RIGHT * 0.5)

205

206

# Show base sets

207

self.add(set_a, set_b, label_a, label_b)

208

self.wait()

209

210

# Demonstrate each operation

211

operations = [

212

("A ∪ B (Union)", Union(set_a, set_b), YELLOW),

213

("A ∩ B (Intersection)", Intersection(set_a, set_b), GREEN),

214

("A - B (Difference)", Difference(set_a, set_b), ORANGE),

215

("A ⊕ B (XOR)", Exclusion(set_a, set_b), PURPLE)

216

]

217

218

for title, operation, color in operations:

219

result = operation.copy()

220

result.set_fill(color, opacity=0.8)

221

result.set_stroke(color, width=3)

222

223

title_text = Text(title, font_size=36).to_edge(UP)

224

225

self.play(

226

Write(title_text),

227

ShowCreation(result),

228

run_time=2

229

)

230

self.wait(2)

231

232

self.play(

233

FadeOut(title_text),

234

FadeOut(result)

235

)

236

```

237

238

### Advanced Shape Analysis

239

240

```python

241

class ShapeAnalysis(Scene):

242

def construct(self):

243

# Create overlapping shapes for analysis

244

triangle = RegularPolygon(3, radius=1.5, color=BLUE, fill_opacity=0.4)

245

hexagon = RegularPolygon(6, radius=1.8, color=RED, fill_opacity=0.4)

246

circle = Circle(radius=1.2, color=GREEN, fill_opacity=0.4)

247

248

triangle.shift(UP * 0.5)

249

hexagon.shift(DOWN * 0.3 + LEFT * 0.4)

250

circle.shift(DOWN * 0.3 + RIGHT * 0.4)

251

252

shapes = VGroup(triangle, hexagon, circle)

253

254

self.play(ShowCreation(shapes), run_time=2)

255

self.wait()

256

257

# Show different combinations

258

combinations = [

259

# All three shapes union

260

("All Combined", Union(triangle, hexagon, circle), YELLOW),

261

# Pairwise intersections

262

("Triangle ∩ Hexagon", Intersection(triangle, hexagon), ORANGE),

263

("Hexagon ∩ Circle", Intersection(hexagon, circle), PURPLE),

264

("Triangle ∩ Circle", Intersection(triangle, circle), PINK),

265

# Triple intersection

266

("All Intersect", Intersection(triangle, hexagon, circle), WHITE)

267

]

268

269

for title, result, color in combinations:

270

analysis = result.copy()

271

analysis.set_fill(color, opacity=0.9)

272

analysis.set_stroke(color, width=4)

273

274

title_text = Text(title, font_size=32).to_edge(UP)

275

276

self.play(Write(title_text))

277

self.play(

278

shapes.animate.set_fill_opacity(0.1),

279

ShowCreation(analysis),

280

run_time=2

281

)

282

self.wait(2)

283

284

self.play(

285

FadeOut(title_text),

286

FadeOut(analysis),

287

shapes.animate.set_fill_opacity(0.4)

288

)

289

290

self.wait()

291

```

292

293

### Dynamic Boolean Operations

294

295

```python

296

class DynamicBoolean(Scene):

297

def construct(self):

298

# Create movable shapes

299

circle = Circle(radius=1, color=BLUE, fill_opacity=0.6)

300

square = Square(side_length=1.8, color=RED, fill_opacity=0.6)

301

302

circle.to_edge(LEFT)

303

square.to_edge(RIGHT)

304

305

# Create result placeholder

306

result_union = Union(circle, square)

307

result_union.set_fill(YELLOW, opacity=0.8)

308

result_union.move_to(ORIGIN)

309

310

self.add(circle, square, result_union)

311

312

# Animate shapes moving and show dynamic boolean result

313

def update_union(mob):

314

new_union = Union(circle, square)

315

new_union.set_fill(YELLOW, opacity=0.8)

316

new_union.move_to(ORIGIN)

317

mob.become(new_union)

318

319

result_union.add_updater(update_union)

320

321

# Move shapes to show dynamic updating

322

self.play(

323

circle.animate.shift(RIGHT * 2),

324

square.animate.shift(LEFT * 2),

325

run_time=4

326

)

327

328

self.play(

329

circle.animate.shift(RIGHT * 1),

330

square.animate.shift(LEFT * 1),

331

run_time=3

332

)

333

334

result_union.clear_updaters()

335

self.wait()

336

```

337

338

## Implementation Details

339

340

### Path Conversion Process

341

342

Boolean operations work by converting ManimGL VMobjects to Skia paths, performing the geometric operations, and converting back:

343

344

1. **VMobject → Skia Path**: Extracts Bezier control points and converts cubic curves to quadratic

345

2. **Boolean Operation**: Uses pathops library functions (union, difference, intersection, xor)

346

3. **Skia Path → VMobject**: Reconstructs path commands into VMobject points

347

348

### Multi-Object Handling

349

350

- **Union**: Single operation combining all paths simultaneously

351

- **Intersection & Exclusion**: Sequential pairwise operations for multiple objects

352

- **Difference**: Single operation between subject and clip objects

353

354

### Integration with ManimGL

355

356

All boolean operation results are fully-featured VMobjects supporting:

357

- Complete styling (stroke, fill, color, opacity)

358

- All transformation methods (rotation, scaling, translation)

359

- Animation compatibility with all ManimGL animations

360

- Point manipulation and curve insertion methods

361

362

### Performance Considerations

363

364

Boolean operations are computationally intensive for complex shapes. For real-time or highly animated scenes, consider:

365

- Pre-computing complex boolean results

366

- Using simpler approximations for preview

367

- Limiting the number of concurrent boolean operations

368

369

The boolean operations module provides powerful tools for geometric construction and mathematical visualization, enabling sophisticated shape analysis and complex geometric demonstrations in ManimGL.