diff --git a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl index 80f3a37bd..8bfbd4878 100644 --- a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl +++ b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl @@ -28,7 +28,7 @@ module ConstructiveSolidGeometry abstract type Cylindrical <: AbstractCoordinateSystem end const CoordinateSystemType = Union{Type{Cartesian}, Type{Cylindrical}} - import Base: print, show + import Base: print, show, float print(io::IO, ::Type{Cartesian}) = print(io, "Cartesian") print(io::IO, ::Type{Cylindrical}) = print(io, "Cylindrical") show(io::IO, CS::CoordinateSystemType) = print(io, CS) @@ -38,7 +38,7 @@ module ConstructiveSolidGeometry const CartesianTicksTuple{T} = NamedTuple{(:x,:y,:z), NTuple{3,Vector{T}}} const CylindricalTicksTuple{T} = NamedTuple{(:r,:φ,:z), NTuple{3,Vector{T}}} - abstract type AbstractGeometry{T <: AbstractFloat} end + abstract type AbstractGeometry{T <: Number} end abstract type AbstractPrimitive{T} <: AbstractGeometry{T} end abstract type ClosedPrimitive end @@ -50,11 +50,16 @@ module ConstructiveSolidGeometry abstract type AbstractConstructiveGeometry{T} <: AbstractGeometry{T} end - _csg_convert_args(eltype::Type{T}, r::Real) where T = convert(T, r) + _csg_convert_args(eltype::Type{T}, r::Real) where T = convert(T, r) _csg_convert_args(eltype::Type{T}, r::Tuple) where T = broadcast(x -> _csg_convert_args(T, x), r) _csg_convert_args(eltype::Type{T}, r::Nothing) where T = nothing + _csg_convert_args(eltype::Type{Quantity{T}}, r::Quantity) where {T} = T(r) + _csg_convert_args(eltype::Type{Quantity{T}}, r::Real) where {T} = T(r) * T(1)u"m" + _csg_convert_args(eltype::Type{T}, r::PtOrVec) where {T, PtOrVec<:StaticArrays.FieldVector} = broadcast(x -> _csg_convert_args(T, x), r) + _csg_convert_args(::Type{RT}, ::Type{T}) where {RT<:Real,T<:Real} = RT + _csg_convert_args(::Type{RT}, ::Type{T}) where {RT<:Real,T<:Quantity} = Quantity{RT} - _csg_get_promoted_eltype(::Type{T}) where {T <: AbstractArray} = eltype(T) + _csg_get_promoted_eltype(::Type{T}) where {T <: AbstractArray} = _csg_get_promoted_eltype.(eltype(T)) _csg_get_promoted_eltype(::Type{T}) where {T <: Real} = T _csg_get_promoted_eltype(::Type{Nothing}) = Int _csg_get_promoted_eltype(::Type{Tuple{T}}) where {T<:Real} = T @@ -62,9 +67,16 @@ module ConstructiveSolidGeometry _csg_get_promoted_eltype(::Type{Tuple{T1,T2}}) where {T1<:Union{Real, Tuple}, T2<:Union{Real, Tuple}} = promote_type(_csg_get_promoted_eltype(T1), _csg_get_promoted_eltype(T2)) _csg_get_promoted_eltype(::Type{Tuple{Nothing,T2}}) where {T2<:Union{Real, Tuple}} = _csg_get_promoted_eltype(T2) _csg_get_promoted_eltype(::Type{Tuple{T1,Nothing}}) where {T1<:Union{Real, Tuple}} = _csg_get_promoted_eltype(T1) + _csg_get_promoted_eltype(::Type{Q}) where {Q <: Quantity}= Q _handle_phi(φ, rotation) = (φ, rotation) _handle_phi(φ::Tuple, rotation) = (abs(φ[2]-φ[1]), rotation*RotZ(φ[1])) + + _precision_type(::Type{T}) where {T <: Real} = T + _precision_type(::Type{Quantity{T}}) where {T <: Real} = T + + _float_precision(::Type{Quantity{T}}) where T = float(T) + _float_precision(::Type{T}) where T = float(T) include("Units.jl") include("PointsAndVectors/PointsAndVectors.jl") diff --git a/src/ConstructiveSolidGeometry/PointsAndVectors/Points.jl b/src/ConstructiveSolidGeometry/PointsAndVectors/Points.jl index 00cc5db8c..612999b67 100644 --- a/src/ConstructiveSolidGeometry/PointsAndVectors/Points.jl +++ b/src/ConstructiveSolidGeometry/PointsAndVectors/Points.jl @@ -109,6 +109,8 @@ end @inline _convert_point(pt::AbstractCoordinatePoint, ::Type{Cylindrical}) = CylindricalPoint(pt) @inline _convert_point(pt::AbstractCoordinatePoint, ::Type{Cartesian}) = CartesianPoint(pt) +scale(cart::CartesianPoint{T}, fact) where T = CartesianPoint{T}(cart.x*fact, cart.y*fact, cart.z*fact) + # function _Δφ(φ1::T, φ2::T)::T where {T} # δφ = mod(φ2 - φ1, T(2π)) # min(δφ, T(2π) - δφ) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl index add510ef6..7662738b7 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl @@ -46,28 +46,30 @@ box: See also [Constructive Solid Geometry (CSG)](@ref). """ -struct Box{T,CO} <: AbstractVolumePrimitive{T,CO} +struct Box{T,RT,CO} <: AbstractVolumePrimitive{T,CO} hX::T hY::T hZ::T origin::CartesianPoint{T} - rotation::SMatrix{3,3,T,9} + rotation::SMatrix{3,3,RT,9} end #Type conversion happens here -function Box{T}(CO,hX, hY, hZ, origin, rotation) where {T} +function Box{T,RT}(CO, hX, hY, hZ, origin, rotation) where {T,RT<:Real} _hX = _csg_convert_args(T, hX) _hY = _csg_convert_args(T, hY) _hZ = _csg_convert_args(T, hZ) - Box{T,CO}(_hX, _hY, _hZ, origin, rotation) + _origin = _csg_convert_args(T, origin) + Box{T,RT,CO}(_hX, _hY, _hZ, _origin, rotation) end #Type promotion happens here -function Box(CO, hX::TX, hY::TY, hZ::TZ, origin::PT, rotation::ROT) where {TX, TY, TZ, PT, ROT} - eltypes = _csg_get_promoted_eltype.((TX, TY, TZ, PT, ROT)) - T = float(promote_type(eltypes...)) - Box{T}(CO,T(hX), T(hY), T(hZ), origin, rotation) +function Box(CO, hX::TX, hY::TY, hZ::TZ, origin::PT, rotation::ROT) where {TX,TY,TZ,PT,ROT} + eltypes = _csg_get_promoted_eltype.((TX,TY,TZ,PT,ROT)) + RT = _float_precision(promote_type(eltypes...)) + T = _csg_convert_args(RT,promote_type(eltypes...)) + Box{T,RT}(CO, RT(hX), RT(hY), RT(hZ), origin, rotation) end function Box(::Type{CO}=ClosedPrimitive; @@ -87,21 +89,22 @@ function Box{T}(::Type{CO}=ClosedPrimitive; origin = zero(CartesianPoint{Float64}), rotation = one(SMatrix{3, 3, Float64, 9}) ) where {T, CO} - Box{T}(CO, hX, hY, hZ, origin, rotation) + RT = _precision_type(T) + Box{T,RT}(CO, hX, hY, hZ, origin, rotation) end -Box{T, CO}( b::Box{T, CO}; COT = CO, +Box{T, RT, CO}( b::Box{T, RT, CO}; COT = CO, origin::CartesianPoint{T} = b.origin, - rotation::SMatrix{3,3,T,9} = b.rotation) where {T, CO<:Union{ClosedPrimitive, OpenPrimitive}} = - Box{T, COT}(b.hX, b.hY, b.hZ, origin, rotation) + rotation::SMatrix{3,3,T,9} = b.rotation) where {T, RT, CO<:Union{ClosedPrimitive, OpenPrimitive}} = + Box{T, RT, COT}(b.hX, b.hY, b.hZ, origin, rotation) -function _in(pt::CartesianPoint{T}, b::Box{<:Any, ClosedPrimitive}; csgtol::T = csg_default_tol(T)) where {T} +function _in(pt::CartesianPoint{T}, b::Box{<:Any, <:Any, ClosedPrimitive}; csgtol::T = csg_default_tol(T)) where {T} abs(pt.x) <= b.hX + csgtol && abs(pt.y) <= b.hY + csgtol && abs(pt.z) <= b.hZ + csgtol end -_in(pt::CartesianPoint{T}, b::Box{<:Any, OpenPrimitive}; csgtol::T = csg_default_tol(T)) where {T} = +_in(pt::CartesianPoint{T}, b::Box{<:Any, <:Any, OpenPrimitive}; csgtol::T = csg_default_tol(T)) where {T} = abs(pt.x) < b.hX - csgtol && abs(pt.y) < b.hY - csgtol && abs(pt.z) < b.hZ - csgtol diff --git a/test/ConstructiveSolidGeometry/CSG_primitives.jl b/test/ConstructiveSolidGeometry/CSG_primitives.jl index 692dd8adc..8aeb8ac98 100644 --- a/test/ConstructiveSolidGeometry/CSG_primitives.jl +++ b/test/ConstructiveSolidGeometry/CSG_primitives.jl @@ -185,8 +185,8 @@ no_translations = (rotation = one(SMatrix{3, 3, T, 9}), translation = zero(Carte @test in(CartesianPoint{Float64}(1e-8,0,0),ellip_open_trafo) end @testset "Box" begin - box1 = @inferred CSG.Box(CSG.ClosedPrimitive,hX=1f0, hY=2f0, hZ=1f0, origin = zero(CartesianPoint{Float16}),rotation = one(SMatrix{3, 3, Float16, 9})) - box2 = @inferred CSG.Box{Float32}(hX=1.0, hY=2f0, hZ=1f0) + box1 = @inferred CSG.Box(CSG.ClosedPrimitive,hX=1f0, hY=2f0, hZ=1f0, origin = CartesianPoint{Float32}(1,1,1),rotation = one(SMatrix{3, 3, Float16, 9})) + box2 = @inferred CSG.Box{Float32}(hX=1.0, hY=2f0, hZ=1f0, origin = CartesianPoint(1,1,1)) @test box1 === box2 dict = Dict("box" => Dict( @@ -204,6 +204,9 @@ no_translations = (rotation = one(SMatrix{3, 3, T, 9}), translation = zero(Carte @test !in(CartesianPoint{Float64}(1,1,3),box_open_trafo) @test !in(CartesianPoint{Float64}(1,1,3+tol),box_closed_trafo) @test in(CartesianPoint{Float64}(1,1,3-tol),box_open_trafo) + # Test box with units + @inferred CSG.Box(CSG.ClosedPrimitive, hX=1u"m", hY=2f0, hZ=1f0) + @inferred CSG.Box{Quantity{Float32}}(CSG.ClosedPrimitive, hX=1u"mm", hY=2f0, hZ=1f0) end @testset "RegularPrism" begin prism1 = @inferred CSG.RegularPrism{3}(CSG.ClosedPrimitive,r=1f0, hZ = 2f0)