openGrid: make the stacking interface layer match the faces it sits between - #136
Open
TheFou wants to merge 1 commit into
Open
openGrid: make the stacking interface layer match the faces it sits between#136TheFou wants to merge 1 commit into
TheFou wants to merge 1 commit into
Conversation
The stacking interface layer was derived from a single tile section, which did not match both of the faces it is sandwiched between. Full: stacked tiles are all zflipped, so the interface sits between a tile's original bottom face (the plate below) and its original top face (the plate above). Those two sections are identical except where screws are counterbored, and only the bottom one was used, so the interface overhung into the screw head recesses of the plate above - 534.400 mm2 of interface against a 507.088 mm2 mating face on a 2x2 board with corner screws. It is now the intersection of both sections. Heavy: the interface was built from openGridLite with topSide alternating per layer, but a Heavy tile is symmetric and both faces meeting an interface are an openGrid top face. Even-numbered interfaces were therefore already correct while odd-numbered ones used the Lite cut-face profile - 0.8 mm ribs instead of 1.5 mm. It now uses the top face section on both sides. Note a Heavy half-tile uses an asymmetric profile, so intersecting both sections would wrongly shrink it there. Also collapses the redundant linear_extrude(projection(linear_extrude(projection (...)))) in interfaceLayer into a single extrusion, and factors the section out into fullTileSection(). Lite is unchanged: its tiles alternate orientation, so the two faces bordering any given interface are always of the same kind. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The stacking interface layer is derived from a single tile cross-section, which does not match both of the faces it is sandwiched between. That has two separate consequences, one for Full and one for Heavy. Lite is correct as-is and is left untouched.
Full — the interface overhangs into the screw counterbores
Stacked Full tiles are all
zflip()ed, so an interface sits between a tile's original bottom face (the plate below) and its original top face (the plate above). The Full tile profile is symmetric, so those two sections are identical except where screws are counterbored — and only the bottom one was used.Measured on a 2×2 board with
Screw_Mounting = "Corners":The 27.3 mm² difference is exactly the four screw head counterbores (ø7.2 against ø4.1). The interface is now the intersection of both sections and measures 507.088 mm², matching the face it meets.
Heavy — every other interface used the wrong profile
The Heavy branch called
interfaceLayer2DwithboardType="Lite"andtopSidealternating per layer. But a Heavy tile is symmetric, and both faces meeting an interface are an openGrid top face. Even-numbered interfaces were therefore already correct, while odd-numbered ones used the Lite cut-face section — 0.8 mm ribs at the waist of the profile instead of the 1.5 mm of the top face.After the fix, both interfaces of a 3-tile stack measure 510.868 mm² instead of alternating. This also explains why a 2-tile Heavy stack is byte-for-byte unchanged: it only has interface #0, which was already right.
A Heavy half-tile uses an asymmetric profile (
full_tile_profilebranches onFull_or_Lite == "Heavy"), so intersecting both sections would wrongly shrink it there — hence the separateboardType == "Heavy"path rather than reusing the Full one.Also in this change
linear_extrude(projection(linear_extrude(projection(...))))ininterfaceLayerinto a single extrusion.fullTileSection()helper.Repro
Interface #0 (z 13.9–14.3) and interface #1 (z 28.3–28.7) have different cross-sections on
main; they are identical after this change.Validation
Differential against
mainat default parameters — for each board type and stack count, rendered both revisions and compared:Stack_Count2 and 3Stack_Count2Stack_Count2 and 3Stack_Count3Decomposed into connected components: same body count and same z ranges before and after (Full stack 3: 0–6.8, 6.9–7.3, 7.4–14.2, 14.3–14.7, 14.8–21.6).
Both rendering backends — the differential above was re-run with
--backend=Manifoldand--backend=CGAL; both agree. Cross-backend volumes match to ~5e-6 %, which is the same tessellation noisemainalready shows on the$fn=30screw cylinders.Configuration sweep — 29 configurations (board sizes 1×1 to 5×5 across the three types, all 5 screw modes, all 3 chamfer modes, adhesive base, both Fill Space modes,
Interface_Separation0, Ironing mode): all renderNoErrorand manifold.MakerWorld compatibility — the constructs used (
intersection()of 2D projections,if/elseunderlinear_extrude) already appear in this file, and the change renders identically on the old CGAL backend, so it does not depend on anything recent. For reference, the Parametric Model Maker backend is a development build of OpenSCAD with Manifold enabled — per a Bambu employee statement relayed in an unofficial but sourced community reference (commitb550957, 2024-11-25, thenc8fbef0, 2025-09-20, with BOSL2 pinned at99fcfc6). There is no official documentation page for this; flagging the source quality rather than presenting it as authoritative.🤖 Generated with Claude Code