Skip to content

Composite rounding of a ClippedPolygon drops its holes #241

Description

@parrangoiz

If you compose two Rounded styles and apply them to a ClippedPolygon that has holes, the holes get dropped.

Minimal repro w/ Julia 1.12.4 and DL main

using DeviceLayout
using DeviceLayout.PreferredUnits
using Unitful: ustrip

outer = centered(Rectangle(100.0μm, 100.0μm))
hole  = centered(Rectangle(40.0μm, 40.0μm))
cp = difference2d(outer, hole)  # ClippedPolygon: one boundary, one hole

total_area(x) = sum(abs(DeviceLayout.Polygons.area(p)) for p in to_polygons(x))

expected = 100.0^2 - 40.0^2
single   = total_area(Rounded(5.0μm)(cp))                      # one rounding pass
composed = total_area(Rounded(5.0μm)(Rounded(5.0μm)(cp)))      # two rounding passes (nested)

println("expected (100² - 40²)        = $(expected) µm²")
println("single Rounded(5µm)          = $(round(ustrip(μm^2, single), digits=1)) µm²   (correct: hole subtracted)")
println("composed Rounded(5µm)∘(5µm)   = $(round(ustrip(μm^2, composed), digits=1)) µm²   (BUG: ≈100² ⇒ hole dropped)")

Tentative diagnosis (needs double-checking)

Composing two Rounded styles (a nested StyledEntity) routes through

to_polygons(::CurvilinearRegion, ::Rounded)   # src/curvilinear.jl:199

which rounds the exterior and each hole independently and then re-runs difference2d:

difference2d(to_polygons(exterior, sty), [to_polygons(h, sty) for h in holes])

The rounded hole loops come back with the wrong winding, so difference2d no longer
subtracts them.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions