forked from 1b-agent/opencadstudio-upstream
feat(python): chamfer, arrays, explode, join, break, stretch and lengthen wrappers
Each is written against the prompt sequence observed in the exploration harness and checked for exact geometry in the real-IPC audit. HATCH is left to create_entity because its command needs an interactive boundary pick. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
1b1785eefb
commit
360dd853ed
5 files changed
+184
-46
No files matched your search
@@ -273,3 +273,14 @@ command, second command, run while active), no command left running, and a one-s
|
|||||||
Not covered: chamfer, arrays, hatch, join, explode, break and the many other commands (reachable through `doc.command` and
|
Not covered: chamfer, arrays, hatch, join, explode, break and the many other commands (reachable through `doc.command` and
|
||||||
`start_command`); reading prompts for commands with a text editor; an on/off setting for script-driven commands.
|
`start_command`); reading prompts for commands with a text editor; an on/off setting for script-driven commands.
|
||||||
|
|
||||||
|
### 2026-09-21: more modify wrappers
|
||||||
|
|
||||||
|
`doc.modify` gained `chamfer`, `array_rect`, `array_polar`, `explode`, `join`, `break_entity`, `stretch` and `lengthen`, each
|
||||||
|
written against the prompt sequence observed in `spike_command_runner_prompts` (STRETCH needs an Enter after the crossing
|
||||||
|
window, LENGTHEN and STRETCH end on Enter, EXPLODE and JOIN use the pre-selection because a pick at their selection prompt
|
||||||
|
selects nothing). `audit_python_modify_wrappers_over_real_ipc` checks exact geometry for each: the chamfer line, all six
|
||||||
|
rectangular-array members, the four polar-array members (start and half turn), the exploded segments and the removed polyline,
|
||||||
|
the joined line without its parts, the two pieces after a break, the stretched and the lengthened end points. HATCH is left to
|
||||||
|
`create_entity("Hatch")`: its command needs an interactive boundary pick that no scripted step can supply. Not wrapped: PEDIT,
|
||||||
|
path and 3-D arrays, and the remaining commands, which stay reachable through `doc.command` and `start_command`.
|
||||||
|
|
||||||
@@ -281,6 +281,13 @@ M.fillet(first, second, radius=2) # radius 0 squares the corner
|
|||||||
M.move([a, b], (0, 0, 0), (5, 5, 0)); M.copy([a], base, target)
|
M.move([a, b], (0, 0, 0), (5, 5, 0)); M.copy([a], base, target)
|
||||||
M.rotate([a], base, 90); M.scale([a], base, 2)
|
M.rotate([a], base, 90); M.scale([a], base, 2)
|
||||||
M.mirror([a], p1, p2, erase_source=False); M.erase([a])
|
M.mirror([a], p1, p2, erase_source=False); M.erase([a])
|
||||||
|
M.chamfer(first, second, 2, 3) # distance 2 along first, 3 along second
|
||||||
|
M.array_rect([a], rows=2, columns=3, row_spacing=10, column_spacing=20)
|
||||||
|
M.array_polar([a], center, count=4, angle=360) # counts include the original
|
||||||
|
M.explode([polyline]); M.join([line1, line2])
|
||||||
|
M.break_entity(line, first_point, second_point)
|
||||||
|
M.stretch(corner1, corner2, base, target) # crossing window, then the displacement
|
||||||
|
M.lengthen(line, 5, at=near_the_end) # delta; negative shortens
|
||||||
```
|
```
|
||||||
|
|
||||||
Each step returns an outcome dict: `status` (`completed` or `waiting_input`),
|
Each step returns an outcome dict: `status` (`completed` or `waiting_input`),
|
||||||
@@ -292,7 +299,8 @@ Each step returns an outcome dict: `status` (`completed` or `waiting_input`),
|
|||||||
also closing any editor or dialog it opened. `doc.command` cancels and raises when
|
also closing any editor or dialog it opened. `doc.command` cancels and raises when
|
||||||
the line leaves a prompt open.
|
the line leaves a prompt open.
|
||||||
|
|
||||||
Selection-based tools (`move`, `copy`, `rotate`, `scale`, `mirror`, `erase`) select
|
Selection-based tools (`move`, `copy`, `rotate`, `scale`, `mirror`, `erase`, the arrays,
|
||||||
|
`explode` and `join`) select
|
||||||
the entities you pass first, so the command skips its own selection prompt. Pick
|
the entities you pass first, so the command skips its own selection prompt. Pick
|
||||||
points default to the middle of a line, arc or circle; give `at=` for anything else.
|
points default to the middle of a line, arc or circle; give `at=` for anything else.
|
||||||
`trim` and `extend` cut or extend against every entity in the drawing. Each command is
|
`trim` and `extend` cut or extend against every entity in the drawing. Each command is
|
||||||
@@ -304,7 +312,9 @@ line names a command that could end the session or re-enter Python: `QUIT`,
|
|||||||
`RECOVER`, `SCRIPT`, `RUNSCRIPT` and any `PY_*`. Commands run on the active
|
`RECOVER`, `SCRIPT`, `RUNSCRIPT` and any `PY_*`. Commands run on the active
|
||||||
document only. Commands that need an interactive surface a script cannot fill
|
document only. Commands that need an interactive surface a script cannot fill
|
||||||
(the rich-text editor, a file dialog) report it in `blocked_by` and are cancelled.
|
(the rich-text editor, a file dialog) report it in `blocked_by` and are cancelled.
|
||||||
`ocs.command_step(kind, options)` is the raw single step behind all of this.
|
Hatching has no wrapper: create it with `create_entity("Hatch", ...)`, because the
|
||||||
|
HATCH command needs an interactive boundary pick. `ocs.command_step(kind, options)`
|
||||||
|
is the raw single step behind all of this.
|
||||||
|
|
||||||
### Historical command-replay experiment (not in the default build)
|
### Historical command-replay experiment (not in the default build)
|
||||||
|
|
||||||
|
|||||||
@@ -751,6 +751,76 @@ class _Modify:
|
|||||||
lambda c: c.token("Y" if erase_source else "N"),
|
lambda c: c.token("Y" if erase_source else "N"),
|
||||||
], entities)
|
], entities)
|
||||||
|
|
||||||
|
def chamfer(self, first, second, distance1, distance2=None, at1=None, at2=None):
|
||||||
|
"""Cut the corner between two lines; `distance1` is measured along `first`
|
||||||
|
and `distance2` (default the same) along `second`. Returns the new line."""
|
||||||
|
if distance2 is None:
|
||||||
|
distance2 = distance1
|
||||||
|
result = self._run("CHAMFER", [
|
||||||
|
lambda c: c.token("D"),
|
||||||
|
lambda c: c.text(distance1),
|
||||||
|
lambda c: c.text(distance2),
|
||||||
|
lambda c: c.entity(first, self._at(first, at1)),
|
||||||
|
lambda c: c.entity(second, self._at(second, at2)),
|
||||||
|
])
|
||||||
|
if not result:
|
||||||
|
raise RuntimeError("CHAMFER produced nothing")
|
||||||
|
return result[0]
|
||||||
|
|
||||||
|
def array_rect(self, entities, rows, columns, row_spacing, column_spacing):
|
||||||
|
"""Rectangular array of the entities: `rows` by `columns` copies counting
|
||||||
|
the original, spaced by `row_spacing` and `column_spacing`. Returns the copies."""
|
||||||
|
return self._run("ARRAYRECT", [
|
||||||
|
lambda c: c.text(rows),
|
||||||
|
lambda c: c.text(columns),
|
||||||
|
lambda c: c.text(row_spacing),
|
||||||
|
lambda c: c.text(column_spacing),
|
||||||
|
], entities)
|
||||||
|
|
||||||
|
def array_polar(self, entities, center, count, angle=360):
|
||||||
|
"""Polar array about `center`: `count` items counting the original, spread
|
||||||
|
over `angle` degrees. Returns the copies."""
|
||||||
|
return self._run("ARRAYPOLAR", [
|
||||||
|
lambda c: c.point(center),
|
||||||
|
lambda c: c.text(count),
|
||||||
|
lambda c: c.text(angle),
|
||||||
|
], entities)
|
||||||
|
|
||||||
|
def explode(self, entities):
|
||||||
|
"""Break polylines, blocks and similar entities into their parts; returns the parts."""
|
||||||
|
return self._run("EXPLODE", [], entities)
|
||||||
|
|
||||||
|
def join(self, entities):
|
||||||
|
"""Join end-to-end lines, arcs and polylines into one entity; returns it."""
|
||||||
|
return self._run("JOIN", [], entities)
|
||||||
|
|
||||||
|
def break_entity(self, entity, first, second):
|
||||||
|
"""Remove the part of `entity` between two points on it; returns the new piece."""
|
||||||
|
return self._run("BREAK", [
|
||||||
|
lambda c: c.entity(entity, first),
|
||||||
|
lambda c: c.point(second),
|
||||||
|
])
|
||||||
|
|
||||||
|
def stretch(self, corner1, corner2, base, target):
|
||||||
|
"""Stretch whatever the crossing window (two opposite corners) catches, moving
|
||||||
|
`base` to `target`; entities fully inside move, ones crossing the edge stretch."""
|
||||||
|
self._run("STRETCH", [
|
||||||
|
lambda c: c.point(corner1),
|
||||||
|
lambda c: c.point(corner2),
|
||||||
|
lambda c: c.enter(),
|
||||||
|
lambda c: c.point(base),
|
||||||
|
lambda c: c.point(target),
|
||||||
|
])
|
||||||
|
|
||||||
|
def lengthen(self, entity, delta, at=None):
|
||||||
|
"""Lengthen (or, negative, shorten) `entity` by `delta` at the end nearest `at`."""
|
||||||
|
self._run("LENGTHEN", [
|
||||||
|
lambda c: c.token("DE"),
|
||||||
|
lambda c: c.text(delta),
|
||||||
|
lambda c: c.entity(entity, self._at(entity, at)),
|
||||||
|
lambda c: c.enter(),
|
||||||
|
])
|
||||||
|
|
||||||
def erase(self, entities):
|
def erase(self, entities):
|
||||||
before = len(list(ocs.entity_handles()))
|
before = len(list(ocs.entity_handles()))
|
||||||
self._select(entities)
|
self._select(entities)
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ class DocumentModelTests(unittest.TestCase):
|
|||||||
outcome = {"status": "completed", "blocked_by": None, "command": "", "prompt": "", "accepts": [],
|
outcome = {"status": "completed", "blocked_by": None, "command": "", "prompt": "", "accepts": [],
|
||||||
"options": [], "entities": 0, "added": 0, "unconsumed": [], "error": None}
|
"options": [], "entities": 0, "added": 0, "unconsumed": [], "error": None}
|
||||||
outcome.update(self.step_outcome.get(kind, {}))
|
outcome.update(self.step_outcome.get(kind, {}))
|
||||||
if kind == "enter":
|
if kind in ("enter", "entity"):
|
||||||
new = max(self.records) + 1
|
new = max(self.records) + 1
|
||||||
self.records[new] = {"handle": new, "kind": "Line", "layer": "0", "_editable": True}
|
self.records[new] = {"handle": new, "kind": "Line", "layer": "0", "_editable": True}
|
||||||
return outcome
|
return outcome
|
||||||
@@ -98,6 +98,22 @@ class DocumentModelTests(unittest.TestCase):
|
|||||||
entity_step = [c for c in self.calls if c[0] == "step" and c[1] == "entity"][0]
|
entity_step = [c for c in self.calls if c[0] == "step" and c[1] == "entity"][0]
|
||||||
self.assertEqual(entity_step[2]["point"], [1, 0, 5.0])
|
self.assertEqual(entity_step[2]["point"], [1, 0, 5.0])
|
||||||
|
|
||||||
|
def test_more_modify_wrappers(self):
|
||||||
|
self.step_outcome = {}
|
||||||
|
self.doc.modify.chamfer(1, 2, 2, 3, at1=(0, 0, 0), at2=(1, 1, 0))
|
||||||
|
texts = [c[2]["text"] for c in self.calls if c[0] == "step" and c[1] == "text"]
|
||||||
|
self.assertEqual(texts, ["2", "3"])
|
||||||
|
self.calls.clear()
|
||||||
|
self.doc.modify.chamfer(1, 2, 4, at1=(0, 0, 0), at2=(1, 1, 0))
|
||||||
|
texts = [c[2]["text"] for c in self.calls if c[0] == "step" and c[1] == "text"]
|
||||||
|
self.assertEqual(texts, ["4", "4"])
|
||||||
|
self.calls.clear()
|
||||||
|
self.doc.modify.array_rect([1], 2, 3, 10, 20)
|
||||||
|
self.assertEqual([c[2]["text"] for c in self.calls if c[0] == "step" and c[1] == "text"], ["2", "3", "10", "20"])
|
||||||
|
self.calls.clear()
|
||||||
|
self.doc.modify.stretch((0, 0), (1, 1), (0, 0), (5, 0))
|
||||||
|
self.assertEqual([c[1] for c in self.calls if c[0] == "step"], ["start", "point", "point", "enter", "point", "point"])
|
||||||
|
|
||||||
def test_batch_edit_and_rollback(self):
|
def test_batch_edit_and_rollback(self):
|
||||||
line = self.doc.entities[1]
|
line = self.doc.entities[1]
|
||||||
self.assertEqual(line.start, (1, 2, 3))
|
self.assertEqual(line.start, (1, 2, 3))
|
||||||
|
|||||||
+74
-43
@@ -8067,6 +8067,22 @@ mi = line((800, 0), (810, 0))
|
|||||||
step('mirror', lambda: M.mirror([mi], (0, 5, 0), (1, 5, 0)))
|
step('mirror', lambda: M.mirror([mi], (0, 5, 0), (1, 5, 0)))
|
||||||
e = line((900, 0), (910, 0))
|
e = line((900, 0), (910, 0))
|
||||||
step('erase', lambda: M.erase([e]))
|
step('erase', lambda: M.erase([e]))
|
||||||
|
ca = line((1300, 0), (1310, 0)); cb = line((1300, 0), (1300, 10))
|
||||||
|
step('chamfer', lambda: M.chamfer(ca, cb, 2, 3, (1308, 0), (1300, 8)))
|
||||||
|
ar = line((1400, 0), (1401, 0))
|
||||||
|
step('array_rect', lambda: M.array_rect([ar], 2, 3, 10, 20))
|
||||||
|
ap = line((1500, 0), (1501, 0))
|
||||||
|
step('array_polar', lambda: M.array_polar([ap], (1500, 10, 0), 4, 360))
|
||||||
|
pl = doc.create_entity('LwPolyline', vertices=[{'location': P(1600, 0)}, {'location': P(1610, 0)}, {'location': P(1610, 10)}])
|
||||||
|
step('explode', lambda: M.explode([pl]))
|
||||||
|
j1 = line((1700, 0), (1705, 0)); j2 = line((1705, 0), (1710, 0))
|
||||||
|
step('join', lambda: M.join([j1, j2]))
|
||||||
|
bk = line((1800, 0), (1810, 0))
|
||||||
|
step('break', lambda: M.break_entity(bk, (1802, 0, 0), (1805, 0, 0)))
|
||||||
|
st = line((1900, 0), (1910, 0))
|
||||||
|
step('stretch', lambda: M.stretch((1908, -2, 0), (1912, 2, 0), (1910, 0, 0), (1915, 0, 0)))
|
||||||
|
ln = line((2000, 0), (2010, 0))
|
||||||
|
step('lengthen', lambda: M.lengthen(ln, 5, (2009, 0, 0)))
|
||||||
step('run_line', lambda: doc.command('LINE 1100,0 1110,10'))
|
step('run_line', lambda: doc.command('LINE 1100,0 1110,10'))
|
||||||
def interactive():
|
def interactive():
|
||||||
with doc.start_command('CIRCLE') as c:
|
with doc.start_command('CIRCLE') as c:
|
||||||
@@ -8112,6 +8128,18 @@ check('bad_point', lambda: ocs.command_step('point', {'point': [0, 0, 0]}))
|
|||||||
assert!(has_line(800.0, 0.0, 810.0, 0.0) && has_line(800.0, 10.0, 810.0, 10.0), "mirror keeps the source and adds the reflection: {:?}", describe());
|
assert!(has_line(800.0, 0.0, 810.0, 0.0) && has_line(800.0, 10.0, 810.0, 10.0), "mirror keeps the source and adds the reflection: {:?}", describe());
|
||||||
assert!(!has_line(900.0, 0.0, 910.0, 0.0), "erase: {:?}", describe());
|
assert!(!has_line(900.0, 0.0, 910.0, 0.0), "erase: {:?}", describe());
|
||||||
assert!(has_line(1100.0, 0.0, 1110.0, 10.0), "doc.command run: {:?}", describe());
|
assert!(has_line(1100.0, 0.0, 1110.0, 10.0), "doc.command run: {:?}", describe());
|
||||||
|
assert!(has_line(1302.0, 0.0, 1300.0, 3.0), "chamfer: {:?}", describe());
|
||||||
|
for (x, y) in [(1400.0, 0.0), (1420.0, 0.0), (1440.0, 0.0), (1400.0, 10.0), (1420.0, 10.0), (1440.0, 10.0)] {
|
||||||
|
assert!(has_line(x, y, x + 1.0, y), "rectangular array member at ({x}, {y}): {:?}", describe());
|
||||||
|
}
|
||||||
|
assert!(has_line(1500.0, 0.0, 1501.0, 0.0) && has_line(1500.0, 20.0, 1499.0, 20.0), "polar array (start and half turn): {:?}", describe());
|
||||||
|
assert_eq!(lines.iter().filter(|l| l.start.x > 1450.0 && l.start.x < 1520.0 || l.end.x > 1450.0 && l.end.x < 1520.0).count(), 4, "polar array has four members");
|
||||||
|
assert!(has_line(1600.0, 0.0, 1610.0, 0.0) && has_line(1610.0, 0.0, 1610.0, 10.0), "explode: {:?}", describe());
|
||||||
|
assert!(!host.document().entities().any(|e| matches!(e, EntityType::LwPolyline(p) if p.vertices.first().is_some_and(|v| near(v.location.x, 1600.0)))), "explode removed the polyline");
|
||||||
|
assert!(has_line(1700.0, 0.0, 1710.0, 0.0) && !has_line(1700.0, 0.0, 1705.0, 0.0), "join: {:?}", describe());
|
||||||
|
assert!(has_line(1800.0, 0.0, 1802.0, 0.0) && has_line(1805.0, 0.0, 1810.0, 0.0) && !has_line(1800.0, 0.0, 1810.0, 0.0), "break: {:?}", describe());
|
||||||
|
assert!(has_line(1900.0, 0.0, 1915.0, 0.0), "stretch: {:?}", describe());
|
||||||
|
assert!(has_line(2000.0, 0.0, 2015.0, 0.0), "lengthen: {:?}", describe());
|
||||||
assert!(circles.iter().any(|c| near(c.center.x, 1200.0) && near(c.radius, 3.0)), "start_command session: {circles:?}");
|
assert!(circles.iter().any(|c| near(c.center.x, 1200.0) && near(c.radius, 3.0)), "start_command session: {circles:?}");
|
||||||
assert!(host.app.tabs[0].active_cmd.is_none(), "no command is left running");
|
assert!(host.app.tabs[0].active_cmd.is_none(), "no command is left running");
|
||||||
|
|
||||||
@@ -8142,8 +8170,8 @@ step('undo_move', lambda: M.move([u], (0, 0, 0), (7, 0, 0)))
|
|||||||
app.tabs[0].is_start = false;
|
app.tabs[0].is_start = false;
|
||||||
let mut host = HostSession::new(&mut app, 0);
|
let mut host = HostSession::new(&mut app, 0);
|
||||||
let show = |label: &str, r: &Result<ocs_plugin_api::host::CommandOutcome, String>| match r {
|
let show = |label: &str, r: &Result<ocs_plugin_api::host::CommandOutcome, String>| match r {
|
||||||
Ok(o) => eprintln!("SPIKE {label}: {} cmd={} prompt={:?} accepts={:?} opts={:?} added={} unconsumed={:?} err={:?}",
|
Ok(o) => eprintln!("SPIKE {label}: {} prompt={:?} accepts={:?} opts={:?} added={} err={:?}",
|
||||||
o.status, o.command, o.prompt, o.accepts, o.options, o.added, o.unconsumed, o.error),
|
o.status, o.prompt, o.accepts, o.options, o.added, o.error),
|
||||||
Err(e) => eprintln!("SPIKE {label}: ERR {e}"),
|
Err(e) => eprintln!("SPIKE {label}: ERR {e}"),
|
||||||
};
|
};
|
||||||
let run = |host: &mut HostSession<'_>, label: &str, r: R| { let out = host.run_command(r); show(label, &out); out };
|
let run = |host: &mut HostSession<'_>, label: &str, r: R| { let out = host.run_command(r); show(label, &out); out };
|
||||||
@@ -8152,60 +8180,63 @@ step('undo_move', lambda: M.move([u], (0, 0, 0), (7, 0, 0)))
|
|||||||
host.document().entities().map(|e| e.common().handle).collect()
|
host.document().entities().map(|e| e.common().handle).collect()
|
||||||
};
|
};
|
||||||
let cancel = |host: &mut HostSession<'_>| { let _ = host.run_command(R::Cancel); };
|
let cancel = |host: &mut HostSession<'_>| { let _ = host.run_command(R::Cancel); };
|
||||||
let hs = mk(&mut host, &["LINE 0,0 10,0", "LINE 5,-5 5,5", "LINE 20,0 30,0", "LINE 0,10 10,10", "LINE 0,20 10,20"]);
|
let hs = mk(&mut host, &["LINE 0,0 10,0", "LINE 0,0 0,10", "PLINE 50,0 60,0 60,10", "LINE 100,0 105,0", "LINE 105,0 110,5", "CIRCLE 200,0 5", "LINE 300,0 310,0"]);
|
||||||
// EXTEND: extend line 3 toward line 2? use boundary line 2 at x=5; extend line hs[0]'s end at x=10? Extend hs[2] (20..30) leftwards to x=5 no; use hs[0] end to the wall at x=15
|
|
||||||
let _ = mk(&mut host, &["LINE 15,-5 15,5"]);
|
|
||||||
let wall = *host.document().entities().last().map(|e| &e.common().handle).unwrap();
|
|
||||||
run(&mut host, "EXTEND start", R::Start { name: "EXTEND".into() });
|
|
||||||
run(&mut host, "EXTEND pick", R::Entity { handle: hs[0], point: [9.0, 0.0, 0.0] });
|
|
||||||
run(&mut host, "EXTEND enter", R::Enter);
|
|
||||||
cancel(&mut host);
|
|
||||||
// FILLET
|
|
||||||
run(&mut host, "FILLET start", R::Start { name: "FILLET".into() });
|
|
||||||
run(&mut host, "FILLET R", R::Token { text: "R".into() });
|
|
||||||
run(&mut host, "FILLET radius", R::Text { text: "2".into() });
|
|
||||||
run(&mut host, "FILLET first", R::Entity { handle: hs[3], point: [2.0, 10.0, 0.0] });
|
|
||||||
run(&mut host, "FILLET second", R::Entity { handle: hs[4], point: [2.0, 20.0, 0.0] });
|
|
||||||
cancel(&mut host);
|
|
||||||
let _ = wall;
|
|
||||||
// CHAMFER
|
// CHAMFER
|
||||||
run(&mut host, "CHAMFER start", R::Start { name: "CHAMFER".into() });
|
run(&mut host, "CHAMFER start", R::Start { name: "CHAMFER".into() });
|
||||||
|
run(&mut host, "CHAMFER D", R::Token { text: "D".into() });
|
||||||
|
run(&mut host, "CHAMFER d1", R::Text { text: "2".into() });
|
||||||
|
run(&mut host, "CHAMFER d2", R::Text { text: "3".into() });
|
||||||
|
run(&mut host, "CHAMFER first", R::Entity { handle: hs[0], point: [8.0, 0.0, 0.0] });
|
||||||
|
run(&mut host, "CHAMFER second", R::Entity { handle: hs[1], point: [0.0, 8.0, 0.0] });
|
||||||
cancel(&mut host);
|
cancel(&mut host);
|
||||||
// selection commands
|
// ARRAYRECT
|
||||||
host.app.tabs[0].scene.replace_selection_exact(&[hs[3]]);
|
host.app.tabs[0].scene.replace_selection_exact(&[hs[6]]);
|
||||||
run(&mut host, "COPY run", R::Run { line: "COPY 0,0 0,3".into() });
|
|
||||||
run(&mut host, "COPY leftover", R::Enter);
|
|
||||||
cancel(&mut host);
|
|
||||||
host.app.tabs[0].scene.replace_selection_exact(&[hs[3]]);
|
|
||||||
run(&mut host, "ROTATE run", R::Run { line: "ROTATE 0,0 90".into() });
|
|
||||||
cancel(&mut host);
|
|
||||||
host.app.tabs[0].scene.replace_selection_exact(&[hs[4]]);
|
|
||||||
run(&mut host, "SCALE run", R::Run { line: "SCALE 0,0 2".into() });
|
|
||||||
cancel(&mut host);
|
|
||||||
host.app.tabs[0].scene.replace_selection_exact(&[hs[4]]);
|
|
||||||
run(&mut host, "MIRROR start", R::Start { name: "MIRROR".into() });
|
|
||||||
run(&mut host, "MIRROR sel", R::Selection);
|
|
||||||
run(&mut host, "MIRROR p1", R::Point { point: [0.0, 0.0, 0.0] });
|
|
||||||
run(&mut host, "MIRROR p2", R::Point { point: [1.0, 0.0, 0.0] });
|
|
||||||
run(&mut host, "MIRROR erase?", R::Token { text: "N".into() });
|
|
||||||
cancel(&mut host);
|
|
||||||
host.app.tabs[0].scene.replace_selection_exact(&[hs[4]]);
|
|
||||||
run(&mut host, "ARRAYRECT start", R::Start { name: "ARRAYRECT".into() });
|
run(&mut host, "ARRAYRECT start", R::Start { name: "ARRAYRECT".into() });
|
||||||
run(&mut host, "ARRAYRECT sel", R::Selection);
|
run(&mut host, "ARRAYRECT rows", R::Text { text: "2".into() });
|
||||||
|
run(&mut host, "ARRAYRECT cols", R::Text { text: "3".into() });
|
||||||
|
run(&mut host, "ARRAYRECT rowdist", R::Text { text: "10".into() });
|
||||||
|
run(&mut host, "ARRAYRECT coldist", R::Text { text: "20".into() });
|
||||||
|
run(&mut host, "ARRAYRECT enter", R::Enter);
|
||||||
cancel(&mut host);
|
cancel(&mut host);
|
||||||
host.app.tabs[0].scene.replace_selection_exact(&[hs[4]]);
|
// ARRAYPOLAR
|
||||||
|
host.app.tabs[0].scene.replace_selection_exact(&[hs[6]]);
|
||||||
run(&mut host, "ARRAYPOLAR start", R::Start { name: "ARRAYPOLAR".into() });
|
run(&mut host, "ARRAYPOLAR start", R::Start { name: "ARRAYPOLAR".into() });
|
||||||
run(&mut host, "ARRAYPOLAR sel", R::Selection);
|
run(&mut host, "ARRAYPOLAR center", R::Point { point: [300.0, 20.0, 0.0] });
|
||||||
|
run(&mut host, "ARRAYPOLAR count", R::Text { text: "4".into() });
|
||||||
|
run(&mut host, "ARRAYPOLAR angle", R::Text { text: "360".into() });
|
||||||
|
run(&mut host, "ARRAYPOLAR enter", R::Enter);
|
||||||
|
cancel(&mut host);
|
||||||
|
// EXPLODE
|
||||||
|
run(&mut host, "EXPLODE start", R::Start { name: "EXPLODE".into() });
|
||||||
|
run(&mut host, "EXPLODE entity", R::Entity { handle: hs[2], point: [55.0, 0.0, 0.0] });
|
||||||
cancel(&mut host);
|
cancel(&mut host);
|
||||||
host.app.tabs[0].scene.replace_selection_exact(&[hs[2]]);
|
host.app.tabs[0].scene.replace_selection_exact(&[hs[2]]);
|
||||||
run(&mut host, "ERASE run", R::Run { line: "ERASE".into() });
|
run(&mut host, "EXPLODE presel", R::Start { name: "EXPLODE".into() });
|
||||||
cancel(&mut host);
|
cancel(&mut host);
|
||||||
host.app.tabs[0].scene.replace_selection_exact(&[hs[0]]);
|
// JOIN
|
||||||
run(&mut host, "EXPLODE run", R::Run { line: "EXPLODE".into() });
|
host.app.tabs[0].scene.replace_selection_exact(&[hs[3], hs[4]]);
|
||||||
|
run(&mut host, "JOIN presel", R::Start { name: "JOIN".into() });
|
||||||
|
run(&mut host, "JOIN enter", R::Enter);
|
||||||
|
cancel(&mut host);
|
||||||
|
// BREAK
|
||||||
|
run(&mut host, "BREAK start", R::Start { name: "BREAK".into() });
|
||||||
|
run(&mut host, "BREAK entity", R::Entity { handle: hs[6], point: [302.0, 0.0, 0.0] });
|
||||||
|
run(&mut host, "BREAK p2", R::Point { point: [305.0, 0.0, 0.0] });
|
||||||
|
cancel(&mut host);
|
||||||
|
// HATCH
|
||||||
|
run(&mut host, "HATCH start", R::Start { name: "HATCH".into() });
|
||||||
|
cancel(&mut host);
|
||||||
|
// STRETCH, LENGTHEN, JOIN, PEDIT
|
||||||
|
run(&mut host, "LENGTHEN start", R::Start { name: "LENGTHEN".into() });
|
||||||
|
cancel(&mut host);
|
||||||
|
run(&mut host, "PEDIT start", R::Start { name: "PEDIT".into() });
|
||||||
|
cancel(&mut host);
|
||||||
|
run(&mut host, "STRETCH start", R::Start { name: "STRETCH".into() });
|
||||||
cancel(&mut host);
|
cancel(&mut host);
|
||||||
eprintln!("SPIKE final entity count {}", host.document().entities().count());
|
eprintln!("SPIKE final entity count {}", host.document().entities().count());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn audit_python_raster_image_definition_linkage_over_real_ipc() {
|
fn audit_python_raster_image_definition_linkage_over_real_ipc() {
|
||||||
use acadrust::objects::ObjectType;
|
use acadrust::objects::ObjectType;
|
||||||
|
|||||||
Reference in new issue
Block a user