-
Notifications
You must be signed in to change notification settings - Fork 279
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: shape clipping #1411
feat: shape clipping #1411
Conversation
Deploying with Cloudflare Pages
|
± Registry diff
📊 PerformanceKeyNote that each bar component rounds up to the nearest 100ms, so each full bar is an overestimate by up to 400ms.
If a row has only one bar instead of four, that means it's not a trio and the bar just shows the total time spent for that example, again rounded up to the nearest 100ms. Data
|
Codecov Report
@@ Coverage Diff @@
## main #1411 +/- ##
==========================================
- Coverage 64.77% 64.42% -0.36%
==========================================
Files 64 64
Lines 7515 7586 +71
Branches 1760 1775 +15
==========================================
+ Hits 4868 4887 +19
- Misses 2521 2570 +49
- Partials 126 129 +3
|
This looks good from the language design end. It's a bit unfortunate we can't just do |
docs: add a line that explains the image makeIdsUnique call
Merged |
Thanks for catching this! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! Thanks for adding this feature. As mentioned, I fixed one issue with id-uniqueness. I also added inline comments for makeIdsUnique
to clarify its purpose (which is not used in this case so I explained why there) and for the implicit group membership of clipping shapes.
Description
Resolves #1405.
We implement shape-clipping and improve a couple of library computation and constraint functions to work with clipped shapes.
Group
ShapeclipPath
PropertyA
Group
shape now has an additionalclipPath
property that takes aClipDataV
value. AClipDataV
value has two variants:NoClip
(which takes no additional data) andClip
(which takes in aShape
object). AClipDataV
can be constructed using one of two computation functions:noClip
takes no parameters and returns theNoClip
variant.clip
takes in a shape and returns theClip
variant with the given shape.The default value of the
Group
shape'sclipPath
property is theNoClip
variant.As an example, suppose we have shapes
s1
ands2
in a group, and we want to clip the group by shapes3
. We can write,A shape involved in the
clipPath
field of aGroup
is considered a part of the group through all stages of the compilation, including the construction of theGroupGraph
, so all the usual rules of shapes not belonging to multiple groups still apply. That is,clipPath
of a group cannot appear in any other group, and cannot be used to clip another group; andCorresponding SVG
Since a shape in
clipPath
is considered a group member, we render them with all other group members. For a group withclipPath
, the generated SVG has structure,The
clipPath
SVG object idsome-id
is the name of the clipping shape, with suffix-clip
. For example, if the clipping shape name ismyShape
, then theclipPath
SVG object id ismyShape-clip
.Bounding Box
Previously, the bounding box of a
Group
shape is simply the min-max-bbox. That is, take the bounding boxes of all group members, and then find the min-x, min-y, max-x, max-y, and use those to construct a new bounding box.If a
Group
shape has a clipping shape, we compute the new bounding box as the previous bounding box, intersecting the bounding box of the clipping shape.In the picture above, the bounding box of the yellow region (the larger ellipse clipped by the smaller ellipse) is computed as the bolded blue rectangle. One may observe that this bounding box is not optimum. Indeed, this box is not a "minimum bounding box" as it can overestimate the object. But this is relatively simple to compute.
Constraint
contains
We add a branch to the
contains
constraint to deal with groups.If a group does not have a clipping shape, checking whether a group contains a shape is equivalent to checking whether some group member contains the shape. We simply compute the
contains
constraint penalty between all of the group members and the shape, and take the minimum. If the minimum of the penalties is small, then one group member must contain the shape.If a group has a clipping shape, then the
contains
constraint between the group and another shape just requires:We compute both constraints, and require that both constraints hold.
Examples with steps to reproduce them
https://clip.penrose-72l.pages.dev/try/?gist=11c14ac7a7e0cf45a13ec68066925b18
This example shows two sets, with their intersection between marked out using clipping. We also demonstrate the bounding box of the intersection (see the rectangle) and the
contains
constraint (the small, red circle is within the intersection).Checklist