Skip to content

Fix sibling component intersections in fused CAD exports (#939)#1384

Merged
joergbrech merged 11 commits into
mainfrom
939-component-intersections-outside-parentchild-relations-for-fused-iges-exports
Jul 20, 2026
Merged

Fix sibling component intersections in fused CAD exports (#939)#1384
joergbrech merged 11 commits into
mainfrom
939-component-intersections-outside-parentchild-relations-for-fused-iges-exports

Conversation

@joergbrech

@joergbrech joergbrech commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Description

Fixes #939.

Fused IGES/STEP/BRep exports of a full aircraft only considered CPACS parent-child relationships when fusing components. Sibling components that geometrically intersect one another but not through their shared parent (e.g. a horizontal and vertical tailplane that both attach to the fuselage and also intersect each other near the tail) were never fused against each
other. Their overlap region showed up as unfused/internal geometry in the exported solid.

An initial fix made the fusing algorithm consider all sibling components pairwise instead of only parent-child pairs, but this still fused them one pair at a time (running result + next component). That incremental approach cannot correctly resolve a genuine mutual/triple intersection between three or more components meeting in the same region (fuselage + HTP + VTP all overlapping near the tail) - it produced a self-intersecting solid with missing faces once tested against a more realistic geometry.

This PR replaces the incremental pairwise fuse with a single n-ary BRepAlgoAPI_Fuse operation over all aircraft components at once (CTiglFusePlane::Perform()), which resolves mutual intersections between any number of components consistently in one pass. A proper TopoDS_SOLID is rebuilt from the operation's result, and per-component face names are propagated for exporters and TiGLCreator picking.

The pairwise intersection-curve computation (used only for the seam overlay in exports and in TiGLCreator's fused-aircraft view, not for the fused solid itself) was reworked so each curve is trimmed against every other component, avoiding stray untrimmed seam wires. This computation is also now performed lazily, only when a caller actually requests it via Intersections(), instead of unconditionally inside Perform() - this alone roughly halves the regression test's runtime and speeds up every other caller that only needs the fused solid. The overlay in TiGLCreator was removed to make the fused visualization faster.

How Has This Been Tested?

  • Added a regression test to tests/integrationtests/testSiblingComponentFuse.cpp with a realistic test geometry where
    fuselage, HTP and VTP all pairwise intersect near the tail. The test checks that the fused shape is topologically valid and has no internal/buried faces.
  • Manually verified the fused export end to end via TIGLCreator'
    aircraft fused (slow)" draw action

Screenshots, that help to understand the changes(if applicabl

image image

Checklist for PR Author:

  • Unit or integration test added (if applicable)
  • Python interface updated (if applicable)
  • Python test added (if Python interface updated)
  • Doxygen docstrings added
  • ChangeLog.md updated

Disclaimer: Parts of this PR were developed with the assistance
(Anthropic's AI coding agent). I have reviewed, tested, and manu
all changes myself before submitting.


Differences in fuse behavior on main and the pr branch

  • C23 from digital hangar is missing tailplane after fuse

    image

    On main:

    image

    Both versions aren't correct

  • D250-TF-2040 from digital hangar

    image

    On main (or more precisely on 1388 crash when usind draw fused aircraft triangulation #1389)

    image
  • Similar issue on main but not on this branch for D250-TFLH2-MHEP-2040 from digital hangar.

I suggest to merge this. From the randomly selected CPACS files the behavior on this branch seems more robust. The C23 has issues both on main and on this branch. This should be examined as part of a separate issue.

@github-actions

github-actions Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

PR Reminders

This PR has changes in src/, TIGLCreator/, and tests/integrationtests/ but not in tests/unittests/, tests/python/, or bindings/python_internal/. ChangeLog.md has changes.

  • 💡 Tip: Please check if new classes need to be added to the Python bindings

This is an automated reminder from CI

@joergbrech joergbrech changed the title WIP In a fused export, don't just fuse along CPACA parent-child relations, but also siblings. Fix sibling component intersections in fused CAD exports (#939) Jul 17, 2026
@codecov

codecov Bot commented Jul 17, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.90244% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 73.19%. Comparing base (76802f0) to head (15bffb8).

Files with missing lines Patch % Lines
src/configuration/CTiglFusePlane.cpp 93.67% 5 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1384      +/-   ##
==========================================
- Coverage   73.21%   73.19%   -0.03%     
==========================================
  Files         324      324              
  Lines       28556    28594      +38     
==========================================
+ Hits        20908    20928      +20     
- Misses       7648     7666      +18     
Flag Coverage Δ
unittests 73.19% <93.90%> (-0.03%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/control_devices/CCPACSControlSurfaces.cpp 95.83% <ø> (ø)
src/cpacs_other/CTiglUIDManager.cpp 86.23% <100.00%> (-1.21%) ⬇️
src/cpacs_other/CTiglUIDManager.h 100.00% <ø> (ø)
src/wing/CCPACSWing.cpp 84.93% <ø> (ø)
src/configuration/CTiglFusePlane.cpp 95.45% <93.67%> (-1.46%) ⬇️

... and 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@joergbrech
joergbrech marked this pull request as ready for review July 17, 2026 13:14
@joergbrech
joergbrech requested a review from ole-alb July 17, 2026 13:14
@ole-alb

ole-alb commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Thank you for that really cool fix. Looks very good. I also tried some configs and everything worked as intended.
Could we also use that OCC-Fuse and completely get rid of CFuseShapes? I think we don't use it a lot.

@joergbrech

Copy link
Copy Markdown
Contributor Author

Could we also use that OCC-Fuse and completely get rid of CFuseShapes? I think we don't use it a lot.

Maybe. Its still used in examples, unit tests and, most critically, in the duct and control surface code. I suppose we could remove it, but I suggest as part of a separate issue. What do you think?

grep -r CFuseShapes * in src gives

boolean_operations/CFuseShapes.cpp:#include "CFuseShapes.h"
boolean_operations/CFuseShapes.cpp:CFuseShapes::CFuseShapes(const PNamedShape parent, const ListPNamedShape &childs)
boolean_operations/CFuseShapes.cpp:CFuseShapes::~CFuseShapes()
boolean_operations/CFuseShapes.cpp:const PNamedShape CFuseShapes::NamedShape()
boolean_operations/CFuseShapes.cpp:CFuseShapes::operator PNamedShape()
boolean_operations/CFuseShapes.cpp:const ListPNamedShape &CFuseShapes::Intersections()
boolean_operations/CFuseShapes.cpp:const ListPNamedShape &CFuseShapes::TrimmedChilds()
boolean_operations/CFuseShapes.cpp:const PNamedShape CFuseShapes::TrimmedParent()
boolean_operations/CFuseShapes.cpp:void CFuseShapes::Perform()
boolean_operations/CFuseShapes.cpp:void CFuseShapes::Clear()
boolean_operations/CFuseShapes.cpp:void CFuseShapes::DoFuse()
boolean_operations/CFuseShapes.h: * @brief CFuseShapes Implement a fuse, where the childs are fused with the parent
boolean_operations/CFuseShapes.h:class CFuseShapes
boolean_operations/CFuseShapes.h:    TIGL_EXPORT CFuseShapes(const PNamedShape parent, const ListPNamedShape& childs);
boolean_operations/CFuseShapes.h:    TIGL_EXPORT virtual ~CFuseShapes();
control_devices/CCPACSControlSurfaces.cpp:                    fusedBoxes = CFuseShapes(fusedBoxes, childs);
control_devices/CCPACSControlSurfaces.cpp:                fusedBoxes = CFuseShapes(fusedBoxes, childs);
ducts/CCPACSDuctAssembly.cpp:#include "CFuseShapes.h"
ducts/CCPACSDuctAssembly.cpp:    tool = CFuseShapes(parentDuct, childDucts);

@joergbrech
joergbrech merged commit ea87e83 into main Jul 20, 2026
17 checks passed
@joergbrech
joergbrech deleted the 939-component-intersections-outside-parentchild-relations-for-fused-iges-exports branch July 20, 2026 14:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Component intersections outside parent/child relations for fused IGES exports

2 participants