@teachinglab/omd 0.5.6 → 0.5.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/canvas/ui/toolbar.js +6 -9
- package/index.js +3 -0
- package/npm-docs/DOCUMENTATION_SUMMARY.md +220 -0
- package/npm-docs/README.md +251 -0
- package/npm-docs/api/api-reference.md +85 -0
- package/npm-docs/api/configuration-options.md +198 -0
- package/npm-docs/api/eventManager.md +83 -0
- package/npm-docs/api/expression-nodes.md +561 -0
- package/npm-docs/api/focusFrameManager.md +145 -0
- package/npm-docs/api/index.md +106 -0
- package/npm-docs/api/main.md +63 -0
- package/npm-docs/api/omdBinaryExpressionNode.md +86 -0
- package/npm-docs/api/omdCanvas.md +84 -0
- package/npm-docs/api/omdConfigManager.md +113 -0
- package/npm-docs/api/omdConstantNode.md +53 -0
- package/npm-docs/api/omdDisplay.md +87 -0
- package/npm-docs/api/omdEquationNode.md +174 -0
- package/npm-docs/api/omdEquationSequenceNode.md +259 -0
- package/npm-docs/api/omdEquationStack.md +193 -0
- package/npm-docs/api/omdFunctionNode.md +83 -0
- package/npm-docs/api/omdGroupNode.md +79 -0
- package/npm-docs/api/omdHelpers.md +88 -0
- package/npm-docs/api/omdLeafNode.md +86 -0
- package/npm-docs/api/omdNode.md +202 -0
- package/npm-docs/api/omdOperationDisplayNode.md +118 -0
- package/npm-docs/api/omdOperatorNode.md +92 -0
- package/npm-docs/api/omdParenthesisNode.md +134 -0
- package/npm-docs/api/omdPopup.md +192 -0
- package/npm-docs/api/omdPowerNode.md +132 -0
- package/npm-docs/api/omdRationalNode.md +145 -0
- package/npm-docs/api/omdSequenceNode.md +128 -0
- package/npm-docs/api/omdSimplification.md +79 -0
- package/npm-docs/api/omdSqrtNode.md +144 -0
- package/npm-docs/api/omdStepVisualizer.md +147 -0
- package/npm-docs/api/omdStepVisualizerHighlighting.md +66 -0
- package/npm-docs/api/omdStepVisualizerInteractiveSteps.md +109 -0
- package/npm-docs/api/omdStepVisualizerLayout.md +71 -0
- package/npm-docs/api/omdStepVisualizerNodeUtils.md +140 -0
- package/npm-docs/api/omdStepVisualizerTextBoxes.md +77 -0
- package/npm-docs/api/omdToolbar.md +131 -0
- package/npm-docs/api/omdTranscriptionService.md +96 -0
- package/npm-docs/api/omdTreeDiff.md +170 -0
- package/npm-docs/api/omdUnaryExpressionNode.md +137 -0
- package/npm-docs/api/omdUtilities.md +83 -0
- package/npm-docs/api/omdVariableNode.md +123 -0
- package/npm-docs/api/selectTool.md +74 -0
- package/npm-docs/api/simplificationEngine.md +98 -0
- package/npm-docs/api/simplificationRules.md +77 -0
- package/npm-docs/api/simplificationUtils.md +64 -0
- package/npm-docs/api/transcribe.md +43 -0
- package/npm-docs/guides/equations.md +854 -0
- package/npm-docs/guides/factory-functions.md +354 -0
- package/npm-docs/guides/getting-started.md +318 -0
- package/npm-docs/guides/quick-examples.md +525 -0
- package/npm-docs/guides/visualizations.md +682 -0
- package/npm-docs/json-schemas.md +826 -0
- package/omd/utils/omdTranscriptionService.js +1 -1
- package/package.json +2 -1
- package/src/index.js +2 -0
- package/src/omdFactory.js +150 -0
|
@@ -0,0 +1,561 @@
|
|
|
1
|
+
# Expression Nodes
|
|
2
|
+
|
|
3
|
+
Expression nodes are the building blocks of mathematical expressions and equations in OMD. They form a tree structure that represents the mathematical content.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
OMD uses a node-based system where every mathematical element is represented as a node in an expression tree. This allows for powerful manipulation, simplification, and visualization of mathematical expressions.
|
|
8
|
+
|
|
9
|
+
## Core Node Classes
|
|
10
|
+
|
|
11
|
+
### omdNode
|
|
12
|
+
|
|
13
|
+
The abstract base class for all nodes in the expression tree.
|
|
14
|
+
|
|
15
|
+
**See**: [omdNode API Documentation](./omdNode.md)
|
|
16
|
+
|
|
17
|
+
### omdEquationNode
|
|
18
|
+
|
|
19
|
+
Represents a complete mathematical equation with left side, right side, and equals sign.
|
|
20
|
+
|
|
21
|
+
**Class**: `omdEquationNode extends omdNode`
|
|
22
|
+
|
|
23
|
+
#### Static Methods
|
|
24
|
+
|
|
25
|
+
**`fromString(equationString)`**
|
|
26
|
+
|
|
27
|
+
Creates an equation node from a string representation.
|
|
28
|
+
|
|
29
|
+
```javascript
|
|
30
|
+
import { omdEquationNode } from '@teachinglab/omd';
|
|
31
|
+
|
|
32
|
+
const equation = omdEquationNode.fromString('2x + 3 = 11');
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
- **Parameters**:
|
|
36
|
+
- `equationString` (string): The equation string (e.g., `"2x + 4 = 10"`)
|
|
37
|
+
- **Returns**: `omdEquationNode`
|
|
38
|
+
- **Throws**: Error if string is not a valid equation
|
|
39
|
+
|
|
40
|
+
#### Properties
|
|
41
|
+
|
|
42
|
+
- **`left`** (omdNode): The left side of the equation
|
|
43
|
+
- **`right`** (omdNode): The right side of the equation
|
|
44
|
+
- **`equalsSign`** (omdOperatorNode): The equals sign operator
|
|
45
|
+
|
|
46
|
+
#### Manipulation Methods
|
|
47
|
+
|
|
48
|
+
**`addToBothSides(value)`**
|
|
49
|
+
|
|
50
|
+
Returns a new equation with a value added to both sides.
|
|
51
|
+
|
|
52
|
+
```javascript
|
|
53
|
+
const newEq = equation.addToBothSides(5);
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
- **Parameters**:
|
|
57
|
+
- `value` (number | object): Value to add
|
|
58
|
+
- **Returns**: `omdEquationNode`
|
|
59
|
+
|
|
60
|
+
**`subtractFromBothSides(value)`**
|
|
61
|
+
|
|
62
|
+
Returns a new equation with a value subtracted from both sides.
|
|
63
|
+
|
|
64
|
+
```javascript
|
|
65
|
+
const newEq = equation.subtractFromBothSides(3);
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
- **Parameters**:
|
|
69
|
+
- `value` (number | object): Value to subtract
|
|
70
|
+
- **Returns**: `omdEquationNode`
|
|
71
|
+
|
|
72
|
+
**`multiplyBothSides(value)`**
|
|
73
|
+
|
|
74
|
+
Returns a new equation with both sides multiplied by a value.
|
|
75
|
+
|
|
76
|
+
```javascript
|
|
77
|
+
const newEq = equation.multiplyBothSides(2);
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
- **Parameters**:
|
|
81
|
+
- `value` (number | object): Value to multiply by
|
|
82
|
+
- **Returns**: `omdEquationNode`
|
|
83
|
+
|
|
84
|
+
**`divideBothSides(value)`**
|
|
85
|
+
|
|
86
|
+
Returns a new equation with both sides divided by a value.
|
|
87
|
+
|
|
88
|
+
```javascript
|
|
89
|
+
const newEq = equation.divideBothSides(2);
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
- **Parameters**:
|
|
93
|
+
- `value` (number | object): Value to divide by
|
|
94
|
+
- **Returns**: `omdEquationNode`
|
|
95
|
+
|
|
96
|
+
**`applyFunction(functionName)`**
|
|
97
|
+
|
|
98
|
+
Applies a function (e.g., sqrt, log) to both sides.
|
|
99
|
+
|
|
100
|
+
```javascript
|
|
101
|
+
const newEq = equation.applyFunction('sqrt');
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
- **Parameters**:
|
|
105
|
+
- `functionName` (string): Name of function to apply
|
|
106
|
+
- **Returns**: `omdEquationNode`
|
|
107
|
+
|
|
108
|
+
**`applyOperation(value, operation, side = 'both')`**
|
|
109
|
+
|
|
110
|
+
Applies an arithmetic operation to one or both sides.
|
|
111
|
+
|
|
112
|
+
```javascript
|
|
113
|
+
const newEq = equation.applyOperation(5, 'add', 'left');
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
- **Parameters**:
|
|
117
|
+
- `value` (number | omdNode): Value to apply
|
|
118
|
+
- `operation` (string): Operation type: `'add'`, `'subtract'`, `'multiply'`, or `'divide'`
|
|
119
|
+
- `side` (string): Side to apply to: `'left'`, `'right'`, or `'both'` (default: `'both'`)
|
|
120
|
+
- **Returns**: `omdEquationNode`
|
|
121
|
+
|
|
122
|
+
**`swapSides()`**
|
|
123
|
+
|
|
124
|
+
Swaps the left and right sides of the equation.
|
|
125
|
+
|
|
126
|
+
```javascript
|
|
127
|
+
const swapped = equation.swapSides();
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
- **Returns**: `omdEquationNode`
|
|
131
|
+
|
|
132
|
+
**`simplify()`**
|
|
133
|
+
|
|
134
|
+
Simplifies both sides using the simplification engine.
|
|
135
|
+
|
|
136
|
+
```javascript
|
|
137
|
+
const result = equation.simplify();
|
|
138
|
+
// Returns: { success: boolean, newRoot: omdEquationNode, message: string }
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
- **Returns**: Object with `success`, `newRoot`, and `message` properties
|
|
142
|
+
|
|
143
|
+
#### Utility Methods
|
|
144
|
+
|
|
145
|
+
**`clone()`**
|
|
146
|
+
|
|
147
|
+
Creates a deep clone of the equation node.
|
|
148
|
+
|
|
149
|
+
```javascript
|
|
150
|
+
const copy = equation.clone();
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
- **Returns**: `omdEquationNode`
|
|
154
|
+
|
|
155
|
+
**`toString()`**
|
|
156
|
+
|
|
157
|
+
Converts the equation to its string representation.
|
|
158
|
+
|
|
159
|
+
```javascript
|
|
160
|
+
const str = equation.toString();
|
|
161
|
+
// Returns: "2x + 3 = 11"
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
- **Returns**: `string`
|
|
165
|
+
|
|
166
|
+
**`evaluate(variables)`**
|
|
167
|
+
|
|
168
|
+
Evaluates both sides with given variable values.
|
|
169
|
+
|
|
170
|
+
```javascript
|
|
171
|
+
const result = equation.evaluate({ x: 4 });
|
|
172
|
+
// Returns: { left: 11, right: 11 }
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
- **Parameters**:
|
|
176
|
+
- `variables` (object): Map of variable names to values
|
|
177
|
+
- **Returns**: Object with `left` and `right` evaluated values
|
|
178
|
+
|
|
179
|
+
**`getLeft()`**
|
|
180
|
+
|
|
181
|
+
Returns the node representing the left side.
|
|
182
|
+
|
|
183
|
+
```javascript
|
|
184
|
+
const leftSide = equation.getLeft();
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
- **Returns**: `omdNode`
|
|
188
|
+
|
|
189
|
+
**`getRight()`**
|
|
190
|
+
|
|
191
|
+
Returns the node representing the right side.
|
|
192
|
+
|
|
193
|
+
```javascript
|
|
194
|
+
const rightSide = equation.getRight();
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
- **Returns**: `omdNode`
|
|
198
|
+
|
|
199
|
+
#### Styling Methods
|
|
200
|
+
|
|
201
|
+
**`setBackgroundStyle(style)`**
|
|
202
|
+
|
|
203
|
+
Configures background styling for the equation node.
|
|
204
|
+
|
|
205
|
+
```javascript
|
|
206
|
+
equation.setBackgroundStyle({
|
|
207
|
+
backgroundColor: '#E3F2FD',
|
|
208
|
+
cornerRadius: 8,
|
|
209
|
+
pill: true
|
|
210
|
+
});
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
- **Parameters**:
|
|
214
|
+
- `style` (object): Style properties (`backgroundColor`, `cornerRadius`, `pill`)
|
|
215
|
+
|
|
216
|
+
**`getEqualsAnchorX()`**
|
|
217
|
+
|
|
218
|
+
Returns the X-coordinate of the equals sign center (for alignment).
|
|
219
|
+
|
|
220
|
+
```javascript
|
|
221
|
+
const anchorX = equation.getEqualsAnchorX();
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
- **Returns**: `number`
|
|
225
|
+
|
|
226
|
+
**`getBackgroundPaddingX()`**
|
|
227
|
+
|
|
228
|
+
Returns the horizontal padding applied by background style.
|
|
229
|
+
|
|
230
|
+
```javascript
|
|
231
|
+
const padding = equation.getBackgroundPaddingX();
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
- **Returns**: `number`
|
|
235
|
+
|
|
236
|
+
#### Visualization Methods
|
|
237
|
+
|
|
238
|
+
**`renderTo(visualizationType, options)`**
|
|
239
|
+
|
|
240
|
+
Renders the equation to different visualization formats.
|
|
241
|
+
|
|
242
|
+
```javascript
|
|
243
|
+
// Render to coordinate plane
|
|
244
|
+
const graphJSON = equation.renderTo('graph', {
|
|
245
|
+
xMin: -10,
|
|
246
|
+
xMax: 10,
|
|
247
|
+
yMin: -10,
|
|
248
|
+
yMax: 10
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
// Render to table
|
|
252
|
+
const tableJSON = equation.renderTo('table', {
|
|
253
|
+
xMin: -5,
|
|
254
|
+
xMax: 5,
|
|
255
|
+
stepSize: 1
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
// Render to balance hanger
|
|
259
|
+
const hangerJSON = equation.renderTo('hanger');
|
|
260
|
+
|
|
261
|
+
// Render to tile equation
|
|
262
|
+
const tileJSON = equation.renderTo('tileequation');
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
- **Parameters**:
|
|
266
|
+
- `visualizationType` (string): Type of visualization: `'graph'`, `'table'`, `'hanger'`, or `'tileequation'`
|
|
267
|
+
- `options` (object): Configuration options specific to visualization type
|
|
268
|
+
- **Returns**: JSON object for the visualization
|
|
269
|
+
|
|
270
|
+
**See**: [omdEquationNode Full API Documentation](./omdEquationNode.md)
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
274
|
+
### Expression Component Nodes
|
|
275
|
+
|
|
276
|
+
#### omdConstantNode
|
|
277
|
+
|
|
278
|
+
Represents numeric constants.
|
|
279
|
+
|
|
280
|
+
```javascript
|
|
281
|
+
import { omdConstantNode } from '@teachinglab/omd';
|
|
282
|
+
|
|
283
|
+
const constant = new omdConstantNode(ast);
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
**See**: [omdConstantNode API Documentation](./omdConstantNode.md)
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
#### omdVariableNode
|
|
291
|
+
|
|
292
|
+
Represents algebraic variables.
|
|
293
|
+
|
|
294
|
+
```javascript
|
|
295
|
+
import { omdVariableNode } from '@teachinglab/omd';
|
|
296
|
+
|
|
297
|
+
const variable = new omdVariableNode(ast);
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
**See**: [omdVariableNode API Documentation](./omdVariableNode.md)
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
#### omdOperatorNode
|
|
305
|
+
|
|
306
|
+
Represents mathematical operators (+, -, ×, ÷, =).
|
|
307
|
+
|
|
308
|
+
```javascript
|
|
309
|
+
import { omdOperatorNode } from '@teachinglab/omd';
|
|
310
|
+
|
|
311
|
+
const operator = new omdOperatorNode(ast);
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
**See**: [omdOperatorNode API Documentation](./omdOperatorNode.md)
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
#### omdBinaryExpressionNode
|
|
319
|
+
|
|
320
|
+
Represents binary operations (addition, subtraction, multiplication, division).
|
|
321
|
+
|
|
322
|
+
```javascript
|
|
323
|
+
import { omdBinaryExpressionNode } from '@teachinglab/omd';
|
|
324
|
+
|
|
325
|
+
const binaryExpr = new omdBinaryExpressionNode(ast);
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
**See**: [omdBinaryExpressionNode API Documentation](./omdBinaryExpressionNode.md)
|
|
329
|
+
|
|
330
|
+
---
|
|
331
|
+
|
|
332
|
+
#### omdUnaryExpressionNode
|
|
333
|
+
|
|
334
|
+
Represents unary operations (negation).
|
|
335
|
+
|
|
336
|
+
```javascript
|
|
337
|
+
import { omdUnaryExpressionNode } from '@teachinglab/omd';
|
|
338
|
+
|
|
339
|
+
const unaryExpr = new omdUnaryExpressionNode(ast);
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
**See**: [omdUnaryExpressionNode API Documentation](./omdUnaryExpressionNode.md)
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
#### omdPowerNode
|
|
347
|
+
|
|
348
|
+
Represents exponentiation (x²).
|
|
349
|
+
|
|
350
|
+
```javascript
|
|
351
|
+
import { omdPowerNode } from '@teachinglab/omd';
|
|
352
|
+
|
|
353
|
+
const power = new omdPowerNode(ast);
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
**See**: [omdPowerNode API Documentation](./omdPowerNode.md)
|
|
357
|
+
|
|
358
|
+
---
|
|
359
|
+
|
|
360
|
+
#### omdRationalNode
|
|
361
|
+
|
|
362
|
+
Represents fractions and rational numbers.
|
|
363
|
+
|
|
364
|
+
```javascript
|
|
365
|
+
import { omdRationalNode } from '@teachinglab/omd';
|
|
366
|
+
|
|
367
|
+
const rational = new omdRationalNode(ast);
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
**See**: [omdRationalNode API Documentation](./omdRationalNode.md)
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
#### omdSqrtNode
|
|
375
|
+
|
|
376
|
+
Represents square root expressions.
|
|
377
|
+
|
|
378
|
+
```javascript
|
|
379
|
+
import { omdSqrtNode } from '@teachinglab/omd';
|
|
380
|
+
|
|
381
|
+
const sqrt = new omdSqrtNode(ast);
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
**See**: [omdSqrtNode API Documentation](./omdSqrtNode.md)
|
|
385
|
+
|
|
386
|
+
---
|
|
387
|
+
|
|
388
|
+
#### omdFunctionNode
|
|
389
|
+
|
|
390
|
+
Represents mathematical functions (sin, cos, log, etc.).
|
|
391
|
+
|
|
392
|
+
```javascript
|
|
393
|
+
import { omdFunctionNode } from '@teachinglab/omd';
|
|
394
|
+
|
|
395
|
+
const func = new omdFunctionNode(ast);
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
**See**: [omdFunctionNode API Documentation](./omdFunctionNode.md)
|
|
399
|
+
|
|
400
|
+
---
|
|
401
|
+
|
|
402
|
+
#### omdParenthesisNode
|
|
403
|
+
|
|
404
|
+
Represents expressions enclosed in parentheses.
|
|
405
|
+
|
|
406
|
+
```javascript
|
|
407
|
+
import { omdParenthesisNode } from '@teachinglab/omd';
|
|
408
|
+
|
|
409
|
+
const paren = new omdParenthesisNode(ast);
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
**See**: [omdParenthesisNode API Documentation](./omdParenthesisNode.md)
|
|
413
|
+
|
|
414
|
+
---
|
|
415
|
+
|
|
416
|
+
### Container Nodes
|
|
417
|
+
|
|
418
|
+
#### omdGroupNode
|
|
419
|
+
|
|
420
|
+
A container for grouping related nodes.
|
|
421
|
+
|
|
422
|
+
```javascript
|
|
423
|
+
import { omdGroupNode } from '@teachinglab/omd';
|
|
424
|
+
|
|
425
|
+
const group = new omdGroupNode(ast);
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
**See**: [omdGroupNode API Documentation](./omdGroupNode.md)
|
|
429
|
+
|
|
430
|
+
---
|
|
431
|
+
|
|
432
|
+
#### omdEquationSequenceNode
|
|
433
|
+
|
|
434
|
+
A container for displaying step-by-step equation solutions.
|
|
435
|
+
|
|
436
|
+
```javascript
|
|
437
|
+
import { omdEquationSequenceNode } from '@teachinglab/omd';
|
|
438
|
+
|
|
439
|
+
const sequence = new omdEquationSequenceNode();
|
|
440
|
+
sequence.addChild(equation1);
|
|
441
|
+
sequence.addChild(equation2);
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
**See**: [omdEquationSequenceNode API Documentation](./omdEquationSequenceNode.md)
|
|
445
|
+
|
|
446
|
+
---
|
|
447
|
+
|
|
448
|
+
## Node Tree Structure
|
|
449
|
+
|
|
450
|
+
Nodes are organized in a tree structure:
|
|
451
|
+
|
|
452
|
+
```
|
|
453
|
+
omdEquationNode
|
|
454
|
+
├── left (omdNode)
|
|
455
|
+
│ └── omdBinaryExpressionNode
|
|
456
|
+
│ ├── left (omdConstantNode: 2)
|
|
457
|
+
│ ├── operator (omdOperatorNode: +)
|
|
458
|
+
│ └── right (omdConstantNode: 3)
|
|
459
|
+
├── equalsSign (omdOperatorNode: =)
|
|
460
|
+
└── right (omdNode)
|
|
461
|
+
└── omdConstantNode: 11
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
## Working with Expression Trees
|
|
465
|
+
|
|
466
|
+
### Creating Nodes from Strings
|
|
467
|
+
|
|
468
|
+
The simplest way to create nodes is from strings:
|
|
469
|
+
|
|
470
|
+
```javascript
|
|
471
|
+
import { omdEquationNode } from '@teachinglab/omd';
|
|
472
|
+
|
|
473
|
+
const equation = omdEquationNode.fromString('2x + 3 = 11');
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
### Manipulating Nodes
|
|
477
|
+
|
|
478
|
+
Nodes can be manipulated to perform mathematical operations:
|
|
479
|
+
|
|
480
|
+
```javascript
|
|
481
|
+
// Start with: 2x + 3 = 11
|
|
482
|
+
const step1 = equation.subtractFromBothSides(3);
|
|
483
|
+
// Result: 2x = 8
|
|
484
|
+
|
|
485
|
+
const step2 = step1.divideBothSides(2);
|
|
486
|
+
// Result: x = 4
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
### Traversing the Tree
|
|
490
|
+
|
|
491
|
+
Nodes can be traversed to analyze structure:
|
|
492
|
+
|
|
493
|
+
```javascript
|
|
494
|
+
const leftSide = equation.getLeft();
|
|
495
|
+
const rightSide = equation.getRight();
|
|
496
|
+
|
|
497
|
+
console.log(equation.toString()); // "2x + 3 = 11"
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
### Evaluating Expressions
|
|
501
|
+
|
|
502
|
+
Nodes can be evaluated with variable values:
|
|
503
|
+
|
|
504
|
+
```javascript
|
|
505
|
+
const result = equation.evaluate({ x: 4 });
|
|
506
|
+
console.log(result); // { left: 11, right: 11 }
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
## Common Patterns
|
|
510
|
+
|
|
511
|
+
### Creating a Step-by-Step Solution
|
|
512
|
+
|
|
513
|
+
```javascript
|
|
514
|
+
import { omdEquationNode, omdEquationStack } from '@teachinglab/omd';
|
|
515
|
+
|
|
516
|
+
const original = omdEquationNode.fromString('2x + 3 = 11');
|
|
517
|
+
const step1 = original.subtractFromBothSides(3);
|
|
518
|
+
const step2 = step1.divideBothSides(2);
|
|
519
|
+
|
|
520
|
+
const steps = [original, step1, step2];
|
|
521
|
+
const stack = new omdEquationStack(steps);
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
### Simplifying Expressions
|
|
525
|
+
|
|
526
|
+
```javascript
|
|
527
|
+
const equation = omdEquationNode.fromString('2x + 3x = 10');
|
|
528
|
+
const result = equation.simplify();
|
|
529
|
+
|
|
530
|
+
if (result.success) {
|
|
531
|
+
console.log(result.newRoot.toString()); // "5x = 10"
|
|
532
|
+
}
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
### Rendering to Visualizations
|
|
536
|
+
|
|
537
|
+
```javascript
|
|
538
|
+
const equation = omdEquationNode.fromString('y = x^2 - 4');
|
|
539
|
+
|
|
540
|
+
// Render to graph
|
|
541
|
+
const graphData = equation.renderTo('graph', {
|
|
542
|
+
xMin: -10,
|
|
543
|
+
xMax: 10,
|
|
544
|
+
yMin: -10,
|
|
545
|
+
yMax: 10
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
// Render to table
|
|
549
|
+
const tableData = equation.renderTo('table', {
|
|
550
|
+
xMin: -5,
|
|
551
|
+
xMax: 5,
|
|
552
|
+
stepSize: 1
|
|
553
|
+
});
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
## See Also
|
|
557
|
+
|
|
558
|
+
- [omdNode Base Class](./omdNode.md)
|
|
559
|
+
- [omdEquationNode Full Documentation](./omdEquationNode.md)
|
|
560
|
+
- [Equations Guide](../guides/equations.md)
|
|
561
|
+
- [JSON Schemas](../json-schemas.md)
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# FocusFrameManager
|
|
2
|
+
|
|
3
|
+
The `FocusFrameManager` is a feature that allows you to define rectangular regions on the canvas called "focus frames." These frames can be used to highlight specific areas of interest, capture their contents as separate SVG or bitmap images, and manage them independently.
|
|
4
|
+
|
|
5
|
+
This is particularly useful for applications where you need to isolate and process or export specific parts of a larger drawing, such as individual mathematical problems on a worksheet or specific diagrams in a complex scene.
|
|
6
|
+
|
|
7
|
+
## Class Definition
|
|
8
|
+
|
|
9
|
+
```javascript
|
|
10
|
+
export class FocusFrameManager {
|
|
11
|
+
// ...
|
|
12
|
+
}
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Constructor
|
|
16
|
+
|
|
17
|
+
### `new FocusFrameManager(canvas)`
|
|
18
|
+
|
|
19
|
+
Creates a new `FocusFrameManager` instance.
|
|
20
|
+
|
|
21
|
+
- **`canvas`** (`OMDCanvas`): The main canvas instance.
|
|
22
|
+
|
|
23
|
+
## Public Methods
|
|
24
|
+
|
|
25
|
+
### `createFrame([options])`
|
|
26
|
+
|
|
27
|
+
Creates a new, independent focus frame on the canvas.
|
|
28
|
+
|
|
29
|
+
- **`options`** (`object`, optional): Configuration for the new frame.
|
|
30
|
+
- `x` (`number`, optional): The x-coordinate of the top-left corner. Default: `0`.
|
|
31
|
+
- `y` (`number`, optional): The y-coordinate of the top-left corner. Default: `0`.
|
|
32
|
+
- `width` (`number`, optional): The width of the frame. Default: `200`.
|
|
33
|
+
- `height` (`number`, optional): The height of the frame. Default: `150`.
|
|
34
|
+
- `showOutline` (`boolean`, optional): Whether to display the frame's border. Default: `true`.
|
|
35
|
+
- `outlineColor` (`string`, optional): The color of the border. Default: `'#007bff'`.
|
|
36
|
+
- `outlineWidth` (`number`, optional): The thickness of the border. Default: `2`.
|
|
37
|
+
- `outlineDashed` (`boolean`, optional): Whether the border should be a dashed line. Default: `false`.
|
|
38
|
+
- **Returns**: `object` - An object containing the `id` of the new frame and a reference to the `frame` instance (`{ id, frame }`).
|
|
39
|
+
- **Emits**: `focusFrameCreated` with `{ id, frame }`.
|
|
40
|
+
|
|
41
|
+
### `removeFrame(frameId)`
|
|
42
|
+
|
|
43
|
+
Removes a specific focus frame from the canvas.
|
|
44
|
+
|
|
45
|
+
- **`frameId`** (`string`): The unique ID of the frame to remove.
|
|
46
|
+
- **Returns**: `boolean` - `true` if the frame was found and removed, `false` otherwise.
|
|
47
|
+
- **Emits**: `focusFrameRemoved` with `{ frameId }`.
|
|
48
|
+
|
|
49
|
+
### `getFrame(frameId)`
|
|
50
|
+
|
|
51
|
+
Retrieves a focus frame instance by its ID.
|
|
52
|
+
|
|
53
|
+
- **`frameId`** (`string`): The ID of the frame to retrieve.
|
|
54
|
+
- **Returns**: `FocusFrame` or `undefined` - The frame instance, or `undefined` if no frame with that ID exists.
|
|
55
|
+
|
|
56
|
+
### `setActiveFrame(frameId)`
|
|
57
|
+
|
|
58
|
+
Sets a specific frame as the "active" one, which can be useful for highlighting or targeting operations.
|
|
59
|
+
|
|
60
|
+
- **`frameId`** (`string`): The ID of the frame to activate.
|
|
61
|
+
- **Returns**: `boolean` - `true` if the frame was successfully activated.
|
|
62
|
+
- **Emits**: `focusFrameActivated` with `{ frameId, frame }`.
|
|
63
|
+
|
|
64
|
+
### `getActiveFrame()`
|
|
65
|
+
|
|
66
|
+
Gets the currently active focus frame.
|
|
67
|
+
|
|
68
|
+
- **Returns**: `FocusFrame` or `null` - The active frame instance, or `null` if no frame is currently active.
|
|
69
|
+
|
|
70
|
+
### `captureActiveFrame()`
|
|
71
|
+
|
|
72
|
+
Captures the SVG content of the currently active focus frame.
|
|
73
|
+
|
|
74
|
+
- **Returns**: `string` or `null` - A string of the SVG content within the active frame's bounds, or `null` if there is no active frame.
|
|
75
|
+
|
|
76
|
+
### `captureAllFrames()`
|
|
77
|
+
|
|
78
|
+
Captures the content of every focus frame on the canvas.
|
|
79
|
+
|
|
80
|
+
- **Returns**: `Map<string, string>` - A Map where keys are frame IDs and values are the SVG content strings for each frame.
|
|
81
|
+
|
|
82
|
+
### `clearAllFrames()`
|
|
83
|
+
|
|
84
|
+
Removes all focus frames from the canvas.
|
|
85
|
+
|
|
86
|
+
- **Emits**: `focusFramesCleared`.
|
|
87
|
+
|
|
88
|
+
### `getFrameIds()`
|
|
89
|
+
|
|
90
|
+
Gets the IDs of all current focus frames.
|
|
91
|
+
|
|
92
|
+
- **Returns**: `Array<string>` - An array of all frame IDs.
|
|
93
|
+
|
|
94
|
+
### `destroy()`
|
|
95
|
+
|
|
96
|
+
Destroys the manager and removes all associated frames and event listeners.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## The `FocusFrame` Class (Internal)
|
|
101
|
+
|
|
102
|
+
The `FocusFrame` class represents a single rectangular frame. It is not exported directly but is returned by `FocusFrameManager` methods.
|
|
103
|
+
|
|
104
|
+
### `setActive(active)`
|
|
105
|
+
|
|
106
|
+
Sets the frame's visual state to active or inactive.
|
|
107
|
+
|
|
108
|
+
- **`active`** (`boolean`): `true` to activate, `false` to deactivate.
|
|
109
|
+
|
|
110
|
+
### `capture()`
|
|
111
|
+
|
|
112
|
+
Captures the canvas content within the frame's bounds.
|
|
113
|
+
|
|
114
|
+
- **Returns**: `string` - The SVG content of the frame as an XML string.
|
|
115
|
+
|
|
116
|
+
### `async toBitmap([format], [quality])`
|
|
117
|
+
|
|
118
|
+
Converts the frame's captured content into a bitmap image.
|
|
119
|
+
|
|
120
|
+
- **`format`** (`string`, optional): The image format (e.g., `'png'`, `'jpeg'`). Default: `'png'`.
|
|
121
|
+
- **`quality`** (`number`, optional): The image quality for formats that support it (0 to 1). Default: `1`.
|
|
122
|
+
- **Returns**: `Promise<Blob>` - A promise that resolves with the image data as a `Blob`.
|
|
123
|
+
|
|
124
|
+
### `async downloadAsBitmap([filename], [format])`
|
|
125
|
+
|
|
126
|
+
Triggers a browser download of the frame's content as a bitmap image.
|
|
127
|
+
|
|
128
|
+
- **`filename`** (`string`, optional): The desired filename. Default: `focus-frame-{id}.png`.
|
|
129
|
+
- **`format`** (`string`, optional): The image format. Default: `'png'`.
|
|
130
|
+
|
|
131
|
+
### `updateBounds(bounds)`
|
|
132
|
+
|
|
133
|
+
Resizes and/or repositions the frame.
|
|
134
|
+
|
|
135
|
+
- **`bounds`** (`object`): An object with the new dimensions and coordinates (`{ x, y, width, height }`).
|
|
136
|
+
|
|
137
|
+
### `getBounds()`
|
|
138
|
+
|
|
139
|
+
Gets the current position and size of the frame.
|
|
140
|
+
|
|
141
|
+
- **Returns**: `object` - An object containing the frame's bounds (`{ x, y, width, height }`).
|
|
142
|
+
|
|
143
|
+
### `destroy()`
|
|
144
|
+
|
|
145
|
+
Removes the frame's visual element from the canvas.
|