Skip to content

Commit

Permalink
Merge pull request #240 from fhagemann/CSG
Browse files Browse the repository at this point in the history
Redefine `Cone` and `Torus`: `φ::Tuple{T,T}` => `φ::T`
  • Loading branch information
fhagemann authored Nov 3, 2021
2 parents 14adeb4 + 14de926 commit 5d3dc11
Show file tree
Hide file tree
Showing 13 changed files with 269 additions and 173 deletions.
13 changes: 8 additions & 5 deletions src/ConstructiveSolidGeometry/Intervals.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,20 @@
@inline _radial_endpoints(r::AbstractInterval) = endpoints(r)
@inline _radial_endpoints(r::Tuple{T,T}) where {T} = r

@inline _in_angular_interval_closed::Real, α_int::Nothing, tol::Real = 0) = true
@inline _in_angular_interval_closed::Real, α_int::AbstractInterval{T}, tol::Real = 0) where {T} = mod- (α_int.left-tol), T(2π)) (α_int.right+tol) - (α_int.left-tol)

@inline _in_angular_interval_closed::T, α_int::T; csgtol::T = csg_default_tol(T)) where {T} = mod+ csgtol, T(2π)) α_int + csgtol
@inline function _in_angular_interval_closed::T, α_int::Tuple{T,T}; csgtol::T = csg_default_tol(T)) where {T}
m = mod- α_int[1], T(2π))
d = (α_int[2] - α_int[1])
m d + csgtol
end

@inline _in_angular_interval_open::T, α_int::T; csgtol::T = csg_default_tol(T)) where {T} = csgtol < mod(α, T(2π)) α_int - csgtol
@inline function _in_angular_interval_open::T, α_int::Tuple{T,T}; csgtol::T = csg_default_tol(T)) where {T}
csgtol < mod- α_int[1], T(2π)) < (α_int[2] - α_int[1]) - csgtol
end

@inline _in_angular_interval_open::T, α_int::Nothing) where {T<:Real} = 0 < mod(α, T(2π)) < T(2π)
@inline _in_angular_interval_open::Real, α_int::AbstractInterval{T}) where {T} = 0 < mod- α_int.left, T(2π)) < width(α_int)
# @inline _in_angular_interval_closed(α::Real, α_int::Nothing, tol::Real = 0) = true
# @inline _in_angular_interval_closed(α::Real, α_int::AbstractInterval{T}, tol::Real = 0) where {T} = mod(α - (α_int.left-tol), T(2π)) ≤ (α_int.right+tol) - (α_int.left-tol)
#
# @inline _in_angular_interval_open(α::T, α_int::Nothing) where {T<:Real} = 0 < mod(α, T(2π)) < T(2π)
# @inline _in_angular_interval_open(α::Real, α_int::AbstractInterval{T}) where {T} = 0 < mod(α - α_int.left, T(2π)) < width(α_int)
6 changes: 3 additions & 3 deletions src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# * TP = Nothing <-> Full in φ
# * ...
# """
@with_kw struct Ellipse{T,TR,TP} <: AbstractLinePrimitive{T}
@with_kw struct Ellipse{T,TR,TP<:Union{Nothing,T}} <: AbstractLinePrimitive{T}
r::TR = 1
φ::TP = nothing

Expand All @@ -21,7 +21,7 @@
end

const Circle{T} = Ellipse{T,T,Nothing}
const PartialCircle{T} = Ellipse{T,T,Tuple{T,T}}
const PartialCircle{T} = Ellipse{T,T,T}

extremum(e::Ellipse{T,T}) where {T} = e.r
extremum(e::Ellipse{T,Tuple{T,T}}) where {T} = max(e.r...)
Expand All @@ -35,7 +35,7 @@ function sample(e::Circle{T}; n = 4)::Vector{CartesianPoint{T}} where {T}
pts
end
function sample(e::PartialCircle{T}; n = 2)::Vector{CartesianPoint{T}} where {T}
φs = range(e.φ[1], stop = e.φ[1], length = n)
φs = range(T(0), stop = e.φ, length = n)
pts = Vector{CartesianPoint{T}}(undef, n)
for i in eachindex(pts)
pts[i] = _transform_into_global_coordinate_system(CartesianPoint(CylindricalPoint{T}(e.r, φs[i], zero(T))), e)
Expand Down
10 changes: 5 additions & 5 deletions src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Surface primitive describing the mantle of a [`Cone`](@ref).
* `TR == Tuple{T, T}`: VaryingCylinderMantle (bottom radius at `r[1]`, top radius at `r[2]`).
* `TP`: Type of the angular range `φ`.
* `TP == Nothing`: Full 2π Cone.
* `TP == Tuple{T, T}`: Partial Cone ranging from `φ[1]` to `φ[2]`.
* `TP == T`: Partial ConeMantle ranging from `0` to `φ`.
* `D`: Direction in which the normal vector points (`:inwards` or `:outwards`).
## Fields
Expand All @@ -20,7 +20,7 @@ Surface primitive describing the mantle of a [`Cone`](@ref).
* `origin::CartesianPoint{T}`: Origin of the `Cone` which has this `ConeMantle` as surface.
* `rotation::SMatrix{3,3,T,9}`: Rotation matrix of the `Cone` which has this `ConeMantle` as surface.
"""
@with_kw struct ConeMantle{T,TR,TP,D} <: AbstractCurvedSurfacePrimitive{T}
@with_kw struct ConeMantle{T,TR,TP<:Union{Nothing,T},D} <: AbstractCurvedSurfacePrimitive{T}
r::TR = 1
φ::TP = nothing
hZ::T = 1
Expand All @@ -39,7 +39,7 @@ radius_at_z(hZ::T, rBot::T, rTop::T, z::T) where {T} = iszero(hZ) ? rBot : rBot
radius_at_z(cm::ConeMantle{T,T}, z::T) where {T} = cm.r
radius_at_z(cm::ConeMantle{T,Tuple{T,T}}, z::T) where {T} = radius_at_z(cm.hZ, cm.r[1], cm.r[2], z)

get_φ_limits(cm::ConeMantle{T,<:Any,Tuple{T,T}}) where {T} = cm.φ[1], cm.φ[2]
get_φ_limits(cm::ConeMantle{T,<:Any,T}) where {T} = T(0), cm.φ
get_φ_limits(cm::ConeMantle{T,<:Any,Nothing}) where {T} = T(0), T(2π)

function normal(cm::ConeMantle{T,T,<:Any,:inwards}, pt::CartesianPoint{T}) where {T}
Expand Down Expand Up @@ -98,7 +98,7 @@ end
get_label_name(::ConeMantle) = "Cone Mantle"

const FullConeMantle{T,D} = ConeMantle{T,Tuple{T,T},Nothing,D} # ugly name but works for now, should just be `ConeMantle`...
const PartialConeMantle{T,D} = ConeMantle{T,Tuple{T,T},Tuple{T,T},D}
const PartialConeMantle{T,D} = ConeMantle{T,Tuple{T,T},T,D}


extremum(cm::FullConeMantle{T}) where {T} = sqrt(cm.hZ^2 + max(cm.r...)^2)
Expand All @@ -120,7 +120,7 @@ function lines(sp::PartialConeMantle{T}; n = 2) where {T}
bot_ellipse = PartialCircle{T}(r = sp.r[1], φ = sp.φ, origin = bot_origin, rotation = sp.rotation)
top_origin = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +sp.hZ), sp)
top_ellipse = PartialCircle{T}(r = sp.r[2], φ = sp.φ, origin = top_origin, rotation = sp.rotation)
φs = range(sp.φ[1], stop = sp.φ[2], length = n)
φs = range(zero(T), stop = sp.φ, length = n)
edges = [ Edge{T}(_transform_into_global_coordinate_system(CartesianPoint(CylindricalPoint{T}(sp.r[1], φ, -sp.hZ)), sp),
_transform_into_global_coordinate_system(CartesianPoint(CylindricalPoint{T}(sp.r[2], φ, +sp.hZ)), sp)) for φ in φs ]
bot_ellipse, top_ellipse, edges
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ Surface primitive describing circular bases, e.g. the top or bottom base of a [`
* `TR == Tuple{T, T}`: Circular Annulus (inner radius at `r[1]`, outer radius at `r[2]`).
* `TP`: Type of the angular range `φ`.
* `TP == Nothing`: Full 2π Cone.
* `TP == Tuple{T, T}`: Partial Cone ranging from `φ[1]` to `φ[2]`.
* `TP == T`: Partial Elliptical Surface ranging from `0` to `φ`.
## Fields
* `r::TR`: Definition of the radius of the `EllipticalSurface` (in m).
* `φ::TP`: Range in polar angle `φ` over which the `EllipticalSurface` extends (in radians).
* `origin::CartesianPoint{T}`: The position of the center of the `EllipticalSurface`.
* `rotation::SMatrix{3,3,T,9}`: Matrix that describes a rotation of the `EllipticalSurface` around its `origin`.
"""
@with_kw struct EllipticalSurface{T,TR,TP} <: AbstractPlanarSurfacePrimitive{T}
@with_kw struct EllipticalSurface{T,TR,TP<:Union{Nothing,T}} <: AbstractPlanarSurfacePrimitive{T}
r::TR = 1
φ::TP = nothing

Expand All @@ -28,14 +28,14 @@ end

flip(es::EllipticalSurface{T,TR,Nothing}) where {T,TR} =
EllipticalSurface{T,TR,Nothing}(es.r, es.φ, es.origin, es.rotation * SMatrix{3,3,T,9}(1,0,0,0,-1,0,0,0,-1))
flip(es::EllipticalSurface{T,TR,Tuple{T,T}}) where {T,TR} =
EllipticalSurface{T,TR,Tuple{T,T}}(es.r, (2π-es.φ[2], 2π-es.φ[1]), es.origin, es.rotation * SMatrix{3,3,T,9}(1,0,0,0,-1,0,0,0,-1))
flip(es::EllipticalSurface{T,TR,T}) where {T,TR} =
EllipticalSurface{T,TR,T}(es.r, es.φ, es.origin, es.rotation * SMatrix{3,3,T,9}(1,0,0,0,-1,0,0,0,-1) * RotZ{T}(T(2π)-es.φ))

const CircularArea{T} = EllipticalSurface{T,T,Nothing}
const PartialCircularArea{T} = EllipticalSurface{T,T,Tuple{T,T}}
const PartialCircularArea{T} = EllipticalSurface{T,T,T}

const Annulus{T} = EllipticalSurface{T,Tuple{T,T},Nothing}
const PartialAnnulus{T} = EllipticalSurface{T,Tuple{T,T},Tuple{T,T}}
const PartialAnnulus{T} = EllipticalSurface{T,Tuple{T,T},T}

Plane(es::EllipticalSurface{T}) where {T} = Plane{T}(es.origin, es.rotation * CartesianVector{T}(zero(T),zero(T),one(T)))

Expand Down Expand Up @@ -86,7 +86,7 @@ get_label_name(::EllipticalSurface) = "Elliptical Surface"
extremum(es::EllipticalSurface{T,T}) where {T} = es.r
extremum(es::EllipticalSurface{T,Tuple{T,T}}) where {T} = es.r[2] # r_out always larger r_in: es.r[2] > es.r[2]

get_φ_limits(es::EllipticalSurface{T,<:Any,Tuple{T,T}}) where {T} = es.φ[1], es.φ[2]
get_φ_limits(es::EllipticalSurface{T,<:Any,T}) where {T} = T(0), es.φ
get_φ_limits(cm::EllipticalSurface{T,<:Any,Nothing}) where {T} = T(0), T(2π)

function lines(sp::CircularArea{T}; n = 2) where {T}
Expand All @@ -98,7 +98,7 @@ function lines(sp::CircularArea{T}; n = 2) where {T}
end
function lines(sp::PartialCircularArea{T}; n = 2) where {T}
circ = PartialCircle{T}(r = sp.r, φ = sp.φ, origin = sp.origin, rotation = sp.rotation)
φs = range(sp.φ[1], stop = sp.φ[2], length = n)
φs = range(T(0), stop = sp.φ, length = n)
edges = [ Edge{T}(_transform_into_global_coordinate_system(CartesianPoint(CylindricalPoint{T}(zero(T), φ, zero(T))), sp),
_transform_into_global_coordinate_system(CartesianPoint(CylindricalPoint{T}(sp.r, φ, zero(T))), sp)) for φ in φs ]
return (circ, edges)
Expand All @@ -115,7 +115,7 @@ end
function lines(sp::PartialAnnulus{T}; n = 2) where {T}
circ_in = PartialCircle{T}(r = sp.r[1], φ = sp.φ, origin = sp.origin, rotation = sp.rotation)
circ_out = PartialCircle{T}(r = sp.r[2], φ = sp.φ, origin = sp.origin, rotation = sp.rotation)
φs = range(sp.φ[1], stop = sp.φ[2], length = n)
φs = range(T(0), stop = sp.φ, length = n)
edges = [ Edge{T}(_transform_into_global_coordinate_system(CartesianPoint(CylindricalPoint{T}(sp.r[1], φ, zero(T))), sp),
_transform_into_global_coordinate_system(CartesianPoint(CylindricalPoint{T}(sp.r[2], φ, zero(T))), sp)) for φ in φs ]
return (circ_in, circ_out, edges)
Expand Down
35 changes: 27 additions & 8 deletions src/ConstructiveSolidGeometry/SurfacePrimitives/TorusMantle.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Surface primitive describing the mantle of a [`Torus`](@ref).
* `T`: Precision type.
* `TP`: Type of the azimuthial angle `φ`.
* `TP == Nothing`: Full 2π in `φ`.
* `TP == Tuple{T,T}`: Partial Torus Mantle ranging from `φ[1]` to `φ[2]`.
* `TP == T`: Partial Torus Mantle ranging from `0` to `φ`.
* `TT`: Type of the polar angle `θ`.
* `TT == Nothing`: Full 2π in `θ`.
* `TP == Tuple{T,T}`: Partial Torus Mantle ranging from `θ[1]` to `θ[2]`.
Expand All @@ -22,7 +22,7 @@ Surface primitive describing the mantle of a [`Torus`](@ref).
* `origin::CartesianPoint{T}`: The position of the center of the `TorusMantle`.
* `rotation::SMatrix{3,3,T,9}`: Matrix that describes a rotation of the `TorusMantle` around its `origin`.
"""
@with_kw struct TorusMantle{T,TP,TT,D} <: AbstractCurvedSurfacePrimitive{T}
@with_kw struct TorusMantle{T,TP<:Union{Nothing,T},TT,D} <: AbstractCurvedSurfacePrimitive{T}
r_torus::T = 1
r_tube::T = 1
φ::TP = nothing
Expand All @@ -35,7 +35,7 @@ end
flip(t::TorusMantle{T,TP,TT,:inwards}) where {T,TP,TT} =
TorusMantle{T,TP,TT,:outwards}(t.r_torus, t.r_tube, t.φ, t.θ, t.origin, t.rotation )

get_φ_limits(tm::TorusMantle{T,Tuple{T,T}}) where {T} = tm.φ[1], tm.φ[2]
get_φ_limits(tm::TorusMantle{T,T}) where {T} = T(0), tm.φ
get_φ_limits(tm::TorusMantle{T,Nothing}) where {T} = T(0), T(2π)

get_θ_limits(tm::TorusMantle{T,<:Any,Tuple{T,T}}) where {T} = tm.θ[1], tm.θ[2]
Expand Down Expand Up @@ -90,9 +90,9 @@ get_label_name(::TorusMantle) = "Torus Mantle"

const FullTorusMantle{T,D} = TorusMantle{T,Nothing,Nothing,D}
const FullPhiTorusMantle{T,D} = TorusMantle{T,Nothing,Tuple{T,T},D}
const FullThetaTorusMantle{T,D} = TorusMantle{T,Tuple{T,T},Nothing,D}
const FullThetaTorusMantle{T,D} = TorusMantle{T,T,Nothing,D}

function lines(tm::TorusMantle{T,TP,TT}) where {T,TP,TT}
function lines(tm::TorusMantle{T,TP,Nothing}) where {T,TP}
top_circ_origin = CartesianPoint{T}(zero(T), zero(T), tm.r_tube)
top_circ_origin = _transform_into_global_coordinate_system(top_circ_origin, tm)
top_circ = Ellipse{T,T,TP}(r = tm.r_torus, φ = tm.φ, origin = top_circ_origin, rotation = tm.rotation)
Expand All @@ -104,10 +104,29 @@ function lines(tm::TorusMantle{T,TP,TT}) where {T,TP,TT}
φmin::T, φmax::T = isnothing(tm.φ) ? (0, π) : get_φ_limits(tm)
tube_circ_1_origin = CartesianPoint(CylindricalPoint{T}(tm.r_torus, φmin, zero(T)))
tube_circ_1_origin = _transform_into_global_coordinate_system(tube_circ_1_origin, tm)
tube_circ_1 = Ellipse{T,T,TT}(r = tm.r_tube, φ = tm.θ, origin = tube_circ_1_origin, rotation = tm.rotation * RotZ(φmin) *RotX(T(π)/2))
tube_circ_1 = Ellipse{T,T,Nothing}(r = tm.r_tube, φ = tm.θ, origin = tube_circ_1_origin, rotation = tm.rotation * RotZ(φmin) * RotX(T(π)/2))
tube_circ_2_origin = CartesianPoint(CylindricalPoint{T}(tm.r_torus, φmax, zero(T)))
tube_circ_2_origin = _transform_into_global_coordinate_system(tube_circ_2_origin, tm)
tube_circ_2 = Ellipse{T,T,TT}(r = tm.r_tube, φ = tm.θ, origin = tube_circ_2_origin, rotation = tm.rotation * RotZ(φmax) * RotX(T(π)/2))
tube_circ_2 = Ellipse{T,T,Nothing}(r = tm.r_tube, φ = tm.θ, origin = tube_circ_2_origin, rotation = tm.rotation * RotZ(φmax) * RotX(T(π)/2))
(bot_circ, outer_circ, top_circ, inner_circ, tube_circ_1, tube_circ_2)
end

function lines(tm::TorusMantle{T,TP,Tuple{T,T}}) where {T,TP}
top_circ_origin = CartesianPoint{T}(zero(T), zero(T), tm.r_tube)
top_circ_origin = _transform_into_global_coordinate_system(top_circ_origin, tm)
top_circ = Ellipse{T,T,TP}(r = tm.r_torus, φ = tm.φ, origin = top_circ_origin, rotation = tm.rotation)
bot_circ_origin = CartesianPoint{T}(zero(T), zero(T), -tm.r_tube)
bot_circ_origin = _transform_into_global_coordinate_system(bot_circ_origin, tm)
bot_circ = Ellipse{T,T,TP}(r = tm.r_torus, φ = tm.φ, origin = bot_circ_origin, rotation = tm.rotation)
inner_circ = Ellipse{T,T,TP}(r = tm.r_torus - tm.r_tube, φ = tm.φ, origin = tm.origin, rotation = tm.rotation)
outer_circ = Ellipse{T,T,TP}(r = tm.r_torus + tm.r_tube, φ = tm.φ, origin = tm.origin, rotation = tm.rotation)
φmin::T, φmax::T = isnothing(tm.φ) ? (0, π) : get_φ_limits(tm)
tube_circ_1_origin = CartesianPoint(CylindricalPoint{T}(tm.r_torus, φmin, zero(T)))
tube_circ_1_origin = _transform_into_global_coordinate_system(tube_circ_1_origin, tm)
tube_circ_1 = Ellipse{T,T,T}(r = tm.r_tube, φ = abs(-(tm.θ...)), origin = tube_circ_1_origin, rotation = tm.rotation * RotZ(φmin) * RotX(T(π)/2) * RotZ(tm.θ[1]))
tube_circ_2_origin = CartesianPoint(CylindricalPoint{T}(tm.r_torus, φmax, zero(T)))
tube_circ_2_origin = _transform_into_global_coordinate_system(tube_circ_2_origin, tm)
tube_circ_2 = Ellipse{T,T,T}(r = tm.r_tube, φ = abs(-(tm.θ...)), origin = tube_circ_2_origin, rotation = tm.rotation * RotZ(φmax) * RotX(T(π)/2) * RotZ(tm.θ[1]))
(bot_circ, outer_circ, top_circ, inner_circ, tube_circ_1, tube_circ_2)
end

Expand Down Expand Up @@ -169,7 +188,7 @@ end
TorusThetaSurface(r::T, φ::TP, hZ::T, origin::CartesianPoint{T}, rotation::SMatrix{3,3,T,9}, ::Val{:flat}) where {T,TP} = EllipticalSurface{T,T,TP}(r,φ,origin,rotation)
TorusThetaSurface(r::T, φ::TP, hZ::T, origin::CartesianPoint{T}, rotation::SMatrix{3,3,T,9}, ::Val{:inwards}) where {T,TP} = ConeMantle{T,T,TP,:inwards}(r,φ,abs(hZ),origin,rotation)
TorusThetaSurface(r::T, φ::TP, hZ::T, origin::CartesianPoint{T}, rotation::SMatrix{3,3,T,9}, ::Val{:outwards}) where {T,TP} = ConeMantle{T,T,TP,:outwards}(r,φ,abs(hZ),origin,rotation)
TorusThetaSurface(r::Tuple{T,T}, φ::TP, hZ::T, origin::CartesianPoint{T}, rotation::SMatrix{3,3,T,9}, ::Val{:flat}) where {T,TP} = EllipticalSurface{T,Tuple{T,T},TP}(ordered(r),φ,origin,rotation)
TorusThetaSurface(r::Tuple{T,T}, φ::TP, hZ::T, origin::CartesianPoint{T}, rotation::SMatrix{3,3,T,9}, ::Val{:flat}) where {T,TP} = EllipticalSurface{T,Tuple{T,T},TP}(ordered(r...),φ,origin,rotation)
TorusThetaSurface(r::Tuple{T,T}, φ::TP, hZ::T, origin::CartesianPoint{T}, rotation::SMatrix{3,3,T,9}, ::Val{:inwards}) where {T,TP} = ConeMantle{T,Tuple{T,T},TP,:inwards}(hZ < 0 ? reverse(r) : r, φ, abs(hZ), origin, rotation)
TorusThetaSurface(r::Tuple{T,T}, φ::TP, hZ::T, origin::CartesianPoint{T}, rotation::SMatrix{3,3,T,9}, ::Val{:outwards}) where {T,TP} = ConeMantle{T,Tuple{T,T},TP,:outwards}(hZ < 0 ? reverse(r) : r, φ, abs(hZ), origin, rotation)

Expand Down
Loading

0 comments on commit 5d3dc11

Please sign in to comment.