From 1a801507de7932568b812b5b98d48745e7874eb6 Mon Sep 17 00:00:00 2001 From: Felix Hagemann <30291312+fhagemann@users.noreply.github.com> Date: Wed, 3 Nov 2021 00:23:31 +0100 Subject: [PATCH 01/10] =?UTF-8?q?Add=20interval=20methods=20for=20`=CF=86`?= =?UTF-8?q?=20being=20a=20number?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ConstructiveSolidGeometry/Intervals.jl | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/ConstructiveSolidGeometry/Intervals.jl b/src/ConstructiveSolidGeometry/Intervals.jl index d12c203c0..463a72c47 100644 --- a/src/ConstructiveSolidGeometry/Intervals.jl +++ b/src/ConstructiveSolidGeometry/Intervals.jl @@ -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) \ No newline at end of file +# @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) \ No newline at end of file From b421fbb4f4d2a2ab82982d34140a46aa8d89060a Mon Sep 17 00:00:00 2001 From: Felix Hagemann <30291312+fhagemann@users.noreply.github.com> Date: Wed, 3 Nov 2021 00:23:55 +0100 Subject: [PATCH 02/10] =?UTF-8?q?Update=20`Cone`:=20`=CF=86::Tuple{T,T}`?= =?UTF-8?q?=20=3D>=20`=CF=86::T`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../VolumePrimitives/Cone.jl | 168 +++++++++--------- 1 file changed, 88 insertions(+), 80 deletions(-) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl index 45c96aeaf..cbfce61af 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl @@ -18,7 +18,7 @@ being aligned with the `xy` plane (before possible rotations). * `TR == Tuple{Tuple{T, T}, Nothing}`: Cone (Tip at the top, bottom is a circular base with inner radius `r[1][1]` and outer radius `r[1][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 Cone ranging from `0` to `φ`. ## Fields * `r::TR`: Definition of the radius of the `Cone` (in m). @@ -61,7 +61,7 @@ cone: to: 4.0 # => r = ((1.0, 2.0), (1.0, 4.0)) phi: from: 0.0° - to: 180.0° # => φ = (0, π) + to: 180.0° # => φ = π h: 2.0 # => hZ = 1.0 ``` This is half a Cone (`φ` goes from 0 to 180°, i.e. only positive `y` are allowed) @@ -73,7 +73,7 @@ from 2 at the bottom to 4 at the top circular base. See also [Constructive Solid Geometry (CSG)](@ref). """ -@with_kw struct Cone{T,CO,TR,TP} <: AbstractVolumePrimitive{T, CO} +@with_kw struct Cone{T,CO,TR,TP<:Union{Nothing,T}} <: AbstractVolumePrimitive{T, CO} r::TR = 1 φ::TP = nothing hZ::T = 1 @@ -84,7 +84,7 @@ end Cone{T,CO,TR,TP}( c::Cone{T,CO,TR,TP}; COT = CO, origin::CartesianPoint{T} = c.origin, - rotation::SMatrix{3,3,T,9} = c.rotation) where {T,CO<:Union{ClosedPrimitive, OpenPrimitive},TR,TP} = + rotation::SMatrix{3,3,T,9} = c.rotation) where {T,CO<:Union{ClosedPrimitive, OpenPrimitive},TR,TP<:Union{Nothing,T}} = Cone{T,COT,TR,TP}(c.r, c.φ, c.hZ, origin, rotation) #################################################################### @@ -100,7 +100,7 @@ ___| =# const Cylinder{T,CO} = Cone{T,CO,T,Nothing} # Full in φ -const PartialCylinder{T,CO} = Cone{T,CO,T,Tuple{T,T}} +const PartialCylinder{T,CO} = Cone{T,CO,T,T} ### Cylinder @@ -119,7 +119,7 @@ end function surfaces(t::Cylinder{T}) where {T} bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) - mantle = ConeMantle{T,Tuple{T,T},Nothing,:inwards}((t.r, t.r), t.φ, t.hZ, t.origin, t.rotation) + mantle = FullConeMantle{T,:inwards}((t.r, t.r), t.φ, t.hZ, t.origin, t.rotation) e_bot = CircularArea{T}(r = t.r, φ = t.φ, origin = bot_center_pt, rotation = t.rotation) e_top = CircularArea{T}(r = t.r, φ = t.φ, origin = top_center_pt, rotation = -t.rotation * RotZ{T}(π)) # normals of the surfaces show inside the volume primitives. @@ -151,15 +151,15 @@ function surfaces(t::PartialCylinder{T}) where {T} e_bot = PartialCircularArea{T}(r = t.r, φ = t.φ, origin = bot_center_pt, rotation = t.rotation) e_top = PartialCircularArea{T}(r = t.r, φ = t.φ, origin = top_center_pt, rotation = -t.rotation * RotZ{T}(π)) poly_l = _transform_into_global_coordinate_system(Quadrangle{T}(( - CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[1], -t.hZ)), - CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[1], +t.hZ)), - CartesianPoint(CylindricalPoint{T}( t.r, t.φ[1], +t.hZ)), - CartesianPoint(CylindricalPoint{T}( t.r, t.φ[1], -t.hZ)) )), t) + CartesianPoint(CylindricalPoint{T}(zero(T), zero(T), -t.hZ)), + CartesianPoint(CylindricalPoint{T}(zero(T), zero(T), +t.hZ)), + CartesianPoint(CylindricalPoint{T}( t.r, zero(T), +t.hZ)), + CartesianPoint(CylindricalPoint{T}( t.r, zero(T), -t.hZ)) )), t) poly_r = _transform_into_global_coordinate_system(Quadrangle{T}(( - CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[2], -t.hZ)), - CartesianPoint(CylindricalPoint{T}( t.r, t.φ[2], -t.hZ)), - CartesianPoint(CylindricalPoint{T}( t.r, t.φ[2], +t.hZ)), - CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[2], +t.hZ)) )), t) + CartesianPoint(CylindricalPoint{T}(zero(T), t.φ, -t.hZ)), + CartesianPoint(CylindricalPoint{T}( t.r, t.φ, -t.hZ)), + CartesianPoint(CylindricalPoint{T}( t.r, t.φ, +t.hZ)), + CartesianPoint(CylindricalPoint{T}(zero(T), t.φ, +t.hZ)) )), t) # normals of the surfaces show inside the volume primitives. (e_top, e_bot, mantle, poly_l, poly_r) end @@ -175,7 +175,7 @@ _____\ =# const VaryingCylinder{T,CO} = Cone{T,CO,Tuple{Tuple{T},Tuple{T}},Nothing} # Full in φ -const PartialVaryingCylinder{T,CO} = Cone{T,CO,Tuple{Tuple{T},Tuple{T}},Tuple{T,T}} +const PartialVaryingCylinder{T,CO} = Cone{T,CO,Tuple{Tuple{T},Tuple{T}},T} function _in(pt::CartesianPoint, c::VaryingCylinder{T,ClosedPrimitive}; csgtol::T = csg_default_tol(T)) where {T} az = abs(pt.z) @@ -193,7 +193,7 @@ end function surfaces(t::VaryingCylinder{T}) where {T} bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) - mantle = ConeMantle{T,Tuple{T,T},Nothing,:inwards}((t.r[1][1], t.r[2][1]), t.φ, t.hZ, t.origin, t.rotation) + mantle = FullConeMantle{T,:inwards}((t.r[1][1], t.r[2][1]), t.φ, t.hZ, t.origin, t.rotation) e_bot = CircularArea{T}(r = t.r[1][1], φ = t.φ, origin = bot_center_pt, rotation = t.rotation) e_top = CircularArea{T}(r = t.r[2][1], φ = t.φ, origin = top_center_pt, rotation = -t.rotation * RotZ{T}(π)) # normals of the surfaces show inside the volume primitives. @@ -220,19 +220,19 @@ end function surfaces(t::PartialVaryingCylinder{T}) where {T} bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) - mantle = ConeMantle{T,Tuple{T,T},Tuple{T,T},:inwards}((t.r[1][1], t.r[2][1]), t.φ, t.hZ, t.origin, t.rotation) + mantle = PartialConeMantle{T,:inwards}((t.r[1][1], t.r[2][1]), t.φ, t.hZ, t.origin, t.rotation) e_bot = PartialCircularArea{T}(r = t.r[1][1], φ = t.φ, origin = bot_center_pt, rotation = t.rotation) e_top = PartialCircularArea{T}(r = t.r[2][1], φ = t.φ, origin = top_center_pt, rotation = -t.rotation * RotZ{T}(π)) poly_l = _transform_into_global_coordinate_system(Quadrangle{T}(( - CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[1], -t.hZ)), - CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[1], +t.hZ)), - CartesianPoint(CylindricalPoint{T}( t.r[2][1], t.φ[1], +t.hZ)), - CartesianPoint(CylindricalPoint{T}( t.r[1][1], t.φ[1], -t.hZ)) )), t) + CartesianPoint(CylindricalPoint{T}(zero(T), zero(T), -t.hZ)), + CartesianPoint(CylindricalPoint{T}(zero(T), zero(T), +t.hZ)), + CartesianPoint(CylindricalPoint{T}( t.r[2][1], zero(T), +t.hZ)), + CartesianPoint(CylindricalPoint{T}( t.r[1][1], zero(T), -t.hZ)) )), t) poly_r = _transform_into_global_coordinate_system(Quadrangle{T}(( - CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[2], -t.hZ)), - CartesianPoint(CylindricalPoint{T}( t.r[1][1], t.φ[2], -t.hZ)), - CartesianPoint(CylindricalPoint{T}( t.r[2][1], t.φ[2], +t.hZ)), - CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[2], +t.hZ)) )), t) + CartesianPoint(CylindricalPoint{T}(zero(T), t.φ, -t.hZ)), + CartesianPoint(CylindricalPoint{T}( t.r[1][1], t.φ, -t.hZ)), + CartesianPoint(CylindricalPoint{T}( t.r[2][1], t.φ, +t.hZ)), + CartesianPoint(CylindricalPoint{T}(zero(T), t.φ, +t.hZ)) )), t) # normals of the surfaces show inside the volume primitives. e_top, e_bot, mantle, poly_l, poly_r end @@ -249,7 +249,7 @@ end =# const VaryingTube{T,CO} = Cone{T,CO,Tuple{Tuple{T,T},Tuple{T,T}},Nothing} # Full in φ -const PartialVaryingTube{T,CO} = Cone{T,CO,Tuple{Tuple{T,T},Tuple{T,T}},Tuple{T,T}} +const PartialVaryingTube{T,CO} = Cone{T,CO,Tuple{Tuple{T,T},Tuple{T,T}},T} #(r_bot_in = r[1][1], r_bot_out = r[1][2], r_top_in = r[2][1], r_top_out = r[2][2]) @@ -271,8 +271,8 @@ end function surfaces(t::VaryingTube{T}) where {T} bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) - inner_mantle = ConeMantle{T,Tuple{T,T},Nothing,:outwards}((t.r[1][1], t.r[2][1]), t.φ, t.hZ, t.origin, t.rotation) - outer_mantle = ConeMantle{T,Tuple{T,T},Nothing,:inwards}( (t.r[1][2], t.r[2][2]), t.φ, t.hZ, t.origin, t.rotation) + inner_mantle = FullConeMantle{T,:outwards}((t.r[1][1], t.r[2][1]), t.φ, t.hZ, t.origin, t.rotation) + outer_mantle = FullConeMantle{T,:inwards}( (t.r[1][2], t.r[2][2]), t.φ, t.hZ, t.origin, t.rotation) e_bot = Annulus{T}(r = (t.r[1][1], t.r[1][2]), φ = t.φ, origin = bot_center_pt, rotation = t.rotation) e_top = Annulus{T}(r = (t.r[2][1], t.r[2][2]), φ = t.φ, origin = top_center_pt, rotation = -t.rotation * RotZ{T}(π)) # normals of the surfaces show inside the volume primitives. @@ -301,20 +301,20 @@ end function surfaces(t::PartialVaryingTube{T}) where {T} bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) - inner_mantle = ConeMantle{T,Tuple{T,T},Tuple{T,T},:outwards}((t.r[1][1], t.r[2][1]), t.φ, t.hZ, t.origin, t.rotation) - outer_mantle = ConeMantle{T,Tuple{T,T},Tuple{T,T},:inwards}( (t.r[1][2], t.r[2][2]), t.φ, t.hZ, t.origin, t.rotation) + inner_mantle = PartialConeMantle{T,:outwards}((t.r[1][1], t.r[2][1]), t.φ, t.hZ, t.origin, t.rotation) + outer_mantle = PartialConeMantle{T,:inwards}( (t.r[1][2], t.r[2][2]), t.φ, t.hZ, t.origin, t.rotation) e_bot = PartialAnnulus{T}(r = (t.r[1][1], t.r[1][2]), φ = t.φ, origin = bot_center_pt, rotation = t.rotation) e_top = PartialAnnulus{T}(r = (t.r[2][1], t.r[2][2]), φ = t.φ, origin = top_center_pt, rotation = -t.rotation * RotZ{T}(π)) poly_l = _transform_into_global_coordinate_system(Quadrangle{T}(( - CartesianPoint(CylindricalPoint{T}(t.r[1][1], t.φ[1], -t.hZ)), - CartesianPoint(CylindricalPoint{T}(t.r[2][1], t.φ[1], +t.hZ)), - CartesianPoint(CylindricalPoint{T}(t.r[2][2], t.φ[1], +t.hZ)), - CartesianPoint(CylindricalPoint{T}(t.r[1][2], t.φ[1], -t.hZ)) )), t) + CartesianPoint(CylindricalPoint{T}(t.r[1][1], zero(T), -t.hZ)), + CartesianPoint(CylindricalPoint{T}(t.r[2][1], zero(T), +t.hZ)), + CartesianPoint(CylindricalPoint{T}(t.r[2][2], zero(T), +t.hZ)), + CartesianPoint(CylindricalPoint{T}(t.r[1][2], zero(T), -t.hZ)) )), t) poly_r = _transform_into_global_coordinate_system(Quadrangle{T}(( - CartesianPoint(CylindricalPoint{T}(t.r[1][1], t.φ[2], -t.hZ)), - CartesianPoint(CylindricalPoint{T}(t.r[1][2], t.φ[2], -t.hZ)), - CartesianPoint(CylindricalPoint{T}(t.r[2][2], t.φ[2], +t.hZ)), - CartesianPoint(CylindricalPoint{T}(t.r[2][1], t.φ[2], +t.hZ)) )), t) + CartesianPoint(CylindricalPoint{T}(t.r[1][1], t.φ, -t.hZ)), + CartesianPoint(CylindricalPoint{T}(t.r[1][2], t.φ, -t.hZ)), + CartesianPoint(CylindricalPoint{T}(t.r[2][2], t.φ, +t.hZ)), + CartesianPoint(CylindricalPoint{T}(t.r[2][1], t.φ, +t.hZ)) )), t) # normals of the surfaces show inside the volume primitives. e_top, e_bot, inner_mantle, outer_mantle, poly_l, poly_r end @@ -330,7 +330,7 @@ __\ =# const UpwardCone{T,CO} = Cone{T,CO,Tuple{Tuple{Nothing,T},Nothing},Nothing} # Full in φ -const PartialUpwardCone{T,CO} = Cone{T,CO,Tuple{Tuple{Nothing,T},Nothing},Tuple{T,T}} +const PartialUpwardCone{T,CO} = Cone{T,CO,Tuple{Tuple{Nothing,T},Nothing},T} function _in(pt::CartesianPoint, c::UpwardCone{T,ClosedPrimitive}; csgtol::T = csg_default_tol(T)) where {T} az = abs(pt.z) @@ -347,7 +347,7 @@ end function surfaces(t::UpwardCone{T}) where {T} bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) - outer_mantle = ConeMantle{T,Tuple{T,T},Nothing,:inwards}( (t.r[1][2], zero(T)), t.φ, t.hZ, t.origin, t.rotation) + outer_mantle = FullConeMantle{T,:inwards}( (t.r[1][2], zero(T)), t.φ, t.hZ, t.origin, t.rotation) e_bot = CircularArea{T}(r = t.r[1][2], φ = t.φ, origin = bot_center_pt, rotation = t.rotation) # normals of the surfaces show inside the volume primitives. e_bot, outer_mantle @@ -372,16 +372,16 @@ end function surfaces(t::PartialUpwardCone{T}) where {T} bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) - outer_mantle = ConeMantle{T,Tuple{T,T},Tuple{T,T},:inwards}( (t.r[1][2], zero(T)), t.φ, t.hZ, t.origin, t.rotation) + outer_mantle = PartialConeMantle{T,:inwards}( (t.r[1][2], zero(T)), t.φ, t.hZ, t.origin, t.rotation) e_bot = PartialCircularArea{T}(r = t.r[1][2], φ = t.φ, origin = bot_center_pt, rotation = t.rotation) poly_l = _transform_into_global_coordinate_system(Triangle{T}(( - CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[1], -t.hZ)), - CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[1], +t.hZ)), - CartesianPoint(CylindricalPoint{T}(t.r[1][2], t.φ[1], -t.hZ)) )), t) + CartesianPoint(CylindricalPoint{T}(zero(T), zero(T), -t.hZ)), + CartesianPoint(CylindricalPoint{T}(zero(T), zero(T), +t.hZ)), + CartesianPoint(CylindricalPoint{T}(t.r[1][2], zero(T), -t.hZ)) )), t) poly_r = _transform_into_global_coordinate_system(Triangle{T}(( - CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[2], -t.hZ)), - CartesianPoint(CylindricalPoint{T}(t.r[1][2], t.φ[2], -t.hZ)), - CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[2], +t.hZ)) )), t) + CartesianPoint(CylindricalPoint{T}(zero(T), t.φ, -t.hZ)), + CartesianPoint(CylindricalPoint{T}(t.r[1][2], t.φ, -t.hZ)), + CartesianPoint(CylindricalPoint{T}(zero(T), t.φ, +t.hZ)) )), t) # normals of the surfaces show inside the volume primitives. e_bot, outer_mantle, poly_l, poly_r end @@ -398,7 +398,7 @@ ___ =# const DownwardCone{T,CO} = Cone{T,CO,Tuple{Nothing,Tuple{Nothing,T}},Nothing} # Full in φ -const PartialDownwardCone{T,CO} = Cone{T,CO,Tuple{Nothing,Tuple{Nothing,T}},Tuple{T,T}} +const PartialDownwardCone{T,CO} = Cone{T,CO,Tuple{Nothing,Tuple{Nothing,T}},T} function _in(pt::CartesianPoint, c::DownwardCone{T,ClosedPrimitive}; csgtol::T = csg_default_tol(T)) where {T} @@ -416,7 +416,7 @@ end function surfaces(t::DownwardCone{T}) where {T} top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) - outer_mantle = ConeMantle{T,Tuple{T,T},Nothing,:inwards}( (zero(T), t.r[2][2]), t.φ, t.hZ, t.origin, t.rotation) + outer_mantle = FullConeMantle{T,:inwards}( (zero(T), t.r[2][2]), t.φ, t.hZ, t.origin, t.rotation) e_top = CircularArea{T}(r = t.r[2][2], φ = t.φ, origin = top_center_pt, rotation = -t.rotation * RotZ{T}(π)) # normals of the surfaces show inside the volume primitives. e_top, outer_mantle @@ -441,16 +441,16 @@ end function surfaces(t::PartialDownwardCone{T}) where {T} bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) - outer_mantle = ConeMantle{T,Tuple{T,T},Tuple{T,T},:inwards}( (t.r[2][2], zero(T)), t.φ, t.hZ, t.origin, t.rotation) + outer_mantle = PartialConeMantle{T,:inwards}( (t.r[2][2], zero(T)), t.φ, t.hZ, t.origin, t.rotation) e_bot = PartialCircularArea{T}(r = t.r[2][2], φ = t.φ, origin = bot_center_pt, rotation = t.rotation) poly_l = _transform_into_global_coordinate_system(Triangle{T}(( - CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[1], -t.hZ)), - CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[1], +t.hZ)), - CartesianPoint(CylindricalPoint{T}(t.r[2][2], t.φ[1], -t.hZ)) )), t) + CartesianPoint(CylindricalPoint{T}(zero(T), zero(T), -t.hZ)), + CartesianPoint(CylindricalPoint{T}(zero(T), zero(T), +t.hZ)), + CartesianPoint(CylindricalPoint{T}(t.r[2][2], zero(T), -t.hZ)) )), t) poly_r = _transform_into_global_coordinate_system(Triangle{T}(( - CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[2], -t.hZ)), - CartesianPoint(CylindricalPoint{T}(t.r[2][2], t.φ[2], -t.hZ)), - CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[2], +t.hZ)) )), t) + CartesianPoint(CylindricalPoint{T}(zero(T), t.φ, -t.hZ)), + CartesianPoint(CylindricalPoint{T}(t.r[2][2], t.φ, -t.hZ)), + CartesianPoint(CylindricalPoint{T}(zero(T), t.φ, +t.hZ)) )), t) # normals of the surfaces show inside the volume primitives. e_bot, outer_mantle, poly_l, poly_r end @@ -468,7 +468,7 @@ end =# const TopClosedTube{T,CO} = Cone{T,CO,Tuple{Tuple{T,T},T},Nothing} # Full in φ -const PartialTopClosedTube{T,CO} = Cone{T,CO,Tuple{Tuple{T,T},T},Tuple{T,T}} +const PartialTopClosedTube{T,CO} = Cone{T,CO,Tuple{Tuple{T,T},T},T} function _in(pt::CartesianPoint, c::TopClosedTube{T,ClosedPrimitive}; csgtol::T = csg_default_tol(T)) where {T} @@ -489,8 +489,8 @@ end function surfaces(t::TopClosedTube{T}) where {T} bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) # top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) - inner_mantle = ConeMantle{T,Tuple{T,T},Nothing,:outwards}((t.r[1][1], t.r[2]), t.φ, t.hZ, t.origin, t.rotation) - outer_mantle = ConeMantle{T,Tuple{T,T},Nothing,:inwards}( (t.r[1][2], t.r[2]), t.φ, t.hZ, t.origin, t.rotation) + inner_mantle = FullConeMantle{T,:outwards}((t.r[1][1], t.r[2]), t.φ, t.hZ, t.origin, t.rotation) + outer_mantle = FullConeMantle{T,:inwards}( (t.r[1][2], t.r[2]), t.φ, t.hZ, t.origin, t.rotation) e_bot = Annulus{T}(r = (t.r[1][1], t.r[1][2]), φ = t.φ, origin = bot_center_pt, rotation = t.rotation) # e_top = Annulus{T}(r = (t.r[2][1], t.r[2][2]), φ = t.φ, origin = top_center_pt, rotation = -t.rotation * RotZ{T}(π)) # normals of the surfaces show inside the volume primitives. @@ -519,18 +519,18 @@ end function surfaces(t::PartialTopClosedTube{T}) where {T} bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) # top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) - inner_mantle = ConeMantle{T,Tuple{T,T},Tuple{T,T},:outwards}((t.r[1][1], t.r[2]), t.φ, t.hZ, t.origin, t.rotation) - outer_mantle = ConeMantle{T,Tuple{T,T},Tuple{T,T},:inwards}( (t.r[1][2], t.r[2]), t.φ, t.hZ, t.origin, t.rotation) + inner_mantle = PartialConeMantle{T,:outwards}((t.r[1][1], t.r[2]), t.φ, t.hZ, t.origin, t.rotation) + outer_mantle = PartialConeMantle{T,:inwards}( (t.r[1][2], t.r[2]), t.φ, t.hZ, t.origin, t.rotation) e_bot = PartialAnnulus{T}(r = (t.r[1][1], t.r[1][2]), φ = t.φ, origin = bot_center_pt, rotation = t.rotation) # e_top = Annulus{T}(r = (t.r[2][1], t.r[2][2]), φ = t.φ, origin = top_center_pt, rotation = -t.rotation * RotZ{T}(π)) poly_l = _transform_into_global_coordinate_system(Triangle{T}(( - CartesianPoint(CylindricalPoint{T}(t.r[1][1], t.φ[1], -t.hZ)), - CartesianPoint(CylindricalPoint{T}( t.r[2], t.φ[1], +t.hZ)), - CartesianPoint(CylindricalPoint{T}(t.r[1][2], t.φ[1], -t.hZ)) )), t) + CartesianPoint(CylindricalPoint{T}(t.r[1][1], zero(T), -t.hZ)), + CartesianPoint(CylindricalPoint{T}( t.r[2], zero(T), +t.hZ)), + CartesianPoint(CylindricalPoint{T}(t.r[1][2], zero(T), -t.hZ)) )), t) poly_r = _transform_into_global_coordinate_system(Triangle{T}(( - CartesianPoint(CylindricalPoint{T}(t.r[1][1], t.φ[2], -t.hZ)), - CartesianPoint(CylindricalPoint{T}(t.r[1][2], t.φ[2], -t.hZ)), - CartesianPoint(CylindricalPoint{T}( t.r[2], t.φ[2], +t.hZ)) )), t) + CartesianPoint(CylindricalPoint{T}(t.r[1][1], t.φ, -t.hZ)), + CartesianPoint(CylindricalPoint{T}(t.r[1][2], t.φ, -t.hZ)), + CartesianPoint(CylindricalPoint{T}( t.r[2], t.φ, +t.hZ)) )), t) # normals of the surfaces show inside the volume primitives. e_bot, inner_mantle, outer_mantle, poly_l, poly_r end @@ -549,7 +549,7 @@ ______ =# const BottomClosedTube{T,CO} = Cone{T,CO,Tuple{T,Tuple{T,T}},Nothing} # Full in φ -const PartialBottomClosedTube{T,CO} = Cone{T,CO,Tuple{T,Tuple{T,T}},Tuple{T,T}} +const PartialBottomClosedTube{T,CO} = Cone{T,CO,Tuple{T,Tuple{T,T}},T} function _in(pt::CartesianPoint, c::BottomClosedTube{T,ClosedPrimitive}; csgtol::T = csg_default_tol(T)) where {T} @@ -570,8 +570,8 @@ end function surfaces(t::BottomClosedTube{T}) where {T} # bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) - inner_mantle = ConeMantle{T,Tuple{T,T},Nothing,:outwards}((t.r[1], t.r[2][1]), t.φ, t.hZ, t.origin, t.rotation) - outer_mantle = ConeMantle{T,Tuple{T,T},Nothing,:inwards}( (t.r[1], t.r[2][2]), t.φ, t.hZ, t.origin, t.rotation) + inner_mantle = FullConeMantle{T,:outwards}((t.r[1], t.r[2][1]), t.φ, t.hZ, t.origin, t.rotation) + outer_mantle = FullConeMantle{T,:inwards}( (t.r[1], t.r[2][2]), t.φ, t.hZ, t.origin, t.rotation) # e_bot = Annulus{T}(r = (t.r[1][1], t.r[1][2]), φ = t.φ, origin = bot_center_pt, rotation = t.rotation) e_top = Annulus{T}(r = (t.r[2][1], t.r[2][2]), φ = t.φ, origin = top_center_pt, rotation = -t.rotation * RotZ{T}(π)) # normals of the surfaces show inside the volume primitives. @@ -600,18 +600,18 @@ end function surfaces(t::PartialBottomClosedTube{T}) where {T} # bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) - inner_mantle = ConeMantle{T,Tuple{T,T},Tuple{T,T},:outwards}((t.r[1], t.r[2][1]), t.φ, t.hZ, t.origin, t.rotation) - outer_mantle = ConeMantle{T,Tuple{T,T},Tuple{T,T},:inwards}( (t.r[1], t.r[2][2]), t.φ, t.hZ, t.origin, t.rotation) + inner_mantle = PartialConeMantle{T,:outwards}((t.r[1], t.r[2][1]), t.φ, t.hZ, t.origin, t.rotation) + outer_mantle = PartialConeMantle{T,:inwards}( (t.r[1], t.r[2][2]), t.φ, t.hZ, t.origin, t.rotation) # e_bot = PartialAnnulus{T}(r = (t.r[1][1], t.r[1][2]), φ = t.φ, origin = bot_center_pt, rotation = t.rotation) e_top = PartialAnnulus{T}(r = (t.r[2][1], t.r[2][2]), φ = t.φ, origin = top_center_pt, rotation = -t.rotation * RotZ{T}(π)) poly_l = _transform_into_global_coordinate_system(Triangle{T}(( - CartesianPoint(CylindricalPoint{T}(t.r[2][1], t.φ[1], +t.hZ)), - CartesianPoint(CylindricalPoint{T}(t.r[2][2], t.φ[1], +t.hZ)), - CartesianPoint(CylindricalPoint{T}( t.r[1], t.φ[1], -t.hZ)) )), t) + CartesianPoint(CylindricalPoint{T}(t.r[2][1], zero(T), +t.hZ)), + CartesianPoint(CylindricalPoint{T}(t.r[2][2], zero(T), +t.hZ)), + CartesianPoint(CylindricalPoint{T}( t.r[1], zero(T), -t.hZ)) )), t) poly_r = _transform_into_global_coordinate_system(Triangle{T}(( - CartesianPoint(CylindricalPoint{T}(t.r[2][1], t.φ[2], +t.hZ)), - CartesianPoint(CylindricalPoint{T}( t.r[1], t.φ[2], -t.hZ)), - CartesianPoint(CylindricalPoint{T}(t.r[2][2], t.φ[2], +t.hZ)) )), t) + CartesianPoint(CylindricalPoint{T}(t.r[2][1], t.φ, +t.hZ)), + CartesianPoint(CylindricalPoint{T}( t.r[1], t.φ, -t.hZ)), + CartesianPoint(CylindricalPoint{T}(t.r[2][2], t.φ, +t.hZ)) )), t) # normals of the surfaces show inside the volume primitives. e_top, inner_mantle, outer_mantle, poly_l, poly_r end @@ -628,7 +628,15 @@ function Geometry(::Type{T}, t::Type{Cone}, dict::AbstractDict, input_units::Nam rotation = get_rotation(T, dict, angle_unit) r = parse_r_of_primitive(T, dict, length_unit, Cone) - φ = parse_φ_of_primitive(T, dict, angle_unit) + φ_interval = parse_φ_of_primitive(T, dict, angle_unit) + φ = if φ_interval isa Tuple{T,T} + rotation = rotation * RotZ{T}(φ_interval[1]) + φ_interval[2] - φ_interval[1] + elseif isnothing(φ_interval) + nothing + else + throw(ConfigFileError("Error when trying to parse φ from configuration file.")) + end hZ = if haskey(dict, "h") _parse_value(T, dict["h"], length_unit) / 2 @@ -684,7 +692,7 @@ function Dictionary(c::Cone{T, <:Any, TR})::OrderedDict{String, Any} where {T, T OrderedDict{String, Any}("from" => c.r[2][1], "to" => c.r[2][2]) end end - if !isnothing(c.φ) dict["phi"] = OrderedDict("from" => string(c.φ[1])*"rad", "to" => string(c.φ[2])*"rad") end + if !isnothing(c.φ) dict["phi"] = OrderedDict("from" => 0, "to" => string(c.φ)*"rad") end dict["h"] = 2*c.hZ if c.origin != zero(CartesianVector{T}) dict["origin"] = c.origin end if c.rotation != one(SMatrix{3,3,T,9}) dict["rotation"] = Dictionary(c.rotation) end From f45ee99442e23029a76cb79bfd923de030387015 Mon Sep 17 00:00:00 2001 From: Felix Hagemann <30291312+fhagemann@users.noreply.github.com> Date: Wed, 3 Nov 2021 00:52:02 +0100 Subject: [PATCH 03/10] =?UTF-8?q?Update=20`ConeMantle`:=20`=CF=86::Tuple{T?= =?UTF-8?q?,T}`=20=3D>=20`=CF=86::T`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SurfacePrimitives/ConeMantle.jl | 10 +++++----- .../plotting/SurfacePrimitives/ConeMantle.jl | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl index fb99ebd91..c6b20032f 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl @@ -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 @@ -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 @@ -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} @@ -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) @@ -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 diff --git a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/ConeMantle.jl b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/ConeMantle.jl index a56456965..e7712a16b 100644 --- a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/ConeMantle.jl +++ b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/ConeMantle.jl @@ -12,7 +12,7 @@ @series begin label := nothing seriestype := :vector - nφ = cm.φ == nothing ? 0 : (cm.φ[2] + cm.φ[1])/2 + nφ = isnothing(cm.φ) ? 0 : cm.φ/2 T = typeof(cm.hZ) npt_obj = CartesianPoint(CylindricalPoint{T}(radius_at_z(cm, zero(T)), nφ, zero(T))) npt = _transform_into_global_coordinate_system(npt_obj, cm) From 839e24528c9d09daceed208ad6467af6f67e16a3 Mon Sep 17 00:00:00 2001 From: Felix Hagemann <30291312+fhagemann@users.noreply.github.com> Date: Wed, 3 Nov 2021 00:53:00 +0100 Subject: [PATCH 04/10] =?UTF-8?q?Update=20`EllipticalSurface`:=20`=CF=86::?= =?UTF-8?q?Tuple{T,T}`=20=3D>=20`=CF=86::T`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SurfacePrimitives/EllipticalSurface.jl | 18 +++++++++--------- .../SurfacePrimitives/EllipticalSurface.jl | 8 ++++---- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl index 3a62647ba..38c5a300f 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl @@ -10,7 +10,7 @@ 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). @@ -18,7 +18,7 @@ Surface primitive describing circular bases, e.g. the top or bottom base of a [` * `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 @@ -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 * RotZ{T}(T(2π)-es.φ)SMatrix{3,3,T,9}(1,0,0,0,-1,0,0,0,-1)) 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))) @@ -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} @@ -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) @@ -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) diff --git a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/EllipticalSurface.jl b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/EllipticalSurface.jl index e39749044..6aeec321b 100644 --- a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/EllipticalSurface.jl +++ b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/EllipticalSurface.jl @@ -14,13 +14,13 @@ end _plt_area(es::CircularArea{T}) where {T} = π*es.r^2 -_plt_area(es::PartialCircularArea{T}) where {T} = π*es.r^2 / ((es.φ[2]-es.φ[1])/2π) +_plt_area(es::PartialCircularArea{T}) where {T} = π*es.r^2 / (es.φ/2π) _plt_area(es::Annulus{T}) where {T} = π*(es.r[2]^2 - es.r[1]^2) -_plt_area(es::PartialAnnulus{T}) where {T} = π*(es.r[2]^2 - es.r[1]^2) / ((es.φ[2]-es.φ[1])/2π) +_plt_area(es::PartialAnnulus{T}) where {T} = π*(es.r[2]^2 - es.r[1]^2) / (es.φ/2π) _plt_get_start_point_for_normal(es::CircularArea{T}) where {T} = es.origin function _plt_get_start_point_for_normal(es::PartialCircularArea{T}) where {T} - cyl = CylindricalPoint{T}(es.r/2, (es.φ[2]+es.φ[1])/2, zero(T)) + cyl = CylindricalPoint{T}(es.r/2, es.φ/2, zero(T)) _transform_into_global_coordinate_system(CartesianPoint(cyl), es) end function _plt_get_start_point_for_normal(es::Annulus{T}) where {T} @@ -28,6 +28,6 @@ function _plt_get_start_point_for_normal(es::Annulus{T}) where {T} _transform_into_global_coordinate_system(CartesianPoint(cyl), es) end function _plt_get_start_point_for_normal(es::PartialAnnulus{T}) where {T} - cyl = CylindricalPoint{T}((es.r[2]+es.r[1])/2, (es.φ[2]+es.φ[1])/2, zero(T)) + cyl = CylindricalPoint{T}((es.r[2]+es.r[1])/2, es.φ/2, zero(T)) _transform_into_global_coordinate_system(CartesianPoint(cyl), es) end From ad028ba68e4dcc34aa053f2fa5c8fe476492beaf Mon Sep 17 00:00:00 2001 From: Felix Hagemann <30291312+fhagemann@users.noreply.github.com> Date: Wed, 3 Nov 2021 00:53:20 +0100 Subject: [PATCH 05/10] =?UTF-8?q?Update=20`Ellipse`:=20`=CF=86::Tuple{T,T}?= =?UTF-8?q?`=20=3D>=20`=CF=86::T`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl | 6 +++--- .../plotting/LinePrimitives/Ellipse.jl | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl b/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl index a3c873e21..40f420728 100644 --- a/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl +++ b/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl @@ -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 @@ -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...) @@ -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) diff --git a/src/ConstructiveSolidGeometry/plotting/LinePrimitives/Ellipse.jl b/src/ConstructiveSolidGeometry/plotting/LinePrimitives/Ellipse.jl index d9a1dab7f..b3e18d2fc 100644 --- a/src/ConstructiveSolidGeometry/plotting/LinePrimitives/Ellipse.jl +++ b/src/ConstructiveSolidGeometry/plotting/LinePrimitives/Ellipse.jl @@ -4,8 +4,8 @@ function edges(e::Ellipse{T,T,Nothing}; n = 4) where {T} pts = map(p -> _transform_into_global_coordinate_system(p, e), pts) edges = [Edge(pts[i], pts[i+1]) for i in 1:n] end -function edges(e::Ellipse{T,T,Tuple{T,T}}; n = 4) where {T} - φs = range(e.φ[1], stop = e.φ[2], length = n + 1) +function edges(e::Ellipse{T,T,T}; n = 4) where {T} + φs = range(T(0), stop = e.φ, length = n + 1) pts = [CartesianPoint(CylindricalPoint{T}(e.r, φ, zero(T))) for φ in φs] pts = map(p -> _transform_into_global_coordinate_system(p, e), pts) edges = [Edge(pts[i], pts[i+1]) for i in 1:n] From 71102cf03c5b20199469d28a029f048efdb19856 Mon Sep 17 00:00:00 2001 From: Felix Hagemann <30291312+fhagemann@users.noreply.github.com> Date: Wed, 3 Nov 2021 01:09:16 +0100 Subject: [PATCH 06/10] =?UTF-8?q?Update=20`Torus`:=20`=CF=86::Tuple{T,T}`?= =?UTF-8?q?=20=3D>=20`=CF=86::T`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../VolumePrimitives/Torus.jl | 87 ++++++++++--------- 1 file changed, 44 insertions(+), 43 deletions(-) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Torus.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Torus.jl index 7ec27f5dc..0a1d2a19a 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Torus.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Torus.jl @@ -14,7 +14,7 @@ radius around a given origin. * `TR == T`: Full tube without cutout (constant radius `r_tube`). * `TP`: Type of the azimuthial angle `φ`. * `TP == Nothing`: Full 2π in `φ`. - * `TP == Tuple{T,T}`: Partial Torus ranging from `φ[1]` to `φ[2]`. + * `TP == T`: Partial Torus ranging from `0` to `φ`. * `TT`: Type of the polar angle `θ`. * `TT == Nothing`: Full 2π in `θ`. * `TP == Tuple{T,T}`: Partial Torus ranging from `θ[1]` to `θ[2]`. @@ -66,7 +66,7 @@ This is a `Torus` with `r_tube` having an inner radius of 1 and an outer radius See also [Constructive Solid Geometry (CSG)](@ref). """ -@with_kw struct Torus{T,CO,TR,TP,TT,TT1,TT2} <: AbstractVolumePrimitive{T,CO} +@with_kw struct Torus{T,CO,TR,TP<:Union{Nothing,T},TT,TT1,TT2} <: AbstractVolumePrimitive{T,CO} r_torus::T = 1 r_tube::TR = 1 # (r_tube_in, r_tube_out) φ::TP = nothing @@ -78,15 +78,15 @@ end Torus{T,CO,TR,TP,TT,TT1,TT2}( t::Torus{T,CO,TR,TP,TT}; COT = CO, origin::CartesianPoint{T} = t.origin, - rotation::SMatrix{3,3,T,9} = t.rotation) where {T,CO<:Union{ClosedPrimitive, OpenPrimitive},TR,TP,TT,TT1,TT2} = + rotation::SMatrix{3,3,T,9} = t.rotation) where {T,CO<:Union{ClosedPrimitive, OpenPrimitive},TR,TP<:Union{Nothing,T},TT,TT1,TT2} = Torus{T,COT,TR,TP,TT,TT1,TT2}(t.r_torus, t.r_tube, t.φ, t.θ, origin, rotation) const FullTorus{T,CO} = Torus{T,CO,T,Nothing,Nothing,Nothing,Nothing} const FullPhiTorus{T,CO,TT1,TT2} = Torus{T,CO,T,Nothing,Tuple{T,T},TT1,TT2} -const FullThetaTorus{T,CO} = Torus{T,CO,T,Tuple{T,T},Nothing,Nothing,Nothing} +const FullThetaTorus{T,CO} = Torus{T,CO,T,T,Nothing,Nothing,Nothing} const HollowTorus{T,CO} = Torus{T,CO,Tuple{T,T},Nothing,Nothing,Nothing,Nothing} const HollowPhiTorus{T,CO,TT1,TT2} = Torus{T,CO,Tuple{T,T},Nothing,Tuple{T,T},TT1,TT2} -const HollowThetaTorus{T,CO} = Torus{T,CO,Tuple{T,T},Tuple{T,T},Nothing,Nothing,Nothing} +const HollowThetaTorus{T,CO} = Torus{T,CO,Tuple{T,T},T,Nothing,Nothing,Nothing} function _get_conemantle_type(θ::Tuple{T,T})::Tuple{Symbol, Symbol} where {T} @@ -107,7 +107,15 @@ function Geometry(::Type{T}, ::Type{Torus}, dict::AbstractDict, input_units::Nam r_torus = _parse_value(T, dict["r_torus"], length_unit) r_tube = _parse_radial_interval(T, dict["r_tube"], length_unit) r_tube isa Tuple{T,T} && iszero(r_tube[1]) ? r_tube = r_tube[2] : nothing - φ = parse_φ_of_primitive(T, dict, angle_unit) + φ_interval = parse_φ_of_primitive(T, dict, angle_unit) + φ = if φ_interval isa Tuple{T,T} + rotation = rotation * RotZ{T}(φ_interval[1]) + φ_interval[2] - φ_interval[1] + elseif isnothing(φ_interval) + nothing + else + throw(ConfigFileError("Error when trying to parse φ from configuration file.")) + end θ = parse_θ_of_primitive(T, dict, angle_unit) TT1, TT2 = _get_conemantle_type(θ) if haskey(dict, "z") @@ -129,7 +137,7 @@ function Dictionary(t::Torus{T,<:Any,TR})::OrderedDict{String, Any} where {T,TR} dict = OrderedDict{String, Any}() dict["r_torus"] = t.r_torus dict["r_tube"] = TR <: Real ? t.r_tube : OrderedDict{String, Any}("from" => t.r_tube[1], "to" => t.r_tube[2]) - if !isnothing(t.φ) dict["phi"] = OrderedDict("from" => string(t.φ[1])*"rad", "to" => string(t.φ[2])*"rad") end + if !isnothing(t.φ) dict["phi"] = OrderedDict("from" => 0, "to" => string(t.φ)*"rad") end if !isnothing(t.θ) dict["theta"] = OrderedDict("from" => string(t.θ[1])*"rad", "to" => string(t.θ[2])*"rad") end if t.origin != zero(CartesianVector{T}) dict["origin"] = t.origin end if t.rotation != one(SMatrix{3,3,T,9}) dict["rotation"] = Dictionary(t.rotation) end @@ -160,36 +168,33 @@ function surfaces(t::FullPhiTorus{T,OpenPrimitive,TT1,TT2}) where {T,TT1,TT2} end function surfaces(t::FullThetaTorus{T,ClosedPrimitive}) where {T} tm = FullThetaTorusMantle{T,:inwards}(t.r_torus, t.r_tube, t.φ, t.θ, t.origin, t.rotation) - φ1, φ2 = t.φ - es1 = CircularArea{T}(t.r_tube, t.θ, t.origin + t.rotation * CartesianVector{T}(t.r_torus * cos(φ1), t.r_torus * sin(φ1), 0), t.rotation * RotZ(φ1) * RotX(-π/2) ) - es2 = CircularArea{T}(t.r_tube, t.θ, t.origin + t.rotation * CartesianVector{T}(t.r_torus * cos(φ2), t.r_torus * sin(φ2), 0), t.rotation * RotZ(φ2) * RotX(π/2) ) + es1 = CircularArea{T}(t.r_tube, t.θ, t.origin + t.rotation * CartesianVector{T}(t.r_torus, 0, 0), t.rotation * RotX(-π/2) ) + es2 = CircularArea{T}(t.r_tube, t.θ, t.origin + t.rotation * CartesianVector{T}(t.r_torus * cos(t.φ), t.r_torus * sin(t.φ), 0), t.rotation * RotZ(t.φ) * RotX(π/2) ) (tm, es1, es2) end function surfaces(t::FullThetaTorus{T,OpenPrimitive}) where {T} tm = FullThetaTorusMantle{T,:outwards}(t.r_torus, t.r_tube, t.φ, t.θ, t.origin, t.rotation) - φ1, φ2 = t.φ - es1 = CircularArea{T}(t.r_tube, t.θ, t.origin + t.rotation * CartesianVector{T}(t.r_torus * cos(φ1), t.r_torus * sin(φ1), 0), t.rotation * RotZ(φ1) * RotX(π/2) ) - es2 = CircularArea{T}(t.r_tube, t.θ, t.origin + t.rotation * CartesianVector{T}(t.r_torus * cos(φ2), t.r_torus * sin(φ2), 0), t.rotation * RotZ(φ2) * RotX(-π/2) ) + φ1, φ2 = T(0), t.φ + es1 = CircularArea{T}(t.r_tube, t.θ, t.origin + t.rotation * CartesianVector{T}(t.r_torus, 0, 0), t.rotation * RotX(π/2) ) + es2 = CircularArea{T}(t.r_tube, t.θ, t.origin + t.rotation * CartesianVector{T}(t.r_torus * cos(t.φ), t.r_torus * sin(t.φ), 0), t.rotation * RotZ(t.φ) * RotX(-π/2) ) (tm, es1, es2) end -function surfaces(t::Torus{T,ClosedPrimitive,T,Tuple{T,T},Tuple{T,T},TT1,TT2}) where {T,TT1,TT2} - tm = TorusMantle{T,Tuple{T,T},Tuple{T,T},:inwards}(t.r_torus, t.r_tube, t.φ, t.θ, t.origin, t.rotation) +function surfaces(t::Torus{T,ClosedPrimitive,T,T,Tuple{T,T},TT1,TT2}) where {T,TT1,TT2} + tm = TorusMantle{T,T,Tuple{T,T},:inwards}(t.r_torus, t.r_tube, t.φ, t.θ, t.origin, t.rotation) θ1, θ2 = t.θ cm1 = TorusThetaSurface((t.r_torus, t.r_torus + t.r_tube * cos(θ1)), t.φ, t.r_tube * sin(θ1)/2, t.origin + t.rotation * CartesianVector{T}(0,0,t.r_tube * sin(θ1)/2), t.rotation, Val{TT1}()) cm2 = TorusThetaSurface((t.r_torus, t.r_torus + t.r_tube * cos(θ2)), t.φ, t.r_tube * sin(θ2)/2, t.origin + t.rotation * CartesianVector{T}(0,0,t.r_tube * sin(θ2)/2), t.rotation, Val{TT2}()) - φ1, φ2 = t.φ - es1 = flip(PartialCircularArea{T}(t.r_tube, t.θ, t.origin + t.rotation * CartesianVector{T}(t.r_torus * cos(φ1), t.r_torus * sin(φ1), 0), t.rotation * RotZ(φ1) * RotX(π/2))) - es2 = PartialCircularArea{T}(t.r_tube, t.θ, t.origin + t.rotation * CartesianVector{T}(t.r_torus * cos(φ2), t.r_torus * sin(φ2), 0), t.rotation * RotZ(φ2) * RotX(π/2)) + es1 = flip(PartialCircularArea{T}(t.r_tube, abs(-(t.θ...)), t.origin + t.rotation * CartesianVector{T}(t.r_torus, 0, 0), t.rotation * RotX(π/2) * RotZ{T}(t.θ[1]))) + es2 = PartialCircularArea{T}(t.r_tube, abs(-(t.θ...)), t.origin + t.rotation * CartesianVector{T}(t.r_torus * cos(t.φ), t.r_torus * sin(t.φ), 0), t.rotation * RotZ(t.φ) * RotX(π/2) * RotZ{T}(t.θ[1])) (tm, cm1, cm2, es1, es2) end -function surfaces(t::Torus{T,OpenPrimitive,T,Tuple{T,T},Tuple{T,T},TT1,TT2}) where {T,TT1,TT2} - tm = TorusMantle{T,Tuple{T,T},Tuple{T,T},:outwards}(t.r_torus, t.r_tube, t.φ, t.θ, t.origin, t.rotation) +function surfaces(t::Torus{T,OpenPrimitive,T,T,Tuple{T,T},TT1,TT2}) where {T,TT1,TT2} + tm = TorusMantle{T,T,Tuple{T,T},:outwards}(t.r_torus, t.r_tube, t.φ, t.θ, t.origin, t.rotation) θ1, θ2 = t.θ cm1 = flip(TorusThetaSurface((t.r_torus, t.r_torus + t.r_tube * cos(θ1)), t.φ, t.r_tube * sin(θ1)/2, t.origin + t.rotation * CartesianVector{T}(0,0,t.r_tube * sin(θ1)/2), t.rotation, Val{TT1}())) cm2 = flip(TorusThetaSurface((t.r_torus, t.r_torus + t.r_tube * cos(θ2)), t.φ, t.r_tube * sin(θ2)/2, t.origin + t.rotation * CartesianVector{T}(0,0,t.r_tube * sin(θ2)/2), t.rotation, Val{TT2}())) - φ1, φ2 = t.φ - es1 = PartialCircularArea{T}(t.r_tube, t.θ, t.origin + t.rotation * CartesianVector{T}(t.r_torus * cos(φ1), t.r_torus * sin(φ1), 0), t.rotation * RotZ(φ1) * RotX(π/2)) - es2 = flip(PartialCircularArea{T}(t.r_tube, t.θ, t.origin + t.rotation * CartesianVector{T}(t.r_torus * cos(φ2), t.r_torus * sin(φ2), 0), t.rotation * RotZ(φ2) * RotX(π/2))) + es1 = PartialCircularArea{T}(t.r_tube, abs(-(t.θ...)), t.origin + t.rotation * CartesianVector{T}(t.r_torus, 0, 0), t.rotation * RotX(π/2) * RotZ{T}(t.θ[1])) + es2 = flip(PartialCircularArea{T}(t.r_tube, abs(-(t.θ...)), t.origin + t.rotation * CartesianVector{T}(t.r_torus * cos(t.φ), t.r_torus * sin(t.φ), 0), t.rotation * RotZ(t.φ) * RotX(π/2) * RotZ{T}(t.θ[1]))) (tm, cm1, cm2, es1, es2) end @@ -215,46 +220,42 @@ function surfaces(t::HollowPhiTorus{T,OpenPrimitive,TT1,TT2}) where {T,TT1,TT2} tm_in = FullPhiTorusMantle{T,:inwards}(t.r_torus, t.r_tube[1], t.φ, t.θ, t.origin, t.rotation) tm_out = FullPhiTorusMantle{T,:outwards}(t.r_torus, t.r_tube[2], t.φ, t.θ, t.origin, t.rotation) θ1, θ2 = t.θ - cm1 = flip(TorusThetaSurface(t.r_torus .+ t.r_tube .* cos(θ1)), t.φ, abs(-(t.r_tube...)) * sin(θ1)/2, t.origin + t.rotation * CartesianVector{T}(0,0,mean(t.r_tube) * sin(θ1)), t.rotation, Val{TT1}()) - cm2 = flip(TorusThetaSurface(t.r_torus .+ t.r_tube .* cos(θ2)), t.φ, abs(-(t.r_tube...)) * sin(θ2)/2, t.origin + t.rotation * CartesianVector{T}(0,0,mean(t.r_tube) * sin(θ2)), t.rotation, Val{TT2}()) + cm1 = flip(TorusThetaSurface(t.r_torus .+ t.r_tube .* cos(θ1), t.φ, abs(-(t.r_tube...)) * sin(θ1)/2, t.origin + t.rotation * CartesianVector{T}(0,0,mean(t.r_tube) * sin(θ1)), t.rotation, Val{TT1}())) + cm2 = flip(TorusThetaSurface(t.r_torus .+ t.r_tube .* cos(θ2), t.φ, abs(-(t.r_tube...)) * sin(θ2)/2, t.origin + t.rotation * CartesianVector{T}(0,0,mean(t.r_tube) * sin(θ2)), t.rotation, Val{TT2}())) (tm_in, tm_out, cm1, cm2) end function surfaces(t::HollowThetaTorus{T,ClosedPrimitive}) where {T} tm_in = FullThetaTorusMantle{T,:outwards}(t.r_torus, t.r_tube[1], t.φ, t.θ, t.origin, t.rotation) tm_out = FullThetaTorusMantle{T,:inwards}(t.r_torus, t.r_tube[2], t.φ, t.θ, t.origin, t.rotation) - φ1, φ2 = t.φ - es1 = Annulus{T}(t.r_tube, t.θ, t.origin + t.rotation * CartesianVector{T}(t.r_torus * cos(φ1), t.r_torus * sin(φ1), 0), t.rotation * RotZ(φ1) * RotX(-π/2) ) - es2 = Annulus{T}(t.r_tube, t.θ, t.origin + t.rotation * CartesianVector{T}(t.r_torus * cos(φ2), t.r_torus * sin(φ2), 0), t.rotation * RotZ(φ2) * RotX(π/2) ) + es1 = Annulus{T}(t.r_tube, abs(-(t.θ...)), t.origin + t.rotation * CartesianVector{T}(t.r_torus, 0, 0), t.rotation * RotX(-π/2) * RotZ{T}(t.θ[1])) + es2 = Annulus{T}(t.r_tube, abs(-(t.θ...)), t.origin + t.rotation * CartesianVector{T}(t.r_torus * cos(t.φ), t.r_torus * sin(t.φ), 0), t.rotation * RotZ(t.φ) * RotX(π/2) * RotZ{T}(t.θ[1])) (tm_in, tm_out, es1, es2) end function surfaces(t::HollowThetaTorus{T,OpenPrimitive}) where {T} tm_in = FullThetaTorusMantle{T,:inwards}(t.r_torus, t.r_tube[1], t.φ, t.θ, t.origin, t.rotation) tm_out = FullThetaTorusMantle{T,:outwards}(t.r_torus, t.r_tube[2], t.φ, t.θ, t.origin, t.rotation) - φ1, φ2 = t.φ - es1 = Annulus{T}(t.r_tube, t.θ, t.origin + t.rotation * CartesianVector{T}(t.r_torus * cos(φ1), t.r_torus * sin(φ1), 0), t.rotation * RotZ(φ1) * RotX(π/2) ) - es2 = Annulus{T}(t.r_tube, t.θ, t.origin + t.rotation * CartesianVector{T}(t.r_torus * cos(φ2), t.r_torus * sin(φ2), 0), t.rotation * RotZ(φ2) * RotX(-π/2) ) + es1 = Annulus{T}(t.r_tube, abs(-(t.θ...)), t.origin + t.rotation * CartesianVector{T}(t.r_torus, 0, 0), t.rotation * RotX(π/2) * RotZ{T}(t.θ[1])) + es2 = Annulus{T}(t.r_tube, abs(-(t.θ...)), t.origin + t.rotation * CartesianVector{T}(t.r_torus * cos(t.φ), t.r_torus * sin(t.φ), 0), t.rotation * RotZ(t.φ) * RotX(-π/2) * RotZ{T}(t.θ[1])) (tm_in, tm_out, es1, es2) end -function surfaces(t::Torus{T,ClosedPrimitive,Tuple{T,T},Tuple{T,T},Tuple{T,T},TT1,TT2}) where {T,TT1,TT2} - tm_in = TorusMantle{T,Tuple{T,T},Tuple{T,T},:outwards}(t.r_torus, t.r_tube[1], t.φ, t.θ, t.origin, t.rotation) - tm_out = TorusMantle{T,Tuple{T,T},Tuple{T,T},:inwards}(t.r_torus, t.r_tube[2], t.φ, t.θ, t.origin, t.rotation) +function surfaces(t::Torus{T,ClosedPrimitive,Tuple{T,T},T,Tuple{T,T},TT1,TT2}) where {T,TT1,TT2} + tm_in = TorusMantle{T,T,Tuple{T,T},:outwards}(t.r_torus, t.r_tube[1], t.φ, t.θ, t.origin, t.rotation) + tm_out = TorusMantle{T,T,Tuple{T,T},:inwards}(t.r_torus, t.r_tube[2], t.φ, t.θ, t.origin, t.rotation) θ1, θ2 = t.θ cm1 = TorusThetaSurface(t.r_torus .+ t.r_tube .* cos(θ1), t.φ, abs(-(t.r_tube...)) * sin(θ1)/2, t.origin + t.rotation * CartesianVector{T}(0,0,mean(t.r_tube) * sin(θ1)), t.rotation, Val{TT1}()) cm2 = TorusThetaSurface(t.r_torus .+ t.r_tube .* cos(θ2), t.φ, abs(-(t.r_tube...)) * sin(θ2)/2, t.origin + t.rotation * CartesianVector{T}(0,0,mean(t.r_tube) * sin(θ2)), t.rotation, Val{TT2}()) - φ1, φ2 = t.φ - es1 = flip(PartialAnnulus{T}(t.r_tube, t.θ, t.origin + t.rotation * CartesianVector{T}(t.r_torus * cos(φ1), t.r_torus * sin(φ1), 0), t.rotation * RotZ(φ1) * RotX(π/2))) - es2 = PartialAnnulus{T}(t.r_tube, t.θ, t.origin + t.rotation * CartesianVector{T}(t.r_torus * cos(φ2), t.r_torus * sin(φ2), 0), t.rotation * RotZ(φ2) * RotX(π/2)) + es1 = flip(PartialAnnulus{T}(t.r_tube, abs(-(t.θ...)), t.origin + t.rotation * CartesianVector{T}(t.r_torus, 0, 0), t.rotation * RotX(π/2) * RotZ{T}(t.θ[1]))) + es2 = PartialAnnulus{T}(t.r_tube, abs(-(t.θ...)), t.origin + t.rotation * CartesianVector{T}(t.r_torus * cos(t.φ), t.r_torus * sin(t.φ), 0), t.rotation * RotZ(t.φ) * RotX(π/2) * RotZ{T}(t.θ[1])) (tm_in, tm_out, cm1, cm2, es1, es2) end -function surfaces(t::Torus{T,OpenPrimitive,Tuple{T,T},Tuple{T,T},Tuple{T,T},TT1,TT2}) where {T,TT1,TT2} - tm_in = TorusMantle{T,Tuple{T,T},Tuple{T,T},:inwards}(t.r_torus, t.r_tube[1], t.φ, t.θ, t.origin, t.rotation) - tm_out = TorusMantle{T,Tuple{T,T},Tuple{T,T},:outwards}(t.r_torus, t.r_tube[2], t.φ, t.θ, t.origin, t.rotation) +function surfaces(t::Torus{T,OpenPrimitive,Tuple{T,T},T,Tuple{T,T},TT1,TT2}) where {T,TT1,TT2} + tm_in = TorusMantle{T,T,Tuple{T,T},:inwards}(t.r_torus, t.r_tube[1], t.φ, t.θ, t.origin, t.rotation) + tm_out = TorusMantle{T,T,Tuple{T,T},:outwards}(t.r_torus, t.r_tube[2], t.φ, t.θ, t.origin, t.rotation) θ1, θ2 = t.θ cm1 = flip(TorusThetaSurface(t.r_torus .+ t.r_tube .* cos(θ1), t.φ, abs(-(t.r_tube...)) * sin(θ1)/2, t.origin + t.rotation * CartesianVector{T}(0,0,mean(t.r_tube) * sin(θ1)), t.rotation, Val{TT1}())) cm2 = flip(TorusThetaSurface(t.r_torus .+ t.r_tube .* cos(θ2), t.φ, abs(-(t.r_tube...)) * sin(θ2)/2, t.origin + t.rotation * CartesianVector{T}(0,0,mean(t.r_tube) * sin(θ2)), t.rotation, Val{TT2}())) - φ1, φ2 = t.φ - es1 = PartialAnnulus{T}(t.r_tube, t.θ, t.origin + t.rotation * CartesianVector{T}(t.r_torus * cos(φ1), t.r_torus * sin(φ1), 0), t.rotation * RotZ(φ1) * RotX(π/2)) - es2 = flip(PartialAnnulus{T}(t.r_tube, t.θ, t.origin + t.rotation * CartesianVector{T}(t.r_torus * cos(φ2), t.r_torus * sin(φ2), 0), t.rotation * RotZ(φ2) * RotX(π/2))) + es1 = PartialAnnulus{T}(t.r_tube, abs(-(t.θ...)), t.origin + t.rotation * CartesianVector{T}(t.r_torus, 0, 0), t.rotation * RotX(π/2) * RotZ{T}(t.θ[1])) + es2 = flip(PartialAnnulus{T}(t.r_tube, abs(-(t.θ...)), t.origin + t.rotation * CartesianVector{T}(t.r_torus * cos(t.φ), t.r_torus * sin(t.φ), 0), t.rotation * RotZ(t.φ) * RotX(π/2) * RotZ{T}(t.θ[1]))) (tm_in, tm_out, cm1, cm2, es1, es2) end From ce23d5675cc94f6ab11296c2cb7827a839d64055 Mon Sep 17 00:00:00 2001 From: Felix Hagemann <30291312+fhagemann@users.noreply.github.com> Date: Wed, 3 Nov 2021 01:09:50 +0100 Subject: [PATCH 07/10] =?UTF-8?q?Update=20`TorusMantle`:=20`=CF=86::Tuple{?= =?UTF-8?q?T,T}`=20=3D>=20`=CF=86::T`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SurfacePrimitives/TorusMantle.jl | 35 ++++++++++++++----- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/TorusMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/TorusMantle.jl index 022a5b0ec..b3e609467 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/TorusMantle.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/TorusMantle.jl @@ -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]`. @@ -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 @@ -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] @@ -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) @@ -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 @@ -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) From b5b007f4c4a0b4cc2df56ca37169869e217698b1 Mon Sep 17 00:00:00 2001 From: Felix Hagemann <30291312+fhagemann@users.noreply.github.com> Date: Wed, 3 Nov 2021 03:21:57 +0100 Subject: [PATCH 08/10] Update implementation for SigGen's `bulletize_PC` --- src/IO/SigGenInterface.jl | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/IO/SigGenInterface.jl b/src/IO/SigGenInterface.jl index 5c9979782..07b9fc719 100644 --- a/src/IO/SigGenInterface.jl +++ b/src/IO/SigGenInterface.jl @@ -291,19 +291,11 @@ function siggentodict(config::Dict; "r" => config["pc_radius"] - config["pc_length"], "h" => 0, "origin" => Dict("z" => config["pc_length"]))), - Dict( "difference" => [ Dict( "torus" => Dict( "r_torus" => config["pc_radius"] - config["pc_length"], "r_tube" => Dict("from" => config["pc_length"], - "to" => config["pc_length"]))), - Dict( "tube" => Dict( - "r" => config["pc_radius"] - config["pc_length"], - "h" => 1.2*config["pc_length"], - "origin" => Dict("z" => 0.4*config["pc_length"]))), - Dict( "tube" => Dict( - "r" => 1.2*config["pc_radius"], - "h" => 1.2*config["pc_radius"], - "origin" => Dict("z" => -0.6 * config["pc_radius"])))])]) + "to" => config["pc_length"]), + "theta" => Dict("from" => 0.0, "to" => 90.0)))]) elseif config["pc_length"] > config["pc_radius"] Dict( "union" => [ Dict( "tube" => Dict( From f2bb8a0239d30d1c66cbd0bcb7c69fa6ffef5c06 Mon Sep 17 00:00:00 2001 From: Felix Hagemann <30291312+fhagemann@users.noreply.github.com> Date: Wed, 3 Nov 2021 02:56:10 +0100 Subject: [PATCH 09/10] Add tests for `Cone` and `Torus` for different cases --- .../CSG_primitives.jl | 66 +++++++++++++++++++ test/runtests.jl | 13 +++- 2 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 test/ConstructiveSolidGeometry/CSG_primitives.jl diff --git a/test/ConstructiveSolidGeometry/CSG_primitives.jl b/test/ConstructiveSolidGeometry/CSG_primitives.jl new file mode 100644 index 000000000..9dbf98030 --- /dev/null +++ b/test/ConstructiveSolidGeometry/CSG_primitives.jl @@ -0,0 +1,66 @@ +using Test +using SolidStateDetectors +using StaticArrays + +import SolidStateDetectors.ConstructiveSolidGeometry as CSG +import SolidStateDetectors.ConstructiveSolidGeometry: Geometry + +T = Float64 + +default_units = SolidStateDetectors.default_unit_tuple() +no_translations = (rotation = one(SMatrix{3, 3, T, 9}), translation = zero(CartesianVector{T})) + +@testset "Test primitive parsing" begin + @testset "Cone" begin + for bot in (2.0, Dict("from" => 1.0, "to" => 2.0)), + top in (2.0, 1.0, Dict("from" => 1.0, "to" => 2.0), Dict("from" => 2.0, "to" => 4.0)), + φmax in (180,360) + + dict = Dict("difference" => [ + Dict("cone" => Dict( + "r" => Dict("bottom" => bot, "top" => top), + "phi" => Dict("from" => "0°", "to" => "$(φmax)°"), + "h" => 1.0)) + for i in 1:2 + ]) + + c = Geometry(T, dict, default_units, no_translations) + + # No warnings or errors when decomposing the Cones into surfaces + @test_nowarn CSG.surfaces(c.a) + @test_nowarn CSG.surfaces(c.b) + + # Check if all Cones are saved the right way + @test c.a isa CSG.Cone + @test c.b isa CSG.Cone + end + end + @testset "Torus" begin + for r_tube in (2.0, Dict("from" => 1.0, "to" => 2.0)), + φmax in (180,360), + θmin in 0:45:90, + θmax in 135:45:270 + + dict = Dict("difference" => [ + Dict( "torus" => Dict( + "r_torus" => 10.0, + "r_tube" => r_tube, + "phi" => Dict("from" => "0°", "to" => "$(φmax)°"), + "theta" => Dict("from" => "$(θmin)°", "to" => "$(θmax)°"))) + for i in 1:2 + ]) + t = Geometry(T, dict, default_units, no_translations) + + # No warnings or errors when decomposing the Torus into surfaces + @test_nowarn CSG.surfaces(t.a) + @test_nowarn CSG.surfaces(t.b) + + # Check that the r field for all ConeMantles is ordered + for surf in CSG.surfaces(t.a) surf isa CSG.ConeMantle && @test_skip surf.r[1] <= surf.r[2] end + + # Check if all Torus are saved the right way + @test t.a isa CSG.Torus + @test t.b isa CSG.Torus + end + end +end \ No newline at end of file diff --git a/test/runtests.jl b/test/runtests.jl index 7b8dee0c9..90c3d68ca 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -17,6 +17,13 @@ end include("SOR_GPU_Backend.jl") end +@testset "ConstructiveSolidGeometry" begin + include("ConstructiveSolidGeometry/CSG_IO.jl") + include("ConstructiveSolidGeometry/CSG_primitives.jl") +end + +T = Float32 + @testset "Test real detectors" begin @testset "Simulate example detector: Inverted Coax" begin sim = Simulation{T}(SSD_examples[:InvertedCoax]) @@ -157,7 +164,7 @@ end end @testset "Diffusion and Self-Repulsion" begin - sim = Simulation(SSD_examples[:InvertedCoax]) + sim = Simulation{T}(SSD_examples[:InvertedCoax]) simulate!(sim, convergence_limit = 1e-5, refinement_limits = [0.2, 0.1], verbose = false) pos = CartesianPoint{T}(0.02,0,0.05); Edep = 1u"eV" @@ -175,7 +182,7 @@ end end @testset "Table Simulation" begin - sim = Simulation(SSD_examples[:InvertedCoax]) + sim = Simulation{T}(SSD_examples[:InvertedCoax]) simulate!(sim, convergence_limit = 1e-5, refinement_limits = [0.2, 0.1], verbose = false) evt_table = Table( @@ -225,4 +232,4 @@ end @test sim == Simulation(nt) end -include("ConstructiveSolidGeometry/CSG_IO.jl") + From 14de926a0a8911fc878a4a8dcde29c84c2f473b6 Mon Sep 17 00:00:00 2001 From: Felix Hagemann <30291312+fhagemann@users.noreply.github.com> Date: Wed, 3 Nov 2021 04:16:34 +0100 Subject: [PATCH 10/10] Fix `flip(::EllipticalSurface)` --- .../SurfacePrimitives/EllipticalSurface.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl index 38c5a300f..de2ba742d 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl @@ -29,7 +29,7 @@ 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,T}) where {T,TR} = - EllipticalSurface{T,TR,T}(es.r, es.φ, es.origin, es.rotation * RotZ{T}(T(2π)-es.φ)SMatrix{3,3,T,9}(1,0,0,0,-1,0,0,0,-1)) + 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,T}