Skip to content

Handle ambiguous region tags in edge specifiers#12302

Open
jtran wants to merge 9 commits into
mainfrom
jtran-face-api-tag-res
Open

Handle ambiguous region tags in edge specifiers#12302
jtran wants to merge 9 commits into
mainfrom
jtran-face-api-tag-res

Conversation

@jtran

@jtran jtran commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Revive #12201.
Original PR description below. The only difference is that we now generate an error if the user specifies an index with sideFaces or endFaces that have been split. We need this engine API to do it correctly, without making the index parameter have a confusing double meaning.


This fixes a face API edge-specifier case where a region-derived tag can map to more than one swept face after region() and extrude().

The concrete case is something like:

edges = [
  {
    sideFaces = [band.tags.circle1, capStart001]
  }
]

Here band.tags.circle1 looks like one logical KCL reference, but the circle segment can contribute two curved side faces in the swept result. Before this change, resolving that tag as a face could fail with Tag circle1 is ambiguous, even though this is a reasonable query from the user's point of view.

This PR keeps the KCL syntax/API the same. It does not add a new user-facing way to name these region pieces. Instead, when KCL resolves face API edge specifiers for fillet and chamfer, a single logical face reference is allowed to resolve to multiple concrete face IDs. KCL then expands the combinations into multiple flat engine EdgeSpecifier payloads.

That means the broad case can work as intended: if sideFaces = [band.tags.circle1, capStart001] describes two concrete edges, both edge references are sent through and both edges can be filleted/chamfered.

The same expansion also works with endFaces. If the user writes:

edges = [
  {
    sideFaces = [band.tags.circle1, capStart001],
    endFaces = [band.tags.line1]
  }
]

KCL still expands the ambiguous sideFaces candidates, but the engine gets to resolve each candidate with the extra endFaces disambiguator. In practice, the candidate that does not touch line1 resolves to nothing, and the candidate that does touch line1 resolves to the intended edge.

One important thing this PR does not do is consume index locally. That was the part of the earlier version that felt wrong. index is supposed to be engine-side disambiguation, so this PR forwards index unchanged on each expanded engine payload [jtran: only if there's one] rather than using it to pick one expanded candidate in KCL. That is not a perfect long-term shape, because a flat EdgeSpecifier cannot preserve the grouping of “this one logical KCL face reference maps to these concrete face IDs”, but it avoids changing the meaning of index behind the user's back.

The longer-term follow-up is to change the lower-level modeling-commands/API shape so each sideFaces or endFaces entry can represent one logical face reference with one or more concrete face IDs. That would let KCL send one grouped topology query instead of expanding to several flat EdgeSpecifiers. I filed that as an ongoing modeling-api issue here: KittyCAD/modeling-api#1252.

So this PR should be read as a practical fix for the current flat API shape, not the final design for logical face references. The underlying issue is still that the lower-level API cannot preserve the grouping of “one KCL face reference resolved to multiple concrete faces”. That is the part tracked in KittyCAD/modeling-api#1252.

There is also a reverse point-and-click consideration for that follow-up. When the engine returns a payload for a selected edge, it does not necessarily need to return grouped logical face references. But it does need to return enough specifiers that the generated KCL still resolves to the clicked edge after modeling-app converts concrete face IDs back into KCL tags. If a concrete side face maps back to a region-derived tag that can expand to multiple faces, then sideFaces alone may be under-specified in KCL and the returned payload may need endFaces or index.

This PR is deliberately narrower than that full API design. It fixes the immediate KCL resolution problem without introducing new KCL syntax, and it leaves a clear TODO for replacing the flat expansion once the lower-level API can represent grouped logical face references.

I added simulation coverage for the broad ambiguous region tag case and the endFaces disambiguation case, because the original problem involved real edge-reference resolution rather than just parsing or mock execution.

Case where it fillets both edges still
image

Case where endFaces resolves to single edge
image

@vercel

vercel Bot commented Jun 30, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
modeling-app Ready Ready Preview, Comment Jul 1, 2026 4:20am

Request Review

Irev-Dev and others added 4 commits June 30, 2026 17:31
Allow face API edge specifiers to resolve a single KCL face reference to
multiple concrete face IDs. This lets region-derived tags, such as a
circle segment that becomes multiple swept side faces, expand into the
corresponding flat engine edge-reference payloads for fillet/chamfer.

Keep index as engine-side disambiguation by forwarding it unchanged on
expanded payloads rather than consuming it in KCL.

Add simulation coverage for the broad ambiguous region tag case and the
endFaces disambiguation case.
@jtran jtran force-pushed the jtran-face-api-tag-res branch from 7e97e28 to 2a9929f Compare June 30, 2026 21:32
@jtran jtran marked this pull request as ready for review June 30, 2026 21:43
@jtran jtran requested a review from a team as a code owner June 30, 2026 21:43
Ok(references)
}

fn face_id_combinations(groups: &[Vec<Uuid>]) -> Vec<Vec<Uuid>> {

@jtran jtran Jun 30, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quadratic runtime here is making me nervous. I'm working on adding some checks to prevent pathological cases.

@jtran jtran Jul 1, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a maximum limit of 256 that causes an error.

@jtran jtran marked this pull request as draft June 30, 2026 23:38
@jtran jtran marked this pull request as ready for review July 1, 2026 04:04
@codspeed-hq

codspeed-hq Bot commented Jul 1, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 126 untouched benchmarks
⏩ 151 skipped benchmarks1


Comparing jtran-face-api-tag-res (f0e96d5) with main (5c8c1fc)

Open in CodSpeed

Footnotes

  1. 151 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

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.

2 participants