diff --git a/.JuliaFormatter.toml b/.JuliaFormatter.toml new file mode 100644 index 00000000..3331778d --- /dev/null +++ b/.JuliaFormatter.toml @@ -0,0 +1,10 @@ +always_for_in = true +always_use_return = true +import_to_using = true +pipe_to_function_call = true +remove_extra_newlines = true +short_to_long_function_def = true +style = "yas" +whitespace_in_kwargs = false +whitespace_ops_in_indices = true +whitespace_typedefs = false diff --git a/docs/make.jl b/docs/make.jl index 65e096d5..f0d2ed04 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -7,24 +7,9 @@ using GeometryBasics # Copy the README to serve as the homepage cp(joinpath(@__DIR__, "..", "README.md"), joinpath(@__DIR__, "src", "index.md")) -makedocs( - format = Documenter.HTML(), - sitename = "GeometryBasics.jl", - pages = [ - "index.md", - "primitives.md", - "rectangles.md", - "polygons.md", - "meshes.md", - "decomposition.md", - "distancefields.md", - "metadata.md", - "api.md", - ], - modules = [GeometryBasics] -) +makedocs(format=Documenter.HTML(), sitename="GeometryBasics.jl", + pages=["index.md", "primitives.md", "rectangles.md", "polygons.md", "meshes.md", + "decomposition.md", "distancefields.md", "metadata.md", "api.md"], + modules=[GeometryBasics]) -deploydocs( - repo = "github.com/JuliaGeometry/GeometryBasics.jl.git", - push_preview = true -) +deploydocs(repo="github.com/JuliaGeometry/GeometryBasics.jl.git", push_preview=true) diff --git a/src/basic_types.jl b/src/basic_types.jl index 9b35129d..aac0d153 100644 --- a/src/basic_types.jl +++ b/src/basic_types.jl @@ -209,7 +209,8 @@ function LineString(points::AbstractVector{<:AbstractPoint}, skip=1) return LineString(connect(points, LineP, skip)) end -function LineString(points::AbstractVector{<:Pair{P,P}}) where {P<:AbstractPoint{N,T}} where {N, T} +function LineString(points::AbstractVector{<:Pair{P,P}}) where {P<:AbstractPoint{N,T}} where {N, + T} return LineString(reinterpret(LineP{N,T,P}, points)) end @@ -261,8 +262,9 @@ function Base.:(==)(a::Polygon, b::Polygon) end function Polygon(exterior::E, - interiors::AbstractVector{E}) where - {E<:AbstractVector{LineP{Dim,T,P}}} where {Dim, T, P} + interiors::AbstractVector{E}) where {E<:AbstractVector{LineP{Dim,T,P}}} where {Dim, + T, + P} return Polygon{Dim,T,P,typeof(exterior),typeof(interiors)}(exterior, interiors) end @@ -279,12 +281,15 @@ function Polygon(exterior::AbstractVector{P}, faces::AbstractVector{<:Integer}, end function Polygon(exterior::AbstractVector{P}, - faces::AbstractVector{<:LineFace}) where {P<:AbstractPoint{Dim,T}} where {Dim, T} + faces::AbstractVector{<:LineFace}) where {P<:AbstractPoint{Dim,T}} where {Dim, + T} return Polygon(LineString(exterior, faces)) end function Polygon(exterior::AbstractVector{P}, - interior::AbstractVector{<:AbstractVector{P}}) where {P<:AbstractPoint{Dim, T}} where {Dim, T} + interior::AbstractVector{<:AbstractVector{P}}) where {P<:AbstractPoint{Dim, + T}} where {Dim, + T} ext = LineString(exterior) # We need to take extra care for empty interiors, since # if we just map over it, it won't infer the element type correctly! @@ -295,7 +300,7 @@ end function coordinates(polygon::Polygon{N,T,PointType}) where {N,T,PointType} exterior = coordinates(polygon.exterior) - return if isempty(polygon.interiors) + if isempty(polygon.interiors) return exterior else result = PointType[] @@ -310,7 +315,6 @@ end """ struct MultiPolygon{Dim,T<:Real,Element<:AbstractPolygon{Dim,T}, A<:AbstractVector{Element}} <: AbstractVector{Element} - polygons::A end @@ -376,7 +380,7 @@ end Tables.schema(mesh::Mesh) = Tables.schema(getfield(mesh, :simplices)) function Base.getproperty(mesh::Mesh, name::Symbol) - return if name === :position + if name === :position # a mesh always has position defined by coordinates... return metafree(coordinates(mesh)) else @@ -386,7 +390,7 @@ end function Base.propertynames(mesh::Mesh) names = propertynames(getfield(mesh, :simplices)) - return if :position in names + if :position in names return names else # a mesh always has positions! diff --git a/src/fixed_arrays.jl b/src/fixed_arrays.jl index a90d6c9e..8d6eb24a 100644 --- a/src/fixed_arrays.jl +++ b/src/fixed_arrays.jl @@ -8,113 +8,109 @@ end macro fixed_vector(name, parent) expr = quote - struct $(name){S,T} <: $(parent){S,T} - data::NTuple{S,T} - - function $(name){S,T}(x::NTuple{S,T}) where {S,T} - return new{S,T}(x) - end - - function $(name){S,T}(x::NTuple{S,Any}) where {S,T} - return new{S,T}(StaticArrays.convert_ntuple(T, x)) - end - end - - size_or(::Type{$(name)}, or) = or - eltype_or(::Type{$(name)}, or) = or - eltype_or(::Type{$(name){S,T} where S}, or) where {T} = T - eltype_or(::Type{$(name){S,T} where T}, or) where {S} = or - eltype_or(::Type{$(name){S,T}}, or) where {S,T} = T - - size_or(::Type{$(name){S,T} where S}, or) where {T} = or - size_or(::Type{$(name){S,T} where T}, or) where {S} = Size{(S,)}() - size_or(::Type{$(name){S,T}}, or) where {S,T} = (S,) - - # Array constructor - function $(name){S}(x::AbstractVector{T}) where {S,T} - @assert S <= length(x) - return $(name){S,T}(ntuple(i -> x[i], Val(S))) - end - - function $(name){S,T1}(x::AbstractVector{T2}) where {S,T1,T2} - @assert S <= length(x) - return $(name){S,T1}(ntuple(i -> T1(x[i]), Val(S))) - end - - function $(name){S,T}(x) where {S,T} - return $(name){S,T}(ntuple(i -> T(x), Val(S))) - end - - $(name){S}(x::T) where {S,T} = $(name){S,T}(ntuple(i -> x, Val(S))) - $(name){1,T}(x::T) where {T} = $(name){1,T}((x,)) - $(name)(x::NTuple{S}) where {S} = $(name){S}(x) - function $(name)(x::T) where {S,T<:Tuple{Vararg{Any,S}}} - return $(name){S,StaticArrays.promote_tuple_eltype(T)}(x) - end - - function $(name){S}(x::T) where {S,T<:Tuple} - return $(name){S,StaticArrays.promote_tuple_eltype(T)}(x) - end - $(name){S,T}(x::StaticVector) where {S,T} = $(name){S,T}(Tuple(x)) - - @generated function (::Type{$(name){S,T}})(x::$(name)) where {S,T} - idx = [:(x[$i]) for i in 1:S] - return quote - $($(name)){S,T}($(idx...)) - end - end - - @generated function Base.convert(::Type{$(name){S,T}}, - x::$(name)) where {S,T} - idx = [:(x[$i]) for i in 1:S] - return quote - $($(name)){S,T}($(idx...)) - end - end - - @generated function (::Type{SV})(x::StaticVector) where {SV<:$(name)} - len = size_or(SV, size(x))[1] - return if length(x) == len - :(SV(Tuple(x))) - elseif length(x) > len - elems = [:(x[$i]) for i in 1:len] - :(SV($(Expr(:tuple, elems...)))) - else - error("Static Vector too short: $x, target type: $SV") - end - end - - Base.@pure StaticArrays.Size(::Type{$(name){S,Any}}) where {S} = Size(S) - Base.@pure StaticArrays.Size(::Type{$(name){S,T}}) where {S,T} = Size(S) - - Base.@propagate_inbounds function Base.getindex(v::$(name){S,T}, - i::Int) where {S,T} - return v.data[i] - end - - Base.Tuple(v::$(name)) = v.data - function Base.convert(::Type{$(name){S,T}}, x::NTuple{S,T}) where {S,T} - return $(name){S,T}(x) - end - function Base.convert(::Type{$(name){S,T}}, x::Tuple) where {S,T} - return $(name){S,T}(convert(NTuple{S,T}, x)) - end - - @generated function StaticArrays.similar_type(::Type{SV}, ::Type{T}, - s::Size{S}) where {SV<:$(name), - T,S} - return if length(S) === 1 - $(name){S[1],T} - else - StaticArrays.default_similar_type(T, s(), Val{length(S)}) - end - end - - Base.:(*)(a::$name, b::$name) = a .* b - function Base.broadcasted(f, a::AbstractArray{T}, - b::$name) where {T<:$name} - return Base.broadcasted(f, a, (b,)) - end + struct $(name){S,T} <: $(parent){S,T} + data::NTuple{S,T} + + function $(name){S,T}(x::NTuple{S,T}) where {S,T} + return new{S,T}(x) + end + + function $(name){S,T}(x::NTuple{S,Any}) where {S,T} + return new{S,T}(StaticArrays.convert_ntuple(T, x)) + end + end + + size_or(::Type{$(name)}, or) = or + eltype_or(::Type{$(name)}, or) = or + eltype_or(::Type{$(name){S,T} where S}, or) where {T} = T + eltype_or(::Type{$(name){S,T} where T}, or) where {S} = or + eltype_or(::Type{$(name){S,T}}, or) where {S,T} = T + + size_or(::Type{$(name){S,T} where S}, or) where {T} = or + size_or(::Type{$(name){S,T} where T}, or) where {S} = Size{(S,)}() + size_or(::Type{$(name){S,T}}, or) where {S,T} = (S,) + + # Array constructor + function $(name){S}(x::AbstractVector{T}) where {S,T} + @assert S <= length(x) + return $(name){S,T}(ntuple(i -> x[i], Val(S))) + end + + function $(name){S,T1}(x::AbstractVector{T2}) where {S,T1,T2} + @assert S <= length(x) + return $(name){S,T1}(ntuple(i -> T1(x[i]), Val(S))) + end + + function $(name){S,T}(x) where {S,T} + return $(name){S,T}(ntuple(i -> T(x), Val(S))) + end + + $(name){S}(x::T) where {S,T} = $(name){S,T}(ntuple(i -> x, Val(S))) + $(name){1,T}(x::T) where {T} = $(name){1,T}((x,)) + $(name)(x::NTuple{S}) where {S} = $(name){S}(x) + function $(name)(x::T) where {S,T<:Tuple{Vararg{Any,S}}} + return $(name){S,StaticArrays.promote_tuple_eltype(T)}(x) + end + + function $(name){S}(x::T) where {S,T<:Tuple} + return $(name){S,StaticArrays.promote_tuple_eltype(T)}(x) + end + $(name){S,T}(x::StaticVector) where {S,T} = $(name){S,T}(Tuple(x)) + + @generated function (::Type{$(name){S,T}})(x::$(name)) where {S,T} + idx = [:(x[$i]) for i in 1:S] + return quote + $($(name)){S,T}($(idx...)) + end + end + + @generated function Base.convert(::Type{$(name){S,T}}, x::$(name)) where {S,T} + idx = [:(x[$i]) for i in 1:S] + return quote + $($(name)){S,T}($(idx...)) + end + end + + @generated function (::Type{SV})(x::StaticVector) where {SV<:$(name)} + len = size_or(SV, size(x))[1] + return if length(x) == len + :(SV(Tuple(x))) + elseif length(x) > len + elems = [:(x[$i]) for i in 1:len] + :(SV($(Expr(:tuple, elems...)))) + else + error("Static Vector too short: $x, target type: $SV") + end + end + + Base.@pure StaticArrays.Size(::Type{$(name){S,Any}}) where {S} = Size(S) + Base.@pure StaticArrays.Size(::Type{$(name){S,T}}) where {S,T} = Size(S) + + Base.@propagate_inbounds function Base.getindex(v::$(name){S,T}, i::Int) where {S,T} + return v.data[i] + end + + Base.Tuple(v::$(name)) = v.data + function Base.convert(::Type{$(name){S,T}}, x::NTuple{S,T}) where {S,T} + return $(name){S,T}(x) + end + function Base.convert(::Type{$(name){S,T}}, x::Tuple) where {S,T} + return $(name){S,T}(convert(NTuple{S,T}, x)) + end + + @generated function StaticArrays.similar_type(::Type{SV}, ::Type{T}, + s::Size{S}) where {SV<:$(name),T,S} + return if length(S) === 1 + $(name){S[1],T} + else + StaticArrays.default_similar_type(T, s(), Val{length(S)}) + end + end + + Base.:(*)(a::$name, b::$name) = a .* b + function Base.broadcasted(f, a::AbstractArray{T}, b::$name) where {T<:$name} + return Base.broadcasted(f, a, (b,)) + end end return esc(expr) end diff --git a/src/offsetintegers.jl b/src/offsetintegers.jl index 63d3decf..12c567be 100644 --- a/src/offsetintegers.jl +++ b/src/offsetintegers.jl @@ -20,7 +20,7 @@ raw(x::Integer) = x value(x::OffsetInteger{O,T}) where {O,T} = raw(x) - O value(x::Integer) = x -function show(io::IO, oi::OffsetInteger{O,T}) where {O,T} +function show(io::IO, oi::OffsetInteger) return print(io, "|$(raw(oi)) (indexes as $(value(oi))|") end @@ -29,23 +29,27 @@ Base.eltype(oi::OffsetInteger) = eltype(typeof(oi)) # constructors and conversion function OffsetInteger{O1,T1}(x::OffsetInteger{O2,T2}) where {O1,O2,T1<:Integer,T2<:Integer} - return OffsetInteger{O1,T1}(T2(x)) + return OffsetInteger{O1,T1}(convert(T2, x)) end OffsetInteger{O}(x::Integer) where {O} = OffsetInteger{O,eltype(x)}(x) OffsetInteger{O}(x::OffsetInteger) where {O} = OffsetInteger{O,eltype(x)}(x) # This constructor has a massive method invalidation as a consequence, # and doesn't seem to be needed, so let's remove it! -(::Type{IT})(x::OffsetInteger) where {IT<:Integer} = IT(value(x)) -Base.@pure pure_max(x1, x2) = x1 > x2 ? x1 : x2 -Base.promote_rule(::Type{T1}, ::Type{OffsetInteger{O,T2}}) where {T1<:Integer,O,T2} = T1 +Base.convert(::Type{IT}, x::OffsetInteger) where {IT<:Integer} = IT(value(x)) + +Base.promote_rule(::Type{IT}, ::Type{<:OffsetInteger}) where {IT<:Integer} = IT + function Base.promote_rule(::Type{OffsetInteger{O1,T1}}, - ::Type{OffsetInteger{O2,T2}}) where {O1,O2,T1,T2} + ::Type{OffsetInteger{O2,T2}}) where {O1,O2,T1<:Integer, + T2<:Integer} return OffsetInteger{pure_max(O1, O2),promote_type(T1, T2)} end -#Need to convert to Int here because of: https://github.com/JuliaLang/julia/issues/35038 +Base.@pure pure_max(x1, x2) = x1 > x2 ? x1 : x2 + +# Need to convert to Int here because of: https://github.com/JuliaLang/julia/issues/35038 Base.to_index(I::OffsetInteger) = convert(Int, raw(OneIndex(I))) Base.to_index(I::OffsetInteger{0}) = convert(Int, raw(I)) diff --git a/src/primitives/pyramids.jl b/src/primitives/pyramids.jl index 531d22d0..ebc350eb 100644 --- a/src/primitives/pyramids.jl +++ b/src/primitives/pyramids.jl @@ -4,7 +4,7 @@ struct Pyramid{T} <: GeometryPrimitive{3,T} width::T end -function coordinates(p::Pyramid{T}, nvertices=nothing) where {T} +function coordinates(p::Pyramid{T}) where {T} leftup = Point{3,T}(-p.width, p.width, 0) / 2 leftdown = Point(-p.width, -p.width, 0) / 2 tip = Point{3,T}(p.middle + Point{3,T}(0, 0, p.length)) @@ -16,6 +16,6 @@ function coordinates(p::Pyramid{T}, nvertices=nothing) where {T} ld, rd] end -function faces(r::Pyramid, nvertices=nothing) where {FT} +function faces(::Pyramid) return (TriangleFace(triangle) for triangle in TupleView{3}(1:18)) end diff --git a/src/viewtypes.jl b/src/viewtypes.jl index e2917728..3232950b 100644 --- a/src/viewtypes.jl +++ b/src/viewtypes.jl @@ -73,22 +73,22 @@ x == [Line(Point(1, 2), Point(3, 4)), Line(Point(5, 6), Point(7, 8))] """ @inline function connect(points::AbstractVector{Point}, P::Type{<:Polytope{N,T} where {N,T}}, - skip::Int=length(P)) where {Point<:AbstractPoint} + skip::Int=length(P)) where {Point <: AbstractPoint} return reinterpret(Polytope(P, Point), TupleView{length(P),skip}(points)) end @inline function connect(points::AbstractVector{T}, P::Type{<:Point{N}}, - skip::Int=N) where {T<:Real,N} + skip::Int=N) where {T <: Real,N} return reinterpret(Point{N,T}, TupleView{N,skip}(points)) end @inline function connect(points::AbstractVector{T}, P::Type{<:AbstractFace{N}}, - skip::Int=N) where {T<:Real,N} + skip::Int=N) where {T <: Real,N} return reinterpret(Face(P, T), TupleView{N,skip}(points)) end @inline function connect(points::AbstractMatrix{T}, - P::Type{<:AbstractPoint{N}}) where {T<:Real,N} + P::Type{<:AbstractPoint{N}}) where {T <: Real,N} return if size(points, 1) === N return reinterpret(Point{N,T}, points) elseif size(points, 2) === N @@ -120,15 +120,13 @@ linestring = FaceView(points, LineFace[...]) Polygon(linestring) ``` """ -struct FaceView{Element,Point<:AbstractPoint,Face<:AbstractFace,P<:AbstractVector{Point}, - F<:AbstractVector{Face}} <: AbstractVector{Element} +struct FaceView{Element,Point <: AbstractPoint,Face <: AbstractFace,P <: AbstractVector{Point},F <: AbstractVector{Face}} <: AbstractVector{Element} elements::P faces::F end -const SimpleFaceView{Dim,T,NFace,IndexType,PointType<:AbstractPoint{Dim,T}, - FaceType<:AbstractFace{NFace,IndexType}} = FaceView{Ngon{Dim,T,NFace,PointType},PointType,FaceType,Vector{PointType},Vector{FaceType}} +const SimpleFaceView{Dim,T,NFace,IndexType,PointType <: AbstractPoint{Dim,T},FaceType <: AbstractFace{NFace,IndexType}} = FaceView{Ngon{Dim,T,NFace,PointType},PointType,FaceType,Vector{PointType},Vector{FaceType}} function Base.getproperty(faceview::FaceView, name::Symbol) return getproperty(getfield(faceview, :elements), name) @@ -143,11 +141,12 @@ Tables.schema(faceview::FaceView) = Tables.schema(getfield(faceview, :elements)) Base.size(faceview::FaceView) = size(getfield(faceview, :faces)) function Base.show(io::IO, ::Type{<:FaceView{Element}}) where {Element} - return if @isdefined Element + if @isdefined Element print(io, "FaceView{", Element, "}") else print(io, "FaceView{T}") end + return end @propagate_inbounds function Base.getindex(x::FaceView{Element}, i) where {Element} @@ -164,7 +163,7 @@ end end function connect(points::AbstractVector{P}, - faces::AbstractVector{F}) where {P<:AbstractPoint,F<:AbstractFace} + faces::AbstractVector{F}) where {P <: AbstractPoint,F <: AbstractFace} return FaceView{Polytope(P, F),P,F,typeof(points),typeof(faces)}(points, faces) end diff --git a/test/geometrytypes.jl b/test/geometrytypes.jl index 12ed06bd..557b58f0 100644 --- a/test/geometrytypes.jl +++ b/test/geometrytypes.jl @@ -11,7 +11,7 @@ end @testset "Cylinder" begin @testset "constructors" begin - o, extr, r = Point2f0(1, 2), Point2f0(3, 4), 5f0 + o, extr, r = Point2f0(1, 2), Point2f0(3, 4), 5.0f0 s = Cylinder(o, extr, r) @test typeof(s) == Cylinder{2,Float32} @test typeof(s) == Cylinder2{Float32} @@ -23,77 +23,59 @@ end @test isapprox(height(s), h) #@test norm(direction(s) - Point{2,Float32}([2,2]./norm([1,2]-[3,4])))<1e-5 @test isapprox(direction(s), Point2f0(2, 2) ./ h) - v1 = rand(Point{3, Float64}); v2 = rand(Point{3, Float64}); R = rand() + v1 = rand(Point{3,Float64}) + v2 = rand(Point{3,Float64}) + R = rand() s = Cylinder(v1, v2, R) - @test typeof(s) == Cylinder{3, Float64} + @test typeof(s) == Cylinder{3,Float64} @test typeof(s) == Cylinder3{Float64} @test origin(s) == v1 @test extremity(s) == v2 @test radius(s) == R @test height(s) == norm(v2 - v1) #@test norm(direction(s) - Point{3,Float64}((v2-v1)./norm(v2-v1)))<1e-10 - @test isapprox(direction(s), (v2-v1) ./ norm(v2 .- v1)) + @test isapprox(direction(s), (v2 - v1) ./ norm(v2 .- v1)) end @testset "decompose" begin - o, extr, r = Point2f0(1, 2), Point2f0(3, 4), 5f0 + o, extr, r = Point2f0(1, 2), Point2f0(3, 4), 5.0f0 s = Cylinder(o, extr, r) - positions = Point{3, Float32}[ - (-0.7677671, 3.767767, 0.0), - (2.767767, 0.23223293, 0.0), - (0.23223293, 4.767767, 0.0), - (3.767767, 1.2322329, 0.0), - (1.2322329, 5.767767, 0.0), - (4.767767, 2.232233, 0.0) - ] + positions = Point{3,Float32}[(-0.7677671, 3.767767, 0.0), + (2.767767, 0.23223293, 0.0), + (0.23223293, 4.767767, 0.0), + (3.767767, 1.2322329, 0.0), (1.2322329, 5.767767, 0.0), + (4.767767, 2.232233, 0.0)] @test decompose(Point3f0, Tesselation(s, (2, 3))) ≈ positions FT = TriangleFace{Int} - faces = FT[ - (1,2,4), - (1,4,3), - (3,4,6), - (3,6,5) - ] - @test faces == decompose(FT, Tesselation(s, (2,3))) - - v1 = Point{3, Float64}(1,2,3); v2 = Point{3, Float64}(4,5,6); R = 5.0 + faces = FT[(1, 2, 4), (1, 4, 3), (3, 4, 6), (3, 6, 5)] + @test faces == decompose(FT, Tesselation(s, (2, 3))) + + v1 = Point{3,Float64}(1, 2, 3) + v2 = Point{3,Float64}(4, 5, 6) + R = 5.0 s = Cylinder(v1, v2, R) - positions = Point{3,Float64}[ - (4.535533905932738,-1.5355339059327373,3.0), - (7.535533905932738,1.4644660940672627,6.0), - (3.0412414523193148,4.041241452319315,-1.0824829046386295), - (6.041241452319315,7.041241452319315,1.9175170953613705), - (-2.535533905932737,5.535533905932738,2.9999999999999996), - (0.46446609406726314,8.535533905932738,6.0), - (-1.0412414523193152,-0.04124145231931431,7.0824829046386295), - (1.9587585476806848,2.9587585476806857,10.08248290463863), - (1,2,3), - (4,5,6) - ] + positions = Point{3,Float64}[(4.535533905932738, -1.5355339059327373, 3.0), + (7.535533905932738, 1.4644660940672627, 6.0), + (3.0412414523193148, 4.041241452319315, + -1.0824829046386295), + (6.041241452319315, 7.041241452319315, + 1.9175170953613705), + (-2.535533905932737, 5.535533905932738, + 2.9999999999999996), + (0.46446609406726314, 8.535533905932738, 6.0), + (-1.0412414523193152, -0.04124145231931431, + 7.0824829046386295), + (1.9587585476806848, 2.9587585476806857, + 10.08248290463863), (1, 2, 3), (4, 5, 6)] @test decompose(Point3{Float64}, Tesselation(s, 8)) ≈ positions - faces = TriangleFace{Int}[ - (3, 2, 1), - (4, 2, 3), - (5, 4, 3), - (6, 4, 5), - (7, 6, 5), - (8, 6, 7), - (1, 8, 7), - (2, 8, 1), - - (3, 1, 9), - (2, 4, 10), - (5, 3, 9), - (4, 6, 10), - (7, 5, 9), - (6, 8, 10), - (1, 7, 9), - (8, 2, 10) - ] + faces = TriangleFace{Int}[(3, 2, 1), (4, 2, 3), (5, 4, 3), (6, 4, 5), (7, 6, 5), + (8, 6, 7), (1, 8, 7), (2, 8, 1), (3, 1, 9), (2, 4, 10), + (5, 3, 9), (4, 6, 10), (7, 5, 9), (6, 8, 10), (1, 7, 9), + (8, 2, 10)] @test faces == decompose(TriangleFace{Int}, Tesselation(s, 8)) m = triangle_mesh(Tesselation(s, 8)) @@ -108,102 +90,79 @@ end end end - @testset "HyperRectangles" begin - a = Rect(Vec(0,0),Vec(1,1)) - pt_expa = Point{2,Int}[(0,0), (1,0), (0,1), (1,1)] - @test decompose(Point{2,Int},a) == pt_expa + a = Rect(Vec(0, 0), Vec(1, 1)) + pt_expa = Point{2,Int}[(0, 0), (1, 0), (0, 1), (1, 1)] + @test decompose(Point{2,Int}, a) == pt_expa mesh = normal_mesh(a) @test decompose(Point2f0, mesh) == pt_expa - b = Rect(Vec(1,1,1),Vec(1,1,1)) - pt_expb = Point{3,Int64}[[1, 1, 1], [1, 1, 2], [1, 2, 2], [1, 2, 1], [1, 1, 1], [2, 1, 1], [2, 1, 2], [1, 1, 2], [1, 1, 1], [1, 2, 1], [2, 2, 1], [2, 1, 1], [2, 2, 2], [1, 2, 2], [1, 1, 2], [2, 1, 2], [2, 2, 2], [2, 1, 2], [2, 1, 1], [2, 2, 1], [2, 2, 2], [2, 2, 1], [1, 2, 1], [1, 2, 2]] + b = Rect(Vec(1, 1, 1), Vec(1, 1, 1)) + pt_expb = Point{3,Int64}[[1, 1, 1], [1, 1, 2], [1, 2, 2], [1, 2, 1], [1, 1, 1], + [2, 1, 1], [2, 1, 2], [1, 1, 2], [1, 1, 1], [1, 2, 1], + [2, 2, 1], [2, 1, 1], [2, 2, 2], [1, 2, 2], [1, 1, 2], + [2, 1, 2], [2, 2, 2], [2, 1, 2], [2, 1, 1], [2, 2, 1], + [2, 2, 2], [2, 2, 1], [1, 2, 1], [1, 2, 2]] @test decompose(Point{3,Int}, b) == pt_expb mesh = normal_mesh(b) end - NFace = NgonFace @testset "Faces" begin - @test convert_simplex(GLTriangleFace, QuadFace{Int}(1,2,3,4)) == (GLTriangleFace(1,2,3), GLTriangleFace(1,3,4)) - @test convert_simplex(NFace{3, ZeroIndex{Int}}, QuadFace{ZeroIndex{Int}}(1,2,3,4)) == (NFace{3,ZeroIndex{Int}}(1,2,3), NFace{3, ZeroIndex{Int}}(1,3,4)) - @test convert_simplex(NFace{3, OffsetInteger{3, Int}}, NFace{4, OffsetInteger{2, Int}}(1,2,3,4)) == ( - NFace{3, OffsetInteger{3, Int}}(1,2,3), - NFace{3, OffsetInteger{3, Int}}(1,3,4) - ) - @test convert_simplex(LineFace{Int}, QuadFace{Int}(1,2,3,4)) == ( - LineFace{Int}(1,2), - LineFace{Int}(2,3), - LineFace{Int}(3,4), - LineFace{Int}(4,1) - ) + @test convert_simplex(GLTriangleFace, QuadFace{Int}(1, 2, 3, 4)) == + (GLTriangleFace(1, 2, 3), GLTriangleFace(1, 3, 4)) + @test convert_simplex(NFace{3,ZeroIndex{Int}}, QuadFace{ZeroIndex{Int}}(1, 2, 3, 4)) == + (NFace{3,ZeroIndex{Int}}(1, 2, 3), NFace{3,ZeroIndex{Int}}(1, 3, 4)) + @test convert_simplex(NFace{3,OffsetInteger{3,Int}}, + NFace{4,OffsetInteger{2,Int}}(1, 2, 3, 4)) == + (NFace{3,OffsetInteger{3,Int}}(1, 2, 3), NFace{3,OffsetInteger{3,Int}}(1, 3, 4)) + @test convert_simplex(LineFace{Int}, QuadFace{Int}(1, 2, 3, 4)) == + (LineFace{Int}(1, 2), LineFace{Int}(2, 3), LineFace{Int}(3, 4), + LineFace{Int}(4, 1)) @testset "NgonFace ambiguity" begin - face = NgonFace((1,2)) - @test convert_simplex(NgonFace{2, UInt32}, face) === (NgonFace{2, UInt32}((1,2)),) + face = NgonFace((1, 2)) + @test convert_simplex(NgonFace{2,UInt32}, face) === (NgonFace{2,UInt32}((1, 2)),) @test convert_simplex(typeof(face), face) === (face,) face = NgonFace((1,)) - @test convert_simplex(NgonFace{1, UInt32}, face) === (NgonFace{1, UInt32}((1,)),) + @test convert_simplex(NgonFace{1,UInt32}, face) === (NgonFace{1,UInt32}((1,)),) @test convert_simplex(typeof(face), face) === (face,) end end - - @testset "Normals" begin - n64 = Vec{3, Float64}[ - (0.0,0.0,-1.0), - (0.0,0.0,-1.0), - (0.0,0.0,-1.0), - (0.0,0.0,-1.0), - (0.0,0.0,1.0), - (0.0,0.0,1.0), - (0.0,0.0,1.0), - (0.0,0.0,1.0), - (-1.0,0.0,0.0), - (-1.0,0.0,0.0), - (-1.0,0.0,0.0), - (-1.0,0.0,0.0), - (1.0,0.0,0.0), - (1.0,0.0,0.0), - (1.0,0.0,0.0), - (1.0,0.0,0.0), - (0.0,1.0,0.0), - (0.0,1.0,0.0), - (0.0,1.0,0.0), - (0.0,1.0,0.0), - (0.0,-1.0,0.0), - (0.0,-1.0,0.0), - (0.0,-1.0,0.0), - (0.0,-1.0,0.0), - ] + n64 = Vec{3,Float64}[(0.0, 0.0, -1.0), (0.0, 0.0, -1.0), (0.0, 0.0, -1.0), + (0.0, 0.0, -1.0), (0.0, 0.0, 1.0), (0.0, 0.0, 1.0), + (0.0, 0.0, 1.0), (0.0, 0.0, 1.0), (-1.0, 0.0, 0.0), + (-1.0, 0.0, 0.0), (-1.0, 0.0, 0.0), (-1.0, 0.0, 0.0), + (1.0, 0.0, 0.0), (1.0, 0.0, 0.0), (1.0, 0.0, 0.0), (1.0, 0.0, 0.0), + (0.0, 1.0, 0.0), (0.0, 1.0, 0.0), (0.0, 1.0, 0.0), (0.0, 1.0, 0.0), + (0.0, -1.0, 0.0), (0.0, -1.0, 0.0), (0.0, -1.0, 0.0), + (0.0, -1.0, 0.0),] n32 = map(Vec{3,Float32}, n64) r = triangle_mesh(centered(Rect3D)) # @test normals(coordinates(r), GeometryBasics.faces(r)) == n32 # @test normals(coordinates(r), GeometryBasics.faces(r)) == n64 end - @testset "HyperSphere" begin - sphere = Sphere{Float32}(Point3f0(0), 1f0) + sphere = Sphere{Float32}(Point3f0(0), 1.0f0) points = decompose(Point, Tesselation(sphere, 3)) - point_target = Point{3,Float32}[ - [0.0, 0.0, 1.0], [1.0, 0.0, 6.12323e-17], [1.22465e-16, 0.0, -1.0], - [-0.0, 0.0, 1.0], [-1.0, 1.22465e-16, 6.12323e-17], - [-1.22465e-16, 1.49976e-32, -1.0], [0.0, -0.0, 1.0], - [1.0, -2.44929e-16, 6.12323e-17], [1.22465e-16,-2.99952e-32, -1.0] - ] + point_target = Point{3,Float32}[[0.0, 0.0, 1.0], [1.0, 0.0, 6.12323e-17], + [1.22465e-16, 0.0, -1.0], [-0.0, 0.0, 1.0], + [-1.0, 1.22465e-16, 6.12323e-17], + [-1.22465e-16, 1.49976e-32, -1.0], [0.0, -0.0, 1.0], + [1.0, -2.44929e-16, 6.12323e-17], + [1.22465e-16, -2.99952e-32, -1.0]] @test points ≈ point_target f = decompose(TriangleFace{Int}, Tesselation(sphere, 3)) - face_target = TriangleFace{Int}[ - [1, 2, 5], [1, 5, 4], [2, 3, 6], [2, 6, 5], - [4, 5, 8], [4, 8, 7], [5, 6, 9], [5, 9, 8] - ] + face_target = TriangleFace{Int}[[1, 2, 5], [1, 5, 4], [2, 3, 6], [2, 6, 5], [4, 5, 8], + [4, 8, 7], [5, 6, 9], [5, 9, 8]] @test f == face_target - circle = Circle(Point2f0(0), 1f0) + circle = Circle(Point2f0(0), 1.0f0) points = decompose(Point2f0, Tesselation(circle, 20)) @test length(points) == 20 tess_circle = Tesselation(circle, 32) @@ -228,10 +187,9 @@ end @test (rect - 4) == FRect3D(base .- 4, wxyz) @test (rect - Vec(2, -2, 7)) == FRect3D(base .- Vec(2, -2, 7), wxyz) - rect = FRect2D(0, 7, 20, 3) - @test (rect * 4) == FRect2D(0, 7*4, 20*4, 3*4) - @test (rect * Vec(2, -2)) == FRect2D(0, -7*2, 20*2, -3*2) + @test (rect * 4) == FRect2D(0, 7 * 4, 20 * 4, 3 * 4) + @test (rect * Vec(2, -2)) == FRect2D(0, -7 * 2, 20 * 2, -3 * 2) base = Vec3f0(1, 2, 3) wxyz = Vec3f0(-2, 4, 2) @@ -241,7 +199,7 @@ end rect1 = Rect(Vec(0.0, 0.0), Vec(1.0, 2.0)) rect2 = Rect(0.0, 0.0, 1.0, 2.0) - @test rect1 isa GeometryBasics.HyperRectangle{2, Float64} + @test rect1 isa GeometryBasics.HyperRectangle{2,Float64} @test rect1 == rect2 split1, split2 = GeometryBasics.split(rect1, 2, 1) @@ -284,8 +242,8 @@ end rect = Rect(0.0, 0.0, 1.0, 1.0) @test min_dist_dim(rect, p, 1) == 4.0 @test min_dist_dim(rect, p, 2) == 3.0 - @test max_dist_dim(rect, p ,1) == 5.0 - @test max_dist_dim(rect, p ,2) == 4.0 + @test max_dist_dim(rect, p, 1) == 5.0 + @test max_dist_dim(rect, p, 2) == 4.0 rect1 = Rect(0.0, 0.0, 1.0, 1.0) rect2 = Rect(3.0, 1.0, 4.0, 2.0) @@ -310,7 +268,6 @@ end rect2 = Rect(1.5, 1.5, 2.0, 2.0) @test overlaps(rect1, rect2) - rect1 = Rect(1.0, 1.0, 2.0, 2.0) rect2 = Rect(0.0, 0.0, 2.0, 1.0) @test !GeometryBasics.starts(rect1, rect2)