@@ -4,55 +4,193 @@ import VortexStepMethod: calculate_filaments_for_plotting
44
55export 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
1013Plot a single `Panel` as a `mesh`.
1114The corner points are ordered as: LE1, TE1, TE2, LE2.
1215This 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
2751end
2852
2953"""
30- plot!(ax, body::VortexStepMethod.BodyAerodynamics; kwargs...)
54+ plot!(ax, body::VortexStepMethod.BodyAerodynamics; use_observables=false, kwargs...)
3155
3256Plot 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
41108end
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
52189end
53190
54191function 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
66236end
67237
0 commit comments