@@ -227,6 +227,94 @@ function create_interpolations(vertices, circle_center_z, radius, gamma_tip, R=I
227227 return (le_interp, te_interp, area_interp)
228228end
229229
230+ """
231+ refine_obj_wing!(wing::AbstractWing; recompute_mapping=true)
232+
233+ Refine OBJ wing by computing position deltas and applying them to refined sections.
234+
235+ This method enables deformation support for OBJ wings by:
236+ 1. Recalculating evenly-spaced gammas for unrefined sections
237+ 2. Computing what unrefined sections SHOULD be (from interpolations)
238+ 3. Computing deltas between current and interpolated positions
239+ 4. Creating refined sections from interpolations + interpolated deltas
240+ 5. Computing panel mapping
241+
242+ # Arguments
243+ - `wing::AbstractWing`: OBJ wing with le_interp/te_interp
244+ - `recompute_mapping::Bool=true`: Whether to recompute refined_panel_mapping
245+
246+ # Effects
247+ Updates wing.refined_sections and wing.non_deformed_sections in-place.
248+ """
249+ function refine_obj_wing! (wing:: AbstractWing ; recompute_mapping= true )
250+ n_unrefined = wing. n_unrefined_sections
251+ n_refined = wing. n_panels + 1
252+
253+ # 1. Calculate evenly spaced gammas for unrefined sections
254+ unrefined_gammas = range (- wing. gamma_tip, wing. gamma_tip, n_unrefined)
255+
256+ # 2. Recalculate what unrefined sections SHOULD be from interpolations
257+ interpolated_unrefined_le = Matrix {Float64} (undef, n_unrefined, 3 )
258+ interpolated_unrefined_te = Matrix {Float64} (undef, n_unrefined, 3 )
259+ for (i, gamma) in enumerate (unrefined_gammas)
260+ interpolated_unrefined_le[i, :] .= [wing. le_interp[j](gamma) for j in 1 : 3 ]
261+ interpolated_unrefined_te[i, :] .= [wing. te_interp[j](gamma) for j in 1 : 3 ]
262+ end
263+
264+ # 3. Compute deltas: current - interpolated
265+ deltas_le = Matrix {Float64} (undef, n_unrefined, 3 )
266+ deltas_te = Matrix {Float64} (undef, n_unrefined, 3 )
267+ for i in 1 : n_unrefined
268+ deltas_le[i, :] .= wing. unrefined_sections[i]. LE_point -
269+ interpolated_unrefined_le[i, :]
270+ deltas_te[i, :] .= wing. unrefined_sections[i]. TE_point -
271+ interpolated_unrefined_te[i, :]
272+ end
273+
274+ # 4. Create refined sections with interpolated deltas
275+ refined_gammas = range (- wing. gamma_tip, wing. gamma_tip, n_refined)
276+ if isempty (wing. refined_sections)
277+ wing. refined_sections = [Section () for _ in 1 : n_refined]
278+ end
279+
280+ for (idx, gamma) in enumerate (refined_gammas)
281+ # Get base position from interpolation
282+ base_le = [wing. le_interp[i](gamma) for i in 1 : 3 ]
283+ base_te = [wing. te_interp[i](gamma) for i in 1 : 3 ]
284+
285+ # Find surrounding unrefined sections for delta interpolation
286+ unrefined_idx = searchsortedlast (collect (unrefined_gammas), gamma)
287+ unrefined_idx = clamp (unrefined_idx, 1 , n_unrefined - 1 )
288+
289+ # Linear interpolation weight
290+ gamma_left = unrefined_gammas[unrefined_idx]
291+ gamma_right = unrefined_gammas[unrefined_idx + 1 ]
292+ t = (gamma - gamma_left) / (gamma_right - gamma_left)
293+
294+ # Interpolate deltas
295+ delta_le = (1 - t) * deltas_le[unrefined_idx, :] +
296+ t * deltas_le[unrefined_idx + 1 , :]
297+ delta_te = (1 - t) * deltas_te[unrefined_idx, :] +
298+ t * deltas_te[unrefined_idx + 1 , :]
299+
300+ # Apply deltas to get final position
301+ final_le = base_le + delta_le
302+ final_te = base_te + delta_te
303+
304+ # Update refined section
305+ aero_model = wing. unrefined_sections[1 ]. aero_model
306+ aero_data = wing. unrefined_sections[1 ]. aero_data
307+ VortexStepMethod. reinit! (wing. refined_sections[idx], final_le, final_te,
308+ aero_model, aero_data)
309+ end
310+
311+ # 5. Compute panel mapping and update non_deformed_sections
312+ recompute_mapping && VortexStepMethod. compute_refined_panel_mapping! (wing)
313+ VortexStepMethod. update_non_deformed_sections! (wing)
314+
315+ return nothing
316+ end
317+
230318"""
231319 center_to_com!(vertices, faces)
232320
@@ -487,34 +575,18 @@ function ObjWing(
487575 push! (sections, Section (LE_point, TE_point, POLAR_MATRICES, aero_data))
488576 end
489577
490- # Create refined sections (evenly spaced including both tips)
491- refined_sections = Section[]
492- for gamma in range (- gamma_tip, gamma_tip, n_panels+ 1 )
493- LE_point = [le_interp[i](gamma) for i in 1 : 3 ]
494- TE_point = [te_interp[i](gamma) for i in 1 : 3 ]
495- push! (refined_sections, Section (LE_point, TE_point, POLAR_MATRICES, aero_data))
496- end
497-
498- # Create non_deformed_sections as copy of refined_sections for deformation support
499- non_deformed_sections = [Section () for _ in 1 : n_panels+ 1 ]
500- for i in 1 : n_panels+ 1
501- reinit! (non_deformed_sections[i], refined_sections[i])
502- end
503-
504578 panel_props = PanelProperties {n_panels} ()
505579 cache = [PreallocationTools. LazyBufferCache ()]
506580
507581 wing = Wing (n_panels, Int16 (n_unrefined_sections), spanwise_distribution, panel_props, MVec3 (spanwise_direction),
508- sections, refined_sections , remove_nan,
509- Int16[],
510- non_deformed_sections , zeros (n_panels), zeros (n_panels),
582+ sections, Section[] , remove_nan, # refined_sections empty
583+ Int16[], # refined_panel_mapping empty
584+ Section[] , zeros (n_panels), zeros (n_panels), # non_deformed, theta, delta
511585 mass, gamma_tip, inertia_tensor, T_cad_body, R_cad_body, radius,
512586 le_interp, te_interp, area_interp, cache)
513587
514- # Compute panel mapping for deformation support
515- VortexStepMethod. compute_refined_panel_mapping! (wing)
516-
517- # Update panel properties
588+ # Auto-refine for backward compatibility
589+ refine_obj_wing! (wing; recompute_mapping= true )
518590 reinit! (wing)
519591
520592 wing
0 commit comments