Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 17 additions & 10 deletions src/curvilinear.jl
Original file line number Diff line number Diff line change
Expand Up @@ -181,14 +181,21 @@ CurvilinearRegion(points::Vector{Point{T}}, segments) where {T} =
CurvilinearRegion(points::Vector{Point{T}}, curves, curve_start_idx) where {T} =
CurvilinearRegion(CurvilinearPolygon(points, curves, curve_start_idx))

to_polygons(e::CurvilinearRegion{T}; kwargs...) where {T} =
to_polygons(difference2d(to_polygons(e.exterior), to_polygons.(e.holes)))
to_polygons(e::CurvilinearRegion, sty::Polygons.Rounded; kwargs...) = to_polygons(
difference2d(
to_polygons(e.exterior, sty; kwargs...),
[to_polygons(h, sty; kwargs...) for h in e.holes]
function to_polygons(e::CurvilinearRegion; kwargs...)
isempty(e.holes) && return [to_polygons(e.exterior; kwargs...)]
return to_polygons(
difference2d(to_polygons(e.exterior; kwargs...), to_polygons.(e.holes; kwargs...))
)
)
end
function to_polygons(e::CurvilinearRegion, sty::Polygons.Rounded; kwargs...)
isempty(e.holes) && return [to_polygons(e.exterior, sty; kwargs...)]
return to_polygons(
difference2d(
to_polygons(e.exterior, sty; kwargs...),
[to_polygons(h, sty; kwargs...) for h in e.holes]
)
)
end

function transform(e::CurvilinearRegion{T}, f::Transformation) where {T}
return CurvilinearRegion{T}(transform(e.exterior, f), transform.(e.holes, Ref(f)))
Expand Down Expand Up @@ -581,7 +588,7 @@ function to_polygons(
iszero(rad_raw) && return to_polygons(ent; kwargs...)
relative = rad_raw isa Real

V = promote_type(float(S), float(T))
V = float(S) # No promotion with T (bypass Unitful.jl#845), entity coordinate type has priority
poly = ent.p
n = length(poly)

Expand Down Expand Up @@ -718,7 +725,7 @@ function to_polygons(
end
end

return Polygon(final_points)
return Polygon{V}(final_points)
end

# Intersect a parallel line (p_offset + s * v_line) with a circle of radius D centered at O.
Expand Down Expand Up @@ -793,7 +800,7 @@ function rounded_corner_line_arc(
min_side_len=radius,
min_angle=1e-3
) where {T, S <: DeviceLayout.Coordinate}
V = promote_type(T, S)
V = float(T)
r = convert(V, radius)

# Check straight edge length against min_side_len
Expand Down
10 changes: 5 additions & 5 deletions src/polygons.jl
Original file line number Diff line number Diff line change
Expand Up @@ -754,13 +754,13 @@ function _round_poly(
) where {T, S <: Coordinate}
iszero(radius) && return pol
# If radius is dimensional, non-relative rounding.
V = ((S <: Length && T <: Length) || (S <: Real && T <: Real)) ? promote_type(T, S) : T
V = float(T)
# Tie break for Real, Real introduces a type instability for non-dimensional.
relative = ((T <: Length) && (S <: Real)) || (relative && T <: Real && S <: Real)

poly = points(pol)
len = length(poly)
new_polygon = Point{float(V)}[]
new_polygon = Point{V}[]
for i in eachindex(poly)
if !(i in corner_indices)
push!(new_polygon, poly[i])
Expand All @@ -783,7 +783,7 @@ function _round_poly(
)
end
end
return Polygon(new_polygon...)
return Polygon(new_polygon)
end

# Perform rounding by creating Polygons of each contour, dispatching
Expand All @@ -799,7 +799,7 @@ function _round_poly(
radius::S;
kwargs...
) where {T, S <: Coordinate}
V = ((S <: Length && T <: Length) || (S <: Real && T <: Real)) ? promote_type(T, S) : T
V = float(T)
new_pol = T == V ? deepcopy(pol) : convert(ClippedPolygon{V}, pol)
round_node!.(new_pol.tree.children, Ref(radius); kwargs...)
return new_pol
Expand Down Expand Up @@ -829,7 +829,7 @@ function rounded_corner(
min_side_len=radius,
min_angle=1e-3
) where {T, S <: Coordinate}
V = promote_type(T, S)
V = float(T)
rad = convert(V, radius)

v1 = (p1 - p0) / norm(p1 - p0)
Expand Down
20 changes: 10 additions & 10 deletions src/solidmodels/render.jl
Original file line number Diff line number Diff line change
Expand Up @@ -198,14 +198,14 @@ function round_to_curvilinearpolygon(
min_side_len=relative ? zero(T) : radius
)::CurvilinearPolygon{T} where {T, S <: Coordinate}
# If radius is dimensional, non-relative rounding.
V = ((S <: Length && T <: Length) || (S <: Real && T <: Real)) ? promote_type(T, S) : T
V = float(T)
# Tie break for Real, Real introduces a type instability for non-dimensional.
relative = ((T <: Length) && (S <: Real)) || (relative && T <: Real && S <: Real)

poly = points(pol)
len = length(poly)
new_points = Point{float(V)}[]
new_curves = Paths.Turn{float(V)}[]
new_points = Point{V}[]
new_curves = Paths.Turn{V}[]
new_curve_start_idx = Int[]

for i in eachindex(poly)
Expand Down Expand Up @@ -248,19 +248,19 @@ function round_to_curvilinearpolygon(
min_side_len=relative ? zero(T) : radius
)::CurvilinearPolygon{T} where {T, S <: Coordinate}
# If radius is dimensional, non-relative rounding.
V = ((S <: Length && T <: Length) || (S <: Real && T <: Real)) ? promote_type(T, S) : T
V = float(T)
# Tie break for Real, Real introduces a type instability for non-dimensional.
relative = ((T <: Length) && (S <: Real)) || (relative && T <: Real && S <: Real)

poly = points(pol)
len = length(poly)
new_points = Point{float(V)}[]
new_curves = Paths.Turn{float(V)}[]
new_points = Point{V}[]
new_curves = Paths.Turn{V}[]
new_curve_start_idx = Int[]

# Track trims for existing curves when rounding line-arc corners
trim_start_pts = Dict{Int, Point{float(V)}}()
trim_end_pts = Dict{Int, Point{float(V)}}()
trim_start_pts = Dict{Int, Point{V}}()
trim_end_pts = Dict{Int, Point{V}}()

# Determine which line-arc corners to round
la_indices = if !isnothing(line_arc_corner_indices)
Expand Down Expand Up @@ -382,7 +382,7 @@ function rounded_corner_segment(
min_side_len=radius,
min_angle=1e-3
) where {T, S <: Coordinate}
V = promote_type(T, S)
V = float(T)
rad = convert(V, radius)

v1 = (p1 - p0) / norm(p1 - p0)
Expand Down Expand Up @@ -441,7 +441,7 @@ function rounded_corner_segment_line_arc(
min_side_len=radius,
min_angle=1e-3
) where {T, S <: Coordinate}
V = promote_type(T, S)
V = float(T)
r = convert(V, radius)
atol = DeviceLayout.Polygons._round_atol(T, S)

Expand Down
10 changes: 10 additions & 0 deletions test/test_line_arc_rounding.jl
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,16 @@
# Relative result should differ from absolute (different radius semantics)
@test length(points(rel_rounded)) != length(rounded_pts) ||
!isapprox(points(rel_rounded)[1], rounded_pts[1]; atol=0.1nm)

# Unitful issue addressed by Unitful.jl PR#845 bypassed
rect = Rectangle(10.0μm2μm, 10.0μm2μm)
cr = CurvilinearRegion(CurvilinearPolygon(points(rect)))
rnd_μm2nm = Rounded(1.0μm2nm)
poly = only(to_polygons(rnd_μm2nm(cr))) # Runs without error
@test coordinatetype(poly) == typeof(1.00μm2μm)
# Test no-holes bypasses difference2d -- point order would be different
@test poly == to_polygons(cr.exterior, rnd_μm2nm)
@test only(to_polygons(cr)) == to_polygons(cr.exterior)
end

@testitem "Horseshoe landing pad rounding" setup = [CommonTestSetup] begin
Expand Down
7 changes: 7 additions & 0 deletions test/test_shapes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,13 @@
@test_nowarn place!(cs, csty, GDSMeta())
c = Cell("main", nm)
@test_nowarn render!(c, cs)

# Use float input polygon coordinatetype -- don't promote with rounded type
r_int = Rectangle(2μm2μm, 2μm2μm)
r_float = Rectangle(2.0μm2μm, 2.0μm2μm)
rnd = Rounded(0.5μm2nm)
@test coordinatetype(to_polygons(rnd(r_int))) == typeof(1.02μm2μm)
@test coordinatetype(to_polygons(rnd(r_float))) == typeof(1.02μm2μm)
end

@testitem "Curvilinear" setup = [CommonTestSetup] begin
Expand Down
Loading