@teachinglab/omd 0.1.0
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/README.md +138 -0
- package/canvas/core/canvasConfig.js +203 -0
- package/canvas/core/omdCanvas.js +475 -0
- package/canvas/drawing/segment.js +168 -0
- package/canvas/drawing/stroke.js +386 -0
- package/canvas/events/eventManager.js +435 -0
- package/canvas/events/pointerEventHandler.js +263 -0
- package/canvas/features/focusFrameManager.js +287 -0
- package/canvas/index.js +49 -0
- package/canvas/tools/eraserTool.js +322 -0
- package/canvas/tools/pencilTool.js +319 -0
- package/canvas/tools/selectTool.js +457 -0
- package/canvas/tools/tool.js +223 -0
- package/canvas/tools/toolManager.js +394 -0
- package/canvas/ui/cursor.js +438 -0
- package/canvas/ui/toolbar.js +304 -0
- package/canvas/utils/boundingBox.js +378 -0
- package/canvas/utils/mathUtils.js +259 -0
- package/docs/api/configuration-options.md +104 -0
- package/docs/api/eventManager.md +68 -0
- package/docs/api/focusFrameManager.md +150 -0
- package/docs/api/index.md +91 -0
- package/docs/api/main.md +58 -0
- package/docs/api/omdBinaryExpressionNode.md +227 -0
- package/docs/api/omdCanvas.md +142 -0
- package/docs/api/omdConfigManager.md +192 -0
- package/docs/api/omdConstantNode.md +117 -0
- package/docs/api/omdDisplay.md +121 -0
- package/docs/api/omdEquationNode.md +161 -0
- package/docs/api/omdEquationSequenceNode.md +301 -0
- package/docs/api/omdEquationStack.md +139 -0
- package/docs/api/omdFunctionNode.md +141 -0
- package/docs/api/omdGroupNode.md +182 -0
- package/docs/api/omdHelpers.md +96 -0
- package/docs/api/omdLeafNode.md +163 -0
- package/docs/api/omdNode.md +101 -0
- package/docs/api/omdOperationDisplayNode.md +139 -0
- package/docs/api/omdOperatorNode.md +127 -0
- package/docs/api/omdParenthesisNode.md +122 -0
- package/docs/api/omdPopup.md +117 -0
- package/docs/api/omdPowerNode.md +127 -0
- package/docs/api/omdRationalNode.md +128 -0
- package/docs/api/omdSequenceNode.md +128 -0
- package/docs/api/omdSimplification.md +110 -0
- package/docs/api/omdSqrtNode.md +79 -0
- package/docs/api/omdStepVisualizer.md +115 -0
- package/docs/api/omdStepVisualizerHighlighting.md +61 -0
- package/docs/api/omdStepVisualizerInteractiveSteps.md +129 -0
- package/docs/api/omdStepVisualizerLayout.md +60 -0
- package/docs/api/omdStepVisualizerNodeUtils.md +140 -0
- package/docs/api/omdStepVisualizerTextBoxes.md +68 -0
- package/docs/api/omdToolbar.md +102 -0
- package/docs/api/omdTranscriptionService.md +76 -0
- package/docs/api/omdTreeDiff.md +134 -0
- package/docs/api/omdUnaryExpressionNode.md +174 -0
- package/docs/api/omdUtilities.md +70 -0
- package/docs/api/omdVariableNode.md +148 -0
- package/docs/api/selectTool.md +74 -0
- package/docs/api/simplificationEngine.md +98 -0
- package/docs/api/simplificationRules.md +77 -0
- package/docs/api/simplificationUtils.md +64 -0
- package/docs/api/transcribe.md +43 -0
- package/docs/api-reference.md +85 -0
- package/docs/index.html +454 -0
- package/docs/user-guide.md +9 -0
- package/index.js +67 -0
- package/omd/config/omdConfigManager.js +267 -0
- package/omd/core/index.js +150 -0
- package/omd/core/omdEquationStack.js +347 -0
- package/omd/core/omdUtilities.js +115 -0
- package/omd/display/omdDisplay.js +443 -0
- package/omd/display/omdToolbar.js +502 -0
- package/omd/nodes/omdBinaryExpressionNode.js +460 -0
- package/omd/nodes/omdConstantNode.js +142 -0
- package/omd/nodes/omdEquationNode.js +1223 -0
- package/omd/nodes/omdEquationSequenceNode.js +1273 -0
- package/omd/nodes/omdFunctionNode.js +352 -0
- package/omd/nodes/omdGroupNode.js +68 -0
- package/omd/nodes/omdLeafNode.js +77 -0
- package/omd/nodes/omdNode.js +557 -0
- package/omd/nodes/omdOperationDisplayNode.js +322 -0
- package/omd/nodes/omdOperatorNode.js +109 -0
- package/omd/nodes/omdParenthesisNode.js +293 -0
- package/omd/nodes/omdPowerNode.js +236 -0
- package/omd/nodes/omdRationalNode.js +295 -0
- package/omd/nodes/omdSqrtNode.js +308 -0
- package/omd/nodes/omdUnaryExpressionNode.js +178 -0
- package/omd/nodes/omdVariableNode.js +123 -0
- package/omd/simplification/omdSimplification.js +171 -0
- package/omd/simplification/omdSimplificationEngine.js +886 -0
- package/omd/simplification/package.json +6 -0
- package/omd/simplification/rules/binaryRules.js +1037 -0
- package/omd/simplification/rules/functionRules.js +111 -0
- package/omd/simplification/rules/index.js +48 -0
- package/omd/simplification/rules/parenthesisRules.js +19 -0
- package/omd/simplification/rules/powerRules.js +143 -0
- package/omd/simplification/rules/rationalRules.js +475 -0
- package/omd/simplification/rules/sqrtRules.js +48 -0
- package/omd/simplification/rules/unaryRules.js +37 -0
- package/omd/simplification/simplificationRules.js +32 -0
- package/omd/simplification/simplificationUtils.js +1056 -0
- package/omd/step-visualizer/omdStepVisualizer.js +597 -0
- package/omd/step-visualizer/omdStepVisualizerHighlighting.js +206 -0
- package/omd/step-visualizer/omdStepVisualizerLayout.js +245 -0
- package/omd/step-visualizer/omdStepVisualizerTextBoxes.js +163 -0
- package/omd/utils/omdNodeOverlay.js +638 -0
- package/omd/utils/omdPopup.js +1084 -0
- package/omd/utils/omdStepVisualizerInteractiveSteps.js +491 -0
- package/omd/utils/omdStepVisualizerNodeUtils.js +268 -0
- package/omd/utils/omdTranscriptionService.js +125 -0
- package/omd/utils/omdTreeDiff.js +734 -0
- package/package.json +46 -0
- package/src/index.js +62 -0
- package/src/json-schemas.md +109 -0
- package/src/omd-json-samples.js +115 -0
- package/src/omd.js +109 -0
- package/src/omdApp.js +391 -0
- package/src/omdAppCanvas.js +336 -0
- package/src/omdBalanceHanger.js +172 -0
- package/src/omdColor.js +13 -0
- package/src/omdCoordinatePlane.js +467 -0
- package/src/omdEquation.js +125 -0
- package/src/omdExpression.js +104 -0
- package/src/omdFunction.js +113 -0
- package/src/omdMetaExpression.js +287 -0
- package/src/omdNaturalExpression.js +564 -0
- package/src/omdNode.js +384 -0
- package/src/omdNumber.js +53 -0
- package/src/omdNumberLine.js +107 -0
- package/src/omdNumberTile.js +119 -0
- package/src/omdOperator.js +73 -0
- package/src/omdPowerExpression.js +92 -0
- package/src/omdProblem.js +55 -0
- package/src/omdRatioChart.js +232 -0
- package/src/omdRationalExpression.js +115 -0
- package/src/omdSampleData.js +215 -0
- package/src/omdShapes.js +476 -0
- package/src/omdSpinner.js +148 -0
- package/src/omdString.js +39 -0
- package/src/omdTable.js +369 -0
- package/src/omdTapeDiagram.js +245 -0
- package/src/omdTerm.js +92 -0
- package/src/omdTileEquation.js +349 -0
- package/src/omdVariable.js +51 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# omdTranscriptionService
|
|
2
|
+
|
|
3
|
+
The `omdTranscriptionService` class provides an interface to an AI-powered transcription service for handwritten content. It sends image data to a server-side endpoint for processing.
|
|
4
|
+
|
|
5
|
+
## Class Definition
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
export class omdTranscriptionService {
|
|
9
|
+
// ...
|
|
10
|
+
}
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Constructor
|
|
14
|
+
|
|
15
|
+
### `new omdTranscriptionService([options])`
|
|
16
|
+
|
|
17
|
+
Creates a new `omdTranscriptionService` instance.
|
|
18
|
+
|
|
19
|
+
* **[options]** (`object`, optional): Configuration options for the service.
|
|
20
|
+
* **endpoint** (`string`, optional): The server endpoint for the transcription service. Defaults to `'/.netlify/functions/transcribe'`.
|
|
21
|
+
* **defaultProvider** (`string`, optional): The default transcription provider to use. Defaults to `'gemini'`.
|
|
22
|
+
|
|
23
|
+
## Public Methods
|
|
24
|
+
|
|
25
|
+
### `transcribe(imageBlob, [options])`
|
|
26
|
+
|
|
27
|
+
Transcribes an image containing handwritten content.
|
|
28
|
+
|
|
29
|
+
* **imageBlob** (`Blob`): The image blob to transcribe.
|
|
30
|
+
* **[options]** (`object`, optional): Transcription options.
|
|
31
|
+
* **prompt** (`string`, optional): A custom prompt for the transcription service.
|
|
32
|
+
* **Returns**: `Promise<object>` - A promise that resolves with the transcription result, containing the `text`, `provider`, and `confidence`.
|
|
33
|
+
|
|
34
|
+
### `transcribeWithFallback(imageBlob, [options])`
|
|
35
|
+
|
|
36
|
+
Transcribes an image with a fallback mechanism (currently, this is the same as `transcribe`).
|
|
37
|
+
|
|
38
|
+
* **imageBlob** (`Blob`): The image blob to transcribe.
|
|
39
|
+
* **[options]** (`object`, optional): Transcription options.
|
|
40
|
+
* **Returns**: `Promise<object>` - A promise that resolves with the transcription result.
|
|
41
|
+
|
|
42
|
+
### `isAvailable()`
|
|
43
|
+
|
|
44
|
+
Checks if the transcription service is available.
|
|
45
|
+
|
|
46
|
+
* **Returns**: `boolean` - `true` if the service is available, `false` otherwise.
|
|
47
|
+
|
|
48
|
+
### `getAvailableProviders()`
|
|
49
|
+
|
|
50
|
+
Gets the available transcription providers.
|
|
51
|
+
|
|
52
|
+
* **Returns**: `Array<string>` - An array of available provider names.
|
|
53
|
+
|
|
54
|
+
### `isProviderAvailable(provider)`
|
|
55
|
+
|
|
56
|
+
Checks if a specific transcription provider is available.
|
|
57
|
+
|
|
58
|
+
* **provider** (`string`): The name of the provider to check.
|
|
59
|
+
* **Returns**: `boolean` - `true` if the provider is available, `false` otherwise.
|
|
60
|
+
|
|
61
|
+
## Example Usage
|
|
62
|
+
|
|
63
|
+
```javascript
|
|
64
|
+
// Create a transcription service instance
|
|
65
|
+
const transcriptionService = new omdTranscriptionService();
|
|
66
|
+
|
|
67
|
+
// Get an image blob from a canvas or file input
|
|
68
|
+
const imageBlob = await getMyImageBlob();
|
|
69
|
+
|
|
70
|
+
// Transcribe the image
|
|
71
|
+
const result = await transcriptionService.transcribe(imageBlob, {
|
|
72
|
+
prompt: 'Transcribe the handwritten math equation.'
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
console.log(result.text); // The transcribed text
|
|
76
|
+
```
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
|
|
2
|
+
# omdTreeDiff
|
|
3
|
+
|
|
4
|
+
Implements a robust tree differencing algorithm to identify changes between two `omdNode` expression trees. Used by `omdStepVisualizerHighlighting` to provide visual feedback on how mathematical expressions transform from one step to the next.
|
|
5
|
+
|
|
6
|
+
## Algorithm Overview
|
|
7
|
+
|
|
8
|
+
`omdTreeDiff` uses a multi-stage approach:
|
|
9
|
+
1. **Special Cases:** Attempts to identify common pedagogical patterns (like adding/subtracting the same value from both sides). If found, highlights those nodes.
|
|
10
|
+
2. **Generate All Matches:** Finds all possible pairs of subtrees between the old and new expressions that are either structurally identical or semantically equivalent (e.g., `2+3` and `5`).
|
|
11
|
+
3. **Select Optimal Set:** Selects the largest, non-overlapping set of matches, identifying the largest common sub-expressions between the two trees.
|
|
12
|
+
4. **Identify Changes:** Any parts of the new tree that are *not* part of these optimal matches are considered changes and are returned for highlighting.
|
|
13
|
+
5. **Educational Mode:** In educational mode, includes additional heuristics to highlight subtle simplifications that might not involve a direct structural change but are important for understanding the transformation.
|
|
14
|
+
|
|
15
|
+
## Class: `omdTreeDiff`
|
|
16
|
+
|
|
17
|
+
```javascript
|
|
18
|
+
import { omdTreeDiff } from './omd/utils/omdTreeDiff.js';
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
## Static Methods
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### `findChangedNodes(oldEquation, newEquation, options)`
|
|
26
|
+
|
|
27
|
+
Main entry point for the tree differencing algorithm. Compares two `omdEquationNode` instances (or any `omdNode` subtrees) and returns a list of nodes in the `newEquation` that have changed or are new.
|
|
28
|
+
|
|
29
|
+
- **Parameters:**
|
|
30
|
+
- `oldEquation` {omdNode} - The root node of the previous expression tree.
|
|
31
|
+
- `newEquation` {omdNode} - The root node of the current expression tree.
|
|
32
|
+
- `options` {Object} (optional) - Configuration options:
|
|
33
|
+
- `educationalMode` {boolean} - If `true`, the diff algorithm will also highlight mathematically neutral changes that are pedagogically significant (e.g., removing `+ 0`). Default: `false`.
|
|
34
|
+
- **Returns:** {Array<omdNode>} An array of `omdNode` instances from `newEquation` that should be highlighted.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
### `findEquationSpecialCases(oldEquation, newEquation)`
|
|
40
|
+
|
|
41
|
+
Identifies specific equation-level transformation patterns, such as adding the same operation (e.g., `+ X` or `- X`) to both sides of an equation. Allows for more intuitive highlighting in common step-by-step solution scenarios.
|
|
42
|
+
|
|
43
|
+
- **Parameters:**
|
|
44
|
+
- `oldEquation` {omdEquationNode} - The previous equation.
|
|
45
|
+
- `newEquation` {omdEquationNode} - The current equation.
|
|
46
|
+
- **Returns:** {Array<omdNode>} An array of nodes to highlight for these special cases, or an empty array if no such pattern is found.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
### `diffSubtrees(oldTree, newTree, educationalMode)`
|
|
52
|
+
|
|
53
|
+
Core recursive differencing method. Attempts to find an optimal matching between subtrees of the `oldTree` and `newTree`. Nodes in `newTree` that do not have a match in `oldTree` are considered changed.
|
|
54
|
+
|
|
55
|
+
- **Parameters:**
|
|
56
|
+
- `oldTree` {omdNode} - The root of the old subtree.
|
|
57
|
+
- `newTree` {omdNode} - The root of the new subtree.
|
|
58
|
+
- `educationalMode` {boolean} - Same as in `findChangedNodes`.
|
|
59
|
+
- **Returns:** {Array<omdNode>} An array of unmatched leaf nodes in `newTree`.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
### `findEducationalHighlights(oldTree, newTree, optimalMatches)`
|
|
65
|
+
|
|
66
|
+
When `educationalMode` is enabled, identifies additional nodes to highlight for pedagogical reasons, even if they don't represent a structural change. Includes cases like the removal of additive/multiplicative identities or double negations.
|
|
67
|
+
|
|
68
|
+
- **Parameters:**
|
|
69
|
+
- `oldTree` {omdNode} - The old expression tree.
|
|
70
|
+
- `newTree` {omdNode} - The new expression tree.
|
|
71
|
+
- `optimalMatches` {Array} - The list of optimally matched subtrees.
|
|
72
|
+
- **Returns:** {Array<omdNode>} Additional nodes to highlight.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
### `findAllSubtreeMatches(oldTree, newTree)`
|
|
78
|
+
|
|
79
|
+
Generates all possible subtree matches between two expression trees. A match is determined by structural or string equivalence.
|
|
80
|
+
|
|
81
|
+
- **Parameters:**
|
|
82
|
+
- `oldTree` {omdNode} - The old expression tree.
|
|
83
|
+
- `newTree` {omdNode} - The new expression tree.
|
|
84
|
+
- **Returns:** {Array<Object>} An array of match objects, each containing `oldNode`, `newNode`, `size`, `score`, and `type` of match.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
### `selectOptimalMatching(matches)`
|
|
90
|
+
|
|
91
|
+
Given a list of all possible subtree matches, selects the optimal, non-overlapping set of matches. Uses a greedy approach, prioritizing larger and higher-scoring matches.
|
|
92
|
+
|
|
93
|
+
- **Parameters:**
|
|
94
|
+
- `matches` {Array<Object>} - The array of potential matches from `findAllSubtreeMatches`.
|
|
95
|
+
- **Returns:** {Array<Object>} The selected optimal matches.
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
### `findUnmatchedLeafNodes(newTree, matches)`
|
|
101
|
+
|
|
102
|
+
Identifies all leaf nodes in the `newTree` that are not covered by any of the `optimalMatches`. These are the nodes that represent the actual changes.
|
|
103
|
+
|
|
104
|
+
- **Parameters:**
|
|
105
|
+
- `newTree` {omdNode} - The new expression tree.
|
|
106
|
+
- `matches` {Array<Object>} - The array of selected optimal matches.
|
|
107
|
+
- **Returns:** {Array<omdNode>} An array of unmatched leaf nodes.
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
## Internal Helper Methods
|
|
111
|
+
|
|
112
|
+
- `_findCommonPrefix(str1, str2)`: Finds the longest common string prefix.
|
|
113
|
+
- `getAllSubtrees(root)`: Recursively collects all subtrees from a given root node.
|
|
114
|
+
- `calculateSimilarity(tree1, tree2)`: Determines the similarity score between two subtrees.
|
|
115
|
+
- `treesStructurallyEqual(tree1, tree2)`: Checks for exact structural equality between two subtrees.
|
|
116
|
+
- `getSubtreeSize(root)`: Calculates the number of nodes in a subtree.
|
|
117
|
+
- `hasNodeOverlap(node, usedNodes)`: Checks if a node or its descendants overlap with a set of used nodes.
|
|
118
|
+
- `markSubtreeAsUsed(root, usedNodes)`: Marks all nodes in a subtree as used.
|
|
119
|
+
- `findUnmatchedOldNodes(oldTree, matches)`: Finds leaf nodes in the old tree that were removed.
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
## How it Works
|
|
123
|
+
|
|
124
|
+
See the Algorithm Overview above for a summary of the process. The class is designed for internal use by step visualizer components.
|
|
125
|
+
|
|
126
|
+
### Example
|
|
127
|
+
|
|
128
|
+
This class is typically used internally by `omdStepVisualizerHighlighting`.
|
|
129
|
+
|
|
130
|
+
```javascript
|
|
131
|
+
// Example of internal usage within omdStepVisualizerHighlighting:
|
|
132
|
+
// const changedNodes = omdTreeDiff.findChangedNodes(previousEquation, currentEquation, { educationalMode: true });
|
|
133
|
+
// changedNodes.forEach(node => node.setExplainHighlight(true));
|
|
134
|
+
```
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# omdUnaryExpressionNode
|
|
2
|
+
|
|
3
|
+
Represents unary operations (like negation) in mathematical expressions (e.g., `-x`, `-(a + b)`). Handles rendering, layout, evaluation, and conversion to math.js AST.
|
|
4
|
+
|
|
5
|
+
## Class: `omdUnaryExpressionNode extends omdNode`
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
import { omdUnaryExpressionNode } from './omd/nodes/omdUnaryExpressionNode.js';
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
### Constructor
|
|
12
|
+
|
|
13
|
+
```javascript
|
|
14
|
+
new omdUnaryExpressionNode(ast)
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**Parameters:**
|
|
18
|
+
- `ast` {Object} - The AST node containing:
|
|
19
|
+
- `args`: Array with exactly 1 operand AST node
|
|
20
|
+
- `op`: Operator symbol (e.g., '-')
|
|
21
|
+
- `fn`: Operation name (e.g., 'unaryMinus')
|
|
22
|
+
|
|
23
|
+
**Description:**
|
|
24
|
+
Creates a node representing a unary operation (like negation) on an expression. Throws an error if the AST does not have exactly one argument.
|
|
25
|
+
|
|
26
|
+
### Properties
|
|
27
|
+
|
|
28
|
+
Inherits all properties from [omdNode](./omdNode.md), plus:
|
|
29
|
+
|
|
30
|
+
#### `op`
|
|
31
|
+
- **Type:** [omdOperatorNode](./omdOperatorNode.md)
|
|
32
|
+
- **Description:** The unary operator node (e.g., '-')
|
|
33
|
+
|
|
34
|
+
#### `operand`
|
|
35
|
+
- **Type:** [omdNode](./omdNode.md)
|
|
36
|
+
- **Description:** The expression being operated on
|
|
37
|
+
|
|
38
|
+
#### `operation`
|
|
39
|
+
- **Type:** string
|
|
40
|
+
- **Description:** The operation name (e.g., 'unaryMinus')
|
|
41
|
+
|
|
42
|
+
### Methods
|
|
43
|
+
|
|
44
|
+
Inherits all methods from [omdNode](./omdNode.md), plus:
|
|
45
|
+
|
|
46
|
+
#### `createOperatorNode(ast)`
|
|
47
|
+
Internal method to create operator node.
|
|
48
|
+
- `ast` {Object} - The AST with operator info
|
|
49
|
+
- **Returns:** omdOperatorNode
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
#### `createExpressionNode(ast)`
|
|
54
|
+
Internal method to create operand node.
|
|
55
|
+
- `ast` {Object} - The AST for the operand
|
|
56
|
+
- **Returns:** omdNode
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
#### `computeDimensions()`
|
|
61
|
+
Calculates dimensions of expression.
|
|
62
|
+
- Computes dimensions of operator and operand
|
|
63
|
+
- Sets total width and height
|
|
64
|
+
- No extra spacing for unary minus
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
#### `updateLayout()`
|
|
69
|
+
Updates positions of elements.
|
|
70
|
+
- Centers operator and operand vertically
|
|
71
|
+
- Places operator before operand
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
#### `clone()`
|
|
76
|
+
Creates a deep clone of the expression node, including operator and operand, and preserves provenance.
|
|
77
|
+
- **Returns:** omdUnaryExpressionNode - New instance with:
|
|
78
|
+
- Cloned AST data
|
|
79
|
+
- Preserved background rectangle
|
|
80
|
+
- Cloned operator and operand
|
|
81
|
+
- Rebuilt argument list
|
|
82
|
+
- Original node's ID added to provenance array
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
#### `toMathJSNode()`
|
|
87
|
+
Converts to math.js AST format.
|
|
88
|
+
- **Returns:** Object - A math.js-compatible AST node with:
|
|
89
|
+
- `type`: "OperatorNode"
|
|
90
|
+
- `op`: Operator symbol
|
|
91
|
+
- `fn`: Operation name
|
|
92
|
+
- `args`: [operand AST]
|
|
93
|
+
- `id`: Node ID
|
|
94
|
+
- `provenance`: Provenance array
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
#### `toString()`
|
|
99
|
+
Convert to string representation.
|
|
100
|
+
- Adds parentheses if needed
|
|
101
|
+
- **Returns:** string - Format: "-operand" or "-(operand)"
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
#### `needsParentheses()`
|
|
106
|
+
Check if operand needs parentheses.
|
|
107
|
+
- **Returns:** boolean - True if operand is binary expression
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
#### `evaluate(variables)`
|
|
112
|
+
Evaluate the expression.
|
|
113
|
+
- `variables` {Object} - Variable name to value mapping
|
|
114
|
+
- **Returns:** number - Negated value for '-', same value for '+'
|
|
115
|
+
- **Returns:** NaN if operand can't be evaluated
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
#### `simplify()`
|
|
120
|
+
Attempt to simplify expression using the central simplification engine.
|
|
121
|
+
- **Returns:** Object with:
|
|
122
|
+
- `success`: Whether simplified
|
|
123
|
+
- `newRoot`: Simplified expression
|
|
124
|
+
- `message`: Description of changes
|
|
125
|
+
|
|
126
|
+
### Static Methods
|
|
127
|
+
|
|
128
|
+
#### `fromString(expressionString)`
|
|
129
|
+
Create node from string.
|
|
130
|
+
- `expressionString` {string} - Expression with unary operation
|
|
131
|
+
- **Returns:** omdUnaryExpressionNode
|
|
132
|
+
- **Throws:** Error if not unary minus operation or if parsing fails
|
|
133
|
+
|
|
134
|
+
### Example
|
|
135
|
+
|
|
136
|
+
```javascript
|
|
137
|
+
// Create from AST
|
|
138
|
+
const node = new omdUnaryExpressionNode({
|
|
139
|
+
type: 'OperatorNode',
|
|
140
|
+
op: '-',
|
|
141
|
+
fn: 'unaryMinus',
|
|
142
|
+
args: [
|
|
143
|
+
{ type: 'SymbolNode', name: 'x' }
|
|
144
|
+
]
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// Complex operand
|
|
148
|
+
const complex = new omdUnaryExpressionNode({
|
|
149
|
+
type: 'OperatorNode',
|
|
150
|
+
op: '-',
|
|
151
|
+
fn: 'unaryMinus',
|
|
152
|
+
args: [{
|
|
153
|
+
type: 'OperatorNode',
|
|
154
|
+
op: '+',
|
|
155
|
+
fn: 'add',
|
|
156
|
+
args: [
|
|
157
|
+
{ type: 'SymbolNode', name: 'x' },
|
|
158
|
+
{ type: 'ConstantNode', value: 1 }
|
|
159
|
+
]
|
|
160
|
+
}]
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
// Render with proper spacing
|
|
164
|
+
node.setFontSize(24);
|
|
165
|
+
node.computeDimensions();
|
|
166
|
+
node.updateLayout();
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### See Also
|
|
170
|
+
|
|
171
|
+
- [omdNode](./omdNode.md) - Parent class
|
|
172
|
+
- [omdOperatorNode](./omdOperatorNode.md) - For operator symbol
|
|
173
|
+
- [omdBinaryExpressionNode](./omdBinaryExpressionNode.md) - For complex operands
|
|
174
|
+
- [omdConstantNode](./omdConstantNode.md) - For numeric operands
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# omdUtilities
|
|
2
|
+
|
|
3
|
+
This module provides a collection of utility functions primarily used for mapping math.js AST nodes to OMD node classes, determining rendering behavior, and calculating text dimensions.
|
|
4
|
+
|
|
5
|
+
## Functions
|
|
6
|
+
|
|
7
|
+
#### `astToOmdType(type, ast)`
|
|
8
|
+
|
|
9
|
+
Maps a math.js AST node type to its corresponding OMD node class. This function is crucial for dynamically creating the correct `omdNode` subclass based on the parsed expression.
|
|
10
|
+
|
|
11
|
+
- **Parameters:**
|
|
12
|
+
- `type` {string} - The `type` property of the AST node (e.g., `"OperatorNode"`, `"ParenthesisNode"`).
|
|
13
|
+
- `ast` {Object} - The full AST node object, which may contain additional context (e.g., `op` for `OperatorNode`).
|
|
14
|
+
- **Returns:** {class} The appropriate `omdNode` class constructor.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
#### `getNodeForAST(ast)`
|
|
19
|
+
|
|
20
|
+
A wrapper function that takes a complete math.js AST node and returns the corresponding OMD node class. It uses `astToOmdType` internally.
|
|
21
|
+
|
|
22
|
+
- **Parameters:**
|
|
23
|
+
- `ast` {Object} - The math.js AST node.
|
|
24
|
+
- **Returns:** {class} The appropriate `omdNode` class constructor.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
#### `getTextBounds(text, fontSize)`
|
|
29
|
+
|
|
30
|
+
Calculates the rendered width and height of a given text string at a specific font size. This is used for precise layout calculations.
|
|
31
|
+
|
|
32
|
+
- **Parameters:**
|
|
33
|
+
- `text` {string} - The text content to measure.
|
|
34
|
+
- `fontSize` {number} - The font size in pixels.
|
|
35
|
+
- **Returns:** {Object} An object with `width` and `height` properties.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
#### `shouldUseFractionNotation(ast)`
|
|
40
|
+
|
|
41
|
+
Determines whether a division operation (represented by an AST node) should be rendered as a fraction (stacked numerator over denominator) or as a linear division (e.g., `a / b`). This is based on the complexity of the numerator and denominator.
|
|
42
|
+
|
|
43
|
+
- **Parameters:**
|
|
44
|
+
- `ast` {Object} - The AST node representing a division operation.
|
|
45
|
+
- **Returns:** {boolean} `true` if it should be a fraction, `false` otherwise.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
#### `isComplexExpression(ast)`
|
|
50
|
+
|
|
51
|
+
Checks if an AST node represents a "complex" expression, typically one that contains multiple operations or nested structures. This is used by `shouldUseFractionNotation` to decide on rendering style.
|
|
52
|
+
|
|
53
|
+
- **Parameters:**
|
|
54
|
+
- `ast` {Object} - The AST node to check.
|
|
55
|
+
- **Returns:** {boolean} `true` if the expression is considered complex, `false` otherwise.
|
|
56
|
+
|
|
57
|
+
### Example
|
|
58
|
+
|
|
59
|
+
```javascript
|
|
60
|
+
import { getNodeForAST, getTextBounds } from './omd/omdUtilities.js';
|
|
61
|
+
|
|
62
|
+
// Example of getting a node class
|
|
63
|
+
const ast = math.parse('x + 2');
|
|
64
|
+
const NodeClass = getNodeForAST(ast);
|
|
65
|
+
const node = new NodeClass(ast);
|
|
66
|
+
|
|
67
|
+
// Example of getting text bounds
|
|
68
|
+
const bounds = getTextBounds('Hello World', 24);
|
|
69
|
+
console.log(`Text width: ${bounds.width}, height: ${bounds.height}`);
|
|
70
|
+
```
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# omdVariableNode
|
|
2
|
+
|
|
3
|
+
Represents a variable (like x, y, a, b) in mathematical expressions.
|
|
4
|
+
|
|
5
|
+
## Class: `omdVariableNode extends omdLeafNode`
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
import { omdVariableNode } from './omd/nodes/omdVariableNode.js';
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
### Constructor
|
|
12
|
+
|
|
13
|
+
```javascript
|
|
14
|
+
new omdVariableNode(nodeData)
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**Parameters:**
|
|
18
|
+
- `nodeData` {Object|string} - The AST node data or variable name
|
|
19
|
+
|
|
20
|
+
**Description:**
|
|
21
|
+
Creates a node representing a variable. Usually created automatically when parsing expressions.
|
|
22
|
+
|
|
23
|
+
### Properties
|
|
24
|
+
|
|
25
|
+
Inherits all properties from [`omdLeafNode`](./omdLeafNode.md), plus:
|
|
26
|
+
|
|
27
|
+
#### `name`
|
|
28
|
+
- **Type:** string
|
|
29
|
+
- **Description:** The variable name (e.g., 'x', 'y', 'theta')
|
|
30
|
+
|
|
31
|
+
#### `type`
|
|
32
|
+
- **Type:** string
|
|
33
|
+
- **Description:** Always "variable"
|
|
34
|
+
|
|
35
|
+
#### `textElement`
|
|
36
|
+
- **Type:** SVGElement
|
|
37
|
+
- **Description:** The SVG text element displaying the variable name
|
|
38
|
+
|
|
39
|
+
### Methods
|
|
40
|
+
|
|
41
|
+
Inherits all methods from [`omdLeafNode`](./omdLeafNode.md), plus:
|
|
42
|
+
|
|
43
|
+
#### `parseName(nodeData)`
|
|
44
|
+
Internal method to extract variable name from AST data.
|
|
45
|
+
- **Returns:** string
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
#### `parseType()`
|
|
50
|
+
Internal method to set node type.
|
|
51
|
+
- **Returns:** "variable"
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
#### `computeDimensions()`
|
|
56
|
+
Calculates dimensions with padding around the variable.
|
|
57
|
+
Overrides base class method.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
#### `updateLayout()`
|
|
62
|
+
Updates the layout of the node.
|
|
63
|
+
Overrides base class method.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
#### `toMathJSNode()`
|
|
68
|
+
Converts to math.js AST format.
|
|
69
|
+
- **Returns:** Object - A math.js-compatible AST node with:
|
|
70
|
+
- `type`: "SymbolNode"
|
|
71
|
+
- `name`: The variable name
|
|
72
|
+
- `id`: Node ID
|
|
73
|
+
- `provenance`: Provenance array
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
#### `highlight(color)`
|
|
78
|
+
Highlights the node and sets text color to white.
|
|
79
|
+
- `color` {omdColor} - The highlight color
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
#### `clearProvenanceHighlights()`
|
|
84
|
+
Clears highlights and resets text color.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
#### `toString()`
|
|
89
|
+
Convert to string representation.
|
|
90
|
+
- **Returns:** string - The variable name
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
#### `evaluate(variables)`
|
|
95
|
+
Evaluates the variable by looking up its value in a map.
|
|
96
|
+
- `variables` {Object} - A map of variable names to their numeric values
|
|
97
|
+
- **Returns:** number - The value of the variable
|
|
98
|
+
- **Throws:** Error if variable is not defined in the map
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
#### `simplify()`
|
|
103
|
+
Attempt to simplify the variable.
|
|
104
|
+
- **Returns:** Object
|
|
105
|
+
- `success`: false (variables cannot be simplified)
|
|
106
|
+
- `newRoot`: null
|
|
107
|
+
- `message`: "Cannot simplify a variable"
|
|
108
|
+
|
|
109
|
+
### Static Methods
|
|
110
|
+
|
|
111
|
+
#### `fromName(name)`
|
|
112
|
+
Create a variable node from a name.
|
|
113
|
+
- `name` {string} - The variable name
|
|
114
|
+
- **Returns:** omdVariableNode
|
|
115
|
+
|
|
116
|
+
### Examples
|
|
117
|
+
|
|
118
|
+
#### Creating Variables
|
|
119
|
+
|
|
120
|
+
```javascript
|
|
121
|
+
// From a name
|
|
122
|
+
const nodeX = omdVariableNode.fromName('x');
|
|
123
|
+
const nodeTheta = omdVariableNode.fromName('θ');
|
|
124
|
+
|
|
125
|
+
// From AST data
|
|
126
|
+
const node = new omdVariableNode({
|
|
127
|
+
type: 'SymbolNode',
|
|
128
|
+
name: 'x'
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// Direct string name
|
|
132
|
+
const nodeY = new omdVariableNode('y');
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
#### Rendering Variables
|
|
136
|
+
|
|
137
|
+
```javascript
|
|
138
|
+
const node = omdVariableNode.fromName('x');
|
|
139
|
+
node.setFontSize(24);
|
|
140
|
+
node.computeDimensions(); // Calculate size with padding
|
|
141
|
+
node.updateLayout(); // Position the text element
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### See Also
|
|
145
|
+
|
|
146
|
+
- [omdLeafNode](./omdLeafNode.md) - Parent class
|
|
147
|
+
- [omdNode](./omdNode.md) - Base class
|
|
148
|
+
- [omdConstantNode](./omdConstantNode.md) - For numeric values
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
|
|
2
|
+
# SelectTool
|
|
3
|
+
|
|
4
|
+
The `SelectTool` is a tool for selecting, moving, and deleting stroke segments on the canvas. It extends the `Tool` class.
|
|
5
|
+
|
|
6
|
+
## Class Definition
|
|
7
|
+
|
|
8
|
+
```javascript
|
|
9
|
+
export class SelectTool extends Tool {
|
|
10
|
+
// ...
|
|
11
|
+
}
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Constructor
|
|
15
|
+
|
|
16
|
+
### `new SelectTool(canvas, [options])`
|
|
17
|
+
|
|
18
|
+
Creates a new `SelectTool` instance.
|
|
19
|
+
|
|
20
|
+
* **canvas** (`OMDCanvas`): The canvas instance.
|
|
21
|
+
* **[options]** (`object`, optional): Configuration options for the tool.
|
|
22
|
+
* **selectionColor** (`string`, optional): The color of the selection box. Defaults to `'#007bff'`.
|
|
23
|
+
* **selectionOpacity** (`number`, optional): The opacity of the selection box. Defaults to `0.3`.
|
|
24
|
+
|
|
25
|
+
## Public Methods
|
|
26
|
+
|
|
27
|
+
### `onPointerDown(event)`
|
|
28
|
+
|
|
29
|
+
Handles the pointer down event to start a selection.
|
|
30
|
+
|
|
31
|
+
* **event** (`PointerEvent`): The pointer event.
|
|
32
|
+
|
|
33
|
+
### `onPointerMove(event)`
|
|
34
|
+
|
|
35
|
+
Handles the pointer move event to update the selection box.
|
|
36
|
+
|
|
37
|
+
* **event** (`PointerEvent`): The pointer event.
|
|
38
|
+
|
|
39
|
+
### `onPointerUp(event)`
|
|
40
|
+
|
|
41
|
+
Handles the pointer up event to complete the selection.
|
|
42
|
+
|
|
43
|
+
* **event** (`PointerEvent`): The pointer event.
|
|
44
|
+
|
|
45
|
+
### `onCancel()`
|
|
46
|
+
|
|
47
|
+
Cancels the current selection operation.
|
|
48
|
+
|
|
49
|
+
### `onKeyboardShortcut(key, event)`
|
|
50
|
+
|
|
51
|
+
Handles keyboard shortcuts for selection-related actions.
|
|
52
|
+
|
|
53
|
+
* **key** (`string`): The key that was pressed.
|
|
54
|
+
* **event** (`KeyboardEvent`): The keyboard event.
|
|
55
|
+
* **Returns**: `boolean` - True if the shortcut was handled, false otherwise.
|
|
56
|
+
|
|
57
|
+
### `getCursor()`
|
|
58
|
+
|
|
59
|
+
Gets the cursor for the tool.
|
|
60
|
+
|
|
61
|
+
* **Returns**: `string` - The CSS cursor name.
|
|
62
|
+
|
|
63
|
+
### `clearSelection()`
|
|
64
|
+
|
|
65
|
+
Clears the current selection.
|
|
66
|
+
|
|
67
|
+
## Properties
|
|
68
|
+
|
|
69
|
+
* **displayName** (`string`): The display name of the tool.
|
|
70
|
+
* **description** (`string`): A description of the tool.
|
|
71
|
+
* **icon** (`string`): The icon for the tool.
|
|
72
|
+
* **shortcut** (`string`): The keyboard shortcut for the tool.
|
|
73
|
+
* **category** (`string`): The category of the tool.
|
|
74
|
+
* **selectedSegments** (`Map<string, Set<number>>`): A map of selected segments, where the key is the stroke ID and the value is a set of segment indices.
|