Skip to content

One fan operation under flatten, reverse and squash #52

Closed

Description

@tophcodes

flatten, reverse and the squash fold (#17) are one operation: a fan of creases at one point of the folded state, at which each existing crease stays, turns the other way, or opens, and new creases are added. Fisher's multifold gives each crease exactly these specifiers (valley, mountain, reverse, unfold) [fisher1994, §3.3.2]. The ladder in notes/2026-09-25-primitive-ladder.md places them as rungs 2 to 4.

  • flatten today: a fan at a paper point in one flap, new creases only.
  • reverse: the axis crosses the spine at a point where four creases meet: the spine in the body (stays), the spine in the tip (turns), the axis in each of the two halves (new).
  • Squash: a fan at one point that opens a crease (Fisher's unfold g-e [fisher1994, p. 24]).

Decided

  • One operation in the kernel; flatten, reverse and squash are syntax over it. What is the same operation mathematically is the same operation in the implementation.
  • reverse moves onto it. The fan operation counts as done when reverse, as syntax over it, passes every existing reverse case, examples/bases/bird-base.bel and examples/crane.bel with unchanged output.
  • A write reaches every layer under its axis (ADR 0036): mark without on scores every layer, fold moves every layer on the side that folds over, moving names a side.
  • A fan moves its tip (ADR 0037): the pieces under the fan joined to the flap carrying its point.
  • squash takes a bare alignment of its spine (ADR 0038): squash (--h onto --ac) or squash (--h onto .p).
  • on marks the named flap alone (ADR 0039).
  • A fan sits at a table point (ADR 0040), with a paper point in every layer under it; flatten takes (on #[…]) to name its anchor. A fan vertex may lie off the paper (ADR 0041).
  • A reverse fold turns the hinges across its opening (ADR 0043).
  • A flatten selects no state by convention: toward goes, an ambiguous flatten fails with one suggestion per remaining state (comment of 2026-09-29, carried out by Fail an ambiguous flatten with suggestions instead of toward #99).
  • A fan moves each piece by the creases on its paper path (ADR 0044): closure around every paper point the paper surrounds, sectors are pieces of paper, letters belong to hinges.
  • staying names a sector of the anchor by points (ADR 0048).

Checklist

Design and records:

Build:

Waiting on a model that needs them:

Superseded: #67, the original build half of this issue, is covered by the build items above.

Afterwards

Petal (#16) needs fans at several points at once (rung 5) and builds on this.


Generated by Claude Code

Activity

  1. added
    enhancementNew feature or request
    kind:designNeeds Toph's judgment: a decision, an ADR, a spec question
    on Sep 25, 2026
  2. tophcodes commented on Sep 28, 2026

    @tophcodes
    OwnerAuthor

    Decided on paper, with the squash of one flap of the preliminary base (Fisher's multifold g-a, g-k, mountain g-j, unfold g-e [fisher1994, p. 24]):

    Which layers move: the tip rule for squash. The fan sits at the closed point, and four layers lie under it on the side of the flap. Only the flap joined to the anchor moves (layers 1 and 2, hinged at .e); the flap behind it stays.

    Under the other rule, every layer under the fan, the flap behind opens at .i as well and the result is two squashes, front and back. The kernel accepts that state (a 10-ray fan at the centre, 24 layer orders), so the rule would not fail; it would silently fold something else. flatten follows that rule today.

    Still open here: whether flatten moves onto the tip rule too. On a single flat sheet every face is joined to the anchor, so the two rules give the same result there.

  3. tophcodes commented on Sep 29, 2026

    @tophcodes
    OwnerAuthor

    Decided on the preliminary base as one flatten (six rays at the centre, examples/bases/preliminary.bel):

    A flatten selects no state by convention. The candidates of a fan share their geometry; they differ only in layer order, and the letters follow from it. When more than one candidate remains, the statement fails as ambiguous, and the error offers one item per remaining candidate that keeps exactly that one. Letters come first, since a folder reads them off a crease pattern and a diagram; an over item comes where letters leave several.

    • toward goes from flatten, with the three rules behind it (moved material toward the point, fewest mountains, material toward the point on top). This settles open-flatten-selection in spec/MODEL.md.
    • The same mechanism as the suggestions for constructions in Draw a selection stage by stage #63.

    On the six rays, 18 letter assignments give a flat state and three have two mountains. Checked with the kernel, each item below keeps exactly one of the 18:

    state letter layers on the .b side, top first
    preliminary base (--bd & .b mountain) a, b, b, c
    .b folded to the front through both layers, .d to the back (--v & --cd mountain) b, b, a, c
    .b to the back, .d to the front (--h & --da mountain) a, c, b, b

    Layer items separate them as well: a over b with b over c keeps the preliminary base, b over a the second state, a over b with c over b the third. Two over items say "between"; no adjacency relation is needed. Checked with helper points in the sectors (.q, .r, .s), which are what makes over hard to write today.

    Not decided, but likely: naming a sector in an over item with the solution-space selector #{…} of #12. #[.b] reads the flat sheet before the solve, and #{.b} would read the .b taco of the candidate.

  4. tophcodes commented on Sep 29, 2026

    @tophcodes
    OwnerAuthor

    Handoff: this issue continues in a new session.

    Decided so far (comments above): the tip rule for squash, and no selection by convention for flatten (#99).

    Still open:

    • Whether the tip rule holds for every fan, flatten included. On a flat sheet both rules agree. On folded paper the kernel today refuses a flatten unless every layer under the fan already carries the rays ("collapse through unaligned layers" in flatten_solve.ml), while def-flatten in spec/MODEL.md scores every layer under the fan. The two disagree.
    • The surface of squash: which flap, and where the opened spine lands. Three candidates, none checked: squash (map --h onto --ac) (moving .e) (the pre-crease as axis, like reverse), squash --h onto --ac (moving .e) (name the spine and its target), and the explicit fan with an opens letter.
    • The fan at a table point over several paper points, shown on a thick reverse fold such as the crane's neck.

    The working method that got these decisions: one real case folded on paper step by step, one image per step (hand-placed SVG, phone layout for anything read on the phone), and every state checked with the kernel before it is drawn.

    The squash of the preliminary base is one 8-ray fan at the paper centre, and the kernel evaluates it on the flat sheet:

    paper square
    mark (through .a .c) as --ac
    mark (through .b .d) as --bd
    mark (map --ab onto --cd) as --h
    mark (map --da onto --bc) as --v
    mark (align (--h onto --ac) (heading --h)) as --s
    mark (align (--h onto --bd) (heading --h)) as --t
    .z = free on --cd from .c at 1/4
    flatten (--h & --bc valley) (--v & --cd valley) (--bd & .d mountain) (--t & --da valley) (--s & --da mountain) (--ac & .a valley) (--v & --ab valley) (--bd & .b mountain) (staying .z)
    

    It fails as ambiguous with 14 layer orders, which is what #99 addresses. Squashing the front and the back flap together, the result of moving every layer under the fan, adds mark (align (--v onto --ac) (heading --v)) as --u and mark (align (--v onto --bd) (heading --v)) as --w and the rays (--ac & .c valley) (--u & --cd mountain) (--w & --cd valley) in place of (--v & --cd valley), with the stayer moved to .z = free on --ab from .a at 1/4; the kernel finds 24 flat layer orders.

  5. tophcodes commented on Sep 29, 2026

    @tophcodes
    OwnerAuthor

    Decided: mark without on scores through every layer under its line, as a hand pressing a crease into the stack does. On folded paper it scores one flap today.

    Still open: what on means. On a book fold, the corner bisector marked (on #[.a]) runs from the corner to the spine. The triangle of the upper layer beside it hangs on the lower layer at the spine, so the upper layer cannot be creased along that line without the lower one. A mark on one flap is only foldable where the flap can move on its own.

    Correction to the handoff above: mark (--x) (on #[.d]) into --x does not give the kernel the line on both layers. A flatten through two layers cannot be checked until #105 lands.

  6. tophcodes commented on Sep 29, 2026

    @tophcodes
    OwnerAuthor

    Decided: fold without moving or up to folds every layer under its axis, as mark without on scores every layer. On the book fold of #105, folding the corner along the bisector through both layers takes two helper points today, (moving .h) (up to .g) on the left edge, since the default moves only the top flap and what lies on it.

  7. tophcodes commented on Sep 29, 2026

    @tophcodes
    OwnerAuthor

    Handoff: this issue continues in a new session.

    Decided since the last handoff:

    The separating case for the tip rule is the four-ray fan near the corner of a book fold, in packages/core/tests/cases/collapse/flatten-through-two-layers.bel. The kernel gives the result of the rule of all layers: both corners fold as one stack, and along a cut below the vertex the layers read d, a, a, d, d, a, a, d from the top. That matches the drawing made by hand. The result of the tip rule, with only the upper layer's corner moving and the lower layer's corner left in view, exists as a hand drawing only.

    Still open:

    • Whether a flatten with an anchor moves the tip. The proposal stands: the rule of reverse for every fan, the tip with an anchor and every layer without one. flatten has no anchor item yet; staying names a stayer sector.
    • What on means. A mark on one flap can be folded only where that flap can move on its own; the corner bisector that reaches the spine cannot.
    • The surface of squash, and the fan at a table point over several paper points, as in the handoff above.

    The working method that got these decisions: one real case folded on paper step by step, an image per step from beloch render --view side (folded state with the cut, crease pattern, section), a hand drawing where the kernel cannot yet evaluate, and every state compared with the paper.

  8. tophcodes commented on Sep 29, 2026

    @tophcodes
    OwnerAuthor

    Decided:

    • A fan moves its tip (ADR 0037). flatten, squash, reverse and later petal move the pieces under the fan that are joined to the flap carrying its point; a single crease moves every layer under it, as ADR 0036 states. On the book of Cut a mark along its extent when a flatten folds it #105 the fan along --x and --y reaches the spine, so its tip holds both layers; the four-ray fan of flatten-through-two-layers.bel does not, and folds the upper corner alone. Move the tip of a flatten #113 carries it out for flatten. Smith draws the same line: layers treated as one take only valley and mountain folds [smith1975oil, p. 17].
    • The surface of squash (ADR 0038, Propose ADR 0038: squash takes a bare alignment of its spine #114). squash (--h onto --ac) or squash (--h onto .p): a bare alignment of the spine and its target, completed by the write with the fold line through the vertex. Before the squash, the two new creases of the preliminary base lie on one table line, the bisector of spine and target, and that line is the axis. reverse keeps complete constructions, since a reverse fold has no vertex.

    Still open:

    • An item that widens a fan to separate flaps. No model needs it yet; the "(two points)" of Vigo's rooster are joined at the spine.
    • Which vertex a bare alignment takes when both ends of the spine lie inside the paper.
    • What on means, and the fan at a table point over several paper points, as in the handoffs above.
  9. tophcodes commented on Sep 29, 2026

    @tophcodes
    OwnerAuthor

    Handoff: the design of this issue is decided; what is left is building it.

    Decided since the last comment:

    • on marks the named flap alone (ADR 0039), also where the flap is hinged to other layers along the line: the folder opens the model partway. Show the opening of the model for a mark on one layer #116 takes up how a diagram shows that step.
    • A fan sits at a table point (ADR 0040), with a paper point in every layer under it, on a folded edge included. flatten takes (on #[…]) to name the flap it folds, anywhere in the stack; without it the anchor is the topmost flap under the point.

    The records: ADR 0036 (a write reaches every layer under its axis), 0037 (a fan moves its tip), 0038 (the surface of squash), 0039, 0040.

    Build order:

    1. Reach every layer under the axis by default, and read moving as a side #111: fold and mark reach every layer; moving names a side (ADR 0036). Independent of the rest.
    2. Move the tip of a flatten #113: flatten at a table point moves the tip of its anchor, with on (ADR 0037, 0040).
    3. Fold reverse as a fan #119: reverse folded as a fan through the path of Move the tip of a flatten #113; its cases, the bird base and the crane unchanged.
    4. Fold a squash from a bare alignment of its spine #115: squash (--h onto …) (ADR 0038).

    Waiting on a model that needs them: the item that widens a fan to separate flaps (ADR 0037), and the vertex of a spine with both ends inside the paper (ADR 0038).

  10. pinned this issue on Oct 2, 2026
  11. tophcodes commented on Oct 20, 2026

    @tophcodes
    OwnerAuthor

    The four items are built: #111, #113, #119 and, with #270, #115. The two points left open above stay where their records keep them: the item that widens a fan to separate flaps (ADR 0037) is one of the questions of #161, and the vertex of a spine with both ends inside the paper (ADR 0038) waits for a model that needs it; the kernel refuses it with a message until then. #269 records that the squash on the preliminary base relies on the fewest-mountains stage, which #99 wants to remove.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestkind:designNeeds Toph's judgment: a decision, an ADR, a spec question

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions