Skip to content

Commit 905ff66

Browse files
juliohmeliascarv
andauthored
Generalize transforms with Primitive (#1005)
* Genearlize transforms with Primitive * More adjustments * More adjustments * More adjustments * More adjustments * Use isparametrized in TransformedGeometry ctor * More adjustments * Update show * Update 'isapprox' of domains * Add 'translate' helper * Apply suggestions * More adjustments * More adjustments * More adjustments * More adjustments * More adjustments * More adjustments * More adjustments * More adjustments * More adjustments * Add show tests * Specialize \to for affine transforms * Update 'isapprox' * Optimize |Stretch * Fix some tests * Update 'Shadow' implementation * Apply suggestions * Apply suggestions * Apply suggestions * Fix tests * Apply suggestions * Apply suggestions * Apply suggestions * More adjustments * Update 'isapprox' * Apply suggestions --------- Co-authored-by: Elias Carvalho <[email protected]>
1 parent 74707c4 commit 905ff66

25 files changed

+248
-211
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,6 @@ ScopedValues = "1.2"
4343
SparseArrays = "1.9"
4444
StaticArrays = "1.0"
4545
StatsBase = "0.33, 0.34"
46-
TransformsBase = "1.4.1"
46+
TransformsBase = "1.6"
4747
Unitful = "1.17"
4848
julia = "1.9"

src/boundary.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,3 +114,5 @@ function boundary(m::Multi)
114114
valid = filter(!isnothing, bounds)
115115
isempty(valid) ? nothing : reduce(merge, valid)
116116
end
117+
118+
boundary(g::TransformedGeometry) = transform(g)(boundary(parent(g)))

src/centroid.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ The centroid of the `geometry`.
99
"""
1010
centroid(g::Geometry) = center(g) # some geometries have a natural center
1111

12-
centroid(p::Polytope) = withcrs(p, sum(to, vertices(p)) / nvertices(p))
13-
1412
centroid(p::Point) = p
1513

1614
centroid(p::Polygon) = centroid(first(rings(p)))
1715

16+
centroid(p::Polytope) = withcrs(p, sum(to, vertices(p)) / nvertices(p))
17+
1818
centroid(b::Box) = withcrs(b, sum(to, extrema(b)) / 2)
1919

2020
centroid(p::Plane) = p(0, 0)

src/domains.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ function nelements end
3131

3232
==(d1::Domain, d2::Domain) = nelements(d1) == nelements(d2) && all(d1[i] == d2[i] for i in 1:nelements(d1))
3333

34-
Base.isapprox(d1::Domain, d2::Domain) = nelements(d1) == nelements(d2) && all(d1[i] d2[i] for i in 1:nelements(d1))
34+
Base.isapprox(d1::Domain, d2::Domain; kwargs...) =
35+
nelements(d1) == nelements(d2) && all(isapprox(d1[i], d2[i]; kwargs...) for i in 1:nelements(d1))
3536

3637
Base.getindex(d::Domain, ind::Int) = element(d, ind)
3738

src/geometries.jl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,19 @@ Base.extrema(g::Geometry) = extrema(boundingbox(g))
6868

6969
Base.summary(io::IO, geom::Geometry) = print(io, prettyname(geom))
7070

71+
function Base.show(io::IO, geom::Geometry)
72+
name = prettyname(geom)
73+
ioctx = IOContext(io, :compact => true)
74+
print(io, "$name(")
75+
printfields(ioctx, geom, singleline=true)
76+
print(io, ")")
77+
end
78+
79+
function Base.show(io::IO, ::MIME"text/plain", geom::Geometry)
80+
summary(io, geom)
81+
printfields(io, geom)
82+
end
83+
7184
# ----------------
7285
# IMPLEMENTATIONS
7386
# ----------------

src/geometries/primitives.jl

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,6 @@ See <https://en.wikipedia.org/wiki/Geometric_primitive>.
1212
"""
1313
abstract type Primitive{M<:Manifold,C<:CRS} <: Geometry{M,C} end
1414

15-
function Base.show(io::IO, geom::Primitive)
16-
name = prettyname(geom)
17-
ioctx = IOContext(io, :compact => true)
18-
print(io, "$name(")
19-
printfields(ioctx, geom, singleline=true)
20-
print(io, ")")
21-
end
22-
23-
function Base.show(io::IO, ::MIME"text/plain", geom::Primitive)
24-
summary(io, geom)
25-
printfields(io, geom)
26-
end
27-
2815
include("primitives/point.jl")
2916
include("primitives/ray.jl")
3017
include("primitives/line.jl")

src/geometries/primitives/ball.jl

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,7 @@ radius(b::Ball) = b.radius
3636
Base.isapprox(b₁::Ball, b₂::Ball; atol=atol(lentype(b₁)), kwargs...) =
3737
isapprox(b₁.center, b₂.center; atol, kwargs...) && isapprox(b₁.radius, b₂.radius; atol, kwargs...)
3838

39-
(b::Ball)(args...) = _ball(Val(embeddim(b)), b, args...)
40-
41-
function _ball(::Val{2}, b, ρ, φ)
39+
function (b::Ball{𝔼{2}})(ρ, φ)
4240
T = numtype(lentype(b))
4341
if< 0 || ρ > 1) ||< 0 || φ > 1)
4442
throw(DomainError((ρ, φ), "b(ρ, φ) is not defined for ρ, φ outside [0, 1]²."))
@@ -52,7 +50,7 @@ function _ball(::Val{2}, b, ρ, φ)
5250
c + Vec(x, y)
5351
end
5452

55-
function _ball(::Val{3}, b, ρ, θ, φ)
53+
function (b::Ball{𝔼{3}})(ρ, θ, φ)
5654
T = numtype(lentype(b))
5755
if< 0 || ρ > 1) ||< 0 || θ > 1) ||< 0 || φ > 1)
5856
throw(DomainError((ρ, θ, φ), "b(ρ, θ, φ) is not defined for ρ, θ, φ outside [0, 1]³."))

src/geometries/primitives/box.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ sides(b::Box) = Tuple(b.max - b.min)
6060
Base.isapprox(b₁::Box, b₂::Box; atol=atol(lentype(b₁)), kwargs...) =
6161
isapprox(b₁.min, b₂.min; atol, kwargs...) && isapprox(b₁.max, b₂.max; atol, kwargs...)
6262

63-
function (b::Box)(uv...)
63+
function (b::Box{<:𝔼})(uv...)
6464
if !all(x -> 0 x 1, uv)
6565
throw(DomainError(uv, "b(u, v, ...) is not defined for u, v, ... outside [0, 1]ⁿ."))
6666
end

src/geometries/primitives/sphere.jl

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,7 @@ radius(s::Sphere) = s.radius
7373
Base.isapprox(s₁::Sphere, s₂::Sphere; atol=atol(lentype(s₁)), kwargs...) =
7474
isapprox(s₁.center, s₂.center; atol, kwargs...) && isapprox(s₁.radius, s₂.radius; atol, kwargs...)
7575

76-
(s::Sphere)(args...) = _sphere(Val(embeddim(s)), s, args...)
77-
78-
function _sphere(::Val{2}, s, φ)
76+
function (s::Sphere{𝔼{2}})(φ)
7977
T = numtype(lentype(s))
8078
if< 0 || φ > 1)
8179
throw(DomainError(φ, "s(φ) is not defined for φ outside [0, 1]."))
@@ -88,7 +86,7 @@ function _sphere(::Val{2}, s, φ)
8886
c + Vec(x, y)
8987
end
9088

91-
function _sphere(::Val{3}, s, θ, φ)
89+
function (s::Sphere{𝔼{3}})(θ, φ)
9290
T = numtype(lentype(s))
9391
if< 0 || θ > 1) ||< 0 || φ > 1)
9492
throw(DomainError((θ, φ), "s(θ, φ) is not defined for θ, φ outside [0, 1]²."))

src/geometries/transformedgeom.jl

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ struct TransformedGeometry{M<:Manifold,C<:CRS,G<:Geometry,T<:Transform} <: Geome
1717
end
1818

1919
function TransformedGeometry(g::Geometry, t::Transform)
20-
p = t(centroid(g))
20+
D = paramdim(g)
21+
T = numtype(lentype(g))
22+
p = t(isparametrized(g) ? g(ntuple(i -> zero(T), D)...) : centroid(g))
2123
TransformedGeometry{manifold(p),crs(p)}(g, t)
2224
end
2325

@@ -43,10 +45,20 @@ transform(g::TransformedGeometry) = g.transform
4345

4446
paramdim(g::TransformedGeometry) = paramdim(g.geometry)
4547

46-
==(g₁::TransformedGeometry, g₂::TransformedGeometry) = g₁.transform == g₂.transform && g₁.geometry == g₂.geometry
48+
==(g₁::TransformedGeometry, g₂::TransformedGeometry) = _isequal(g₁, g₂)
49+
50+
==(g₁::TransformedGeometry, g₂::Geometry) = _isequal(g₁, g₂)
51+
52+
==(g₁::Geometry, g₂::TransformedGeometry) = _isequal(g₁, g₂)
4753

4854
Base.isapprox(g₁::TransformedGeometry, g₂::TransformedGeometry; atol=atol(lentype(g₁)), kwargs...) =
49-
isapprox(g₁.geometry, g₂.geometry; atol, kwargs...) && g₁.transform == g₂.transform
55+
_isapprox(g₁, g₂; atol, kwargs...)
56+
57+
Base.isapprox(g₁::TransformedGeometry, g₂::Geometry; atol=atol(lentype(g₁)), kwargs...) =
58+
_isapprox(g₁, g₂; atol, kwargs...)
59+
60+
Base.isapprox(g₁::Geometry, g₂::TransformedGeometry; atol=atol(lentype(g₁)), kwargs...) =
61+
_isapprox(g₁, g₂; atol, kwargs...)
5062

5163
(g::TransformedGeometry)(uvw...) = g.transform(g.geometry(uvw...))
5264

@@ -74,7 +86,16 @@ rings(p::TransformedPolygon) = map(p.transform, rings(p.geometry))
7486
# IO METHODS
7587
# -----------
7688

77-
function Base.summary(io::IO, g::TransformedGeometry)
78-
name = prettyname(g.geometry)
79-
print(io, "Transformed$name")
89+
prettyname(g::TransformedGeometry) = "Transformed$(prettyname(g.geometry))"
90+
91+
# -----------------
92+
# HELPER FUNCTIONS
93+
# -----------------
94+
95+
_isequal(g₁, g₂) = pointify(g₁) == pointify(g₂)
96+
97+
function _isapprox(g₁, g₂; kwargs...)
98+
ps₁ = pointify(g₁)
99+
ps₂ = pointify(g₂)
100+
length(ps₁) == length(ps₂) && all(isapprox(p₁, p₂; atol, kwargs...) for (p₁, p₂) in zip(ps₁, ps₂))
80101
end

0 commit comments

Comments
 (0)