Don't trim loft at profiles by default - #1331
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #1331 +/- ##
==========================================
- Coverage 73.20% 73.14% -0.07%
==========================================
Files 324 324
Lines 28546 28683 +137
==========================================
+ Hits 20898 20980 +82
- Misses 7648 7703 +55
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
PR RemindersThis PR has changes in
This is an automated reminder from CI |
…ts and actually caused problems here)
30c4e42 to
f6cac5d
Compare
|
Because flap geometries are somewhat fragile in TiGL and I am worried, that this PR introduces a regression, I decided to do a manual visual analysis of the flaps of a bunch of CPACS files we have. I only checked geometry, no other issues like weird deflection paths or intersecting geometries during deflection etc. TL;DR: Performance is consistently better on this branch, but flap and slat geometry regresses in a majority of configs — the wing cutouts near trailing edge devices and side caps on leading edge devices are frequently broken. Overall, main is still the better base to ship. Legend
Test Suite
Digital Hangar
Other (local/confidential)
Remark: A config with ❌ might still have good geometries for almost all flaps and I am reporting only failures here. So the situation is not quite as dire as it looks. I commented on performance only if I noticed that it was extremely slow. ConclusionPerformance is consistently better on this branch (sometimes dramatically so, e.g. on D150-BWB-2035 or the EX* configs). The boolean operations around control surface devices are clearly sensitive to trimmed vs. untrimmed loft input. In total, 10 out of 17 configs are better on main, 3 are better on this branch, and 4 are roughly equal. The PR consistently introduces missing outer side caps on InnerSlat1UID. |
Don't trim loft at profiles by default
Fixes #1262.
By default,
GetLoft()now returns an untrimmed loft (a single continuous surface) for wings, fuselages, ducts, vessels and engine pylons. The previous trimmed behavior (UV seams / one face per profile segment) is still available via the newGetTrimmedLoft().Motivation
TiGL 3 lofts a wing/fuselage as a single surface across all sections. To preserve the historical per-segment face count we used to trim the result at every profile. That trimming hurts downstream post-processing: meshers are unnecessarily constrained by the extra face boundaries, and the seams reduce continuity for boolean operations. After discussion with users we accept the breaking change and skip profile trimming by default.
@sdeinert, this removes trimming as kinks as well.
This is a breaking change:
GetLoft()output (face count, UV parameterization) changes for wings and fuselages. UseGetTrimmedLoft()to restore the old result.There should be no geometric difference, because we just trimmed at isocurves previously, but some algorithms have slightly different behavior when confronted with trimmed vs. untrimmed faces. For instance, intersection algorithms or volume calculations in OCCT use approximations for intersection/boundary curves, and these approximations might cut off kinks and corners in the untrimmed loft, which were not present in the trimmed loft faces. This is especially apparent for wings, which are lofted linearly.
While all tests succeed, there is a real danger that due to this difference we introduce unnoticed and untested regressions. In the worst case, wing cutouts or other operations suddenly fail for CPACS configurations which worked before with the trimmed lofts.
One concrete regression was discovered and fixed during this development: leading edge devices (control surfaces on the leading edge) rely on boolean intersection between the device flap geometry and the wing loft. When the wing loft became untrimmed, the boolean returned an empty shape, silently dropping the device geometry. The fix builds leading edge device geometry against the trimmed clean shape via the new
GetTrimmedWingCleanShape().Architecture
Each affected component builds both a trimmed and an untrimmed loft lazily and caches them separately.
CTiglMakeLoft— newsetEnableProfileCutting(bool)(defaultfalse).When
false, the sewn faces are returned directly (noCutShellAtUVParameters/
CutShellAtKinks). Whentrue, the original cutting behavior is applied.ITiglGeometricComponent/CTiglAbstractGeometricComponent— addGetTrimmedLoft(); the base implementation falls back toGetLoft().CCPACSWing— splitwingCleanShapecache intowingCleanShapeUntrimmed/wingCleanShapeTrimmed;GetLoft(),BuildLoft()andGetWingCleanShape()now return untrimmed. AddsGetUntrimmedLoft(),GetTrimmedLoft(),GetTrimmedWingCleanShape().CTiglWingBuildertakes anenableProfileCuttingflag.CCPACSFuselage— splitcleanLoftintocleanLoftUntrimmed/cleanLoftTrimmed; addsGetUntrimmedLoft()/GetTrimmedLoft()(duct cutouts still applied to both).CCPACSDuct,CCPACSVessel,CCPACSEnginePylon— gain trimmed/untrimmedcaches and
GetTrimmedLoft()/GetUntrimmedLoft(). Vessels built from designparameters have no trimmed loft (
GetTrimmedLoft()returns null / falls back).CCPACSFuselageSegment/CCPACSWingSegment— per-segment lofts are nowextracted from the parent's trimmed loft, so per-profile face indexing is
preserved.
CCPACSComponent— addsGetTrimmedLoft()/GetUntrimmedLoft()for APIconsistency; both return
GetLoft()(generic multi-segment shapes are nottrimmable).
CTiglPatchShell— hardened against empty / single-face / compound inputs(throws or handles gracefully instead of failing on degenerate shells).
Control surface devices (leading edge devices) — contained a small fiddle factor that was previously introduced as a workaround. With untrimmed lofts, the situation is reversed. Adding it breaks the geometry of simpletest-flaps.cpacs.xml, without it it looks good. The boolean operations around control devices are fragile in general, regardless of this PR.
TiGLCreator
Untrimmed lofts need finer tessellation to render cleanly. Immediately after the shape especially fuselages looked like someone had taken a bite from them. The reason for this is that the tesselation accuracy is a relative value with respect to the bounding box diaogonal of a shape. Before, this meant that tesselation accuracy was coupled to segment bounds, now it is coupled to the fuselage bounds.
The default tessellation accuracy value and slider endpoints were re-tuned, an angular deviation (
tesselationDeviationAngle()) is now applied to displayed shapes, and slider values are clamped to valid ranges. With the application of the angular deviation, we an now actually increase the default tesselation by a factor of 10 and still get reasonable looking results. This might speed up loading times in TiGLCreator.API summary
GetLoft()GetUntrimmedLoft()GetTrimmedLoft()CCPACSWingCCPACSFuselageCCPACSDuctCCPACSVesselCCPACSEnginePylonCCPACSComponentGetLoft()GetLoft()CCPACSWingadditionally exposesGetTrimmedWingCleanShape()alongside theexisting
GetWingCleanShape()(untrimmed).How Has This Been Tested?
(
tiglExports.cpp24→16,tiglSystems.cpp4→3 and 10→3,tiglTanks.cpp).GetTrimmedLoft()(
testDuct.cpp,testFuselageStandardProfileSuperellipse.cpp).tiglGetCrossSectionAreatolerance relaxed to accommodate OCCT's b-splineapproximation of intersection boundaries on the untrimmed surface.
leadingEdgeDeviceFlapShapeNotEmptyguards the controlsurface device boolean intersection fix.
Screenshots
Disclaimer:
This PR has been co-authored with AI, but all AI parts have been thoroughly checked by me.
Checklist:
tiglLoftTrimming.cpp,tiglControlSurfaceDevice.cpp)