deform_section shrink-wraps the shape it is given even at delta = 0, with the default ShrinkWrap(clearance=0.0). On a section that has already been wrapped once and is thin, that second wrap produces a curve whose upper and lower surfaces cross each other over most of the chord. It is not an airfoil, so neither backend has a meaningful answer for it: XFoil's panel code can terminate the process on one — the branch agent/BeyondTheSim.jl-53 guards against being handed it — and NeuralFoil will answer from a Kulfan fit of a self-crossing curve without saying anything is wrong.
How it shows up
One mesh section of a kite wing, sliced from its .obj and wrapped once with the wing's own mesh: settings, gives a clean contour: 239 nodes, zero crossings, 32° maximum turn between panels. Running that same raw point cloud through shrink_wrap and then deform_section(x, y, 0.0) gives 239 nodes again and, depending on the rolling-ball radius, 29 to 60 crossing panel pairs, with the contour doubling back on itself exactly (a 180.0° turn) at every radius from 0.15 up:
min_concave_radius |
crossing panel pairs |
max turn |
lower surface monotone |
| 0.05 |
34 |
45.0° |
no |
| 0.10 |
34 |
48.3° |
yes |
| 0.15 |
60 |
180.0° |
no |
| 0.20 |
58 |
180.0° |
no |
| 0.30 |
48 |
180.0° |
yes |
| 0.40 |
29 |
180.0° |
yes |
| 0.60 |
29 |
180.0° |
yes |
| 0.80 |
35 |
180.0° |
yes |
one wrap only, no deform_section |
0 |
32.3° |
yes |
The last row is the same cloud through a single shrink_wrap, so the tangle is made by the second wrap rather than present in the slice.
The section is a thin, strongly cambered one near mid-span; clearance is 0.0, so the wrap hugs the cloud and the rolling ball has very little room between the two surfaces.
What I would do
Either have deform_section skip the re-wrap when the shape it is handed is already a clean wrap, or have shrink_wrap refuse to return a contour that crosses itself rather than returning one. Which of the two is right depends on whether a caller is ever meant to wrap an already-wrapped contour at all, and either way it changes the geometry every generated polar is computed on, so it wants a decision rather than a patch.
I have not started this. Found while fixing 1-Bart-1/BeyondTheSim.jl#53, where the crossing contour ended the Julia process inside XFoil.
From 1-Bart-1/BeyondTheSim.jl#53 · task BeyondTheSim.jl-53
deform_sectionshrink-wraps the shape it is given even atdelta = 0, with the defaultShrinkWrap(clearance=0.0). On a section that has already been wrapped once and is thin, that second wrap produces a curve whose upper and lower surfaces cross each other over most of the chord. It is not an airfoil, so neither backend has a meaningful answer for it: XFoil's panel code can terminate the process on one — the branchagent/BeyondTheSim.jl-53guards against being handed it — and NeuralFoil will answer from a Kulfan fit of a self-crossing curve without saying anything is wrong.How it shows up
One mesh section of a kite wing, sliced from its
.objand wrapped once with the wing's ownmesh:settings, gives a clean contour: 239 nodes, zero crossings, 32° maximum turn between panels. Running that same raw point cloud throughshrink_wrapand thendeform_section(x, y, 0.0)gives 239 nodes again and, depending on the rolling-ball radius, 29 to 60 crossing panel pairs, with the contour doubling back on itself exactly (a 180.0° turn) at every radius from 0.15 up:min_concave_radiusdeform_sectionThe last row is the same cloud through a single
shrink_wrap, so the tangle is made by the second wrap rather than present in the slice.The section is a thin, strongly cambered one near mid-span;
clearanceis0.0, so the wrap hugs the cloud and the rolling ball has very little room between the two surfaces.What I would do
Either have
deform_sectionskip the re-wrap when the shape it is handed is already a clean wrap, or haveshrink_wraprefuse to return a contour that crosses itself rather than returning one. Which of the two is right depends on whether a caller is ever meant to wrap an already-wrapped contour at all, and either way it changes the geometry every generated polar is computed on, so it wants a decision rather than a patch.I have not started this. Found while fixing 1-Bart-1/BeyondTheSim.jl#53, where the crossing contour ended the Julia process inside XFoil.
From 1-Bart-1/BeyondTheSim.jl#53 · task
BeyondTheSim.jl-53