diff --git a/skills/beamletopticsprojects/FORMAT.md b/skills/beamletopticsprojects/FORMAT.md index 19d60f4..2271cc4 100644 --- a/skills/beamletopticsprojects/FORMAT.md +++ b/skills/beamletopticsprojects/FORMAT.md @@ -40,7 +40,8 @@ One line per entry; components first, then sources, then groups, then systems: from that method when a person changes the shape on its card (see "Own code" in `SKILL.md`). - `pos` is the absolute position (m), `rot` the rotation since construction in **degrees** (unlike BeamletOptics, whose rotations take radians): first about the global x-axis, then y, then z. Both - are optional. + are optional. `pos` moves the object there from wherever its code builds it, also a source with a + start in its code; a line without `pos` keeps the position of its code. - `catalog = (...)` belongs to the GUI (its page "Edit"); delete it when you change the constructor. - `@system`: members are components; a component may be in several systems, a source in at most one. `static = true` makes a `StaticSystem`. Each system is traced on its own (`trace(p, :S1)`); a detector that is in several systems is the exception in the window, which adds up their hits. diff --git a/skills/beamletopticsprojects/SKILL.md b/skills/beamletopticsprojects/SKILL.md index d963b20..1e2ece9 100644 --- a/skills/beamletopticsprojects/SKILL.md +++ b/skills/beamletopticsprojects/SKILL.md @@ -95,7 +95,10 @@ Bench/ label = "fold", systems = [:S1], by = "claude")`: picks the next free id of its prefix in the same write (no other participant can take it meanwhile) and returns it; a source goes into the `sources` of one system. `pos` is in m, `rot` in degrees (not radians as in - BeamletOptics); the prefixes of the ids are listed in `FORMAT.md`. + BeamletOptics); the prefixes of the ids are listed in `FORMAT.md`. `pos` places the object + exactly, also a beam whose code has a start of its own; without `pos` it stays where its code + builds it, e.g. `add!(".", "Beam([0.0, -0.05, 0.0], [0.0, 1.0, 0.0], 1.064e-6)")` starts at + y = −0.05 m. - `set!(".", :L9; pos, rot, code, label, by)` changes only the given fields of a line (a group: its label; move groups with `move!`). - `move!(".", [:G1, :FIOS1]; offset = (0.3, 0, 0), rot = (0, 0, 10), pivot = :center, by)` moves diff --git a/src/Edit.jl b/src/Edit.jl index 6862eaf..8bb5b44 100644 --- a/src/Edit.jl +++ b/src/Edit.jl @@ -3,7 +3,7 @@ Adding, changing, copying and removing lines of system.jl with checks, in one wr =# """ - add!(dir, code::AbstractString; id = nothing, pos = (0, 0, 0), rot = (0, 0, 0), label = nothing, + add!(dir, code::AbstractString; id = nothing, pos = nothing, rot = (0, 0, 0), label = nothing, systems = Symbol[], by = nothing) -> Symbol Adds a line for the object built by `code` (a constructor, e.g. `"RoundPlanoMirror(0.0254, 0.006)"`) @@ -14,7 +14,9 @@ is a beam or a beam group, else a `@component`. [`id_prefix`](@ref)), chosen in the same load and write, so no other participant can take it in between; a given `id` that is taken throws. `pos` (in m) and `rot` (angles in degrees or a 3×3 matrix, see [`rotation_matrix`](@ref)) are the pose of the line, `label` the name shown instead of -the id. The new line becomes a member of the `systems` (ids of systems); a source goes into the +the id. `pos` places the object exactly, also one whose code has a position of its own (e.g. the +start of a beam); without `pos` the object stays where its code builds it, and the line has no +`pos`. The new line becomes a member of the `systems` (ids of systems); a source goes into the `sources` of at most one system. The changed project is checked before anything is written: the code builds in the module of the @@ -36,7 +38,7 @@ add!(".", "Beam([0.0, 0.0, 0.0], [0.0, 1.0, 0.0], 1.064e-6)"; systems = [:S1]) add!(dir::AbstractString, code::AbstractString; kwargs...) = _retry_changed(() -> _add_once!(dir, code; kwargs...)) -function _add_once!(dir::AbstractString, code::AbstractString; id = nothing, pos = (0, 0, 0), +function _add_once!(dir::AbstractString, code::AbstractString; id = nothing, pos = nothing, rot = (0, 0, 0), label = nothing, systems = Symbol[], by = nothing) p = load_project(dir) what = isnothing(id) ? "the new line" : "`$id`" diff --git a/test/TestEdit.jl b/test/TestEdit.jl index 8b721a2..b3907be 100644 --- a/test/TestEdit.jl +++ b/test/TestEdit.jl @@ -94,10 +94,11 @@ end @test maximum(abs, BMO.position(p[:M3]) - [0.1, 0.4, 0.0]) ≤ 1e-15 @test occursin("@component M3 = RoundPlanoMirror(0.0254, 0.006) pos = (0.1, 0.4, 0.0) rot = (0.0, 0.0, 45.0) uid", String(text(dir))) - # zero angles are no rotation + # zero angles are no rotation; without `pos` the line has none, the object stays as built @test P.add!(dir, "Detector(0.01)"; label = "Camera") === :D2 p = load_project(dir) - @test entry(p, :D2).rot === nothing && entry(p, :D2).pos == (0.0, 0.0, 0.0) + @test entry(p, :D2).rot === nothing && entry(p, :D2).pos === nothing + @test BMO.position(p[:D2]) == [0.0, 0.0, 0.0] @test entry(p, :D2).label == "Camera" id = P.add!(dir, "Beam([0.0, 0.0, 0.0], [1.0, 0.0, 0.0], 6.33e-7)"; pos = (0.0, 0.0, 0.01), @@ -109,6 +110,14 @@ end # a given id that is free @test P.add!(dir, "Detector(0.01)"; id = :Cam) === :Cam @test has(load_project(dir), :Cam) + # a source whose code has a start of its own starts there without `pos` (#11), and at `pos` + # with it + id = P.add!(dir, "GaussianBeamlet([0.0, -0.1, 0.0], [0.0, 1.0, 0.0], 1e-6, 1e-3)") + p = load_project(dir) + @test entry(p, id).pos === nothing && BMO.position(p[id]) ≈ [0.0, -0.1, 0.0] + @test !occursin("pos =", only(filter(l -> startswith(l, "@source $id ="), split(String(text(dir)), '\n')))) + id = P.add!(dir, "GaussianBeamlet([0.0, -0.1, 0.0], [0.0, 1.0, 0.0], 1e-6, 1e-3)"; pos = (0.0, 0.2, 0.0)) + @test BMO.position(load_project(dir)[id]) ≈ [0.0, 0.2, 0.0] end @testset "a taken id, a source in two systems" begin