Skip to content

Commit 2031982

Browse files
committed
Use plot and plot! with obs
1 parent 112fced commit 2031982

File tree

1 file changed

+187
-17
lines changed

1 file changed

+187
-17
lines changed

ext/VortexStepMethodMakieExt.jl

Lines changed: 187 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,55 +4,193 @@ import VortexStepMethod: calculate_filaments_for_plotting
44

55
export plot_geometry, plot_distribution, plot_polars, save_plot, show_plot, plot_polar_data
66

7+
# Global storage for panel mesh observables (for dynamic plotting)
8+
const PANEL_MESH_OBSERVABLES = Ref{Union{Nothing, Dict}}(nothing)
9+
710
"""
8-
plot!(ax, panel::VortexStepMethod.Panel; kwargs...)
11+
plot!(ax, panel::VortexStepMethod.Panel; use_observables=false, kwargs...)
912
1013
Plot a single `Panel` as a `mesh`.
1114
The corner points are ordered as: LE1, TE1, TE2, LE2.
1215
This creates two triangles: (LE1, TE1, TE2) and (LE1, TE2, LE2).
16+
17+
If `use_observables=true`, creates observables for dynamic updates.
1318
"""
14-
function Makie.plot!(ax, panel::VortexStepMethod.Panel; color=(:red, 0.2), R_b_w=nothing, T_b_w=nothing, kwargs...)
19+
function Makie.plot!(ax, panel::VortexStepMethod.Panel; color=(:red, 0.2), R_b_w=nothing, T_b_w=nothing,
20+
use_observables=false, kwargs...)
1521
plots = []
1622
points = [Point3f(panel.corner_points[:, i]) for i in 1:4]
1723
if !isnothing(R_b_w) && !isnothing(T_b_w)
1824
points = [Point3f(R_b_w * p + T_b_w) for p in points]
1925
end
20-
faces = [Makie.GLTriangleFace(1, 2, 3), Makie.GLTriangleFace(1, 3, 4)]
21-
p = mesh!(ax, points, faces; color, transparency=true, kwargs...)
22-
push!(plots, p)
23-
border_points = [points..., points[1]]
24-
p = lines!(ax, border_points; color=:black, transparency=true, kwargs...)
25-
push!(plots, p)
26+
27+
if use_observables
28+
# Create observables for dynamic updates
29+
vertices_obs = Observable(points)
30+
faces_obs = Observable([Makie.GLTriangleFace(1, 2, 3), Makie.GLTriangleFace(1, 3, 4)])
31+
border_obs = Observable([points..., points[1]])
32+
33+
p = mesh!(ax, vertices_obs, faces_obs; color, transparency=true, kwargs...)
34+
push!(plots, p)
35+
p = lines!(ax, border_obs; color=:black, transparency=true, kwargs...)
36+
push!(plots, p)
37+
38+
# Note: Observables are stored at the body level, not individual panel level
39+
# Individual panels need their parent body for proper tracking
40+
else
41+
# Static plotting (original behavior)
42+
faces = [Makie.GLTriangleFace(1, 2, 3), Makie.GLTriangleFace(1, 3, 4)]
43+
p = mesh!(ax, points, faces; color, transparency=true, kwargs...)
44+
push!(plots, p)
45+
border_points = [points..., points[1]]
46+
p = lines!(ax, border_points; color=:black, transparency=true, kwargs...)
47+
push!(plots, p)
48+
end
49+
2650
return plots
2751
end
2852

2953
"""
30-
plot!(ax, body::VortexStepMethod.BodyAerodynamics; kwargs...)
54+
plot!(ax, body::VortexStepMethod.BodyAerodynamics; use_observables=false, kwargs...)
3155
3256
Plot a `BodyAerodynamics` object by plotting each of its panels.
57+
58+
If `use_observables=true`, creates observables for dynamic updates keyed by (body_id, panel_index).
59+
Otherwise, creates static plots (original behavior).
3360
"""
34-
function Makie.plot!(ax, body::VortexStepMethod.BodyAerodynamics; color=(:red, 0.2), R_b_w=nothing, T_b_w=nothing, kwargs...)
61+
function Makie.plot!(ax, body::VortexStepMethod.BodyAerodynamics; color=(:red, 0.2), R_b_w=nothing, T_b_w=nothing,
62+
use_observables=false, kwargs...)
3563
plots = []
36-
for panel in body.panels
37-
p = Makie.plot!(ax, panel; color, R_b_w, T_b_w, kwargs...)
38-
push!(plots, p)
64+
65+
if use_observables
66+
# Initialize global storage if needed
67+
if isnothing(PANEL_MESH_OBSERVABLES[])
68+
PANEL_MESH_OBSERVABLES[] = Dict()
69+
end
70+
71+
body_id = objectid(body)
72+
73+
# Create observables for each panel
74+
for (panel_idx, panel) in enumerate(body.panels)
75+
# Compute initial points
76+
points = [Point3f(panel.corner_points[:, i]) for i in 1:4]
77+
if !isnothing(R_b_w) && !isnothing(T_b_w)
78+
points = [Point3f(R_b_w * p + T_b_w) for p in points]
79+
end
80+
81+
# Create observables
82+
vertices_obs = Observable(points)
83+
faces_obs = Observable([Makie.GLTriangleFace(1, 2, 3), Makie.GLTriangleFace(1, 3, 4)])
84+
border_obs = Observable([points..., points[1]])
85+
86+
# Plot using observables
87+
p = mesh!(ax, vertices_obs, faces_obs; color, transparency=true, kwargs...)
88+
push!(plots, p)
89+
p = lines!(ax, border_obs; color=:black, transparency=true, kwargs...)
90+
push!(plots, p)
91+
92+
# Store observables with stable key
93+
PANEL_MESH_OBSERVABLES[][(body_id, panel_idx)] = (
94+
vertices = vertices_obs,
95+
border = border_obs,
96+
faces = faces_obs
97+
)
98+
end
99+
else
100+
# Static plotting (original behavior)
101+
for panel in body.panels
102+
p = Makie.plot!(ax, panel; color, R_b_w, T_b_w, use_observables=false, kwargs...)
103+
push!(plots, p)
104+
end
39105
end
106+
40107
return plots
41108
end
42109

43-
function Makie.plot(panel::VortexStepMethod.Panel; size = (1200, 800), kwargs...)
110+
111+
"""
112+
plot!(body::VortexStepMethod.BodyAerodynamics; R_b_w=nothing, T_b_w=nothing)
113+
114+
Update existing body aerodynamics plot observables with current geometry.
115+
This updates all panels in the body using their current corner_points.
116+
117+
Requires that `plot(body; use_observables=true)` or `plot!(ax, body; use_observables=true)`
118+
was called first to create the observables.
119+
"""
120+
function Makie.plot!(body::VortexStepMethod.BodyAerodynamics; R_b_w=nothing, T_b_w=nothing, kwargs...)
121+
# Check if observables exist
122+
if isnothing(PANEL_MESH_OBSERVABLES[])
123+
error("No panel observables found. Call plot(body; use_observables=true) first.")
124+
end
125+
126+
body_id = objectid(body)
127+
128+
# Update each panel using stable (body_id, panel_idx) key
129+
for (panel_idx, panel) in enumerate(body.panels)
130+
key = (body_id, panel_idx)
131+
if !haskey(PANEL_MESH_OBSERVABLES[], key)
132+
error("No observables found for body $body_id panel $panel_idx. " *
133+
"Call plot(body; use_observables=true) first.")
134+
end
135+
136+
# Get observables for this panel
137+
obs = PANEL_MESH_OBSERVABLES[][key]
138+
139+
# Recompute vertices from current panel.corner_points
140+
points = [Point3f(panel.corner_points[:, i]) for i in 1:4]
141+
if !isnothing(R_b_w) && !isnothing(T_b_w)
142+
points = [Point3f(R_b_w * p + T_b_w) for p in points]
143+
end
144+
145+
# Update observables
146+
obs.vertices[] = points
147+
obs.border[] = [points..., points[1]]
148+
end
149+
150+
return nothing
151+
end
152+
153+
function Makie.plot(panel::VortexStepMethod.Panel; size = (1200, 800),
154+
R_b_w=nothing, T_b_w=nothing, color=(:red, 0.2), kwargs...)
44155
fig = Figure(; size)
45156
ax = Axis3(fig[1, 1]; aspect = :data,
46157
xlabel = "X", ylabel = "Y", zlabel = "Z",
47158
azimuth = 9/8*π, zoommode = :cursor, viewmode = :fit,
48159
)
49160

50-
plot!(ax, panel; kwargs...)
161+
# Create observables for panel geometry
162+
points = [Point3f(panel.corner_points[:, i]) for i in 1:4]
163+
if !isnothing(R_b_w) && !isnothing(T_b_w)
164+
points = [Point3f(R_b_w * p + T_b_w) for p in points]
165+
end
166+
167+
vertices_obs = Observable(points)
168+
faces_obs = Observable([Makie.GLTriangleFace(1, 2, 3), Makie.GLTriangleFace(1, 3, 4)])
169+
170+
# Plot mesh using observables
171+
mesh!(ax, vertices_obs, faces_obs; color, transparency=true, kwargs...)
172+
173+
# Plot border
174+
border_obs = Observable([points..., points[1]])
175+
lines!(ax, border_obs; color=:black, transparency=true, kwargs...)
176+
177+
# Store observables globally for updates
178+
panel_id = objectid(panel)
179+
if isnothing(PANEL_MESH_OBSERVABLES[])
180+
PANEL_MESH_OBSERVABLES[] = Dict()
181+
end
182+
PANEL_MESH_OBSERVABLES[][panel_id] = (
183+
vertices = vertices_obs,
184+
border = border_obs,
185+
faces = faces_obs
186+
)
187+
51188
return fig
52189
end
53190

54191
function Makie.plot(body_aero::VortexStepMethod.BodyAerodynamics; size = (1200, 800),
55-
limitmargin = 0.1, kwargs...)
192+
limitmargin = 0.1, R_b_w=nothing, T_b_w=nothing, color=(:red, 0.2),
193+
kwargs...)
56194
fig = Figure(; size)
57195
ax = Axis3(fig[1, 1]; aspect = :data,
58196
xlabel = "X", ylabel = "Y", zlabel = "Z",
@@ -61,7 +199,39 @@ function Makie.plot(body_aero::VortexStepMethod.BodyAerodynamics; size = (1200,
61199
yautolimitmargin=(limitmargin, limitmargin),
62200
zautolimitmargin=(limitmargin, limitmargin),
63201
)
64-
plot!(ax, body_aero; kwargs...)
202+
203+
# Initialize global storage if needed
204+
if isnothing(PANEL_MESH_OBSERVABLES[])
205+
PANEL_MESH_OBSERVABLES[] = Dict()
206+
end
207+
208+
body_id = objectid(body_aero)
209+
210+
# Create observables for each panel using stable (body_id, panel_idx) key
211+
for (panel_idx, panel) in enumerate(body_aero.panels)
212+
# Compute initial points
213+
points = [Point3f(panel.corner_points[:, i]) for i in 1:4]
214+
if !isnothing(R_b_w) && !isnothing(T_b_w)
215+
points = [Point3f(R_b_w * p + T_b_w) for p in points]
216+
end
217+
218+
# Create observables
219+
vertices_obs = Observable(points)
220+
faces_obs = Observable([Makie.GLTriangleFace(1, 2, 3), Makie.GLTriangleFace(1, 3, 4)])
221+
border_obs = Observable([points..., points[1]])
222+
223+
# Plot using observables
224+
mesh!(ax, vertices_obs, faces_obs; color, transparency=true, kwargs...)
225+
lines!(ax, border_obs; color=:black, transparency=true, kwargs...)
226+
227+
# Store observables with stable key
228+
PANEL_MESH_OBSERVABLES[][(body_id, panel_idx)] = (
229+
vertices = vertices_obs,
230+
border = border_obs,
231+
faces = faces_obs
232+
)
233+
end
234+
65235
return fig
66236
end
67237

0 commit comments

Comments
 (0)