diff --git a/.gitignore b/.gitignore index 1ec6aa9..6b24424 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,7 @@ assets/temp ./Manifest.toml ./test/Manifest.toml ./docs/Manifest.toml + +# Code Coverage Files +./*.cov +./test/*.cov diff --git a/dev/Manifest.toml b/dev/Manifest.toml new file mode 100644 index 0000000..736877c --- /dev/null +++ b/dev/Manifest.toml @@ -0,0 +1,211 @@ +# This file is machine-generated - editing it directly is not advised + +julia_version = "1.10.2" +manifest_format = "2.0" +project_hash = "6fc39199866dbf8fc8ebb862d97ebc30b0e913ce" + +[[deps.Artifacts]] +uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" + +[[deps.Base64]] +uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" + +[[deps.BitFlags]] +git-tree-sha1 = "2dc09997850d68179b69dafb58ae806167a32b1b" +uuid = "d1d4a3ce-64b1-5f1a-9ba4-7e7e69966f35" +version = "0.1.8" + +[[deps.CodecZlib]] +deps = ["TranscodingStreams", "Zlib_jll"] +git-tree-sha1 = "59939d8a997469ee05c4b4944560a820f9ba0d73" +uuid = "944b1d66-785c-5afd-91f1-9de20f533193" +version = "0.7.4" + +[[deps.ConcurrentUtilities]] +deps = ["Serialization", "Sockets"] +git-tree-sha1 = "9c4708e3ed2b799e6124b5673a712dda0b596a9b" +uuid = "f0e56b4a-5159-44fe-b623-3e5288b988bb" +version = "2.3.1" + +[[deps.Coverage]] +deps = ["CoverageTools", "HTTP", "JSON", "LibGit2", "MbedTLS"] +git-tree-sha1 = "4fb5effc927fddc76a213dc4b1871dc41b666686" +uuid = "a2441757-f6aa-5fb2-8edb-039e3f45d037" +version = "1.6.0" + +[[deps.CoverageTools]] +git-tree-sha1 = "cc5595feb314d3b226ed765a001a40ca451ad687" +uuid = "c36e975a-824b-4404-a568-ef97ca766997" +version = "1.3.0" + +[[deps.Dates]] +deps = ["Printf"] +uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" + +[[deps.ExceptionUnwrapping]] +deps = ["Test"] +git-tree-sha1 = "dcb08a0d93ec0b1cdc4af184b26b591e9695423a" +uuid = "460bff9d-24e4-43bc-9d9f-a8973cb893f4" +version = "0.1.10" + +[[deps.HTTP]] +deps = ["Base64", "CodecZlib", "ConcurrentUtilities", "Dates", "ExceptionUnwrapping", "Logging", "LoggingExtras", "MbedTLS", "NetworkOptions", "OpenSSL", "Random", "SimpleBufferStream", "Sockets", "URIs", "UUIDs"] +git-tree-sha1 = "db864f2d91f68a5912937af80327d288ea1f3aee" +uuid = "cd3eb016-35fb-5094-929b-558a96fad6f3" +version = "1.10.3" + +[[deps.InteractiveUtils]] +deps = ["Markdown"] +uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" + +[[deps.JLLWrappers]] +deps = ["Artifacts", "Preferences"] +git-tree-sha1 = "7e5d6779a1e09a36db2a7b6cff50942a0a7d0fca" +uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210" +version = "1.5.0" + +[[deps.JSON]] +deps = ["Dates", "Mmap", "Parsers", "Unicode"] +git-tree-sha1 = "31e996f0a15c7b280ba9f76636b3ff9e2ae58c9a" +uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" +version = "0.21.4" + +[[deps.LibGit2]] +deps = ["Base64", "LibGit2_jll", "NetworkOptions", "Printf", "SHA"] +uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" + +[[deps.LibGit2_jll]] +deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll"] +uuid = "e37daf67-58a4-590a-8e99-b0245dd2ffc5" +version = "1.6.4+0" + +[[deps.LibSSH2_jll]] +deps = ["Artifacts", "Libdl", "MbedTLS_jll"] +uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" +version = "1.11.0+1" + +[[deps.Libdl]] +uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" + +[[deps.Logging]] +uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" + +[[deps.LoggingExtras]] +deps = ["Dates", "Logging"] +git-tree-sha1 = "c1dd6d7978c12545b4179fb6153b9250c96b0075" +uuid = "e6f89c97-d47a-5376-807f-9c37f3926c36" +version = "1.0.3" + +[[deps.Markdown]] +deps = ["Base64"] +uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" + +[[deps.MbedTLS]] +deps = ["Dates", "MbedTLS_jll", "MozillaCACerts_jll", "NetworkOptions", "Random", "Sockets"] +git-tree-sha1 = "c067a280ddc25f196b5e7df3877c6b226d390aaf" +uuid = "739be429-bea8-5141-9913-cc70e7f3736d" +version = "1.1.9" + +[[deps.MbedTLS_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" +version = "2.28.2+1" + +[[deps.Mmap]] +uuid = "a63ad114-7e13-5084-954f-fe012c677804" + +[[deps.MozillaCACerts_jll]] +uuid = "14a3606d-f60d-562e-9121-12d972cd8159" +version = "2023.1.10" + +[[deps.NetworkOptions]] +uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" +version = "1.2.0" + +[[deps.OpenSSL]] +deps = ["BitFlags", "Dates", "MozillaCACerts_jll", "OpenSSL_jll", "Sockets"] +git-tree-sha1 = "af81a32750ebc831ee28bdaaba6e1067decef51e" +uuid = "4d8831e6-92b7-49fb-bdf8-b643e874388c" +version = "1.4.2" + +[[deps.OpenSSL_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "60e3045590bd104a16fefb12836c00c0ef8c7f8c" +uuid = "458c3c95-2e84-50aa-8efc-19380b2a3a95" +version = "3.0.13+0" + +[[deps.Parsers]] +deps = ["Dates", "PrecompileTools", "UUIDs"] +git-tree-sha1 = "8489905bcdbcfac64d1daa51ca07c0d8f0283821" +uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" +version = "2.8.1" + +[[deps.PrecompileTools]] +deps = ["Preferences"] +git-tree-sha1 = "03b4c25b43cb84cee5c90aa9b5ea0a78fd848d2f" +uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a" +version = "1.2.0" + +[[deps.Preferences]] +deps = ["TOML"] +git-tree-sha1 = "9306f6085165d270f7e3db02af26a400d580f5c6" +uuid = "21216c6a-2e73-6563-6e65-726566657250" +version = "1.4.3" + +[[deps.Printf]] +deps = ["Unicode"] +uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" + +[[deps.Random]] +deps = ["SHA"] +uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" + +[[deps.SHA]] +uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" +version = "0.7.0" + +[[deps.Serialization]] +uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" + +[[deps.SimpleBufferStream]] +git-tree-sha1 = "874e8867b33a00e784c8a7e4b60afe9e037b74e1" +uuid = "777ac1f9-54b0-4bf8-805c-2214025038e7" +version = "1.1.0" + +[[deps.Sockets]] +uuid = "6462fe0b-24de-5631-8697-dd941f90decc" + +[[deps.TOML]] +deps = ["Dates"] +uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" +version = "1.0.3" + +[[deps.Test]] +deps = ["InteractiveUtils", "Logging", "Random", "Serialization"] +uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[[deps.TranscodingStreams]] +git-tree-sha1 = "3caa21522e7efac1ba21834a03734c57b4611c7e" +uuid = "3bb67fe8-82b1-5028-8e26-92a6c54297fa" +version = "0.10.4" +weakdeps = ["Random", "Test"] + + [deps.TranscodingStreams.extensions] + TestExt = ["Test", "Random"] + +[[deps.URIs]] +git-tree-sha1 = "67db6cc7b3821e19ebe75791a9dd19c9b1188f2b" +uuid = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4" +version = "1.5.1" + +[[deps.UUIDs]] +deps = ["Random", "SHA"] +uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" + +[[deps.Unicode]] +uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" + +[[deps.Zlib_jll]] +deps = ["Libdl"] +uuid = "83775a58-1f1d-513f-b197-d71354ab007a" +version = "1.2.13+1" diff --git a/dev/Project.toml b/dev/Project.toml new file mode 100644 index 0000000..4fbdc47 --- /dev/null +++ b/dev/Project.toml @@ -0,0 +1,2 @@ +[deps] +Coverage = "a2441757-f6aa-5fb2-8edb-039e3f45d037" diff --git a/dev/coverage.jl b/dev/coverage.jl new file mode 100644 index 0000000..ed0fa73 --- /dev/null +++ b/dev/coverage.jl @@ -0,0 +1,21 @@ +# Usage: +# > julia coverage.jl +# in terminal + +import Pkg + +Pkg.activate("../") +Pkg.resolve() + +import Coverage + +Pkg.test(coverage = true) + +tested, total = Coverage.process_folder("../") |> Coverage.get_summary + +ratio = tested / total + +Coverage.clean_folder("../") + + +@info "Coverage: $ratio" \ No newline at end of file diff --git a/src/Comodo.jl b/src/Comodo.jl index 82b4e22..a298baa 100644 --- a/src/Comodo.jl +++ b/src/Comodo.jl @@ -38,5 +38,8 @@ export slidercontrol # Export types/structs export ConnectivitySet +# Export imported packages +export GeometryBasics + end # module diff --git a/src/functions.jl b/src/functions.jl index 04f0832..5d69fec 100644 --- a/src/functions.jl +++ b/src/functions.jl @@ -134,13 +134,13 @@ represent ordered data representing a curve. function interp_biharmonic_spline(x::Union{Vector{T}, AbstractRange{T}},y::Union{Vector{T}, AbstractRange{T}},xi::Union{Vector{T}, AbstractRange{T}}; extrapolate_method=:linear,pad_data=:linear) where T<:Real # Pad data if needed - if isa(x,AbstractRange{eltype(x)}) + if isa(x,AbstractRange{T}) xx = collect(x) else xx = deepcopy(x) end - if isa(y,AbstractRange{eltype(y)}) + if isa(y,AbstractRange{T}) yy = collect(y) else yy = deepcopy(y) @@ -179,7 +179,7 @@ function interp_biharmonic_spline(x::Union{Vector{T}, AbstractRange{T}},y::Union elseif pad_data==:none # No padding else - error(""" Invalid pad_data method provided, valued options are: linear, constant, and none """) + error("Invalid pad_data method provided, valued options are :linear, :constant, and :none") end # Change behaviour depending on extrapolation method @@ -214,12 +214,13 @@ function interp_biharmonic_spline(x::Union{Vector{T}, AbstractRange{T}},y::Union # Allow extrapolation as per the biharmonic function yi = interp_biharmonic(xx,yy,xi) else - error(""" Invalid extrapolate_method method provided, valued options are: linear, constant, and biharmonic """) + error("Invalid extrapolate_method method provided, valued options are :linear, :constant, and :biharmonic") end return yi end + """ interp_biharmonic(x,y,xi) @@ -300,12 +301,13 @@ end function lerp_(x,y,xi) j = findfirst(x.>xi) - if j==1 # Deal with extrapolation at the start - i=1 - j=2 - elseif isnothing(j) # Deal with extrapolation at the end + + if isnothing(j) # Deal with extrapolation at the end j = length(x) i = j-1 + elseif isone(j) # Deal with extrapolation at the start + i=1 + j=2 else i = j-1 end @@ -369,10 +371,10 @@ function mindist(V1,V2; getIndex=false, skipSelf = false ) end end -function unique_dict_index(X; sort_entries=false) +function unique_dict_index(X::AbstractVector{T}; sort_entries=false) where T<:Real # Here a normal Dict is used to keep track of unique elements. Normal dicts do not maintain element insertion order. # Hence the unique indices need to seperately be tracked. - T = eltype(X) + # T = eltype(X) d = Dict{T,Nothing}() # Use dict to keep track of used values xUni = Vector{T}() indUnique = Vector{Int64}() @@ -419,10 +421,10 @@ function unique_dict_index_inverse(X; sort_entries=false) return xUni, indUnique, indInverse end -function unique_dict_index_count(X; sort_entries=false) +function unique_dict_index_count(X::AbstractVector{T}; sort_entries=false) where T<:Real # Here a normal Dict is used to keep track of unique elements. Normal dicts do not maintain element insertion order. # Hence the unique indices need to seperately be tracked. - T = eltype(X) + # T = eltype(X) d = Dict{T,Int64}() # Use dict to keep track of used values xUni = Vector{T}() indUnique = Vector{Int64}() @@ -448,10 +450,10 @@ function unique_dict_index_count(X; sort_entries=false) return xUni, indUnique, c end -function unique_dict_index_inverse_count(X; sort_entries=false) +function unique_dict_index_inverse_count(X::AbstractVector{T}; sort_entries=false) where T <: Real # Here a normal Dict is used to keep track of unique elements. Normal dicts do not maintain element insertion order. # Hence the unique indices need to seperately be tracked. - T = eltype(X) + # T = eltype(X) d = Dict{T,Int64}() # Use dict to keep track of used values xUni = Vector{T}() indUnique = Vector{Int64}() @@ -480,10 +482,10 @@ function unique_dict_index_inverse_count(X; sort_entries=false) return xUni, indUnique, indInverse,c end -function unique_dict_count(X; sort_entries=false) +function unique_dict_count(X::AbstractVector{T}; sort_entries=false) where T <: Real # Here a normal Dict is used to keep track of unique elements. Normal dicts do not maintain element insertion order. # Hence the unique indices need to seperately be tracked. - T = eltype(X) + # T = eltype(X) d = Dict{T,Int64}() # Use dict to keep track of used values xUni = Vector{T}() c = Vector{Int64}() @@ -506,10 +508,10 @@ function unique_dict_count(X; sort_entries=false) return xUni, c end -function unique_dict_inverse(X; sort_entries=false) +function unique_dict_inverse(X::AbstractVector{T}; sort_entries=false) where T <: Real # Here a normal Dict is used to keep track of unique elements. Normal dicts do not maintain element insertion order. # Hence the unique indices need to seperately be tracked. - T = eltype(X) + # T = eltype(X) d = Dict{T,Int64}() # Use dict to keep track of used values xUni = Vector{T}() indInverse = Vector{Int64}(undef,length(X)) @@ -579,7 +581,7 @@ function ind2sub(siz,ind) m = prod(siz) if any(ind.>m) || any(ind.<1) - error("Encountered index value of out of valid range 1:"*string(m)) + error("Encountered index value of out of valid range 1:$m") end if length(ind)>1 @@ -597,7 +599,7 @@ function ind2sub_(ind,numDim,k) a = Vector{Int64}(undef,numDim) # Initialise a for q ∈ numDim:-1:1 # For all dimensions - if q==1 # First 1st dimension + if isone(q) # First 1st dimension a[1] = rem(ind-1,k[1]) + 1 else p = rem(ind-1,k[q-1]) + 1 # "previous" @@ -870,20 +872,20 @@ end function togeometrybasics_faces(FM::Matrix{Int64}) # Loop over face matrix and convert to GeometryBasics vector of Faces (e.g. QuadFace, or TriangleFace) - if size(FM,2)==3 # Triangles - F = Vector{TriangleFace{Int64}}(undef,size(FM,1)) - for q ∈ 1:1:size(FM,1) + n, m = size(FM) + if m == 3 # Triangles + F = Vector{TriangleFace{Int64}}(undef, n) + for q ∈ 1:1:n F[q] = TriangleFace{Int64}(FM[q,:]) end - elseif size(FM,2)==4 # Quads - F = Vector{QuadFace{Int64}}(undef,size(FM,1)) - for q ∈ 1:1:size(FM,1) + elseif m == 4 # Quads + F = Vector{QuadFace{Int64}}(undef, n) + for q ∈ 1:1:n F[q] = QuadFace{Int64}(FM[q,:]) end else # Other mesh type - m=size(FM,2) - F = Vector{m,NgonFace{Int64}}(undef,size(FM,1)) - for q ∈ 1:1:size(FM,1) + F = Vector{m,NgonFace{Int64}}(undef, n) + for q ∈ 1:1:n F[q] = NgonFace{m,Int64}(FM[q,:]) end end @@ -892,26 +894,29 @@ end function togeometrybasics_points(VM) # Loop over vertex matrix and convert to GeometryBasics vector of Points - V=Vector{GeometryBasics.Point{3, Float64}}(undef,length(VM)) - for q ∈ 1:1:size(VM,1) + n = length(VM) + V=Vector{GeometryBasics.Point{3, Float64}}(undef, n) + for q ∈ 1:1:n V[q] = GeometryBasics.Point{3, Float64}(VM[q]) end return V end function togeometrybasics_points(VM::Matrix{Float64}) + n = length(VM) # Loop over vertex matrix and convert to GeometryBasics vector of Points - V=Vector{GeometryBasics.Point{3, Float64}}(undef,size(VM,1)) - for q ∈ 1:1:size(VM,1) + V=Vector{GeometryBasics.Point{3, Float64}}(undef, n) + for q ∈ 1:1:n V[q] = GeometryBasics.Point{3, Float64}(VM[q,:]) end return V end function togeometrybasics_points(VM::Vector{Vector{Int64}}) + n = length(VM) # Loop over vertex matrix and convert to GeometryBasics vector of Points - V=Vector{GeometryBasics.Point{3, Float64}}(undef,length(VM)) - for q ∈ 1:1:size(VM,1) + V=Vector{GeometryBasics.Point{3, Float64}}(undef, n) + for q ∈ 1:1:n V[q] = GeometryBasics.Point{3, Float64}(VM[q]) end return V @@ -996,7 +1001,7 @@ r::Float64, defining circumsphere radius """ function platonicsolid(n::Integer,r=1.0) - if n==1 + if isone(n) M = tetrahedron(r) elseif n==2 M = cube(r) @@ -1010,8 +1015,8 @@ function platonicsolid(n::Integer,r=1.0) return M end -function unique_dict(X) - d = OrderedDict{eltype(X),Int64}() # Use dict to keep track of used values +function unique_dict(X::AbstractVector{T}) where T <: Real + d = OrderedDict{T ,Int64}() # Use dict to keep track of used values indUnique = Vector{Int64}() indReverse = Vector{Int64}(undef,length(X)) # c = Vector{Int64}() @@ -1044,9 +1049,9 @@ end function subtri(F,V,n; method = :linear) - if n==0 + if iszero(n) return F,V - elseif n==1 + elseif isone(n) E = meshedges(F) Eu,_,indReverse = gunique(E; return_unique=true, return_index=true, return_inverse=true, sort_entries=true) @@ -1107,7 +1112,7 @@ function subtri(F,V,n; method = :linear) # Create complete point set Vn = [Vv;Vm] # Updated orignals and new "mid-edge-ish" points else - error("""Incorrect metod. Use: "linear" or "loop" """) + error("Incorrect metod. Use :linear or :loop") end return Fn,Vn @@ -1121,9 +1126,9 @@ function subtri(F,V,n; method = :linear) end function subquad(F,V,n; method=:linear) - if n==0 + if iszero(n) return F,V - elseif n==1 + elseif isone(n) # Get edges E = meshedges(F) # Non-unique edges @@ -1264,7 +1269,7 @@ function hexbox(boxDim,boxEl) end F_uni,indUni,c_uni = gunique(F,return_index=true, return_inverse=false,return_counts=true,sort_entries=true) - Lb = c_uni.==1 + Lb = isone.(c_uni) Fb = F_uni[Lb] CF_type_uni = CF_type[indUni] CFb_type = CF_type_uni[Lb] @@ -1696,7 +1701,6 @@ latter, triangles are formed by slashing the quads. """ function loftlinear(V1,V2;num_steps=2,close_loop=true,face_type=:tri) - num_loop = length(V1) T = eltype(V1) # Linearly blending points from first to last @@ -1815,7 +1819,7 @@ function normalplot(ax,M; type_flag=:face, color=:black,linewidth=3,scaleval=mis elseif type_flag == :vertex N = vertexnormal(F,V) else - error(""" Incorrect type_flag, use :face or :vertex """) + error("Incorrect type_flag, use :face or :vertex") end hp = dirplot(ax,V,N; color=color,linewidth=linewidth,scaleval=scaleval,style=:from) @@ -1824,13 +1828,19 @@ function normalplot(ax,M; type_flag=:face, color=:black,linewidth=3,scaleval=mis return hp end -function wrapindex(i::UnitRange{Int64},n) - return 1 .+ mod.(i .+ (n-1),n) -end +# function wrapindex(i::UnitRange{Int64},n) +# return 1 .+ mod.(i .+ (n-1),n) +# end +# +# function wrapindex(i::Vector{Int64},n) +# return 1 .+ mod.(i .+ (n-1),n) +# end -function wrapindex(i::Vector{Int64},n) +# Both Vector{Int64} and UnitRange{Int64} are subtypes of +# AbstractVector{Int64} +function wrapindex(i::AbstractVector{Int64}, n) return 1 .+ mod.(i .+ (n-1),n) -end +end function wrapindex(i::Int64,n) return 1+mod(i+(n-1),n) @@ -1854,7 +1864,7 @@ function edgeangles(F,V) return A end -function quad2tri(F,V; convert_method = :angle) +function quad2tri(F,V; convert_method = :angle)::Vector{TriangleFace{Int64}} # Local functions for slash based conversion forw_slash(f) = [[f[1],f[2],f[3]],[f[3],f[4],f[1]]] # Forward slash back_slash(f) = [[f[1],f[2],f[4]],[f[2],f[3],f[4]]] # Back slash @@ -1880,7 +1890,7 @@ function quad2tri(F,V; convert_method = :angle) ft = fb end else - error("""Incorrect conver_method set, use forward, backward, or angle """) + error("Incorrect conver_method set, use :forward, :backward, or :angle") end push!(Ft,ft[1]) push!(Ft,ft[2]) @@ -1888,7 +1898,7 @@ function quad2tri(F,V; convert_method = :angle) return Ft end -function remove_unused_vertices(F,V) +function remove_unused_vertices(F,V)::Tuple T = eltype(F) indUsed = elements2indices(F) Vc = V[indUsed] # Remove unused points @@ -1922,7 +1932,7 @@ function trisurfslice(F,V,n = (0.0,0.0,1.0), p = mean(V,dims=1); snapTolerance = end else # Some below -> cut nBelow = sum(lf) # Number of nodes below - if nBelow==1 # 2-above, 1 below + if isone(nBelow) # 2-above, 1 below indP = f[wrapindex(findfirst(lf) .+ (0:2),3)] e1 = sort(indP[[1,2]]) @@ -1976,7 +1986,7 @@ function trisurfslice(F,V,n = (0.0,0.0,1.0), p = mean(V,dims=1); snapTolerance = return remove_unused_vertices(Fn,Vn) end -function count_edge_face(F,E_uni=missing,indReverse=missing) +function count_edge_face(F,E_uni=missing,indReverse=missing)::Vector{Int64} if ismissing(E_uni) || ismissing(indReverse) E = meshedges(F) E_uni,_,indReverse = gunique(E; return_unique=true, return_index=true, return_inverse=true, sort_entries=true) @@ -1996,7 +2006,7 @@ function boundaryedges(F) E = meshedges(F) Eu,_,indReverse = gunique(E; return_unique=true, return_index=true, return_inverse=true, sort_entries=true) count_E2F = count_edge_face(F,Eu,indReverse) - return Eu[count_E2F.==1] + return Eu[isone.(count_E2F)] end function edges2curve(Eb) @@ -2021,7 +2031,7 @@ function edges2curve(Eb) return ind end -function pointspacingmean(V) +function pointspacingmean(V)::Float64 # Equivalent to: mean(norm.(diff(V,dims=1))) p = 0.0 n = length(V) @@ -2038,11 +2048,11 @@ function extrudecurve(V1,d; s=1, n=Point{3, Float64}(0.0,0.0,1.0),num_steps=miss num_steps = num_steps + Int64(iseven(num_steps)) # Force uneven end end - if s==1 # Allong n from V1 + if isone(s) # Allong n from V1 p = d.*n - elseif s==-1 # Against n from V1 + elseif isone(-s) # Against n from V1 p = -d.*n - elseif s==0 # Extrude both ways from V1 + elseif iszero(s) # Extrude both ways from V1 p = d.*n V1 = [(eltype(V1))(v.-p./2) for v ∈ V1] #Shift V1 in negative direction end @@ -2068,7 +2078,7 @@ function meshgroup(F; con_type = :v) # FACE-FACE connectivity con_F2F = con_face_face(F,E_uni,indReverse,con_E2F,con_F2E) else - error(""" Wrong `con_type`, use :v or :e """) + error("Wrong `con_type`, use :v or :e") end if all(isempty.(con_F2F)) # Completely disconnected face set (e.g. raw STL import) @@ -2100,7 +2110,7 @@ function meshgroup(F; con_type = :v) end if np == length(seen) # Group full c += 1 # Increment group counter - i = findfirst(C.==0) + i = findfirst(iszero.(C)) end end end diff --git a/test/Project.toml b/test/Project.toml index df0d618..0c36332 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -1,3 +1,2 @@ [deps] -GeometryBasics = "5c1252a2-5f33-56bf-86c9-59e7332b4326" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/test/runtests.jl b/test/runtests.jl index 42ad9d9..f6f1fb3 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,4 +1,4 @@ -using Test, Comodo, GeometryBasics +using Test, Comodo, Comodo.GeometryBasics @testset "elements2indices" verbose = true begin @testset "Tri. faces" begin @@ -251,6 +251,24 @@ Ci = interp_biharmonic([[0.0, 0.0, -1.0], [0.0, 0.0, 1.0]], [-10, 10], [[0.0, 0. @test result == [0.0 0.0 5.0; 0.0 0.0 5.0; 0.0 0.0 5.0] end + @testset "vectors to vector" begin + eps = 0.001 + v1 = [[1, 2, 3], [0, 0, 0]] + v2 = [0, 0, 0] + result = dist(v1, v2) + @test result isa Matrix + @test isapprox(result, [3.7416573867739413; 0.0;;], atol = eps) + end + + @testset "vector to vectors" begin + eps = 0.001 + v1 = [[1, 2, 3], [0, 0, 0]] + v2 = [0, 0, 0] + result = dist(v2, v1) + @test result isa Matrix + @test isapprox(result, [3.7416573867739413 0.0], atol = eps) + end + @testset "vector of points to vector of points" begin V1 = Vector{GeometryBasics.Point{3,Float64}}(undef, 4) V1[1] = GeometryBasics.Point{3,Float64}(1.0, 0.0, 0.0) @@ -628,4 +646,96 @@ end @test isapprox(S.spline.basis.M.left[2], Float64[1.2080446399615536 0.0; 0.7919553600384465 0.5123829689520382; 0.0 1.4876170310479617], atol=eps) -end \ No newline at end of file +end + + +@testset "nbezier" begin + + eps = 0.001 + + P = Vector{GeometryBasics.Point{3, Float64}}(undef,4) + P[1 ] = GeometryBasics.Point{3, Float64}( 0.0, 0.0, 0.0) + P[2 ] = GeometryBasics.Point{3, Float64}( 1.0, 0.0, 0.0) + P[3 ] = GeometryBasics.Point{3, Float64}( 1.0, 1.0, 0.0) + P[4 ] = GeometryBasics.Point{3, Float64}( 1.0, 1.0, 1.0) + + n = 25 # Number of points + + V = nbezier(P,n) # Get Bezier fit points + + expected = Point3{Float64}[[0.0, 0.0, 0.0], [0.11986400462962965, 0.005063657407407407, 7.233796296296296e-5], [0.22974537037037032, 0.019675925925925923, 0.0005787037037037037], [0.330078125, 0.04296875, 0.001953125], [0.4212962962962963, 0.07407407407407407, 0.004629629629629629], [0.503833912037037, 0.11212384259259262, 0.009042245370370372], [0.578125, 0.15625, 0.015625], [0.6446035879629629, 0.20558449074074078, 0.024811921296296304], [0.7037037037037037, 0.25925925925925924, 0.037037037037037035], [0.755859375, 0.31640625, 0.052734375], [0.8015046296296295, 0.3761574074074074, 0.07233796296296298], [0.8410734953703705, 0.43764467592592593, 0.09628182870370369], [0.875, 0.5, 0.125], [0.9037181712962963, 0.562355324074074, 0.1589265046296296], [0.9276620370370372, 0.6238425925925928, 0.19849537037037043], [0.947265625, 0.68359375, 0.244140625], [0.9629629629629629, 0.7407407407407407, 0.2962962962962963], [0.9751880787037037, 0.7944155092592593, 0.3553964120370371], [0.984375, 0.84375, 0.421875], [0.9909577546296297, 0.8878761574074074, 0.4961660879629629], [0.9953703703703705, 0.925925925925926, 0.5787037037037038], [0.998046875, 0.95703125, 0.669921875], [0.9994212962962963, 0.9803240740740741, 0.7702546296296295], [0.9999276620370372, 0.9949363425925927, 0.8801359953703706], [1.0, 1.0, 1.0]] + + @test typeof(V) == Vector{Point3{Float64}} + + @test isapprox(V, expected, atol = eps) + +end + +@testset "mindist" begin + + eps = 0.01 + + V1 = [[1, 2, 3], [0, 0, 0]] + V2 = [[4, 5, 6], [0, 0, 0]] + + result = mindist(V1, V2) + + @test result isa Vector{Float64} + + @test isapprox(result, [3.7416573867739413, 0.0], atol = eps) + +end + + +@testset "unique_dict_index" begin + + result1, result2 = Comodo.unique_dict_index([1, 2, 3, 3, 3, 4, 4, 4, 5]) + + @test result1 == [1, 2, 3, 4, 5] + @test result2 == [1, 2, 3, 6, 9] + +end + + +@testset "unique_dict_index_count" begin + + result1, result2, result3 = Comodo.unique_dict_index_count([1, 2, 3, 3, 3, 4, 4, 4, 5]) + + @test result1 == [1, 2, 3, 4, 5] + @test result2 == [1, 2, 3, 6, 9] + @test result3 == [1, 1, 3, 3, 1] + +end + + +@testset "unique_dict_index_inverse_count" begin + + r1, r2, r3, r4 = Comodo.unique_dict_index_inverse_count([1, 2, 3, 3, 3, 4, 4, 4, 5]) + + @test r1 == [1, 2, 3, 4, 5] + @test r2 == [1, 2, 3, 6, 9] + @test r3 == [1, 2, 3, 3, 3, 4, 4, 4, 5] + @test r4 == [1, 1, 3, 3, 1] + +end + + +@testset "unique_dict_count" begin + + result1, result2 = Comodo.unique_dict_count([1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 5]) + + @test result1 == [1, 2, 3, 4, 5] + @test result2 == [3, 4, 2, 1, 1] + +end + + +@testset "unique_dict_inverse" begin + + result1, result2 = Comodo.unique_dict_inverse([1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 5]) + + @test result1 == [1, 2, 3, 4, 5] + @test result2 == [1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 5] + +end +