diff --git a/Project.toml b/Project.toml index 169fbd6..7ad59b5 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "GridVisualize" uuid = "5eed8a63-0fb0-45eb-886d-8d5a387d12b8" authors = ["Juergen Fuhrmann "] -version = "1.4.1" +version = "1.5.0" [deps] ColorSchemes = "35d6a980-a343-548e-a6ea-1d62b119f2f4" @@ -20,13 +20,6 @@ OrderedCollections = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" -[weakdeps] -CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0" -GLMakie = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a" -Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" -PlutoVista = "646e1f28-b900-46d7-9d87-d554eb38a413" -PyPlot = "d330b81b-6aea-500a-939a-2ce795aea3ee" - [compat] CairoMakie = "0.11.3" ColorSchemes = "3" @@ -36,7 +29,7 @@ ElasticArrays = "1" ExtendableGrids = "0.9,1" GLMakie = "0.9" GeometryBasics = "0.4.1" -GridVisualizeTools = "0.3,1" +GridVisualizeTools = "1.1" HypertextLiteral = "0.9" Interpolations = "0.14, 0.15" IntervalSets = "0.7" @@ -56,3 +49,10 @@ GLMakie = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a" Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" PlutoVista = "646e1f28-b900-46d7-9d87-d554eb38a413" PyPlot = "d330b81b-6aea-500a-939a-2ce795aea3ee" + +[weakdeps] +CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0" +GLMakie = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a" +Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" +PlutoVista = "646e1f28-b900-46d7-9d87-d554eb38a413" +PyPlot = "d330b81b-6aea-500a-939a-2ce795aea3ee" diff --git a/docs/makeplots.jl b/docs/makeplots.jl index 1444723..a95493d 100644 --- a/docs/makeplots.jl +++ b/docs/makeplots.jl @@ -75,6 +75,13 @@ function makeplots(picdir; Plotter = GLMakie, extension = "png") fname = joinpath(picdir, "plotting_movie." * "gif") p = plotting_movie(; filename = fname, Plotter = Plotter) @test isfile(fname) - println("plotting_movie") + println("movie") + + p = plotting_custom(; Plotter = Plotter) + fname = joinpath(picdir, "plotting_custom." * extension) + save(fname, p; Plotter = Plotter) + @test isfile(fname) + println("custom") + true end diff --git a/docs/src/api.md b/docs/src/api.md index 3bc09aa..d1cd5c5 100644 --- a/docs/src/api.md +++ b/docs/src/api.md @@ -45,10 +45,19 @@ streamplot streamplot! ``` +## Custom plots +```@docs +customplot +customplot! +``` ## Keyword Arguments ```@docs available_kwargs ``` - +## Supporting methods +```@docs +vectorsample +quiverdata +``` diff --git a/examples/plotting.jl b/examples/plotting.jl index 7f2cfd8..4dd41bf 100644 --- a/examples/plotting.jl +++ b/examples/plotting.jl @@ -72,7 +72,7 @@ end # ![](plotting_func1d.svg) # ### Function on 2D grid -function func2d(; n = 20) +function func2d(; n = 30) g = grid2d(; n = n) g, map((x, y) -> sinpi(2 * x) * sinpi(3.5 * y), g) end @@ -119,17 +119,17 @@ function vec2d(; n = 20) map((x, y) -> cospi(2 * x) * cospi(3.5 * y), g)') end -function plotting_vec2d(; Plotter = default_plotter(), kwargs...) - g, f = vec2d() +function plotting_vec2d(; Plotter = default_plotter(), n = 20, kwargs...) + g, f = vec2d(; n = n) vectorplot(g, f; Plotter = Plotter, kwargs...) end # ![](plotting_vec2d.svg) # ### 2D stream # Stream plots are currently only available with PyPlot and Makie -function plotting_stream2d(; Plotter = default_plotter(), kwargs...) - g, f = vec2d() - GridVisualize.streamplot(g, f; Plotter = Plotter, spacing = 0.01, kwargs...) +function plotting_stream2d(; Plotter = default_plotter(), n = 50, kwargs...) + g, f = vec2d(; n = n) + GridVisualize.streamplot(g, f; Plotter = Plotter, rasterpoints = 100, kwargs...) end # ![](plotting_stream2d.svg) @@ -216,8 +216,8 @@ function plotting_multiscene(; Plotter = default_plotter(), resolution = (1000, end # ![](plotting_multiscene.svg) -# ## Plots of functions on subgrids interfaces -# We can jointly plot functions on different subgrids whic +# ## Plots of functions on subgrids +# We can jointly plot functions on different subgrids which # e.g. model a particle density jumping at a heterointerface # Currently supported for PyPlot and Makie # @@ -306,3 +306,18 @@ function plotting_jfunc3d(; end # ![](plotting_jfunc3d.svg) + +# ## Custom plots +function plotting_custom(; Plotter = default_plotter(), kwargs...) + vis = GridVisualizer(; Plotter = Plotter) + grid = grid2d() + gridplot!(vis, grid) + customplot!(vis) do ax + ismakie(Plotter) && Plotter.scatter!(ax, rand(10), rand(10), fill(0.1, 10); color = :blue, markersize = 20) + ispyplot(Plotter) && ax.scatter(rand(10), rand(10); s = 500) + isplots(Plotter) && Plotter.scatter!(ax, rand(10), rand(10); color = :blue, markersize = 10, label = nothing) + end + reveal(vis) +end + +# ![](plotting_custom.svg) diff --git a/examples/plutovista.jl b/examples/plutovista.jl index 7ad6065..8aea82f 100644 --- a/examples/plutovista.jl +++ b/examples/plutovista.jl @@ -1,5 +1,5 @@ ### A Pluto.jl notebook ### -# v0.19.32 +# v0.19.35 using Markdown using InteractiveUtils @@ -348,7 +348,7 @@ function qv2d(; n = 20, stream = false, kwargs...) end # ╔═╡ 812af347-7606-4c54-b155-88322d20d921 -qv2d(; n = 50, spacing = 0.5) +qv2d(; n = 50, rasterpoints=16) # ╔═╡ 09998521-68b6-45b4-8c1d-ae73bbd431ad md""" @@ -431,646 +431,6 @@ gridplot(simplexgrid(XX, YY); aspect = 0.1) # ╔═╡ ba5111b8-0dca-42d2-970f-1e88f5392324 html"""
""" -# ╔═╡ 00000000-0000-0000-0000-000000000001 -PLUTO_PROJECT_TOML_CONTENTS = """ -[deps] -ExtendableGrids = "cfc395e8-590f-11e8-1f13-43a2532b2fa8" -GridVisualize = "5eed8a63-0fb0-45eb-886d-8d5a387d12b8" -HypertextLiteral = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2" -Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" -PlutoUI = "7f904dfe-b85e-4ff6-b463-dae2292396a8" -PlutoVista = "646e1f28-b900-46d7-9d87-d554eb38a413" -Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" - -[compat] -ExtendableGrids = "~1.1.0" -GridVisualize = "~1.1.7" -HypertextLiteral = "~0.9.4" -PlutoUI = "~0.7.52" -PlutoVista = "~1.0.1" -Revise = "~3.5.6" -""" - -# ╔═╡ 00000000-0000-0000-0000-000000000002 -PLUTO_MANIFEST_TOML_CONTENTS = """ -# This file is machine-generated - editing it directly is not advised - -julia_version = "1.9.4" -manifest_format = "2.0" -project_hash = "e16c3e55d1b87c5f4dccb5b049d023b943a3107e" - -[[deps.AbstractPlutoDingetjes]] -deps = ["Pkg"] -git-tree-sha1 = "91bd53c39b9cbfb5ef4b015e8b582d344532bd0a" -uuid = "6e696c72-6542-2067-7265-42206c756150" -version = "1.2.0" - -[[deps.AbstractTrees]] -git-tree-sha1 = "faa260e4cb5aba097a73fab382dd4b5819d8ec8c" -uuid = "1520ce14-60c1-5f80-bbc7-55ef81b5835c" -version = "0.4.4" - -[[deps.Adapt]] -deps = ["LinearAlgebra", "Requires"] -git-tree-sha1 = "76289dc51920fdc6e0013c872ba9551d54961c24" -uuid = "79e6a3ab-5dfb-504d-930d-738a2a938a0e" -version = "3.6.2" -weakdeps = ["StaticArrays"] - - [deps.Adapt.extensions] - AdaptStaticArraysExt = "StaticArrays" - -[[deps.ArgTools]] -uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" -version = "1.1.1" - -[[deps.Artifacts]] -uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" - -[[deps.Base64]] -uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" - -[[deps.Bijections]] -git-tree-sha1 = "71281c0c28f97e0adeed24fdaa6bf7d37177f297" -uuid = "e2ed5e7c-b2de-5872-ae92-c73ca462fb04" -version = "0.1.5" - -[[deps.CodeTracking]] -deps = ["InteractiveUtils", "UUIDs"] -git-tree-sha1 = "c0216e792f518b39b22212127d4a84dc31e4e386" -uuid = "da1fd8a2-8d9e-5ec2-8556-3022fb5608a2" -version = "1.3.5" - -[[deps.CodecZlib]] -deps = ["TranscodingStreams", "Zlib_jll"] -git-tree-sha1 = "02aa26a4cf76381be7f66e020a3eddeb27b0a092" -uuid = "944b1d66-785c-5afd-91f1-9de20f533193" -version = "0.7.2" - -[[deps.ColorSchemes]] -deps = ["ColorTypes", "ColorVectorSpace", "Colors", "FixedPointNumbers", "PrecompileTools", "Random"] -git-tree-sha1 = "67c1f244b991cad9b0aa4b7540fb758c2488b129" -uuid = "35d6a980-a343-548e-a6ea-1d62b119f2f4" -version = "3.24.0" - -[[deps.ColorTypes]] -deps = ["FixedPointNumbers", "Random"] -git-tree-sha1 = "eb7f0f8307f71fac7c606984ea5fb2817275d6e4" -uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f" -version = "0.11.4" - -[[deps.ColorVectorSpace]] -deps = ["ColorTypes", "FixedPointNumbers", "LinearAlgebra", "Requires", "Statistics", "TensorCore"] -git-tree-sha1 = "a1f44953f2382ebb937d60dafbe2deea4bd23249" -uuid = "c3611d14-8923-5661-9e6a-0046d554d3a4" -version = "0.10.0" - - [deps.ColorVectorSpace.extensions] - SpecialFunctionsExt = "SpecialFunctions" - - [deps.ColorVectorSpace.weakdeps] - SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b" - -[[deps.Colors]] -deps = ["ColorTypes", "FixedPointNumbers", "Reexport"] -git-tree-sha1 = "fc08e5930ee9a4e03f84bfb5211cb54e7769758a" -uuid = "5ae59095-9a9b-59fe-a467-6f913c188581" -version = "0.12.10" - -[[deps.Compat]] -deps = ["UUIDs"] -git-tree-sha1 = "8a62af3e248a8c4bad6b32cbbe663ae02275e32c" -uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" -version = "4.10.0" -weakdeps = ["Dates", "LinearAlgebra"] - - [deps.Compat.extensions] - CompatLinearAlgebraExt = "LinearAlgebra" - -[[deps.CompilerSupportLibraries_jll]] -deps = ["Artifacts", "Libdl"] -uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" -version = "1.0.5+0" - -[[deps.ConstructionBase]] -deps = ["LinearAlgebra"] -git-tree-sha1 = "c53fc348ca4d40d7b371e71fd52251839080cbc9" -uuid = "187b0558-2788-49d3-abe0-74a17ed4e7c9" -version = "1.5.4" - - [deps.ConstructionBase.extensions] - ConstructionBaseIntervalSetsExt = "IntervalSets" - ConstructionBaseStaticArraysExt = "StaticArrays" - - [deps.ConstructionBase.weakdeps] - IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953" - StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" - -[[deps.DataAPI]] -git-tree-sha1 = "8da84edb865b0b5b0100c0666a9bc9a0b71c553c" -uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a" -version = "1.15.0" - -[[deps.DataStructures]] -deps = ["Compat", "InteractiveUtils", "OrderedCollections"] -git-tree-sha1 = "3dbd312d370723b6bb43ba9d02fc36abade4518d" -uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" -version = "0.18.15" - -[[deps.DataValueInterfaces]] -git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6" -uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464" -version = "1.0.0" - -[[deps.Dates]] -deps = ["Printf"] -uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" - -[[deps.Distributed]] -deps = ["Random", "Serialization", "Sockets"] -uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b" - -[[deps.DocStringExtensions]] -deps = ["LibGit2"] -git-tree-sha1 = "2fb1e02f2b635d0845df5d7c167fec4dd739b00d" -uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" -version = "0.9.3" - -[[deps.Downloads]] -deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"] -uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" -version = "1.6.0" - -[[deps.EarCut_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "e3290f2d49e661fbd94046d7e3726ffcb2d41053" -uuid = "5ae413db-bbd1-5e63-b57d-d24a61df00f5" -version = "2.2.4+0" - -[[deps.ElasticArrays]] -deps = ["Adapt"] -git-tree-sha1 = "e1c40d78de68e9a2be565f0202693a158ec9ad85" -uuid = "fdbdab4c-e67f-52f5-8c3f-e7b388dad3d4" -version = "1.2.11" - -[[deps.ExtendableGrids]] -deps = ["AbstractTrees", "Bijections", "Dates", "DocStringExtensions", "ElasticArrays", "InteractiveUtils", "LinearAlgebra", "Printf", "Random", "Requires", "SparseArrays", "StaticArrays", "StatsBase", "Test", "WriteVTK"] -git-tree-sha1 = "3f0e26d8ba5603978daeb54aa02de4a52593c3f5" -uuid = "cfc395e8-590f-11e8-1f13-43a2532b2fa8" -version = "1.1.0" - - [deps.ExtendableGrids.extensions] - ExtendableGridsGmshExt = "Gmsh" - - [deps.ExtendableGrids.weakdeps] - Gmsh = "705231aa-382f-11e9-3f0c-b7cb4346fdeb" - -[[deps.Extents]] -git-tree-sha1 = "5e1e4c53fa39afe63a7d356e30452249365fba99" -uuid = "411431e0-e8b7-467b-b5e0-f676ba4f2910" -version = "0.1.1" - -[[deps.FileWatching]] -uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" - -[[deps.FillArrays]] -deps = ["LinearAlgebra", "Random"] -git-tree-sha1 = "a20eaa3ad64254c61eeb5f230d9306e937405434" -uuid = "1a297f60-69ca-5386-bcde-b61e274b549b" -version = "1.6.1" -weakdeps = ["SparseArrays", "Statistics"] - - [deps.FillArrays.extensions] - FillArraysSparseArraysExt = "SparseArrays" - FillArraysStatisticsExt = "Statistics" - -[[deps.FixedPointNumbers]] -deps = ["Statistics"] -git-tree-sha1 = "335bfdceacc84c5cdf16aadc768aa5ddfc5383cc" -uuid = "53c48c17-4a7d-5ca2-90c5-79b7896eea93" -version = "0.8.4" - -[[deps.GPUArraysCore]] -deps = ["Adapt"] -git-tree-sha1 = "2d6ca471a6c7b536127afccfa7564b5b39227fe0" -uuid = "46192b85-c4d5-4398-a991-12ede77f4527" -version = "0.1.5" - -[[deps.GeoInterface]] -deps = ["Extents"] -git-tree-sha1 = "d53480c0793b13341c40199190f92c611aa2e93c" -uuid = "cf35fbd7-0cd7-5166-be24-54bfbe79505f" -version = "1.3.2" - -[[deps.GeometryBasics]] -deps = ["EarCut_jll", "Extents", "GeoInterface", "IterTools", "LinearAlgebra", "StaticArrays", "StructArrays", "Tables"] -git-tree-sha1 = "424a5a6ce7c5d97cca7bcc4eac551b97294c54af" -uuid = "5c1252a2-5f33-56bf-86c9-59e7332b4326" -version = "0.4.9" - -[[deps.GridVisualize]] -deps = ["ColorSchemes", "Colors", "DocStringExtensions", "ElasticArrays", "ExtendableGrids", "GeometryBasics", "GridVisualizeTools", "HypertextLiteral", "LinearAlgebra", "Observables", "OrderedCollections", "Printf", "StaticArrays"] -git-tree-sha1 = "4d0fc636d5989043aaa240d54284ef92e68f0879" -uuid = "5eed8a63-0fb0-45eb-886d-8d5a387d12b8" -version = "1.1.7" - - [deps.GridVisualize.weakdeps] - CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0" - GLMakie = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a" - Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" - PlutoVista = "646e1f28-b900-46d7-9d87-d554eb38a413" - PyPlot = "d330b81b-6aea-500a-939a-2ce795aea3ee" - -[[deps.GridVisualizeTools]] -deps = ["ColorSchemes", "Colors", "DocStringExtensions", "StaticArraysCore"] -git-tree-sha1 = "5c7c69e512b6b65cdbc52cdaae1c75a0e186087a" -uuid = "5573ae12-3b76-41d9-b48c-81d0b6e61cc5" -version = "0.3.1" - -[[deps.Hyperscript]] -deps = ["Test"] -git-tree-sha1 = "8d511d5b81240fc8e6802386302675bdf47737b9" -uuid = "47d2ed2b-36de-50cf-bf87-49c2cf4b8b91" -version = "0.0.4" - -[[deps.HypertextLiteral]] -deps = ["Tricks"] -git-tree-sha1 = "c47c5fa4c5308f27ccaac35504858d8914e102f9" -uuid = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2" -version = "0.9.4" - -[[deps.IOCapture]] -deps = ["Logging", "Random"] -git-tree-sha1 = "d75853a0bdbfb1ac815478bacd89cd27b550ace6" -uuid = "b5f81e59-6552-4d32-b1f0-c071b021bf89" -version = "0.2.3" - -[[deps.InteractiveUtils]] -deps = ["Markdown"] -uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" - -[[deps.IrrationalConstants]] -git-tree-sha1 = "630b497eafcc20001bba38a4651b327dcfc491d2" -uuid = "92d709cd-6900-40b7-9082-c6be49f344b6" -version = "0.2.2" - -[[deps.IterTools]] -git-tree-sha1 = "4ced6667f9974fc5c5943fa5e2ef1ca43ea9e450" -uuid = "c8e1da08-722c-5040-9ed9-7db0dc04731e" -version = "1.8.0" - -[[deps.IteratorInterfaceExtensions]] -git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856" -uuid = "82899510-4779-5014-852e-03e436cf321d" -version = "1.0.0" - -[[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.JuliaInterpreter]] -deps = ["CodeTracking", "InteractiveUtils", "Random", "UUIDs"] -git-tree-sha1 = "0592b1810613d1c95eeebcd22dc11fba186c2a57" -uuid = "aa1ae85d-cabe-5617-a682-6adf51b2e16a" -version = "0.9.26" - -[[deps.LibCURL]] -deps = ["LibCURL_jll", "MozillaCACerts_jll"] -uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" -version = "0.6.4" - -[[deps.LibCURL_jll]] -deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"] -uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" -version = "8.4.0+0" - -[[deps.LibGit2]] -deps = ["Base64", "NetworkOptions", "Printf", "SHA"] -uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" - -[[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.Libiconv_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl"] -git-tree-sha1 = "f9557a255370125b405568f9767d6d195822a175" -uuid = "94ce4f54-9a6c-5748-9c1c-f9c7231a4531" -version = "1.17.0+0" - -[[deps.LightXML]] -deps = ["Libdl", "XML2_jll"] -git-tree-sha1 = "e129d9391168c677cd4800f5c0abb1ed8cb3794f" -uuid = "9c8b4983-aa76-5018-a973-4c85ecc9e179" -version = "0.9.0" - -[[deps.LinearAlgebra]] -deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"] -uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" - -[[deps.LogExpFunctions]] -deps = ["DocStringExtensions", "IrrationalConstants", "LinearAlgebra"] -git-tree-sha1 = "7d6dd4e9212aebaeed356de34ccf262a3cd415aa" -uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688" -version = "0.3.26" - - [deps.LogExpFunctions.extensions] - LogExpFunctionsChainRulesCoreExt = "ChainRulesCore" - LogExpFunctionsChangesOfVariablesExt = "ChangesOfVariables" - LogExpFunctionsInverseFunctionsExt = "InverseFunctions" - - [deps.LogExpFunctions.weakdeps] - ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" - ChangesOfVariables = "9e997f8a-9a97-42d5-a9f1-ce6bfc15e2c0" - InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112" - -[[deps.Logging]] -uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" - -[[deps.LoweredCodeUtils]] -deps = ["JuliaInterpreter"] -git-tree-sha1 = "60168780555f3e663c536500aa790b6368adc02a" -uuid = "6f1432cf-f94c-5a45-995e-cdbf5db27b0b" -version = "2.3.0" - -[[deps.MIMEs]] -git-tree-sha1 = "65f28ad4b594aebe22157d6fac869786a255b7eb" -uuid = "6c6e2e6c-3030-632d-7369-2d6c69616d65" -version = "0.1.4" - -[[deps.Markdown]] -deps = ["Base64"] -uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" - -[[deps.MbedTLS_jll]] -deps = ["Artifacts", "Libdl"] -uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" -version = "2.28.2+0" - -[[deps.Missings]] -deps = ["DataAPI"] -git-tree-sha1 = "f66bdc5de519e8f8ae43bdc598782d35a25b1272" -uuid = "e1d29d7a-bbdc-5cf2-9ac0-f12de2c33e28" -version = "1.1.0" - -[[deps.Mmap]] -uuid = "a63ad114-7e13-5084-954f-fe012c677804" - -[[deps.MozillaCACerts_jll]] -uuid = "14a3606d-f60d-562e-9121-12d972cd8159" -version = "2022.10.11" - -[[deps.NetworkOptions]] -uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" -version = "1.2.0" - -[[deps.Observables]] -git-tree-sha1 = "6862738f9796b3edc1c09d0890afce4eca9e7e93" -uuid = "510215fc-4207-5dde-b226-833fc4488ee2" -version = "0.5.4" - -[[deps.OpenBLAS_jll]] -deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"] -uuid = "4536629a-c528-5b80-bd46-f80d51c5b363" -version = "0.3.21+4" - -[[deps.OrderedCollections]] -git-tree-sha1 = "2e73fe17cac3c62ad1aebe70d44c963c3cfdc3e3" -uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" -version = "1.6.2" - -[[deps.Parsers]] -deps = ["Dates", "PrecompileTools", "UUIDs"] -git-tree-sha1 = "716e24b21538abc91f6205fd1d8363f39b442851" -uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" -version = "2.7.2" - -[[deps.Pkg]] -deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"] -uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" -version = "1.9.2" - -[[deps.PlutoUI]] -deps = ["AbstractPlutoDingetjes", "Base64", "ColorTypes", "Dates", "FixedPointNumbers", "Hyperscript", "HypertextLiteral", "IOCapture", "InteractiveUtils", "JSON", "Logging", "MIMEs", "Markdown", "Random", "Reexport", "URIs", "UUIDs"] -git-tree-sha1 = "e47cd150dbe0443c3a3651bc5b9cbd5576ab75b7" -uuid = "7f904dfe-b85e-4ff6-b463-dae2292396a8" -version = "0.7.52" - -[[deps.PlutoVista]] -deps = ["AbstractPlutoDingetjes", "ColorSchemes", "Colors", "DocStringExtensions", "GridVisualizeTools", "HypertextLiteral", "UUIDs"] -git-tree-sha1 = "5be7548065d668761814809e2c7ee33310a3d82f" -uuid = "646e1f28-b900-46d7-9d87-d554eb38a413" -version = "1.0.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 = "00805cd429dcb4870060ff49ef443486c262e38e" -uuid = "21216c6a-2e73-6563-6e65-726566657250" -version = "1.4.1" - -[[deps.Printf]] -deps = ["Unicode"] -uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" - -[[deps.REPL]] -deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"] -uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" - -[[deps.Random]] -deps = ["SHA", "Serialization"] -uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" - -[[deps.Reexport]] -git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b" -uuid = "189a3867-3050-52da-a836-e630ba90ab69" -version = "1.2.2" - -[[deps.Requires]] -deps = ["UUIDs"] -git-tree-sha1 = "838a3a4188e2ded87a4f9f184b4b0d78a1e91cb7" -uuid = "ae029012-a4dd-5104-9daa-d747884805df" -version = "1.3.0" - -[[deps.Revise]] -deps = ["CodeTracking", "Distributed", "FileWatching", "JuliaInterpreter", "LibGit2", "LoweredCodeUtils", "OrderedCollections", "Pkg", "REPL", "Requires", "UUIDs", "Unicode"] -git-tree-sha1 = "609c26951d80551620241c3d7090c71a73da75ab" -uuid = "295af30f-e4ad-537b-8983-00126c2a3abe" -version = "3.5.6" - -[[deps.SHA]] -uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" -version = "0.7.0" - -[[deps.Serialization]] -uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" - -[[deps.Sockets]] -uuid = "6462fe0b-24de-5631-8697-dd941f90decc" - -[[deps.SortingAlgorithms]] -deps = ["DataStructures"] -git-tree-sha1 = "c60ec5c62180f27efea3ba2908480f8055e17cee" -uuid = "a2af1166-a08f-5f64-846c-94a0d3cef48c" -version = "1.1.1" - -[[deps.SparseArrays]] -deps = ["Libdl", "LinearAlgebra", "Random", "Serialization", "SuiteSparse_jll"] -uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" - -[[deps.StaticArrays]] -deps = ["LinearAlgebra", "Random", "StaticArraysCore"] -git-tree-sha1 = "0adf069a2a490c47273727e029371b31d44b72b2" -uuid = "90137ffa-7385-5640-81b9-e52037218182" -version = "1.6.5" -weakdeps = ["Statistics"] - - [deps.StaticArrays.extensions] - StaticArraysStatisticsExt = "Statistics" - -[[deps.StaticArraysCore]] -git-tree-sha1 = "36b3d696ce6366023a0ea192b4cd442268995a0d" -uuid = "1e83bf80-4336-4d27-bf5d-d5a4f845583c" -version = "1.4.2" - -[[deps.Statistics]] -deps = ["LinearAlgebra", "SparseArrays"] -uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" -version = "1.9.0" - -[[deps.StatsAPI]] -deps = ["LinearAlgebra"] -git-tree-sha1 = "1ff449ad350c9c4cbc756624d6f8a8c3ef56d3ed" -uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0" -version = "1.7.0" - -[[deps.StatsBase]] -deps = ["DataAPI", "DataStructures", "LinearAlgebra", "LogExpFunctions", "Missings", "Printf", "Random", "SortingAlgorithms", "SparseArrays", "Statistics", "StatsAPI"] -git-tree-sha1 = "1d77abd07f617c4868c33d4f5b9e1dbb2643c9cf" -uuid = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" -version = "0.34.2" - -[[deps.StructArrays]] -deps = ["Adapt", "ConstructionBase", "DataAPI", "GPUArraysCore", "StaticArraysCore", "Tables"] -git-tree-sha1 = "0a3db38e4cce3c54fe7a71f831cd7b6194a54213" -uuid = "09ab397b-f2b6-538f-b94a-2f83cf4a842a" -version = "0.6.16" - -[[deps.SuiteSparse_jll]] -deps = ["Artifacts", "Libdl", "Pkg", "libblastrampoline_jll"] -uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c" -version = "5.10.1+6" - -[[deps.TOML]] -deps = ["Dates"] -uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" -version = "1.0.3" - -[[deps.TableTraits]] -deps = ["IteratorInterfaceExtensions"] -git-tree-sha1 = "c06b2f539df1c6efa794486abfb6ed2022561a39" -uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c" -version = "1.0.1" - -[[deps.Tables]] -deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "LinearAlgebra", "OrderedCollections", "TableTraits"] -git-tree-sha1 = "a1f34829d5ac0ef499f6d84428bd6b4c71f02ead" -uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" -version = "1.11.0" - -[[deps.Tar]] -deps = ["ArgTools", "SHA"] -uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" -version = "1.10.0" - -[[deps.TensorCore]] -deps = ["LinearAlgebra"] -git-tree-sha1 = "1feb45f88d133a655e001435632f019a9a1bcdb6" -uuid = "62fd8b95-f654-4bbd-a8a5-9c27f68ccd50" -version = "0.1.1" - -[[deps.Test]] -deps = ["InteractiveUtils", "Logging", "Random", "Serialization"] -uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" - -[[deps.TranscodingStreams]] -deps = ["Random", "Test"] -git-tree-sha1 = "9a6ae7ed916312b41236fcef7e0af564ef934769" -uuid = "3bb67fe8-82b1-5028-8e26-92a6c54297fa" -version = "0.9.13" - -[[deps.Tricks]] -git-tree-sha1 = "eae1bb484cd63b36999ee58be2de6c178105112f" -uuid = "410a4b4d-49e4-4fbc-ab6d-cb71b17b3775" -version = "0.1.8" - -[[deps.URIs]] -git-tree-sha1 = "b7a5e99f24892b6824a954199a45e9ffcc1c70f0" -uuid = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4" -version = "1.5.0" - -[[deps.UUIDs]] -deps = ["Random", "SHA"] -uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" - -[[deps.Unicode]] -uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" - -[[deps.VTKBase]] -git-tree-sha1 = "c2d0db3ef09f1942d08ea455a9e252594be5f3b6" -uuid = "4004b06d-e244-455f-a6ce-a5f9919cc534" -version = "1.0.1" - -[[deps.WriteVTK]] -deps = ["Base64", "CodecZlib", "FillArrays", "LightXML", "TranscodingStreams", "VTKBase"] -git-tree-sha1 = "7b46936613e41cfe1c6a5897d243ddcab8feabec" -uuid = "64499a7a-5c06-52f2-abe2-ccb03c286192" -version = "1.18.0" - -[[deps.XML2_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Libiconv_jll", "Zlib_jll"] -git-tree-sha1 = "24b81b59bd35b3c42ab84fa589086e19be919916" -uuid = "02c8fc9c-b97f-50b9-bbe4-9be30ff0a78a" -version = "2.11.5+0" - -[[deps.Zlib_jll]] -deps = ["Libdl"] -uuid = "83775a58-1f1d-513f-b197-d71354ab007a" -version = "1.2.13+0" - -[[deps.libblastrampoline_jll]] -deps = ["Artifacts", "Libdl"] -uuid = "8e850b90-86db-534c-a0d3-1478176c7d93" -version = "5.8.0+0" - -[[deps.nghttp2_jll]] -deps = ["Artifacts", "Libdl"] -uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" -version = "1.52.0+1" - -[[deps.p7zip_jll]] -deps = ["Artifacts", "Libdl"] -uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" -version = "17.4.0+0" -""" - # ╔═╡ Cell order: # ╠═9701cbe0-d048-11eb-151b-67dda7b72b71 # ╠═68e2c958-b417-4ba1-9577-697304fe140a @@ -1139,5 +499,3 @@ version = "17.4.0+0" # ╠═3efbeb11-eaa4-4fc5-bd5f-b3bdb63e7772 # ╠═ccd274d2-68c0-40e0-8ba7-b8421f5ec9d3 # ╟─ba5111b8-0dca-42d2-970f-1e88f5392324 -# ╟─00000000-0000-0000-0000-000000000001 -# ╟─00000000-0000-0000-0000-000000000002 diff --git a/src/GridVisualize.jl b/src/GridVisualize.jl index 649b367..bb4ce24 100644 --- a/src/GridVisualize.jl +++ b/src/GridVisualize.jl @@ -18,6 +18,7 @@ using ExtendableGrids include("dispatch.jl") include("common.jl") +export quiverdata, vectorsample include("pyplot.jl") include("makie.jl") include("vtkview.jl") @@ -29,6 +30,7 @@ export scalarplot, scalarplot! export gridplot, gridplot! export vectorplot, vectorplot! export streamplot, streamplot! +export customplot, customplot! export save, reveal, backend! export isplots, isvtkview, ispyplot, ismakie, isplutovista export GridVisualizer, SubVisualizer diff --git a/src/common.jl b/src/common.jl index 90733ee..95226a0 100644 --- a/src/common.jl +++ b/src/common.jl @@ -9,14 +9,15 @@ Return corresponding points and facets for each region for drawing as mesh (Maki or trisurf (pyplot) """ function GridVisualizeTools.extract_visible_cells3D(grid::ExtendableGrid, xyzcut; + gridscale = 1.0, primepoints = zeros(0, 0), Tp = SVector{3, Float32}, Tf = SVector{3, Int32}) - coord = grid[Coordinates] + coord = grid[Coordinates] * gridscale cellnodes = grid[CellNodes] cellregions = grid[CellRegions] nregions = grid[NumCellRegions] - extract_visible_cells3D(coord, cellnodes, cellregions, nregions, xyzcut; + extract_visible_cells3D(coord, cellnodes, cellregions, nregions, [xyzcut...] * gridscale; primepoints = primepoints, Tp = Tp, Tf = Tf) end @@ -31,15 +32,16 @@ Return corresponding points and facets for each region for drawing as mesh (Maki or trisurf (pyplot) """ function GridVisualizeTools.extract_visible_bfaces3D(grid::ExtendableGrid, xyzcut; + gridscale = 1.0, primepoints = zeros(0, 0), Tp = SVector{3, Float32}, Tf = SVector{3, Int32}) - coord = grid[Coordinates] + coord = grid[Coordinates] * gridscale bfacenodes = grid[BFaceNodes] bfaceregions = grid[BFaceRegions] nbregions = grid[NumBFaceRegions] - extract_visible_bfaces3D(coord, bfacenodes, bfaceregions, nbregions, xyzcut; + extract_visible_bfaces3D(coord, bfacenodes, bfaceregions, nbregions, [xyzcut...] * gridscale; primepoints = primepoints, Tp = Tp, Tf = Tf) end @@ -49,16 +51,17 @@ end Extract isosurfaces and plane interpolation for function on 3D tetrahedral mesh. See [`marching_tetrahedra(coord,cellnodes,func,planes,flevels;tol, primepoints, primevalues, Tv, Tp, Tf)`](@ref) """ -function GridVisualizeTools.marching_tetrahedra(grid::ExtendableGrid, func, planes, flevels; +function GridVisualizeTools.marching_tetrahedra(grid::ExtendableGrid, func, planes, flevels; gridscale = 1.0, kwargs...) - coord = grid[Coordinates] + coord = grid[Coordinates] * gridscale cellnodes = grid[CellNodes] marching_tetrahedra(coord, cellnodes, func, planes, flevels; kwargs...) end function GridVisualizeTools.marching_tetrahedra(grids::Vector{ExtendableGrid{Tv, Ti}}, funcs, planes, flevels; + gridscale = 1.0, kwargs...) where {Tv, Ti} - coord = [grid[Coordinates] for grid in grids] + coord = [grid[Coordinates] * gridscale for grid in grids] cellnodes = [grid[CellNodes] for grid in grids] marching_tetrahedra(coord, cellnodes, funcs, planes, flevels; kwargs...) end @@ -69,25 +72,25 @@ end Collect isoline snippets on triangles ready for linesegments! """ -function GridVisualizeTools.marching_triangles(grid::ExtendableGrid, func, levels) - coord::Matrix{Float64} = grid[Coordinates] +function GridVisualizeTools.marching_triangles(grid::ExtendableGrid, func, levels; gridscale = 1.0) + coord::Matrix{Float64} = grid[Coordinates] * gridscale cellnodes::Matrix{Int32} = grid[CellNodes] marching_triangles(coord, cellnodes, func, levels) end -function GridVisualizeTools.marching_triangles(grids::Vector{ExtendableGrid{Tv, Ti}}, funcs, levels) where {Tv, Ti} - coords = [grid[Coordinates] for grid in grids] +function GridVisualizeTools.marching_triangles(grids::Vector{ExtendableGrid{Tv, Ti}}, funcs, levels; gridscale = 1.0) where {Tv, Ti} + coords = [grid[Coordinates] * gridscale for grid in grids] cellnodes = [grid[CellNodes] for grid in grids] marching_triangles(coords, cellnodes, funcs, levels) end ############################################## # Create meshes from grid data -function regionmesh(grid, iregion) +function regionmesh(grid, gridscale, iregion) coord = grid[Coordinates] cn = grid[CellNodes] cr = grid[CellRegions] - @views points = [Point2f(coord[:, i]) for i = 1:size(coord, 2)] + @views points = [Point2f(coord[:, i] * gridscale) for i = 1:size(coord, 2)] faces = Vector{GLTriangleFace}(undef, 0) for i = 1:length(cr) if cr[i] == iregion @@ -97,7 +100,7 @@ function regionmesh(grid, iregion) Mesh(points, faces) end -function bfacesegments(grid, ibreg) +function bfacesegments(grid, gridscale, ibreg) coord = grid[Coordinates] nbfaces = num_bfaces(grid) bfacenodes = grid[BFaceNodes] @@ -106,15 +109,15 @@ function bfacesegments(grid, ibreg) for ibface = 1:nbfaces if bfaceregions[ibface] == ibreg push!(points, - Point2f(coord[1, bfacenodes[1, ibface]], coord[2, bfacenodes[1, ibface]])) + Point2f(coord[1, bfacenodes[1, ibface]] * gridscale, coord[2, bfacenodes[1, ibface]] * gridscale)) push!(points, - Point2f(coord[1, bfacenodes[2, ibface]], coord[2, bfacenodes[2, ibface]])) + Point2f(coord[1, bfacenodes[2, ibface]] * gridscale, coord[2, bfacenodes[2, ibface]] * gridscale)) end end points end -function bfacesegments3(grid, ibreg) +function bfacesegments3(grid, gridscale, ibreg) coord = grid[Coordinates] nbfaces = num_bfaces(grid) bfacenodes = grid[BFaceNodes] @@ -123,10 +126,10 @@ function bfacesegments3(grid, ibreg) for ibface = 1:nbfaces if bfaceregions[ibface] == ibreg push!(points, - Point3f(coord[1, bfacenodes[1, ibface]], coord[2, bfacenodes[1, ibface]], + Point3f(coord[1, bfacenodes[1, ibface]] * gridscale, coord[2, bfacenodes[1, ibface]] * gridscale, 0.0)) push!(points, - Point3f(coord[1, bfacenodes[2, ibface]], coord[2, bfacenodes[2, ibface]], + Point3f(coord[1, bfacenodes[2, ibface]] * gridscale, coord[2, bfacenodes[2, ibface]] * gridscale, 0.0)) end end @@ -134,25 +137,37 @@ function bfacesegments3(grid, ibreg) end """ -$(TYPEDSIGNATURES) + vectorsample(grid::ExtendableGrid{Tv, Ti}, v; + offset = :default, + rasterpoints = 15, + reltol = 1.0e-10, + gridscale = 1.0, + xlimits = (1, -1), + ylimits = (1, -1), + zlimits = (1, -1)) where {Tv, Ti} Extract values of given vector field (either nodal values of a piecewise linear vector field or a callback function providing evaluation of the vector field for given generalized barycentric coordinates). at all sampling points on `offset+ i*spacing` for i in Z^d defined by the tuples offset and spacing. +Returned values can be fed into [`quiverdata`](@ref) By default, offset is at the minimum of grid coordinates, and spacing is defined the largest grid extend divided by 10. - - The intermediate `rasterflux` in future versions can be used to calculate streamlines. The code is 3D ready. """ -function vectorsample(grid::ExtendableGrid{Tv, Ti}, v; offset = :default, - spacing = :default, reltol = 1.0e-10, xlimits = (1, -1), ylimits = (1, -1), zlimits = (1, -1)) where {Tv, Ti} - coord = grid[Coordinates] +function vectorsample(grid::ExtendableGrid{Tv, Ti}, v; + offset = :default, + rasterpoints = 32, + reltol = 1.0e-10, + gridscale = 1.0, + xlimits = (1, -1), + ylimits = (1, -1), + zlimits = (1, -1)) where {Tv, Ti} + coord = grid[Coordinates] * gridscale cn = grid[CellNodes] ncells::Int = num_cells(grid) @@ -160,7 +175,15 @@ function vectorsample(grid::ExtendableGrid{Tv, Ti}, v; offset = :default, eltype = dim == 2 ? Triangle2D : Tetrahedron3D - L2G = ExtendableGrids.L2GTransformer(eltype, grid, ON_CELLS) + scaledgrid = grid + if gridscale != 1.0 + scaledgrid = ExtendableGrid{coord_type(grid), index_type(grid)}() + for (k, v) in grid.components + scaledgrid.components[k] = v + end + scaledgrid[Coordinates] = coord + end + L2G = ExtendableGrids.L2GTransformer(eltype, scaledgrid, ON_CELLS) # memory for inverse of local transformation matrix invA = zeros(dim + 1, dim + 1) @@ -179,9 +202,10 @@ function vectorsample(grid::ExtendableGrid{Tv, Ti}, v; offset = :default, if zlimits[1] < zlimits[2] cminmax[3] = zlimits[:] end - if offset == :default offset = [cminmax[i][1] for i = 1:dim] + else + offset = offset * gridscale end # extent of domain @@ -191,12 +215,7 @@ function vectorsample(grid::ExtendableGrid{Tv, Ti}, v; offset = :default, tol = reltol * extent # point spacing - if spacing == :default - spacing = [extent / 15 for i = 1:dim] - elseif isa(spacing, Number) - spacing = [spacing for i = 1:dim] - end - # else assume spacing vector has been given + spacing = [extent / rasterpoints for i = 1:dim] # index range ijkmax = ones(Int, 3) @@ -208,6 +227,7 @@ function vectorsample(grid::ExtendableGrid{Tv, Ti}, v; offset = :default, # spanned by x,y and z coordinate vectors. Here, we build them # in order to avoid to calculate them from the raster indices rastercoord = [zeros(Float32, ijkmax[idim]) for idim = 1:dim] + for idim = 1:dim rastercoord[idim] = collect(range(offset[idim]; step = spacing[idim], length = ijkmax[idim])) @@ -319,19 +339,28 @@ function isolevels(ctx, funcs) end """ -$(TYPEDSIGNATURES) + function quiverdata(rastercoord, + rasterflux; + vscale = 1.0, + vnormalize = true, + vconstant = false) + -Extract nonzero fluxes for quiver plots from rastergrid. +Extract nonzero fluxes for quiver plots from rastergrid obtained by [`vectorsample`](@ref). Returns qc, qv - `d x nquiver` matrices. If vnormalize is true, the vector field is normalized to vscale*min(spacing), otherwise, it is scaled by vscale -Result data are meant to be ready for being passed to calls to `quiver`. +Result data are meant to be ready for being passed to calls to `quiver` with various plotting backends. """ -function quiverdata(rastercoord, rasterflux; vscale = 1.0, vnormalize = true, vconstant = false) +function quiverdata(rastercoord, + rasterflux; + vscale = 1.0, + vnormalize = true, + vconstant = false) dim = length(rastercoord) imax = length(rastercoord[1]) diff --git a/src/dispatch.jl b/src/dispatch.jl index 75aadf7..b5f56e6 100644 --- a/src/dispatch.jl +++ b/src/dispatch.jl @@ -324,7 +324,8 @@ function default_plot_kwargs() :levelalpha => Pair(0.25, "3D isolevel alpha"), :planealpha => Pair(0.25, "3D plane section alpha"), :tetxplane_tol => Pair(0.0, "tolerance for tet-plane intersection in 3D"), - :spacing => Pair(:default, "Spacing of quiver points in vector plot"), + :rasterpoints => Pair(16, + "Number of quiver points resp. half number of streamplot interpolation points in the maximum extent direction. "), :offset => Pair(:default, "Offset of quiver grid"), :vscale => Pair(1.0, "Vector field scale for quiver grid"), :vconstant => Pair(false, "Set all arrow length constant in vector plot"), @@ -334,7 +335,7 @@ function default_plot_kwargs() :yplanes => Pair([prevfloat(Inf)], "3D y plane positions or number thereof"), :zplanes => Pair([prevfloat(Inf)], "3D z plane positions or number thereof"), :zoom => Pair(1.0, "Zoom level"), - :gridscale => Pair(1.0, "grid scale factor"), + :gridscale => Pair(1, "Grid scale factor. Will be applied also to planes, spacing"), :azim => Pair(-60, "3D azimuth angle (in degrees)"), :elev => Pair(30, "3D elevation angle (in degrees)"), :perspectiveness => Pair(0.25, @@ -347,7 +348,8 @@ function default_plot_kwargs() :backend => Pair(:default, "Backend for PlutoVista plot"), :dim => Pair(1, "Data dimension for PlutoVista plot"), :regions => Pair(:all, "List of regions to plot"), - :species => Pair(1, "Number of species to plot or number of species in regions")) + :species => Pair(1, "Number of species to plot or number of species in regions"), + :spacing => Pair(nothing, "Removed from API")) end # @@ -552,6 +554,9 @@ Plot piecewise linear vector field as quiver plot. function vectorplot!(ctx::SubVisualizer, grid::ExtendableGrid, func; kwargs...) _update_context!(ctx, Dict(:clear => true, :show => false, :reveal => false)) _update_context!(ctx, kwargs) + if ctx[:spacing] != nothing + @warn "`spacing` has been removed from keyword arguments, use `rasterpoints` to control spacing" + end vectorplot!(ctx, plottertype(ctx[:Plotter]), Val{dim_space(grid)}, grid, func) end @@ -616,6 +621,9 @@ Plot piecewise linear vector field as stream plot. function streamplot!(ctx::SubVisualizer, grid::ExtendableGrid, func; kwargs...) _update_context!(ctx, Dict(:clear => true, :show => false, :reveal => false)) _update_context!(ctx, kwargs) + if ctx[:spacing] != nothing + @warn "`spacing` has been removed from keyword arguments, use `rasterpoints` to control spacing" + end streamplot!(ctx, plottertype(ctx[:Plotter]), Val{dim_space(grid)}, grid, func) end @@ -662,6 +670,50 @@ function streamplot(X::AbstractVector, kwargs...,) streamplot(simplexgrid(X, Y, Z), func; kwargs...) end +################################################################################### +"$(TYPEDSIGNATURES)" +function customplot!(ctx::SubVisualizer, func; kwargs...) + _update_context!(ctx, Dict(:clear => true, :show => false, :reveal => false)) + _update_context!(ctx, kwargs) + if ctx[:spacing] != nothing + @warn "`spacing` has been removed from keyword arguments, use `rasterpoints` to control spacing" + end + customplot!(ctx, plottertype(ctx[:Plotter]), func) +end + +""" +$(TYPEDSIGNATURES) + +Variant for do block syntax. +""" +function customplot!(func, ctx::SubVisualizer; kwargs...) + customplot!(ctx, func; kwargs...) +end + +"$(TYPEDSIGNATURES)" +function customplot!(p::GridVisualizer, func; kwargs...) + customplot!(p[1, 1], func; kwargs...) +end + +""" +$(TYPEDSIGNATURES) + +Variant for do block syntax. +""" +function customplot!(func, p::GridVisualizer; kwargs...) + customplot!(p[1, 1], func; kwargs...) +end + +""" +$(TYPEDSIGNATURES) + +Custom user plot. +""" +function customplot(func; Plotter = default_plotter(), kwargs...) + customplot!(GridVisualizer(; Plotter = Plotter, kwargs...), func; show = true) +end + +################################################################################### """ $(TYPEDSIGNATURES) @@ -720,6 +772,8 @@ streamplot!(ctx::Nothing, grid::ExtendableGrid, func::Function; kwargs...) = not streamplot!(ctx, ::Type{Nothing}, ::Type{Val{2}}, grid, func) = nothing streamplot!(ctx, ::Type{Nothing}, ::Type{Val{3}}, grid, func) = nothing +customplot!(ctx::Nothing, func::Function; kwargs...) = nothing + save(fname, scene, Plotter::Nothing, ::Type{Nothing}) = nothing displayable(ctx, Any) = nothing reveal(p, ::Type{Nothing}) = nothing diff --git a/src/makie.jl b/src/makie.jl index 1fe764f..d4e70d6 100644 --- a/src/makie.jl +++ b/src/makie.jl @@ -189,21 +189,21 @@ scenekwargs(ctx) = Dict( #1D grid # Point list for node markers -function basemesh1d(grid) +function basemesh1d(grid, gridscale) coord = vec(grid[Coordinates]) ncoord = length(coord) points = Vector{Point2f}(undef, 0) (xmin, xmax) = extrema(coord) - h = (xmax - xmin) / 40.0 + h = gridscale * (xmax - xmin) / 40.0 for i = 1:ncoord - push!(points, Point2f(coord[i], h)) - push!(points, Point2f(coord[i], -h)) + push!(points, Point2f(coord[i] * gridscale, h)) + push!(points, Point2f(coord[i] * gridscale, -h)) end points end # Point list for intervals -function regionmesh1d(grid, iregion) +function regionmesh1d(grid, gridscale, iregion) coord = vec(grid[Coordinates]) points = Vector{Point2f}(undef, 0) cn = grid[CellNodes] @@ -211,44 +211,44 @@ function regionmesh1d(grid, iregion) ncells = length(cr) for i = 1:ncells if cr[i] == iregion - push!(points, Point2f(coord[cn[1, i]], 0)) - push!(points, Point2f(coord[cn[2, i]], 0)) + push!(points, Point2f(coord[cn[1, i]] * gridscale, 0)) + push!(points, Point2f(coord[cn[2, i]] * gridscale, 0)) end end points end # Point list for boundary nodes -function bregionmesh1d(grid, ibreg) +function bregionmesh1d(grid, gridscale, ibreg) nbfaces = num_bfaces(grid) bfacenodes = grid[BFaceNodes] bfaceregions = grid[BFaceRegions] coord = vec(grid[Coordinates]) points = Vector{Point2f}(undef, 0) (xmin, xmax) = extrema(coord) - h = (xmax - xmin) / 20.0 + h = gridscale * (xmax - xmin) / 20.0 for ibface = 1:nbfaces if bfaceregions[ibface] == ibreg - push!(points, Point2f(coord[bfacenodes[1, ibface]], h)) - push!(points, Point2f(coord[bfacenodes[1, ibface]], -h)) + push!(points, Point2f(coord[bfacenodes[1, ibface]] * gridscale, h)) + push!(points, Point2f(coord[bfacenodes[1, ibface]] * gridscale, -h)) end end points end # Point list for scene size -function scenecorners1d(grid) +function scenecorners1d(grid, gridscale) coord = vec(grid[Coordinates]) (xmin, xmax) = extrema(coord) - h = (xmax - xmin) / 40.0 - [Point2f(xmin, -5 * h), Point2f(xmax, 5 * h)] + h = gridscale * (xmax - xmin) / 40.0 + [Point2f(xmin * gridscale, -5 * h), Point2f(xmax * gridscale, 5 * h)] end function gridplot!(ctx, TP::Type{MakieType}, ::Type{Val{1}}, grid) XMakie = ctx[:Plotter] nregions = num_cellregions(grid) nbregions = num_bfaceregions(grid) - + gridscale = ctx[:gridscale] if !haskey(ctx, :scene) ctx[:scene] = XMakie.Axis(ctx[:figure]; yticklabelsvisible = false, @@ -262,20 +262,20 @@ function gridplot!(ctx, TP::Type{MakieType}, ::Type{Val{1}}, grid) # Set scene size with invisible markers XMakie.scatter!(ctx[:scene], - map(g -> scenecorners1d(grid), ctx[:grid]); + map(g -> scenecorners1d(grid, gridscale), ctx[:grid]); color = :white, markersize = 0.0, strokewidth = 0,) # Draw node markers XMakie.linesegments!(ctx[:scene], - map(g -> basemesh1d(g), ctx[:grid]); + map(g -> basemesh1d(g, gridscale), ctx[:grid]); color = :black,) # Colored cell regions for i = 1:nregions XMakie.linesegments!(ctx[:scene], - map(g -> regionmesh1d(g, i), ctx[:grid]); + map(g -> regionmesh1d(g, gridscale, i), ctx[:grid]); color = cmap[i], linewidth = 4, label = "c $(i)",) @@ -284,7 +284,7 @@ function gridplot!(ctx, TP::Type{MakieType}, ::Type{Val{1}}, grid) # Colored boundary grid for i = 1:nbregions XMakie.linesegments!(ctx[:scene], - map(g -> bregionmesh1d(g, i), ctx[:grid]); + map(g -> bregionmesh1d(g, gridscale, i), ctx[:grid]); color = bcmap[i], linewidth = 4, label = "b$(i)",) @@ -317,6 +317,7 @@ function scalarplot!(ctx, TP::Type{MakieType}, ::Type{Val{1}}, grids, parentgrid ctx[:title] = " " end ctx[:scalarplot1d] = true + gridscale = ctx[:gridscale] # ... keep this for the case we are unsorted function polysegs(grid, func) points = Vector{Point2f}(undef, 0) @@ -325,8 +326,8 @@ function scalarplot!(ctx, TP::Type{MakieType}, ::Type{Val{1}}, grids, parentgrid for icell = 1:num_cells(grid) i1 = cellnodes[1, icell] i2 = cellnodes[2, icell] - x1 = coord[1, i1] - x2 = coord[1, i2] + x1 = coord[1, i1] * gridscale + x2 = coord[1, i2] * gridscale push!(points, Point2f(x1, func[i1])) push!(points, Point2f(x2, func[i2])) end @@ -335,15 +336,15 @@ function scalarplot!(ctx, TP::Type{MakieType}, ::Type{Val{1}}, grids, parentgrid function polyline(grid, func) coord = grid[Coordinates] - points = [Point2f(coord[1, i], func[i]) for i = 1:length(func)] + points = [Point2f(coord[1, i] * gridscale, func[i]) for i = 1:length(func)] end coord = parentgrid[Coordinates] xlimits = ctx[:xlimits] ylimits = ctx[:limits] - xmin = coord[1, 1] - xmax = coord[1, end] + xmin = coord[1, 1] * gridscale + xmax = coord[1, end] * gridscale xauto = true yauto = true if xlimits[1] < xlimits[2] @@ -562,7 +563,7 @@ function gridplot!(ctx, TP::Type{MakieType}, ::Type{Val{2}}, grid) ctx[:cmap] = cmap for i = 1:nregions XMakie.poly!(ctx[:scene], - map(g -> regionmesh(g, i), ctx[:grid]); + map(g -> regionmesh(g, ctx[:gridscale], i), ctx[:grid]); color = cmap[i], strokecolor = :black, strokewidth = ctx[:linewidth],) @@ -573,7 +574,7 @@ function gridplot!(ctx, TP::Type{MakieType}, ::Type{Val{2}}, grid) ctx[:bcmap] = bcmap for i = 1:nbregions lp = XMakie.linesegments!(ctx[:scene], - map(g -> bfacesegments(g, i), ctx[:grid]); + map(g -> bfacesegments(g, ctx[:gridscale], i), ctx[:grid]); label = "$(i)", color = bcmap[i], linewidth = 4,) @@ -626,6 +627,7 @@ end # 2D function function scalarplot!(ctx, TP::Type{MakieType}, ::Type{Val{2}}, grids, parentgrid, funcs) XMakie = ctx[:Plotter] + gridscale = ctx[:gridscale] # Create GeometryBasics.mesh from grid data. function make_mesh(grids, funcs, elevation) @@ -635,7 +637,6 @@ function scalarplot!(ctx, TP::Type{MakieType}, ::Type{Val{2}}, grids, parentgrid cellnodes = [grid[CellNodes] for grid in grids] ncells = [num_cells(grid) for grid in grids] offsets = zeros(Int, ngrids) - for i = 2:ngrids offsets[i] = offsets[i - 1] + npoints[i - 1] end @@ -645,7 +646,7 @@ function scalarplot!(ctx, TP::Type{MakieType}, ::Type{Val{2}}, grids, parentgrid k = 1 for j = 1:ngrids for i = 1:npoints[j] - points[k] = Point3f(coords[j][1, i], coords[j][2, i], -0.1) + points[k] = Point3f(coords[j][1, i] * gridscale, coords[j][2, i] * gridscale, -0.1) k = k + 1 end end @@ -654,7 +655,8 @@ function scalarplot!(ctx, TP::Type{MakieType}, ::Type{Val{2}}, grids, parentgrid k = 1 for j = 1:ngrids for i = 1:npoints[j] - points[k] = Point3f(coords[j][1, i], coords[j][2, i], funcs[j][i] * elevation) + points[k] = Point3f(coords[j][1, i] * gridscale, coords[j][2, i] * gridscale, + funcs[j][i] * elevation * gridscale) k = k + 1 end end @@ -731,7 +733,7 @@ function scalarplot!(ctx, TP::Type{MakieType}, ::Type{Val{2}}, grids, parentgrid # draw the isolines via marching triangles if ctx[:elevation] ≈ 0 XMakie.linesegments!(ctx[:scene], - map(data -> marching_triangles(data.g, data.f, data.l), ctx[:contourdata]); + map(data -> marching_triangles(data.g, data.f, data.l; gridscale), ctx[:contourdata]); color = :black, linewidth = ctx[:linewidth],) end @@ -746,7 +748,7 @@ end function vectorplot!(ctx, TP::Type{MakieType}, ::Type{Val{2}}, grid, func) XMakie = ctx[:Plotter] - rc, rv = vectorsample(grid, func; spacing = ctx[:spacing], offset = ctx[:offset]) + rc, rv = vectorsample(grid, func; gridscale = ctx[:gridscale], rasterpoints = ctx[:rasterpoints], offset = ctx[:offset]) qc, qv = quiverdata(rc, rv; vscale = ctx[:vscale], vnormalize = ctx[:vnormalize], vconstant = ctx[:vconstant]) set_plot_data!(ctx, :arrowdata, (qc = qc, qv = qv)) @@ -775,14 +777,23 @@ end function streamplot!(ctx, TP::Type{MakieType}, ::Type{Val{2}}, grid, func) XMakie = ctx[:Plotter] - rc, rv0 = vectorsample(grid, func; spacing = ctx[:spacing], offset = ctx[:offset]) - srv = size(rv0) - rv = reshape(rv0, (srv[1], srv[2], srv[3])) + rc, rv = vectorsample(grid, func; rasterpoints = 2 * ctx[:rasterpoints], offset = ctx[:offset], xlimits = ctx[:xlimits], + ylimits = ctx[:ylimits], gridscale = ctx[:gridscale]) + x = rc[1] y = rc[2] + ix = linear_interpolation((x, y), rv[1, :, :]) iy = linear_interpolation((x, y), rv[2, :, :]) f(x, y) = Point2(ix(x, y), iy(x, y)) + + xextent = x[end] - x[begin] + yextent = y[end] - y[begin] + + maxextent = max(xextent, yextent) + gridstep = maxextent / (2 * ctx[:rasterpoints]) + gridsize = (Int(ceil(xextent / gridstep)), Int(ceil(yextent / gridstep)), 2 * ctx[:rasterpoints]) + set_plot_data!(ctx, :streamdata, (xinterval = x[begin] .. x[end], yinterval = y[begin] .. y[end], f = f)) if !haskey(ctx, :streamplot) @@ -793,12 +804,15 @@ function streamplot!(ctx, TP::Type{MakieType}, ::Type{Val{2}}, grid, func) scenekwargs(ctx)...,) add_scene!(ctx, ctx[:scene]) end - ctx[:streamplot] = XMakie.streamplot!(ctx[:scene], map(data -> data.f, ctx[:streamdata]), map(data -> data.xinterval, ctx[:streamdata]), map(data -> data.yinterval, ctx[:streamdata]); - linewidth = ctx[:linewidth], colormap = ctx[:colormap]) + linewidth = ctx[:linewidth], + colormap = ctx[:colormap], + gridsize = gridsize, + arrow_size = 7.5, + stepsize = 0.01 * maxextent) XMakie.reset_limits!(ctx[:scene]) end reveal(ctx, TP) @@ -808,15 +822,15 @@ end ####################################################################################### # 3D Grid -function xyzminmax(grid::ExtendableGrid) +function xyzminmax(grid::ExtendableGrid, gridscale) coord = grid[Coordinates] ndim = size(coord, 1) xyzmin = zeros(ndim) xyzmax = ones(ndim) for idim = 1:ndim @views mn, mx = extrema(coord[idim, :]) - xyzmin[idim] = mn - xyzmax[idim] = mx + xyzmin[idim] = mn * gridscale + xyzmax[idim] = mx * gridscale end xyzmin, xyzmax end @@ -869,7 +883,7 @@ function makescene3d(ctx) GL[1, 2] = XMakie.Colorbar(ctx[:figure]; colormap = ctx[:colormap], colorrange = ctx[:crange], - ticks = map(d -> d.l, ctx[:data]), + ticks = map(d -> d.c, ctx[:data]), tickformat = "{:.2e}", width = 15, ticklabelsize = 0.5 * ctx[:fontsize],) @@ -877,7 +891,7 @@ function makescene3d(ctx) GL[2, 1] = XMakie.Colorbar(ctx[:figure]; colormap = ctx[:colormap], colorrange = ctx[:crange], - ticks = map(d -> d.l, ctx[:data]), + ticks = map(d -> d.c, ctx[:data]), tickformat = "{:.2e}", height = 15, ticklabelsize = 0.5 * ctx[:fontsize], @@ -912,22 +926,24 @@ function gridplot!(ctx, TP::Type{MakieType}, ::Type{Val{3}}, grid) nbregions = num_bfaceregions(grid) XMakie = ctx[:Plotter] - xyzmin, xyzmax = xyzminmax(grid) + xyzmin, xyzmax = xyzminmax(grid, ctx[:gridscale]) xyzstep = (xyzmax - xyzmin) / 100 - function adjust_planes() - ctx[:xplanes][1] = max(xyzmin[1], min(xyzmax[1], ctx[:xplanes][1])) - ctx[:yplanes][1] = max(xyzmin[2], min(xyzmax[2], ctx[:yplanes][1])) - ctx[:zplanes][1] = max(xyzmin[3], min(xyzmax[3], ctx[:zplanes][1])) + function adjust_planes(xplane, yplane, zplane) + ctx[:ixplane] = max(xyzmin[1], min(xyzmax[1], xplane)) + ctx[:iyplane] = max(xyzmin[2], min(xyzmax[2], yplane)) + ctx[:izplane] = max(xyzmin[3], min(xyzmax[3], zplane)) end - adjust_planes() + adjust_planes(ctx[:xplanes][1], + ctx[:yplanes][1], + ctx[:zplanes][1]) if !haskey(ctx, :scene) ctx[:data] = Observable((g = grid, - x = ctx[:xplanes][1], - y = ctx[:yplanes][1], - z = ctx[:zplanes][1], + x = ctx[:ixplane], + y = ctx[:iyplane], + z = ctx[:izplane], t = ctx[:title])) ctx[:scene] = makeaxis3d(ctx) @@ -940,7 +956,8 @@ function gridplot!(ctx, TP::Type{MakieType}, ::Type{Val{3}}, grid) # We draw a mesh for each color. if ctx[:interior] ctx[:celldata] = map(d -> extract_visible_cells3D(d.g, - (d.x, d.y, d.z); + [d.x, d.y, d.z] / ctx[:gridscale]; + gridscale = ctx[:gridscale], primepoints = hcat(xyzmin, xyzmax), Tp = Point3f, Tf = GLTriangleFace,), @@ -967,7 +984,8 @@ function gridplot!(ctx, TP::Type{MakieType}, ::Type{Val{3}}, grid) ############# Visible boundary faces ctx[:facedata] = map(d -> extract_visible_bfaces3D(d.g, - (d.x, d.y, d.z); + [d.x, d.y, d.z] / ctx[:gridscale]; + gridscale = ctx[:gridscale], primepoints = hcat(xyzmin, xyzmax), Tp = Point3f, Tf = GLTriangleFace,), @@ -993,7 +1011,8 @@ function gridplot!(ctx, TP::Type{MakieType}, ::Type{Val{3}}, grid) if ctx[:outlinealpha] > 0.0 ctx[:outlinedata] = map(d -> extract_visible_bfaces3D(d.g, - xyzmax; + xyzmax / ctx[:gridscale]; + gridscale = ctx[:gridscale], primepoints = hcat(xyzmin, xyzmax), Tp = Point3f, Tf = GLTriangleFace,), @@ -1013,23 +1032,24 @@ function gridplot!(ctx, TP::Type{MakieType}, ::Type{Val{3}}, grid) ##### Interaction scene_interaction(ctx[:scene].scene, XMakie, [:z, :y, :x, :q]) do delta, key if key == :x - ctx[:xplanes][1] += delta * xyzstep[1] - ctx[:status][] = @sprintf("x=%.3g", ctx[:xplanes][1]) + ctx[:ixplane] += delta * xyzstep[1] + ctx[:status][] = @sprintf("x=%.3g", ctx[:ixplane]) elseif key == :y - ctx[:yplanes][1] += delta * xyzstep[2] - ctx[:status][] = @sprintf("y=%.3g", ctx[:yplanes][1]) + ctx[:iyplane] += delta * xyzstep[2] + ctx[:status][] = @sprintf("y=%.3g", ctx[:iyplane]) elseif key == :z - ctx[:zplanes][1] += delta * xyzstep[3] - ctx[:status][] = @sprintf("z=%.3g", ctx[:zplanes][1]) + ctx[:izplane] += delta * xyzstep[3] + ctx[:status][] = @sprintf("z=%.3g", ctx[:izplane]) elseif key == :q ctx[:status][] = " " end - adjust_planes() + + adjust_planes(ctx[:ixplane], ctx[:iyplane], ctx[:izplane]) ctx[:data][] = (g = grid, - x = ctx[:xplanes][1], - y = ctx[:yplanes][1], - z = ctx[:zplanes][1], + x = ctx[:ixplane], + y = ctx[:iyplane], + z = ctx[:izplane], t = ctx[:title]) end @@ -1039,9 +1059,9 @@ function gridplot!(ctx, TP::Type{MakieType}, ::Type{Val{3}}, grid) else ctx[:data][] = (g = grid, - x = ctx[:xplanes][1], - y = ctx[:yplanes][1], - z = ctx[:zplanes][1], + x = ctx[:ixplane], + y = ctx[:iyplane], + z = ctx[:izplane], t = ctx[:title]) end @@ -1050,8 +1070,9 @@ end # 3d function function scalarplot!(ctx, TP::Type{MakieType}, ::Type{Val{3}}, grids, parentgrid, funcs) - levels, crange = isolevels(ctx, funcs) + levels, crange, colorbarticks = isolevels(ctx, funcs) ctx[:crange] = crange + ctx[:colorbarticks] = colorbarticks nan_replacement = 0.5 * (crange[1] + crange[2]) make_mesh(pts, fcs) = Mesh(pts, fcs) @@ -1073,7 +1094,7 @@ function scalarplot!(ctx, TP::Type{MakieType}, ::Type{Val{3}}, grids, parentgrid XMakie = ctx[:Plotter] cmap = XMakie.to_colormap(ctx[:colormap]) - xyzmin, xyzmax = xyzminmax(parentgrid) + xyzmin, xyzmax = xyzminmax(parentgrid, ctx[:gridscale]) xyzstep = (xyzmax - xyzmin) / 100 fstep = (crange[2] - crange[1]) / 100 @@ -1081,35 +1102,26 @@ function scalarplot!(ctx, TP::Type{MakieType}, ::Type{Val{3}}, grids, parentgrid fstep = 0.1 end - # function adjust_planes() - # ctx[:xplanes][1]=max(xyzmin[1],min(xyzmax[1],ctx[:xplanes][1]) ) - # ctx[:yplanes][1]=max(xyzmin[2],min(xyzmax[2],ctx[:yplanes][1]) ) - # ctx[:zplanes][1]=max(xyzmin[3],min(xyzmax[3],ctx[:zplanes][1]) ) - # ctx[:flevel]=max(fminmax[1],min(fminmax[2],ctx[:flevel])) - # end + ctx[:ixplanes] = collect(ctx[:xplanes]) * ctx[:gridscale] + ctx[:iyplanes] = collect(ctx[:yplanes]) * ctx[:gridscale] + ctx[:izplanes] = collect(ctx[:zplanes]) * ctx[:gridscale] - # adjust_planes() - - ctx[:xplanes] = collect(ctx[:xplanes]) - ctx[:yplanes] = collect(ctx[:yplanes]) - ctx[:zplanes] = collect(ctx[:zplanes]) - - x = ctx[:xplanes] - y = ctx[:yplanes] - z = ctx[:zplanes] + x = ctx[:ixplanes] + y = ctx[:iyplanes] + z = ctx[:izplanes] ε = 1.0e-5 * (xyzmax .- xyzmin) - ctx[:xplanes] = isa(x, Number) ? - collect(range(xyzmin[1] + ε[1], xyzmax[1] - ε[1]; length = ceil(x))) : x - ctx[:yplanes] = isa(y, Number) ? - collect(range(xyzmin[2] + ε[2], xyzmax[2] - ε[2]; length = ceil(y))) : y - ctx[:zplanes] = isa(z, Number) ? - collect(range(xyzmin[3] + ε[3], xyzmax[3] - ε[3]; length = ceil(z))) : z + ctx[:ixplanes] = isa(x, Number) ? + collect(range(xyzmin[1] + ε[1], xyzmax[1] - ε[1]; length = ceil(x))) : x + ctx[:iyplanes] = isa(y, Number) ? + collect(range(xyzmin[2] + ε[2], xyzmax[2] - ε[2]; length = ceil(y))) : y + ctx[:izplanes] = isa(z, Number) ? + collect(range(xyzmin[3] + ε[3], xyzmax[3] - ε[3]; length = ceil(z))) : z - ctx[:xplanes][1] = min(xyzmax[1], ctx[:xplanes][1]) - ctx[:yplanes][1] = min(xyzmax[2], ctx[:yplanes][1]) - ctx[:zplanes][1] = min(xyzmax[3], ctx[:zplanes][1]) + ctx[:ixplanes] = max.(xyzmin[1], min.(xyzmax[1], ctx[:ixplanes])) + ctx[:iyplanes] = max.(xyzmin[2], min.(xyzmax[2], ctx[:iyplanes])) + ctx[:izplanes] = max.(xyzmin[3], min.(xyzmax[3], ctx[:izplanes])) ctx[:levels] = levels @@ -1117,10 +1129,11 @@ function scalarplot!(ctx, TP::Type{MakieType}, ::Type{Val{3}}, grids, parentgrid ctx[:data] = Observable((g = grids, p = parentgrid, f = funcs, - x = ctx[:xplanes], - y = ctx[:yplanes], - z = ctx[:zplanes], + x = ctx[:ixplanes], + y = ctx[:iyplanes], + z = ctx[:izplanes], l = ctx[:levels], + c = ctx[:colorbarticks], t = ctx[:title])) ctx[:scene] = makeaxis3d(ctx) @@ -1128,7 +1141,8 @@ function scalarplot!(ctx, TP::Type{MakieType}, ::Type{Val{3}}, grids, parentgrid #### Transparent outline if ctx[:outlinealpha] > 0.0 ctx[:outlinedata] = map(d -> extract_visible_bfaces3D(d.p, - xyzmax; + xyzmax / ctx[:gridscale]; + gridscale = ctx[:gridscale], primepoints = hcat(xyzmin, xyzmax), Tp = Point3f, Tf = GLTriangleFace,), @@ -1149,6 +1163,7 @@ function scalarplot!(ctx, TP::Type{MakieType}, ::Type{Val{3}}, grids, parentgrid d.f, makeplanes(xyzmin, xyzmax, d.x, d.y, d.z), []; + gridscale = ctx[:gridscale], primepoints = hcat(xyzmin, xyzmax), primevalues = crange, tol = ctx[:tetxplane_tol], @@ -1161,6 +1176,7 @@ function scalarplot!(ctx, TP::Type{MakieType}, ::Type{Val{3}}, grids, parentgrid d.f, [], d.l; + gridscale = ctx[:gridscale], primepoints = hcat(xyzmin, xyzmax), primevalues = crange, tol = ctx[:tetxplane_tol], @@ -1183,27 +1199,31 @@ function scalarplot!(ctx, TP::Type{MakieType}, ::Type{Val{3}}, grids, parentgrid #### Interactions scene_interaction(ctx[:scene].scene, XMakie, [:z, :y, :x, :l, :q]) do delta, key if key == :x - ctx[:xplanes] .+= delta * xyzstep[1] - ctx[:status][] = "x=[" * mapreduce(x -> @sprintf("%.3g,", x), *, ctx[:xplanes]) * "]" + ctx[:ixplanes] .+= delta * xyzstep[1] + ctx[:status][] = "x=[" * mapreduce(x -> @sprintf("%.3g,", x), *, ctx[:ixplanes][1]) * "]" elseif key == :y - ctx[:yplanes] .+= delta * xyzstep[2] - ctx[:status][] = "y=[" * mapreduce(y -> @sprintf("%.3g,", y), *, ctx[:yplanes]) * "]" + ctx[:iyplanes] .+= delta * xyzstep[2] + ctx[:status][] = "y=[" * mapreduce(y -> @sprintf("%.3g,", y), *, ctx[:iyplanes][1]) * "]" elseif key == :z - ctx[:zplanes] .+= delta * xyzstep[3] - ctx[:status][] = "z=[" * mapreduce(z -> @sprintf("%.3g,", z), *, ctx[:zplanes]) * "]" + ctx[:izplanes] .+= delta * xyzstep[3] + ctx[:status][] = "z=[" * mapreduce(z -> @sprintf("%.3g,", z), *, ctx[:izplanes][1]) * "]" elseif key == :l ctx[:levels] .+= delta * fstep ctx[:status][] = "l=[" * mapreduce(l -> @sprintf("%.3g,", l), *, ctx[:levels]) * "]" elseif key == :q ctx[:status][] = " " end - # adjust_planes() + + ctx[:ixplanes] = max.(xyzmin[1], min.(xyzmax[1], ctx[:ixplanes])) + ctx[:iyplanes] = max.(xyzmin[2], min.(xyzmax[2], ctx[:iyplanes])) + ctx[:izplanes] = max.(xyzmin[3], min.(xyzmax[3], ctx[:izplanes])) + ctx[:data][] = (g = grids, p = parentgrid, f = funcs, - x = ctx[:xplanes], - y = ctx[:yplanes], - z = ctx[:zplanes], + x = ctx[:ixplanes], + y = ctx[:iyplanes], + z = ctx[:izplanes], l = ctx[:levels], t = ctx[:title]) end @@ -1213,9 +1233,9 @@ function scalarplot!(ctx, TP::Type{MakieType}, ::Type{Val{3}}, grids, parentgrid ctx[:data][] = (g = grids, p = parentgrid, f = funcs, - x = ctx[:xplanes], - y = ctx[:yplanes], - z = ctx[:zplanes], + x = ctx[:ixplanes], + y = ctx[:iyplanes], + z = ctx[:izplanes], l = ctx[:levels], t = ctx[:title]) end @@ -1247,3 +1267,16 @@ end # Christophe Meyer 4 hours ago # Thanks! lines(x, y, axis = (targetlimits = lims,)) indeed makes the limits update.^ # I found that autolimits!(axis) gave good results, even better than me manually computing limits! + +function customplot!(ctx, TP::Type{MakieType}, func) + XMakie = ctx[:Plotter] + if !haskey(ctx, :scene) + ctx[:scene] = XMakie.Axis(ctx[:figure]; + title = ctx[:title], + aspect = XMakie.DataAspect(), + scenekwargs(ctx)...,) + add_scene!(ctx, ctx[:scene]) + end + func(ctx[:scene]) + reveal(ctx, TP) +end diff --git a/src/plots.jl b/src/plots.jl index d6870c4..57990ec 100644 --- a/src/plots.jl +++ b/src/plots.jl @@ -92,14 +92,15 @@ function gridplot!(ctx, TP::Type{PlotsType}, ::Type{Val{1}}, grid) bfaceregions = grid[BFaceRegions] nbfaceregions = grid[NumBFaceRegions] - xmin = minimum(coord) - xmax = maximum(coord) + gridscale = ctx[:gridscale] + xmin = minimum(coord) * gridscale + xmax = maximum(coord) * gridscale h = (xmax - xmin) / 20.0 cmap = region_cmap(ncellregions) for icell = 1:num_cells(grid) - x1 = coord[1, cellnodes[1, icell]] - x2 = coord[1, cellnodes[2, icell]] + x1 = coord[1, cellnodes[1, icell]] * gridscale + x2 = coord[1, cellnodes[2, icell]] * gridscale Plots.plot!(p, [x1, x1], [-h, h]; linewidth = 0.5, color = :black, label = "") Plots.plot!(p, [x2, x2], [-h, h]; linewidth = 0.5, color = :black, label = "") Plots.plot!(p, @@ -113,7 +114,7 @@ function gridplot!(ctx, TP::Type{PlotsType}, ::Type{Val{1}}, grid) cmap = bregion_cmap(nbfaceregions) for ibface = 1:num_bfaces(grid) if bfaceregions[ibface] > 0 - x1 = coord[1, bfacenodes[1, ibface]] + x1 = coord[1, bfacenodes[1, ibface]] * gridscale Plots.plot!(p, [x1, x1], [-2 * h, 2 * h]; @@ -133,7 +134,7 @@ function gridplot!(ctx, TP::Type{PlotsType}, ::Type{Val{2}}, grid) p = ctx[:ax] cellregions = grid[CellRegions] cellnodes = grid[CellNodes] - coord = grid[Coordinates] + coord = grid[Coordinates] * ctx[:gridscale] ncellregions = grid[NumCellRegions] bfacenodes = grid[BFaceNodes] bfaceregions = grid[BFaceRegions] @@ -207,7 +208,7 @@ function scalarplot!(ctx, TP::Type{PlotsType}, ::Type{Val{1}}, grids, parentgrid end p = ctx[:ax] - coord = grid[Coordinates] + coord = grid[Coordinates] * ctx[:gridscale] xmin = coord[1, 1] xmax = coord[1, end] ymin = func[1] @@ -260,7 +261,7 @@ function scalarplot!(ctx, TP::Type{PlotsType}, ::Type{Val{1}}, grids, parentgrid else markevery = ctx[:markevery] markershape = ctx[:markershape] - X = vec(grid[Coordinates]) + X = vec(coord) if markershape == :none Plots.plot!(p, X, @@ -316,13 +317,13 @@ end $(SIGNATURES) Return rectangular grid data + function to be splatted into Plots calls """ -function rectdata(grid, U) +function rectdata(grid, gridscale, U) if dim_grid(grid) == 1 && haskey(grid, XCoordinates) - return grid[XCoordinates], U + return grid[XCoordinates] * gridscale, U end if dim_grid(grid) == 2 && haskey(grid, XCoordinates) && haskey(grid, YCoordinates) - X = grid[XCoordinates] - Y = grid[YCoordinates] + X = grid[XCoordinates] * gridscale + Y = grid[YCoordinates] * gridscale return X, Y, transpose(reshape(U, length(X), length(Y))) end nothing @@ -331,7 +332,7 @@ end function scalarplot!(ctx, TP::Type{PlotsType}, ::Type{Val{2}}, grids, parentgrid, funcs) grid = grids[1] func = funcs[1] - rdata = rectdata(grid, func) + rdata = rectdata(grid, ctx[:gridscale], func) Plots = ctx[:Plotter] if !haskey(ctx, :ax) ctx[:ax] = Plots.plot(; title = ctx[:title]) @@ -343,7 +344,13 @@ function scalarplot!(ctx, TP::Type{PlotsType}, ::Type{Val{2}}, grids, parentgrid p = ctx[:ax] levels, crange, colorbarticks = isolevels(ctx, func) - colorlevels = collect(crange[1]:((crange[2] - crange[1]) / (ctx[:colorlevels] - 1)):crange[2]) + eps = 1.0e-5 + if crange[1] == crange[2] + eps = 1.0e-5 + else + eps = (crange[2] - crange[1]) * 1.0e-15 + end + colorlevels = range(crange[1] - eps, crange[2] + eps; length = ctx[:colorlevels]) Plots.contourf!(p, rdata...; @@ -362,7 +369,7 @@ function vectorplot!(ctx, TP::Type{PlotsType}, ::Type{Val{2}}, grid, func) ctx[:ax] = Plots.plot(; title = ctx[:title]) end p = ctx[:ax] - rc, rv = vectorsample(grid, func; spacing = ctx[:spacing], offset = ctx[:offset]) + rc, rv = vectorsample(grid, func; gridscale = ctx[:gridscale], rasterpoints = ctx[:rasterpoints], offset = ctx[:offset]) qc, qv = quiverdata(rc, rv; vscale = ctx[:vscale], vnormalize = ctx[:vnormalize]) Plots.quiver!(p, qc[1, :], qc[2, :]; quiver = (qv[1, :], qv[2, :]), color = :black) @@ -390,3 +397,11 @@ function scalarplot!(ctx, TP::Type{PlotsType}, ::Type{Val{3}}, grids, parentgrid @warn "3D Scalarplot with Plots backend is not available." reveal(ctx, TP) end + +function customplot!(ctx, TP::Type{PlotsType}, func) + if !haskey(ctx, :ax) + ctx[:ax] = Plots.plot(; title = ctx[:title]) + end + func(ctx[:ax]) + reveal(ctx, TP) +end diff --git a/src/plutovista.jl b/src/plutovista.jl index e4cf6d0..661036f 100644 --- a/src/plutovista.jl +++ b/src/plutovista.jl @@ -98,7 +98,7 @@ function gridplot!(ctx, TP::Type{PlutoVistaType}, ::Type{Val{1}}, grid) coord = grid[Coordinates] cellregions = grid[CellRegions] cellnodes = grid[CellNodes] - coord = grid[Coordinates] + coord = grid[Coordinates] * ctx[:gridscale] ncellregions = grid[NumCellRegions] bfacenodes = grid[BFaceNodes] bfaceregions = grid[BFaceRegions] @@ -181,7 +181,7 @@ function scalarplot!(ctx, for ifunc = 1:nfuncs func = funcs[ifunc] grid = grids[ifunc] - coord = grid[Coordinates] + coord = grid[Coordinates] * ctx[:gridscale] if ifunc == 1 PlutoVista.plot!(ctx[:figure], @@ -228,7 +228,6 @@ function gridplot!(ctx, TP::Type{PlutoVistaType}, ::Type{Val{2}}, grid) nbregions = num_bfaceregions(grid) cmap = region_cmap(nregions) bcmap = bregion_cmap(nbregions) - PlutoVista = ctx[:Plotter] pts = grid[Coordinates] tris = grid[CellNodes] @@ -271,7 +270,7 @@ function scalarplot!(ctx, end allcoords = hcat(coords...) - + levels, crange, colorbarticks = isolevels(ctx, funcs) allcellnodes = Matrix{Int}(undef, 3, sum(ncells)) k = 1 for j = 1:ngrids @@ -290,8 +289,8 @@ function scalarplot!(ctx, allcellnodes, vcat(funcs...); colormap = ctx[:colormap], - levels = ctx[:levels], - colorbarticks = ctx[:colorbarticks], + levels, + colorbarticks = colorbarticks, limits = ctx[:limits], backend = ctx[:backend], zoom = ctx[:zoom], @@ -307,7 +306,7 @@ function vectorplot!(ctx, TP::Type{PlutoVistaType}, ::Type{Val{2}}, grid, func) PlutoVista = ctx[:Plotter] PlutoVista.backend!(ctx[:figure]; backend = ctx[:backend], datadim = 2) - rc, rv = vectorsample(grid, func; spacing = ctx[:spacing], offset = ctx[:offset]) + rc, rv = vectorsample(grid, func; rasterpoints = ctx[:rasterpoints], offset = ctx[:offset], gridscale = ctx[:gridscale]) qc, qv = quiverdata(rc, rv; vscale = ctx[:vscale], vnormalize = ctx[:vnormalize]) PlutoVista.quiver2d!(ctx[:figure], qc, qv) diff --git a/src/pyplot.jl b/src/pyplot.jl index 8e9665f..6d77bff 100644 --- a/src/pyplot.jl +++ b/src/pyplot.jl @@ -85,15 +85,15 @@ const leglocs = Dict(:none => "", $(SIGNATURES) Return tridata to be splatted to PyPlot calls """ -function tridata(grid::ExtendableGrid) - coord = grid[Coordinates] +function tridata(grid::ExtendableGrid, gridscale) + coord = grid[Coordinates] * gridscale cellnodes = Matrix(grid[CellNodes]) coord[1, :], coord[2, :], transpose(cellnodes .- 1) end -function tridata(grids) +function tridata(grids, gridscale) ngrids = length(grids) - coords = [grid[Coordinates] for grid in grids] + coords = [grid[Coordinates] * gridscale for grid in grids] npoints = [num_nodes(grid) for grid in grids] cellnodes = [grid[CellNodes] for grid in grids] ncells = [num_cells(grid) for grid in grids] @@ -154,14 +154,15 @@ function gridplot!(ctx, TP::Type{PyPlotType}, ::Type{Val{1}}, grid) ax.get_yaxis().set_ticks([]) ax.set_ylim(-5 * h, xmax - xmin) cmap = region_cmap(ncellregions) + gridscale = ctx[:gridscale] for icell = 1:num_cells(grid) ireg = cellregions[icell] label = crflag[ireg] ? "c$(ireg)" : "" crflag[ireg] = false - x1 = coord[1, cellnodes[1, icell]] - x2 = coord[1, cellnodes[2, icell]] + x1 = coord[1, cellnodes[1, icell]] * gridscale + x2 = coord[1, cellnodes[2, icell]] * gridscale ax.plot([x1, x2], [0, 0]; linewidth = 3.0, @@ -177,7 +178,7 @@ function gridplot!(ctx, TP::Type{PyPlotType}, ::Type{Val{1}}, grid) if ireg > 0 label = brflag[ireg] ? "b$(ireg)" : "" brflag[ireg] = false - x1 = coord[1, bfacenodes[1, ibface]] + x1 = coord[1, bfacenodes[1, ibface]] * ctx[:gridscale] ax.plot([x1, x1], [-2 * h, 2 * h]; linewidth = 3.0, @@ -214,7 +215,6 @@ function gridplot!(ctx, TP::Type{PyPlotType}, ::Type{Val{2}}, grid) fig = ctx[:figure] cellregions = grid[CellRegions] cellnodes = grid[CellNodes] - coord = grid[Coordinates] ncellregions = grid[NumCellRegions] nbfaceregions = grid[NumBFaceRegions] ncellregions = grid[NumCellRegions] @@ -226,7 +226,7 @@ function gridplot!(ctx, TP::Type{PyPlotType}, ::Type{Val{2}}, grid) crflag = ones(Bool, ncellregions) brflag = ones(Bool, nbfaceregions) ax.set_aspect(ctx[:aspect]) - tridat = tridata(grid) + tridat = tridata(grid, ctx[:gridscale]) cmap = region_cmap(ncellregions) cdata = ax.tripcolor(tridat...; facecolors = grid[CellRegions], @@ -250,16 +250,18 @@ function gridplot!(ctx, TP::Type{PyPlotType}, ::Type{Val{2}}, grid) ax.triplot(tridat...; color = "k", linewidth = ctx[:linewidth]) if nbfaceregions > 0 + gridscale = ctx[:gridscale] + coord = grid[Coordinates] cmap = bregion_cmap(nbfaceregions) # see https://gist.github.com/gizmaa/7214002 - c1 = [coord[:, bfacenodes[1, i]] for i = 1:num_sources(bfacenodes)] - c2 = [coord[:, bfacenodes[2, i]] for i = 1:num_sources(bfacenodes)] + c1 = [coord[:, bfacenodes[1, i]] for i = 1:num_sources(bfacenodes)] * gridscale + c2 = [coord[:, bfacenodes[2, i]] for i = 1:num_sources(bfacenodes)] * gridscale rgb = [rgbtuple(cmap[bfaceregions[i]]) for i = 1:length(bfaceregions)] ax.add_collection(PyPlot.matplotlib.collections.LineCollection(collect(zip(c1, c2)); colors = rgb, linewidth = 3,)) for i = 1:nbfaceregions - ax.plot(coord[1, 1:1], coord[2, 1:1]; label = "$(i)", color = rgbtuple(cmap[i])) + ax.plot(coord[1, 1:1] * gridscale, coord[2, 1:1] * gridscale; label = "$(i)", color = rgbtuple(cmap[i])) end end if ctx[:legend] != :none @@ -287,10 +289,10 @@ function gridplot!(ctx, TP::Type{PyPlotType}, ::Type{Val{3}}, grid) nregions = num_cellregions(grid) nbregions = num_bfaceregions(grid) - + gridscale = ctx[:gridscale] xyzmin = zeros(3) xyzmax = ones(3) - coord = grid[Coordinates] + coord = grid[Coordinates] * gridscale @views for idim = 1:3 xyzmin[idim] = minimum(coord[idim, :]) xyzmax[idim] = maximum(coord[idim, :]) @@ -307,7 +309,8 @@ function gridplot!(ctx, TP::Type{PyPlotType}, ::Type{Val{3}}, grid) xyzcut = [ctx[:xplanes][1], ctx[:yplanes][1], ctx[:zplanes][1]] if ctx[:interior] - regpoints0, regfacets0 = extract_visible_cells3D(grid, xyzcut; primepoints = hcat(xyzmin, xyzmax)) + regpoints0, regfacets0 = extract_visible_cells3D(grid, xyzcut; gridscale = ctx[:gridscale], + primepoints = hcat(xyzmin, xyzmax)) regfacets = [reshape(reinterpret(Int32, regfacets0[i]), (3, length(regfacets0[i]))) for i = 1:nregions] regpoints = [reshape(reinterpret(Float32, regpoints0[i]), (3, length(regpoints0[i]))) for @@ -326,7 +329,8 @@ function gridplot!(ctx, TP::Type{PyPlotType}, ::Type{Val{3}}, grid) end end - bregpoints0, bregfacets0 = extract_visible_bfaces3D(grid, xyzcut; primepoints = hcat(xyzmin, xyzmax)) + bregpoints0, bregfacets0 = extract_visible_bfaces3D(grid, xyzcut; gridscale = ctx[:gridscale], + primepoints = hcat(xyzmin, xyzmax)) bregfacets = [reshape(reinterpret(Int32, bregfacets0[i]), (3, length(bregfacets0[i]))) for i = 1:nbregions] bregpoints = [reshape(reinterpret(Float32, bregpoints0[i]), (3, length(bregpoints0[i]))) for @@ -395,7 +399,7 @@ function scalarplot!(ctx, TP::Type{PyPlotType}, ::Type{Val{1}}, grids, parentgri pplot = ax.semilogy end end - + gridscale = ctx[:gridscale] if ctx[:cellwise] # not checked, outdated for icell = 1:num_cells(grid) i1 = cellnodes[1, icell] @@ -415,7 +419,7 @@ function scalarplot!(ctx, TP::Type{PyPlotType}, ::Type{Val{1}}, grids, parentgri if ctx[:markershape] == :none for ifunc = 1:nfuncs func = funcs[ifunc] - coord = grids[ifunc][Coordinates] + coord = grids[ifunc][Coordinates] * gridscale if ctx[:label] !== "" && ifunc == 1 pplot(coord[1, :], func; @@ -434,7 +438,7 @@ function scalarplot!(ctx, TP::Type{PyPlotType}, ::Type{Val{1}}, grids, parentgri else for ifunc = 1:nfuncs func = funcs[ifunc] - coord = grids[ifunc][Coordinates] + coord = grids[ifunc][Coordinates] * gridscale if ctx[:label] !== "" && ifunc == 1 pplot(coord[1, :], func; @@ -505,19 +509,19 @@ function scalarplot!(ctx, TP::Type{PyPlotType}, ::Type{Val{2}}, grids, parentgri levels, crange, colorbarticks = isolevels(ctx, funcs) eps = 1.0e-5 if crange[1] == crange[2] - eps=1.0e-5 + eps = 1.0e-5 else - eps=(crange[2]-crange[1])*1.0e-15 + eps = (crange[2] - crange[1]) * 1.0e-15 end - - colorlevels=range(crange[1]-eps, crange[2]+eps, length=ctx[:colorlevels]) + + colorlevels = range(crange[1] - eps, crange[2] + eps; length = ctx[:colorlevels]) # if !haskey(ctx, :grid) || !seemingly_equal(ctx[:grid], grid) # ctx[:grid] = grids # ctx[:tridata] = tridata(grids) # end - tdat = tridata(grids) + tdat = tridata(grids, ctx[:gridscale]) func = vcat(funcs...) cnt = ax.tricontourf(tdat..., func; @@ -559,27 +563,29 @@ function scalarplot!(ctx, TP::Type{PyPlotType}, ::Type{Val{3}}, grids, parentgri end ax = ctx[:ax] fig = ctx[:figure] - + griscale = ctx[:gridscale] xyzmin = zeros(3) xyzmax = ones(3) coord = parentgrid[Coordinates] @views for idim = 1:3 - xyzmin[idim] = minimum(coord[idim, :]) - xyzmax[idim] = maximum(coord[idim, :]) + xyzmin[idim] = minimum(coord[idim, :]) * ctx[:gridscale] + xyzmax[idim] = maximum(coord[idim, :]) * ctx[:gridscale] end - xyzcut = [ctx[:xplanes], ctx[:yplanes], ctx[:zplanes]] + xyzcut = [ctx[:xplanes], ctx[:yplanes], ctx[:zplanes]] * ctx[:gridscale] levels, crange, colorbarticks = isolevels(ctx, funcs) - eps = 1.0e-5 + if crange[1] == crange[2] - crange = (crange[1] - eps, crange[1] + eps) - colorlevels = collect(crange[1]:((crange[2] - crange[1]) / (1)):crange[2]) + eps = 1.0e-5 else - colorlevels = collect(crange[1]:((crange[2] - crange[1]) / (ctx[:colorlevels] - 1)):crange[2]) + eps = (crange[2] - crange[1]) * 1.0e-15 end + colorlevels = range(crange[1] - eps, crange[2] + eps; length = ctx[:colorlevels]) + planes = makeplanes(xyzmin, xyzmax, ctx[:xplanes], ctx[:yplanes], ctx[:zplanes]) - ccoord0, faces0, values = marching_tetrahedra(grids, funcs, planes, levels; tol = ctx[:tetxplane_tol]) + ccoord0, faces0, values = marching_tetrahedra(grids, funcs, planes, levels; gridscale = ctx[:gridscale], + tol = ctx[:tetxplane_tol]) faces = reshape(reinterpret(Int32, faces0), (3, length(faces0))) ccoord = reshape(reinterpret(Float32, ccoord0), (3, length(ccoord0))) @@ -657,8 +663,8 @@ function vectorplot!(ctx, TP::Type{PyPlotType}, ::Type{Val{2}}, grid, func) ax.set_aspect(ctx[:aspect]) ax.set_title(ctx[:title]) - rc, rv = vectorsample(grid, func; spacing = ctx[:spacing], offset = ctx[:offset], xlimits = ctx[:xlimits], - ylimits = ctx[:ylimits]) + rc, rv = vectorsample(grid, func; rasterpoints = ctx[:rasterpoints], offset = ctx[:offset], xlimits = ctx[:xlimits], + ylimits = ctx[:ylimits], gridscale = ctx[:gridscale]) qc, qv = quiverdata(rc, rv; vscale = ctx[:vscale], vnormalize = ctx[:vnormalize], vconstant = ctx[:vconstant]) # For the kwargs, see @@ -714,8 +720,8 @@ function streamplot!(ctx, TP::Type{PyPlotType}, ::Type{Val{2}}, grid, func) xout, yout end - rc, rv = vectorsample(grid, func; spacing = ctx[:spacing], offset = ctx[:offset], xlimits = ctx[:xlimits], - ylimits = ctx[:ylimits]) + rc, rv = vectorsample(grid, func; rasterpoints = 2 * ctx[:rasterpoints], offset = ctx[:offset], xlimits = ctx[:xlimits], + ylimits = ctx[:ylimits], gridscale = ctx[:gridscale]) X, Y = meshgrid(rc) @@ -725,3 +731,19 @@ function streamplot!(ctx, TP::Type{PyPlotType}, ::Type{Val{2}}, grid, func) reveal(ctx, TP) end + +function customplot!(ctx, TP::Type{PyPlotType}, func) + PyPlot = ctx[:Plotter] + if !haskey(ctx, :ax) + ctx[:ax] = ctx[:figure].add_subplot(ctx[:layout]..., ctx[:iplot]) + end + # if ctx[:clear] + # if haskey(ctx, :cbar) + # ctx[:cbar].remove() + # end + # ctx[:ax].remove() + # ctx[:ax] = ctx[:figure].add_subplot(ctx[:layout]..., ctx[:iplot]) + # end + func(ctx[:ax]) + reveal(ctx, TP) +end