feat(automation): richer query geometry + layers/header introspection
query now emits geometry for Ellipse/Text/MText/Polyline/Insert (on top of Line/Circle/Arc/Point). Add layers op (name, ACI/RGB colour, on/off, frozen, locked + current layer) and header op (units, PDMODE/PDSIZE, LTSCALE, annotation scale, current layer/text style). ocs.py gains layers()/header(). Lets an agent read the drawing's structure and settings, not just entity counts. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
707c143212
commit
d4f5ed3135
3 changed files with 80 additions and 1 deletions
|
|
@ -19,7 +19,9 @@ can act → observe → act.
|
|||
| `{"op":"open","path":"plan.dwg"}` | entity summary |
|
||||
| `{"op":"run","cmd":"LAYER Walls"}` | `{"ok":true,"cmd":...,"entities":N,"added":D}` |
|
||||
| `{"op":"entities"}` | `{"ok":true,"total":N,"by_type":{"Line":42,...}}` |
|
||||
| `{"op":"query","type":"Line","layer":"Walls"}` | per-entity `{handle,type,layer,…geometry}` (filters + `limit` optional) |
|
||||
| `{"op":"query","type":"Line","layer":"Walls"}` | per-entity `{handle,type,layer,…geometry}` (Line/Circle/Arc/Point/Ellipse/Text/MText/Polyline/Insert; filters + `limit` optional) |
|
||||
| `{"op":"layers"}` | layers `{name,color,off,frozen,locked}` + the current layer |
|
||||
| `{"op":"header"}` | drawing variables (units, PDMODE/PDSIZE, LTSCALE, …) |
|
||||
| `{"op":"select","handles":["2B"]}` | set the selection (by `handles`, `type`, or `layer`; `clear` to deselect) → `{"ok":true,"selected":N}` |
|
||||
| `{"op":"undo"}` / `{"op":"redo"}` | step the document history → entity summary |
|
||||
| `{"op":"save","path":"out.dwg"}` | `{"ok":true,"saved":"out.dwg"}` (path optional once opened/saved) |
|
||||
|
|
|
|||
|
|
@ -79,6 +79,14 @@ class Ocs:
|
|||
"""List entities (handle, type, layer, geometry), optionally filtered."""
|
||||
return self._send(op="query", type=type, layer=layer, limit=limit)
|
||||
|
||||
def layers(self) -> dict[str, Any]:
|
||||
"""List layers (name, color, on/off, frozen, locked) and the current one."""
|
||||
return self._send(op="layers")
|
||||
|
||||
def header(self) -> dict[str, Any]:
|
||||
"""Read drawing header variables (units, PDMODE/PDSIZE, LTSCALE, …)."""
|
||||
return self._send(op="header")
|
||||
|
||||
def select(
|
||||
self,
|
||||
handles: Optional[list[str]] = None,
|
||||
|
|
|
|||
|
|
@ -86,6 +86,31 @@ fn entity_json(e: &acadrust::EntityType) -> Value {
|
|||
E::Point(p) => {
|
||||
map.insert("location".into(), v3(p.location));
|
||||
}
|
||||
E::Ellipse(el) => {
|
||||
map.insert("center".into(), v3(el.center));
|
||||
map.insert("major_axis".into(), v3(el.major_axis));
|
||||
}
|
||||
E::Text(t) => {
|
||||
map.insert("value".into(), json!(t.value));
|
||||
map.insert("position".into(), v3(t.insertion_point));
|
||||
map.insert("height".into(), json!(t.height));
|
||||
}
|
||||
E::MText(t) => {
|
||||
map.insert("value".into(), json!(t.value));
|
||||
map.insert("position".into(), v3(t.insertion_point));
|
||||
map.insert("height".into(), json!(t.height));
|
||||
}
|
||||
E::LwPolyline(pl) => {
|
||||
let pts: Vec<Value> = pl
|
||||
.vertices
|
||||
.iter()
|
||||
.map(|v| json!([v.location.x, v.location.y]))
|
||||
.collect();
|
||||
map.insert("vertices".into(), json!(pts));
|
||||
}
|
||||
E::Insert(ins) => {
|
||||
map.insert("block".into(), json!(ins.block_name));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
obj
|
||||
|
|
@ -151,6 +176,50 @@ impl OpenCADStudio {
|
|||
}
|
||||
"entities" => self.entity_summary(),
|
||||
"query" => self.entity_query(&req),
|
||||
"layers" => {
|
||||
let i = self.active_tab;
|
||||
let layers: Vec<Value> = self
|
||||
.tabs[i]
|
||||
.scene
|
||||
.document
|
||||
.layers
|
||||
.iter()
|
||||
.map(|l| {
|
||||
let mut o = json!({
|
||||
"name": l.name,
|
||||
"off": l.is_off(),
|
||||
"frozen": l.is_frozen(),
|
||||
"locked": l.is_locked(),
|
||||
});
|
||||
let m = o.as_object_mut().expect("json object");
|
||||
if let Some(aci) = l.color.index() {
|
||||
m.insert("color".into(), json!(aci));
|
||||
}
|
||||
if let Some((r, g, b)) = l.color.rgb() {
|
||||
m.insert("rgb".into(), json!([r, g, b]));
|
||||
}
|
||||
o
|
||||
})
|
||||
.collect();
|
||||
json!({
|
||||
"ok": true,
|
||||
"current": self.tabs[i].scene.document.header.current_layer_name,
|
||||
"layers": layers,
|
||||
})
|
||||
}
|
||||
"header" => {
|
||||
let h = &self.tabs[self.active_tab].scene.document.header;
|
||||
json!({
|
||||
"ok": true,
|
||||
"current_layer": h.current_layer_name,
|
||||
"current_text_style": h.current_text_style_name,
|
||||
"insertion_units": h.insertion_units,
|
||||
"pdmode": h.point_display_mode,
|
||||
"pdsize": h.point_display_size,
|
||||
"ltscale": h.linetype_scale,
|
||||
"annotation_scale_value": h.annotation_scale_value,
|
||||
})
|
||||
}
|
||||
"undo" => {
|
||||
let _ = self.update(super::Message::Undo);
|
||||
self.entity_summary()
|
||||
|
|
|
|||
Loading…
Reference in a new issue