Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions documentation/Example Prompts.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ Create a triangle with vertices A(0,0), B(4,0), C(0,3) and construct its circumc
Construct the incircle of triangle ABC.
Create points P(0,0), Q(6,0), R(3,5) and draw the circle passing through all three.

# Relation Inspection
Create segments s1 from (0,0) to (4,0) and s2 from (0,2) to (4,2), then check if they are parallel.
Are segments AB and CD perpendicular?
Create points A(0,0), B(3,0), C(6,0) and check if they are collinear.
Create four points on a circle and verify they are concyclic.
Check if triangles T1 and T2 are similar.
Draw a tangent line to circle c1 and verify the tangency with inspect_relation.

# Regression Analysis
Fit a linear regression to x_data=[1,2,3,4,5] and y_data=[2.1,3.9,6.2,7.8,10.1]. Show the data points and fitted curve.
Fit a quadratic polynomial (degree 2) to x_data=[0,1,2,3,4] and y_data=[0,1,4,9,16]. Report the R-squared value.
Expand Down
34 changes: 34 additions & 0 deletions documentation/Reference Manual.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4256,6 +4256,40 @@ Examples (as user prompts):
- "Create an undirected weighted graph named G2 with vertices A, B, C, D, E and edges A-B (3), A-C (1), B-C (7), B-D (5), C-D (2), D-E (7), C-E (8)."
- "On graph G2, compute the minimum spanning tree and highlight the MST edges."

### Relation Inspection

- `inspect_relation(operation, objects, object_types)`: Check and explain geometric relations between objects on the canvas.

#### Supported operations (`inspect_relation`)
1. Direction: `parallel`, `perpendicular`
2. Point alignment: `collinear`, `concyclic`
3. Measurement: `equal_length`
4. Triangle comparison: `similar`, `congruent`
5. Tangency: `tangent` (segment+circle or circle+circle)
6. Line concurrence: `concurrent` (3+ segments meet at one point)
7. Incidence: `point_on_line`, `point_on_circle`
8. Automatic: `auto` (runs all applicable checks for the given type combination)

Parameters:
1. `operation`: one of the enum values above.
2. `objects`: array of drawable names (e.g. `["s1", "s2"]`).
3. `object_types`: parallel array of type tags (`"point"`, `"segment"`, `"vector"`, `"circle"`, `"ellipse"`, `"triangle"`, `"rectangle"`).

Return data:
1. Successful checks return `operation`, `result` (boolean), `explanation`, `tolerance_used`, and `details`.
2. Errors return `{"error": "..."}`.
3. `auto` returns a summary with all applicable checks and their individual results.

Examples (as user prompts):
1. Check parallelism:
- "Create segments s1 from (0,0) to (4,0) and s2 from (0,2) to (4,2). Are s1 and s2 parallel?"
2. Check concyclic points:
- "Create points A(5,0), B(0,5), C(-5,0), D(0,-5). Are A, B, C, D concyclic?"
3. Check triangle similarity:
- "Create triangle T1 with vertices (0,0),(3,0),(0,4) and T2 with vertices (0,0),(6,0),(0,8). Are T1 and T2 similar?"
4. Auto-inspect:
- "Create two segments and use auto inspection to check all applicable relations."

### Plot and Statistical Drawable Classes

The following drawable classes support statistical plots, bar charts, and distribution visualizations.
Expand Down
2 changes: 1 addition & 1 deletion documentation/todo.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
- CSV workflow: import/export datasets through chat commands with validation and schema feedback
- plotting suite: scatter/histogram/box plots, polar plots, implicit plots from natural language intents
- [done] geometric construction toolkit: midpoint/perpendicular/parallel/bisectors/circumcircle/incircle through declarative commands (PR #41 + circumcircle/incircle follow-up)
- relation inspector: explain and verify geometric relations (parallel/perpendicular/collinear/concyclic/equal-length) on demand
- [done] relation inspector: explain and verify geometric relations (parallel/perpendicular/collinear/concyclic/equal-length) on demand
- transform workflows: reflection/dilation/shear/rotation/translation using object references and constraint-aware execution
- interaction tools: tracing, root/extrema/intersection discovery, parameter sweeps, and dynamic slider orchestration from chat
- statistics workflows: summaries, additional distributions, and probability calculators with explanation-friendly output
Expand Down
4 changes: 2 additions & 2 deletions server_tests/data/tool_discovery_cases.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
"metadata": {
"schema_version": 1,
"description": "Tool discovery benchmark cases for search_tools semantic routing.",
"expected_tool_count": 87,
"expected_tool_hash": "932b5456edb8acedd97213b4f7fc186b483f1439c437f04fe63f7e3ad0395462",
"expected_tool_count": 88,
"expected_tool_hash": "83e8adde606967b1d631a908ea6dd55c4a98ca7ae56ec0975027bf85d6332c3e",
"confusion_clusters": {
"convert_cluster": [
"convert",
Expand Down
53 changes: 53 additions & 0 deletions static/client/canvas.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
from utils.math_utils import MathUtils
from utils.style_utils import StyleUtils
from utils.graph_analyzer import GraphAnalyzer
from utils.relation_inspector import RelationInspector
from utils.computation_utils import ComputationUtils
from geometry.graph_state import GraphState
from managers.undo_redo_manager import UndoRedoManager
Expand Down Expand Up @@ -1163,6 +1164,58 @@ def analyze_graph(
return {"error": "Graph not found or spec missing"}
return cast(Dict[str, Any], GraphAnalyzer.analyze(state, operation, params))

# ------------------- Relation Inspection -------------------

def inspect_relation(
self,
*,
operation: str,
objects: List[str],
object_types: List[str],
) -> Dict[str, Any]:
"""Check a geometric relation among named canvas objects.

Args:
operation: Relation to check (e.g. ``"parallel"``, ``"auto"``).
objects: Names of drawables to inspect.
object_types: Parallel list of type tags for each name.

Returns:
Result dict from :class:`RelationInspector`.
"""
if len(objects) != len(object_types):
return {"error": "Error: objects and object_types must have the same length"}

resolved: List[Any] = []
for name, otype in zip(objects, object_types):
obj = self._resolve_drawable_by_type(name, otype)
if obj is None:
return {"error": f"Error: {otype} '{name}' not found on canvas"}
resolved.append(obj)

return cast(
Dict[str, Any],
RelationInspector.inspect(operation, resolved, object_types),
)

def _resolve_drawable_by_type(self, name: str, obj_type: str) -> Optional[Any]:
"""Look up a drawable by *name* and *obj_type* string."""
if obj_type == "point":
return self.get_point_by_name(name)
if obj_type == "segment":
return self.get_segment_by_name(name)
if obj_type == "vector":
return self.drawable_manager.vector_manager.get_vector_by_name(name)
if obj_type == "circle":
return self.get_circle_by_name(name)
if obj_type == "ellipse":
return self.get_ellipse_by_name(name)
if obj_type == "triangle":
return self.drawable_manager.drawables.get_triangle_by_name(name)
if obj_type == "rectangle":
return self.drawable_manager.drawables.get_rectangle_by_name(name)
return None

# ------------------- Circle Methods -------------------
def get_circle(self, center_x: float, center_y: float, radius: float) -> Optional["Drawable"]:
"""Get a circle by its center coordinates and radius"""
Expand Down
Loading