diff --git a/CairoMakie/src/primitives.jl b/CairoMakie/src/primitives.jl index 1309a95e7ca..63a645d55cb 100644 --- a/CairoMakie/src/primitives.jl +++ b/CairoMakie/src/primitives.jl @@ -580,6 +580,7 @@ function draw_atomic(scene::Scene, screen::Screen, @nospecialize(primitive::Unio ctx = screen.context image = primitive[3][] xs, ys = primitive[1][], primitive[2][] + if !(xs isa AbstractVector) l, r = extrema(xs) N = size(image, 1) @@ -620,8 +621,8 @@ function draw_atomic(scene::Scene, screen::Screen, @nospecialize(primitive::Unio # find projected image corners # this already takes care of flipping the image to correct cairo orientation space = to_value(get(primitive, :space, :data)) - xy = project_position(scene, space, Point2f(first.(imsize)), model) - xymax = project_position(scene, space, Point2f(last.(imsize)), model) + xy = project_position(scene, space, Point2{Float64}(first.(imsize)), model) + xymax = project_position(scene, space, Point2{Float64}(last.(imsize)), model) w, h = xymax .- xy can_use_fast_path = !(is_vector && !interpolate) && regular_grid && identity_transform @@ -718,7 +719,7 @@ end function draw_mesh2D(scene, screen, @nospecialize(plot), @nospecialize(mesh)) @get_attribute(plot, (color,)) color = to_color(hasproperty(mesh, :color) ? mesh.color : color) - vs = decompose(Point2f, mesh)::Vector{Point2f} + vs = decompose(Point2{Float64}, mesh)::Vector{Point2{Float64}} fs = decompose(GLTriangleFace, mesh)::Vector{GLTriangleFace} uv = decompose_uv(mesh)::Union{Nothing, Vector{Vec2f}} model = plot.model[]::Mat4f @@ -739,7 +740,7 @@ function draw_mesh2D(scene, screen, @nospecialize(plot), @nospecialize(mesh)) end function draw_mesh2D(scene, screen, per_face_cols, space::Symbol, transform_func, - vs::Vector{Point2f}, fs::Vector{GLTriangleFace}, model::Mat4f) + vs::Vector{Point2{Float64}}, fs::Vector{GLTriangleFace}, model::Mat4f) ctx = screen.context # Priorize colors of the mesh if present @@ -784,7 +785,7 @@ function draw_mesh3D(scene, screen, attributes, mesh; pos = Vec4f(0), scale = 1f matcap = to_value(get(attributes, :matcap, nothing)) color = hasproperty(mesh, :color) ? mesh.color : color - meshpoints = decompose(Point3f, mesh)::Vector{Point3f} + meshpoints = decompose(Point3{Float64}, mesh)::Vector{Point3{Float64}} meshfaces = decompose(GLTriangleFace, mesh)::Vector{GLTriangleFace} meshnormals = decompose_normals(mesh)::Vector{Vec3f} meshuvs = texturecoordinates(mesh)::Union{Nothing, Vector{Vec2f}} @@ -830,8 +831,8 @@ function draw_mesh3D( vs = broadcast(meshpoints, (transform_func,)) do v, f # Should v get a nan2zero? v = Makie.apply_transform(f, v, space) - p4d = to_ndim(Vec4f, scale .* to_ndim(Vec3f, v, 0f0), 1f0) - view * (model * p4d .+ to_ndim(Vec4f, pos, 0f0)) + p4d = to_ndim(Vec4{Float64}, scale .* to_ndim(Vec3{Float64}, v, 0.0), 1.0) + view * (model * p4d .+ to_ndim(Vec4{Float64}, pos, 0.0)) end ns = map(n -> normalize(normalmatrix * n), meshnormals) diff --git a/CairoMakie/src/utils.jl b/CairoMakie/src/utils.jl index f3a2ad4cca0..bebb5abfb98 100644 --- a/CairoMakie/src/utils.jl +++ b/CairoMakie/src/utils.jl @@ -10,15 +10,15 @@ end function _project_position(scene, space, point, model, yflip) res = scene.camera.resolution[] - p4d = to_ndim(Vec4f, to_ndim(Vec3f, point, 0f0), 1f0) - clip = Makie.space_to_clip(scene.camera, space) * model * p4d + p4d = to_ndim(Vec4{Float64}, to_ndim(Vec3{Float64}, point, 0.0), 1.0) + clip = Mat4{Float64}(Makie.space_to_clip(scene.camera, space)) * Mat4{Float64}(model) * p4d @inbounds begin # between -1 and 1 p = (clip ./ clip[4])[Vec(1, 2)] # flip y to match cairo - p_yflip = Vec2f(p[1], (1f0 - 2f0 * yflip) * p[2]) + p_yflip = Vec2{Float64}(p[1], (1.0 - 2.0 * yflip) * p[2]) # normalize to between 0 and 1 - p_0_to_1 = (p_yflip .+ 1f0) ./ 2f0 + p_0_to_1 = (p_yflip .+ 1.0) ./ 2.0 end # multiply with scene resolution for final position return p_0_to_1 .* res diff --git a/GLMakie/src/GLAbstraction/GLUniforms.jl b/GLMakie/src/GLAbstraction/GLUniforms.jl index 17f83cc7ec8..8aacf04f0c7 100644 --- a/GLMakie/src/GLAbstraction/GLUniforms.jl +++ b/GLMakie/src/GLAbstraction/GLUniforms.jl @@ -15,11 +15,11 @@ opengl_postfix(T) = error("Object $T is not a supported uniform element type") opengl_prefix(x::Type{T}) where {T <: Union{FixedPoint, Float32, Float16}} = "" -opengl_prefix(x::Type{T}) where {T <: Float64} = "d" +opengl_prefix(x::Type{T}) where {T <: Float64} = error("Float64") # "d" opengl_prefix(x::Type{Cint}) = "i" opengl_prefix(x::Type{T}) where {T <: Union{Cuint, UInt8, UInt16}} = "u" -opengl_postfix(x::Type{Float64}) = "dv" +opengl_postfix(x::Type{Float64}) = error("Float64") # "dv" opengl_postfix(x::Type{Float32}) = "fv" opengl_postfix(x::Type{Cint}) = "iv" opengl_postfix(x::Type{Cuint}) = "uiv" diff --git a/GLMakie/src/drawing_primitives.jl b/GLMakie/src/drawing_primitives.jl index 7cfd5126fd4..571e8a19a1d 100644 --- a/GLMakie/src/drawing_primitives.jl +++ b/GLMakie/src/drawing_primitives.jl @@ -51,25 +51,25 @@ function connect_camera!(plot, gl_attributes, cam, space = gl_attributes[:space] end get!(gl_attributes, :view) do return lift(plot, cam.view, space) do view, space - return is_data_space(space) ? view : Mat4f(I) + return is_data_space(space) ? Mat4f(view) : Mat4f(I) end end get!(gl_attributes, :normalmatrix) do return lift(plot, gl_attributes[:view], gl_attributes[:model]) do v, m i = Vec(1, 2, 3) - return transpose(inv(v[i, i] * m[i, i])) + return transpose(inv(Mat3f(v[i, i]) * Mat3f(m[i, i]))) end end get!(gl_attributes, :projection) do return lift(cam.projection, cam.pixel_space, space) do _, _, space - return Makie.space_to_clip(cam, space, false) + return Mat4f(Makie.space_to_clip(cam, space, false)) end end get!(gl_attributes, :projectionview) do return lift(plot, cam.projectionview, cam.pixel_space, space) do _, _, space - Makie.space_to_clip(cam, space, true) + Mat4f(Makie.space_to_clip(cam, space, true)) end end @@ -203,12 +203,13 @@ function draw_atomic(screen::Screen, scene::Scene, @nospecialize(x::Union{Scatte space = get(gl_attributes, :space, :data) # needs to happen before connect_camera! call positions = handle_view(x[1], gl_attributes) positions = apply_transform(transform_func_obs(x), positions, space) + positions = map(el32convert, positions) if x isa Scatter mspace = get(gl_attributes, :markerspace, :pixel) cam = scene.camera gl_attributes[:preprojection] = map(space, mspace, cam.projectionview, cam.resolution) do space, mspace, _, _ - return Makie.clip_to_space(cam, mspace) * Makie.space_to_clip(cam, space) + return Mat4f(Makie.clip_to_space(cam, mspace) * Makie.space_to_clip(cam, space)) end # fast pixel does its own setup if !(marker[] isa FastPixel) @@ -283,6 +284,7 @@ function draw_atomic(screen::Screen, scene::Scene, @nospecialize(x::Lines)) data[:fast] = true positions = apply_transform(transform_func, positions, space) + positions = map(el32convert, positions) else linewidth = gl_attributes[:thickness] data[:pattern] = map((ls, lw) -> ls .* _mean(lw), linestyle, linewidth) @@ -322,6 +324,7 @@ function draw_atomic(screen::Screen, scene::Scene, @nospecialize(x::LineSegments space = get(gl_attributes, :space, :data) # needs to happen before connect_camera! call positions = handle_view(x.converted[1], data) positions = apply_transform(transform_func_obs(x), positions, space) + positions = map(el32convert, positions) if haskey(data, :color) && data[:color][] isa AbstractVector{<: Number} c = pop!(data, :color) data[:color] = el32convert(c) @@ -357,7 +360,6 @@ function draw_atomic(screen::Screen, scene::Scene, lift(getindex, x, glyph_data, i) end - filter!(gl_attributes) do (k, v) # These are liftkeys without model !(k in ( @@ -400,9 +402,8 @@ function draw_atomic(screen::Screen, scene::Scene, gl_attributes[:distancefield] = get_texture!(atlas) gl_attributes[:visible] = x.visible cam = scene.camera - # gl_attributes[:preprojection] = Observable(Mat4f(I)) gl_attributes[:preprojection] = map(space, markerspace, cam.projectionview, cam.resolution) do s, ms, pv, res - Makie.clip_to_space(cam, ms) * Makie.space_to_clip(cam, s) + Mat4f(Makie.clip_to_space(cam, ms) * Makie.space_to_clip(cam, s)) end connect_camera!(x, gl_attributes, cam, markerspace) @@ -484,13 +485,6 @@ function draw_atomic(screen::Screen, scene::Scene, x::Image) end end -function update_positions(mesh::GeometryBasics.Mesh, positions) - points = coordinates(mesh) - attr = GeometryBasics.attributes(points) - delete!(attr, :position) # position == metafree(points) - return GeometryBasics.Mesh(meta(positions; attr...), faces(mesh)) -end - function mesh_inner(screen::Screen, mesh, transfunc, gl_attributes, space=:data) # signals not supported for shading yet gl_attributes[:shading] = to_value(pop!(gl_attributes, :shading)) @@ -519,9 +513,12 @@ function mesh_inner(screen::Screen, mesh, transfunc, gl_attributes, space=:data) end mesh = map(mesh, transfunc, space) do mesh, func, space if !Makie.is_identity_transform(func) - return update_positions(mesh, apply_transform.((func,), mesh.position, space)) + pos = apply_transform.((func,), mesh.position, space) + else + pos = mesh.position end - return mesh + m = el32convert(mesh, pos) + return m end return draw_mesh(screen, mesh, gl_attributes) end @@ -572,14 +569,14 @@ function draw_atomic(screen::Screen, scene::Scene, x::Surface) xypos = map(t, x[1], x[2], space) do t, x, y, space # Only if transform doesn't do anything, we can stay linear in 1/2D if Makie.is_identity_transform(t) - return (x, y) + return (el32convert(x), el32convert(y)) else matrix = if x isa AbstractMatrix && y isa AbstractMatrix apply_transform.((t,), Point.(x, y), space) else # If we do any transformation, we have to assume things aren't on the grid anymore # so x + y need to become matrices. - [apply_transform(t, Point(x, y), space) for x in x, y in y] + Point3f[apply_transform(t, Point(x, y), space) for x in x, y in y] end return (first.(matrix), last.(matrix)) end diff --git a/GLMakie/src/postprocessing.jl b/GLMakie/src/postprocessing.jl index 3c295d158a6..d639c012fbb 100644 --- a/GLMakie/src/postprocessing.jl +++ b/GLMakie/src/postprocessing.jl @@ -173,7 +173,7 @@ function ssao_postprocessor(framebuffer, shader_cache) a = pixelarea(scene)[] glScissor(minimum(a)..., widths(a)...) # update uniforms - data1[:projection] = scene.camera.projection[] + data1[:projection] = Mat4f(scene.camera.projection[]) data1[:bias] = scene.ssao.bias[] data1[:radius] = scene.ssao.radius[] GLAbstraction.render(pass1) diff --git a/WGLMakie/src/imagelike.jl b/WGLMakie/src/imagelike.jl index bf20aafaeba..76f93a1c038 100644 --- a/WGLMakie/src/imagelike.jl +++ b/WGLMakie/src/imagelike.jl @@ -33,7 +33,7 @@ function draw_mesh(mscene::Scene, mesh, plot; uniforms...) get!(uniforms, :interpolate_in_fragment_shader, true) uniforms[:normalmatrix] = map(mscene.camera.view, plot.model) do v, m i = Vec(1, 2, 3) - return transpose(inv(v[i, i] * m[i, i])) + return Mat3f(transpose(inv(v[i, i] * m[i, i]))) end for key in (:diffuse, :specular, :shininess, :backlight) @@ -88,13 +88,13 @@ function limits_to_uvmesh(plot) rect = lift(px, py) do x, y xmin, xmax = extrema(x) ymin, ymax = extrema(y) - return Rect2(xmin, ymin, xmax - xmin, ymax - ymin) + return Rect2f(xmin, ymin, xmax - xmin, ymax - ymin) end positions = Buffer(lift(rect-> decompose(Point2f, rect), rect)) faces = Buffer(lift(rect -> decompose(GLTriangleFace, rect), rect)) uv = Buffer(lift(decompose_uv, rect)) - else - grid(x, y, trans, space) = Makie.matrix_grid(p-> apply_transform(trans, p, space), x, y, zeros(length(x), length(y))) + else + grid(x, y, trans, space) = Makie.el32convert(Makie.matrix_grid(p-> apply_transform(trans, p, space), x, y, zeros(length(x), length(y)))) resolution = lift((x, y) -> (length(x), length(y)), px, py; ignore_equal_values=true) positions = Buffer(lift(grid, px, py, t, get(plot, :space, :data))) faces = Buffer(lift(fast_faces, resolution)) @@ -115,7 +115,7 @@ end function create_shader(mscene::Scene, plot::Surface) # TODO OWN OPTIMIZED SHADER ... Or at least optimize this a bit more ... px, py, pz = plot[1], plot[2], plot[3] - grid(x, y, z, trans, space) = Makie.matrix_grid(p-> apply_transform(trans, p, space), x, y, z) + grid(x, y, z, trans, space) = el32convert(Makie.matrix_grid(p-> apply_transform(trans, p, space), x, y, z)) positions = Buffer(lift(grid, px, py, pz, transform_func_obs(plot), get(plot, :space, :data))) rect = lift(z -> Tesselation(Rect2(0f0, 0f0, 1f0, 1f0), size(z)), pz) faces = Buffer(lift(r -> decompose(GLTriangleFace, r), rect)) diff --git a/WGLMakie/src/meshes.jl b/WGLMakie/src/meshes.jl index 832272dbcb6..7526d64b3ea 100644 --- a/WGLMakie/src/meshes.jl +++ b/WGLMakie/src/meshes.jl @@ -1,6 +1,6 @@ function vertexbuffer(x, trans, space) pos = decompose(Point, x) - return apply_transform(trans, pos, space) + return el32convert(apply_transform(trans, pos, space)) end function vertexbuffer(x::Observable, p) @@ -41,7 +41,7 @@ function create_shader(scene::Scene, plot::Makie.Mesh) for (key, default) in (:uv => Vec2f(0), :normals => Vec3f(0)) if haskey(data, key) - attributes[key] = Buffer(get_attribute(mesh_signal, key)) + attributes[key] = Buffer(map(el32convert, get_attribute(mesh_signal, key))) else uniforms[key] = Observable(default) end @@ -121,7 +121,7 @@ function create_shader(scene::Scene, plot::Makie.Mesh) uniforms[:normalmatrix] = map(scene.camera.view, plot.model) do v, m i = Vec(1, 2, 3) - return transpose(inv(v[i, i] * m[i, i])) + return transpose(Mat3f(inv(v[i, i] * m[i, i]))) end # id + picking gets filled in JS, needs to be here to emit the correct shader uniforms diff --git a/WGLMakie/src/particles.jl b/WGLMakie/src/particles.jl index d12ad0c9fce..3ff54d2aa2b 100644 --- a/WGLMakie/src/particles.jl +++ b/WGLMakie/src/particles.jl @@ -54,7 +54,9 @@ function create_shader(scene::Scene, plot::MeshScatter) return k in per_instance_keys && !(isscalar(v[])) end space = get(plot, :space, :data) - per_instance[:offset] = apply_transform(transform_func_obs(plot), plot[1], space) + per_instance[:offset] = map(transform_func_obs(plot), plot[1], space) do tf, pos, space + el32convert(apply_transform(tf, pos, space)) + end for (k, v) in per_instance per_instance[k] = Buffer(lift_convert(k, v, plot)) @@ -71,7 +73,7 @@ function create_shader(scene::Scene, plot::MeshScatter) end handle_color!(uniform_dict, per_instance) - instance = convert_attribute(plot.marker[], key"marker"(), key"meshscatter"()) + instance = el32convert(convert_attribute(plot.marker[], key"marker"(), key"meshscatter"())) if !hasproperty(instance, :uv) uniform_dict[:uv] = Vec2f(0) @@ -182,7 +184,7 @@ function scatter_shader(scene::Scene, attributes, plot) handle_color!(uniform_dict, per_instance) - instance = uv_mesh(Rect2(-0.5f0, -0.5f0, 1f0, 1f0)) + instance = uv_mesh(Rect2f(-0.5f0, -0.5f0, 1f0, 1f0)) # Don't send obs, since it's overwritten in JS to be updated by the camera uniform_dict[:resolution] = to_value(scene.camera.resolution) @@ -204,7 +206,9 @@ function create_shader(scene::Scene, plot::Scatter) space = get(attributes, :space, :data) cam = scene.camera attributes[:preprojection] = Mat4f(I) # calculate this in JS - attributes[:pos] = apply_transform(transform_func_obs(plot), plot[1], space) + attributes[:pos] = map(transform_func_obs(plot), plot[1], space) do tf, pos, space + el32convert(apply_transform(tf, pos, space)) + end quad_offset = get(attributes, :marker_offset, Observable(Vec2f(0))) attributes[:marker_offset] = Vec3f(0) diff --git a/WGLMakie/src/serialization.jl b/WGLMakie/src/serialization.jl index 044d31d8192..c8aa630a064 100644 --- a/WGLMakie/src/serialization.jl +++ b/WGLMakie/src/serialization.jl @@ -345,5 +345,10 @@ function serialize_camera(scene::Scene) # a view matrix change! ep = cam.eyeposition[] return [vec(collect(view)), vec(collect(proj)), Int32[res...], Float32[ep...]] + # eyepos32 = Vector{Float32}(cam.eyeposition[]) + # res32 = Vector{Int32}(res) + # view32 = Vector{Float32}(vec(view)) + # proj32 = Vector{Float32}(vec(proj)) + # return [view32, proj32, res32, eyepos32] end -end +end \ No newline at end of file diff --git a/docs/documentation/recipes.md b/docs/documentation/recipes.md index 326c72add69..183d33c5f8f 100644 --- a/docs/documentation/recipes.md +++ b/docs/documentation/recipes.md @@ -238,7 +238,9 @@ function Makie.plot!( push!(bar_tos[], s.close) end append!(colors[], [x.close > x.open for x in stockvalues]) - colors[] = colors[] + notify(linesegs) + notify(colors) + return end # connect `update_plot` so that it is called whenever `times` diff --git a/src/Makie.jl b/src/Makie.jl index c0ec3d157ae..ac1fea8c369 100644 --- a/src/Makie.jl +++ b/src/Makie.jl @@ -91,6 +91,13 @@ const RGBAf = RGBA{Float32} const RGBf = RGB{Float32} const NativeFont = FreeTypeAbstraction.FTFont +const Vec2e = Vec2{Float64} +const Vec3e = Vec3{Float64} +const Vec4e = Vec4{Float64} +const Point2e = Point2{Float64} +const Point3e = Point3{Float64} +const Point4e = Point4{Float64} + const ASSETS_DIR = RelocatableFolders.@path joinpath(@__DIR__, "..", "assets") assetpath(files...) = normpath(joinpath(ASSETS_DIR, files...)) diff --git a/src/basic_recipes/ablines.jl b/src/basic_recipes/ablines.jl index 6e3786d82c1..06024020b52 100644 --- a/src/basic_recipes/ablines.jl +++ b/src/basic_recipes/ablines.jl @@ -23,23 +23,16 @@ function Makie.plot!(p::ABLines) limits = lift(projview_to_2d_limits, p, scene.camera.projectionview) - points = Observable(Point2f[]) - - onany(p, limits, p[1], p[2]) do lims, intercept, slope - inv = inverse_transform(transf) - empty!(points[]) - f(x) = x * b + a + points = map(p, limits, p[1], p[2]) do lims, intercept, slope + points = sizehint!(Point2e[], 2length(slope)) broadcast_foreach(intercept, slope) do intercept, slope - f(x) = intercept + slope * x xmin, xmax = first.(extrema(lims)) - push!(points[], Point2f(xmin, f(xmin))) - push!(points[], Point2f(xmax, f(xmax))) + push!(points, Point2e(xmin, slope * xmin + intercept)) + push!(points, Point2e(xmax, slope * xmax + intercept)) end - notify(points) + return points end - notify(p[1]) - linesegments!(p, points; p.attributes...) p end diff --git a/src/basic_recipes/annotations.jl b/src/basic_recipes/annotations.jl index 941614d2301..a30daa48943 100644 --- a/src/basic_recipes/annotations.jl +++ b/src/basic_recipes/annotations.jl @@ -10,15 +10,15 @@ $(ATTRIBUTES) default_theme(scene, Text) end -function convert_arguments(::Type{<: Annotations}, +function Makie.convert_arguments(::Type{<: Annotations}, strings::AbstractVector{<: AbstractString}, - text_positions::AbstractVector{<: Point{N}}) where N + text_positions::AbstractVector{<: Point}) return (map(strings, text_positions) do str, pos - (String(str), Point{N, Float32}(pos)) + (String(str), pos) end,) end -function plot!(plot::Annotations) +function Makie.plot!(plot::Annotations) # annotations are not necessary anymore with the different text behavior text!(plot, plot[1]; plot.attributes...) plot diff --git a/src/basic_recipes/arc.jl b/src/basic_recipes/arc.jl index b13042c402d..83a265597d7 100644 --- a/src/basic_recipes/arc.jl +++ b/src/basic_recipes/arc.jl @@ -21,11 +21,11 @@ $(ATTRIBUTES) ) end -function plot!(p::Arc) +function Makie.plot!(p::Arc) args = getindex.(p, (:origin, :radius, :start_angle, :stop_angle, :resolution)) positions = lift(p, args...) do origin, radius, start_angle, stop_angle, resolution return map(range(start_angle, stop=stop_angle, length=resolution)) do angle - return origin .+ Point2f((cos(angle), sin(angle)) .* radius) + return origin .+ Point2((cos(angle), sin(angle)) .* radius) end end attr = Attributes(p) diff --git a/src/basic_recipes/arrows.jl b/src/basic_recipes/arrows.jl index b3f35002e0e..22164367f6f 100644 --- a/src/basic_recipes/arrows.jl +++ b/src/basic_recipes/arrows.jl @@ -102,13 +102,20 @@ function _circle(origin, r, normal, N) end -convert_arguments(::Type{<: Arrows}, x, y, u, v) = (Point2f.(x, y), Vec2f.(u, v)) +function convert_arguments(::Type{<: Arrows}, x, y, u, v) + FT = floattype(x, y, u, v) + return (Point2{FT}.(x, y), Vec2{FT}.(u, v)) +end function convert_arguments(::Type{<: Arrows}, x::AbstractVector, y::AbstractVector, u::AbstractMatrix, v::AbstractMatrix) - (vec(Point2f.(x, y')), vec(Vec2f.(u, v))) + FT = floattype(x, y, u, v) + return (vec(Point2{FT}.(x, y')), vec(Vec2{FT}.(u, v))) +end +function convert_arguments(::Type{<: Arrows}, x, y, z, u, v, w) + FT = floattype(x, y, u, v) + return (Point3{FT}.(x, y, z), Vec3{FT}.(u, v, w)) end -convert_arguments(::Type{<: Arrows}, x, y, z, u, v, w) = (Point3f.(x, y, z), Vec3f.(u, v, w)) -function plot!(arrowplot::Arrows{<: Tuple{AbstractVector{<: Point{N}}, V}}) where {N, V} +function plot!(arrowplot::Arrows{<: Tuple{AbstractVector{<: Point{N, T}}, V}}) where {N, T, V} @extract arrowplot ( points, directions, colormap, normalize, align, arrowtail, color, linecolor, linestyle, linewidth, lengthscale, @@ -130,9 +137,9 @@ function plot!(arrowplot::Arrows{<: Tuple{AbstractVector{<: Point{N}}, V}}) wher if align in (:head, :lineend, :tailend, :headstart, :center) shift = s .* dir else - shift = Vec2f(0) + shift = zero(dir) end - return Point2f(p1 .- shift) => Point2f(p1 .- shift .+ (dir .* s)) + return Point2{T}(p1 .- shift) => Point2{T}(p1 .- shift .+ (dir .* s)) end end @@ -195,11 +202,11 @@ function plot!(arrowplot::Arrows{<: Tuple{AbstractVector{<: Point{N}}, V}}) wher start = lift(arrowplot, points, directions, align, lengthscale) do points, dirs, align, scales return broadcast(points, dirs, scales) do p, dir, s if align in (:head, :lineend, :tailend, :headstart, :center) - shift = Vec3f(0) + shift = zero(dir) else shift = -s .* dir end - return Point3f(p .- shift) + return Point3{T}(p .- shift) end end marker_tail = lift((at, q) -> arrow_tail(3, at, q), arrowplot, arrowtail, quality) diff --git a/src/basic_recipes/axis.jl b/src/basic_recipes/axis.jl index f9744a8efb5..e962254bfd4 100644 --- a/src/basic_recipes/axis.jl +++ b/src/basic_recipes/axis.jl @@ -208,14 +208,14 @@ end function labelposition(ranges, dim, dir, tgap, origin::StaticVector{N}) where N a, b = extrema(ranges[dim]) - whalf = Float32(((b - a) / 2)) - halfaxis = unit(Point{N, Float32}, dim) .* whalf + whalf = Float64(((b - a) / 2)) + halfaxis = unit(Point{N, Float64}, dim) .* whalf origin .+ (halfaxis .+ (normalize(dir) * tgap)) end _widths(x::Tuple{<: Number, <: Number}) = x[2] - x[1] -_widths(x) = Float32(maximum(x) - minimum(x)) +_widths(x) = Float64(maximum(x) - minimum(x)) to3tuple(x::Tuple{Any}) = (x[1], x[1], x[1]) to3tuple(x::Tuple{Any, Any}) = (x[1], x[2], x[2]) @@ -245,7 +245,7 @@ function draw_axis3d(textbuffer, linebuffer, scale, limits, ranges_labels, fonts mini, maxi = first.(limits), last.(limits) - origin = Point{N, Float32}(min.(mini, first.(ranges))) + origin = Point{N, Float64}(min.(mini, first.(ranges))) limit_widths = max.(last.(ranges), maxi) .- origin % = minimum(limit_widths) / 100 # percentage tfontsize = (%) .* tfontsize @@ -258,8 +258,8 @@ function draw_axis3d(textbuffer, linebuffer, scale, limits, ranges_labels, fonts tgap = 0.01limit_widths[offset_indices] .* tgap for i in 1:N - axis_vec = unit(Point{N, Float32}, i) - width = Float32(limit_widths[i]) + axis_vec = unit(Point{N, Float64}, i) + width = Float64(limit_widths[i]) stop = origin .+ (width .* axis_vec) if showaxis[i] append!(linebuffer, [origin, stop], color = axiscolors[i], linewidth = axislinewidth[i]) @@ -267,14 +267,14 @@ function draw_axis3d(textbuffer, linebuffer, scale, limits, ranges_labels, fonts if showticks[i] range = ranges[i] j = offset_indices[i] - tickdir = unit(Vec{N, Float32}, j) - offset2 = Float32(limit_widths[j] + tgap[i]) * tickdir + tickdir = unit(Vec{N, Float64}, j) + offset2 = Float64(limit_widths[j] + tgap[i]) * tickdir for (j, tick) in enumerate(range) labels = ticklabels[i] if length(labels) >= j str = labels[j] if !isempty(str) - startpos = (origin .+ ((Float32(tick - origin[i]) * axis_vec)) .+ offset2) + startpos = (origin .+ ((Float64(tick - origin[i]) * axis_vec)) .+ offset2) push!( textbuffer, str, startpos, color = ttextcolor[i], rotation = trotation[i], @@ -301,10 +301,10 @@ function draw_axis3d(textbuffer, linebuffer, scale, limits, ranges_labels, fonts thickness = gridthickness[i] for _j = (i + 1):(i + N - 1) j = mod1(_j, N) - dir = unit(Point{N, Float32}, j) + dir = unit(Point{N, Float64}, j) range = ranges[j] for tick in range - offset = Float32(tick - origin[j]) * dir + offset = Float64(tick - origin[j]) * dir append!( linebuffer, [origin .+ offset, stop .+ offset], color = c, linewidth = thickness @@ -321,9 +321,9 @@ function plot!(scene::SceneLike, ::Type{<: Axis3D}, attributes::Attributes, args axis = Axis3D(scene, attributes, args) # Disable any non linear transform for the axis plot! axis.transformation.transform_func[] = identity - textbuffer = TextBuffer(axis, Point3, transparency = true, markerspace = :data, + textbuffer = TextBuffer(axis, Point3e, transparency = true, markerspace = :data, inspectable = axis.inspectable, visible = axis.visible) - linebuffer = LinesegmentBuffer(axis, Point3, transparency = true, inspectable = axis.inspectable, + linebuffer = LinesegmentBuffer(axis, Point3e, transparency = true, inspectable = axis.inspectable, visible = axis.visible) tstyle, ticks, frame = to_value.(getindex.(axis, (:names, :ticks, :frame))) diff --git a/src/basic_recipes/band.jl b/src/basic_recipes/band.jl index b0434868c1a..bdd476e7a70 100644 --- a/src/basic_recipes/band.jl +++ b/src/basic_recipes/band.jl @@ -17,7 +17,7 @@ $(ATTRIBUTES) attr end -convert_arguments(::Type{<: Band}, x, ylower, yupper) = (Point2f.(x, ylower), Point2f.(x, yupper)) +convert_arguments(::Type{<: Band}, x, ylower, yupper) = (Point2.(x, ylower), Point2.(x, yupper)) function band_connect(n) ns = 1:n-1 diff --git a/src/basic_recipes/barplot.jl b/src/basic_recipes/barplot.jl index b62164c1f15..05cb205ebf9 100644 --- a/src/basic_recipes/barplot.jl +++ b/src/basic_recipes/barplot.jl @@ -57,7 +57,7 @@ function bar_rectangle(x, y, width, fillto, in_y_direction) ymin = min(fillto, y) ymax = max(fillto, y) w = abs(width) - rect = Rectf(x - (w / 2f0), ymin, w, ymax - ymin) + rect = Rect(x - (w / 2), ymin, w, ymax - ymin) return in_y_direction ? rect : flip(rect) end @@ -173,7 +173,7 @@ function barplot_labels(xpositions, ypositions, bar_labels, in_y_direction, flip if length(bar_labels) == length(xpositions) attributes = text_attributes(ypositions, in_y_direction, flip_labels_at, color_over_background, color_over_bar, label_offset) label_pos = map(xpositions, ypositions, bar_labels) do x, y, l - return (string(l), in_y_direction ? Point2f(x, y) : Point2f(y, x)) + return (string(l), in_y_direction ? Point2(x, y) : Point2(y, x)) end return (label_pos, attributes...) else @@ -185,8 +185,8 @@ function barplot_labels(xpositions, ypositions, bar_labels, in_y_direction, flip end function Makie.plot!(p::BarPlot) - - labels = Observable(Tuple{String, Point2f}[]) + FT = floattype(p[1]) + labels = Observable(Tuple{String, Point2{FT}}[]) label_aligns = Observable(Vec2f[]) label_offsets = Observable(Vec2f[]) label_colors = Observable(RGBAf[]) diff --git a/src/basic_recipes/bracket.jl b/src/basic_recipes/bracket.jl index 3260a54c24c..4a0bf73a47a 100644 --- a/src/basic_recipes/bracket.jl +++ b/src/basic_recipes/bracket.jl @@ -31,13 +31,20 @@ $(ATTRIBUTES) ) end -Makie.convert_arguments(::Type{<:Bracket}, point1::VecTypes, point2::VecTypes) = ([(Point2f(point1), Point2f(point2))],) -Makie.convert_arguments(::Type{<:Bracket}, x1::Real, y1::Real, x2::Real, y2::Real) = ([(Point2f(x1, y1), Point2f(x2, y2))],) +function Makie.convert_arguments(::Type{<:Bracket}, point1::VecTypes{2, T1}, point2::VecTypes{2, T2}) where {T1, T2} + FT = floattype(T1, T2) + return ([(Point2{FT}(point1), Point2{FT}(point2))],) +end +function Makie.convert_arguments(::Type{<:Bracket}, x1::Real, y1::Real, x2::Real, y2::Real) + FT = floattype(x1, y1, x2, y2) + return ([(Point2{FT}(x1, y1), Point2{FT}(x2, y2))],) +end function Makie.convert_arguments(::Type{<:Bracket}, x1::AbstractVector{<:Real}, y1::AbstractVector{<:Real}, x2::AbstractVector{<:Real}, y2::AbstractVector{<:Real}) + FT = floattype(x1, y1, x2, y2) points = broadcast(x1, y1, x2, y2) do x1, y1, x2, y2 - (Point2f(x1, y1), Point2f(x2, y2)) + (Point2{FT}(x1, y1), Point2{FT}(x2, y2)) end - (points,) + return (points,) end function Makie.plot!(pl::Bracket) diff --git a/src/basic_recipes/buffers.jl b/src/basic_recipes/buffers.jl index 823ddbcae32..05d41fee024 100644 --- a/src/basic_recipes/buffers.jl +++ b/src/basic_recipes/buffers.jl @@ -4,17 +4,17 @@ efficiently append + push new values to them =# function LinesegmentBuffer( - scene::SceneLike, ::Type{Point{N}} = Point{2}; + scene::SceneLike, ::Type{PT} = Point2f; color = RGBAf[], linewidth = Float32[], kw_args... - ) where N + ) where PT <: Point linesegments!( - scene, Point{N, Float32}[]; color = color, + scene, PT[]; color = color, linewidth = linewidth, kw_args... ) end -function append!(lsb::LineSegments, positions::Vector{Point{N, Float32}}; color = :black, linewidth = 1.0) where N +function append!(lsb::LineSegments, positions::Vector{<: Point}; color = :black, linewidth = 1.0) thickv = same_length_array(positions, linewidth, key"linewidth"()) colorv = same_length_array(positions, color, key"color"()) append!(lsb[1][], positions) @@ -23,7 +23,7 @@ function append!(lsb::LineSegments, positions::Vector{Point{N, Float32}}; color return end -function push!(tb::LineSegments, positions::Point{N, Float32}; kw_args...) where N +function push!(tb::LineSegments, positions::Point; kw_args...) append!(tb, [positions]; kw_args...) end @@ -43,16 +43,16 @@ function finish!(lsb::LineSegments) end function TextBuffer( - scene::SceneLike, ::Type{Point{N}} = Point{2}; + scene::SceneLike, ::Type{PT} = Point2f; rotation = [Quaternionf(0,0,0,1)], color = RGBAf[RGBAf(0,0,0,0)], fontsize = Float32[0], font = [defaultfont()], align = [Vec2f(0)], kw_args... - ) where N + ) where PT <: Point annotations!( - scene, String[" "], [Point{N, Float32}(0)]; + scene, String[" "], [PT(0)]; rotation = rotation, color = color, fontsize = fontsize, @@ -82,17 +82,20 @@ function finish!(tb::Annotations) end -function push!(tb::Annotations, text::String, position::VecTypes{N}; kw_args...) where N - append!(tb, [(String(text), Point{N, Float32}(position))]; kw_args...) +function push!( + tb::Annotations{Tuple{Vector{Tuple{String, Point{N, T}}}}}, + text::String, position::VecTypes{N}; kw_args... + ) where {N, T} + append!(tb, [(String(text), Point{N, T}(position))]; kw_args...) end -function append!(tb::Annotations, text::Vector{String}, positions::Vector{Point{N, Float32}}; kw_args...) where N +function append!(tb::Annotations, text::Vector{String}, positions::Vector{<: Point}; kw_args...) text_positions = convert_argument(Annotations, text, positions)[1] append!(tb, text_positions; kw_args...) return end -function append!(tb::Annotations, text_positions::Vector{Tuple{String, Point{N, Float32}}}; kw_args...) where N +function append!(tb::Annotations, text_positions::Vector{Tuple{String, PT}}; kw_args...) where PT <: Point append!(tb[1][], text_positions) kw = Dict(kw_args) for key in (:color, :rotation, :fontsize, :font, :align) diff --git a/src/basic_recipes/contourf.jl b/src/basic_recipes/contourf.jl index 60eb88ec6e6..02613d20660 100644 --- a/src/basic_recipes/contourf.jl +++ b/src/basic_recipes/contourf.jl @@ -48,24 +48,24 @@ end # _computed_extendhigh function _get_isoband_levels(levels::Int, mi, ma) - edges = Float32.(LinRange(mi, ma, levels+1)) + return collect(LinRange(mi, ma, levels+1)) end function _get_isoband_levels(levels::AbstractVector{<:Real}, mi, ma) - edges = Float32.(levels) + edges = convert_single_argument(levels) @assert issorted(edges) - edges + return edges end conversion_trait(::Type{<:Contourf}) = ContinuousSurface() function _get_isoband_levels(::Val{:normal}, levels, values) - _get_isoband_levels(levels, extrema_nan(values)...) + return _get_isoband_levels(levels, extrema_nan(values)...) end function _get_isoband_levels(::Val{:relative}, levels::AbstractVector, values) mi, ma = extrema_nan(values) - Float32.(levels .* (ma - mi) .+ mi) + return convert_single_argument(levels .* (ma - mi) .+ mi) end @@ -93,29 +93,31 @@ function Makie.plot!(c::Contourf{<:Tuple{<:AbstractVector{<:Real}, <:AbstractVec c.attributes[:_computed_extendhigh] = highcolor is_extended_high = lift(!isnothing, c, highcolor) - PolyType = typeof(Polygon(Point2f[], [Point2f[]])) + PolyType = typeof(Polygon(Point2e[], [Point2e[]])) polys = Observable(PolyType[]) colors = Observable(Float64[]) - function calculate_polys(xs, ys, zs, levels::Vector{Float32}, is_extended_low, is_extended_high) + function calculate_polys(xs, ys, zs, levels::Vector{<:Real}, is_extended_low, is_extended_high) empty!(polys[]) empty!(colors[]) levels = copy(levels) @assert issorted(levels) + is_extended_low && pushfirst!(levels, -Inf) is_extended_high && push!(levels, Inf) lows = levels[1:end-1] highs = levels[2:end] # zs needs to be transposed to match rest of makie - isos = Isoband.isobands(xs, ys, zs', lows, highs) + # this converts each input to Float64 and always returns Float64's + isos = Isoband.isobands(xs, ys, zs', lows, highs) levelcenters = (highs .+ lows) ./ 2 for (i, (center, group)) in enumerate(zip(levelcenters, isos)) - points = Point2f.(group.x, group.y) + points = Point2.(group.x, group.y) polygroups = _group_polys(points, group.id) for polygroup in polygroups outline = polygroup[1] @@ -180,7 +182,7 @@ function _group_polys(points, ids) # each group has first an outer polygon, and then its holes # TODO: don't specifically type this 2f0? - groups = Vector{Vector{Point2f}}[] + groups = Vector{Vector{Point2e}}[] # a dict that maps index in `polys` to index in `groups` for outer polys outerindex_groupdict = Dict{Int, Int}() diff --git a/src/basic_recipes/contours.jl b/src/basic_recipes/contours.jl index e0a9d98e748..df5b578090f 100644 --- a/src/basic_recipes/contours.jl +++ b/src/basic_recipes/contours.jl @@ -56,49 +56,49 @@ $(ATTRIBUTES) default_theme(scene, Contour) end -angle(p1::Union{Vec2f,Point2f}, p2::Union{Vec2f,Point2f})::Float32 = +angle(p1::VecTypes{2, T}, p2::VecTypes{2, T}) where T = atan(p2[2] - p1[2], p2[1] - p1[1]) # result in [-π, π] -function label_info(lev, vertices, col) +function label_info(level, vertices::Vector{<: VecTypes{N, FT}}, color) where {N, FT} mid = ceil(Int, 0.5f0 * length(vertices)) - pts = (vertices[max(firstindex(vertices), mid - 1)], vertices[mid], vertices[min(mid + 1, lastindex(vertices))]) - ( - lev, - map(p -> to_ndim(Point3f, p, lev), Tuple(pts)), - col, + pts = ( + to_ndim(Point3{FT}, vertices[max(firstindex(vertices), mid - 1)], level), + to_ndim(Point3{FT}, vertices[mid], level), + to_ndim(Point3{FT}, vertices[min(mid + 1, lastindex(vertices))], level) ) + return (level, pts, color) end -function contourlines(::Type{<: Contour}, contours, cols, labels) - points = Point2f[] +function contourlines(::Type{<: Contour}, contours, cols, labels, FT::Type) + points = Point2{FT}[] colors = RGBA{Float32}[] - lev_pos_col = Tuple{Float32,NTuple{3,Point2f},RGBA{Float32}}[] + lev_pos_col = Tuple{FT, NTuple{3, Point2{FT}}, RGBA{Float32}}[] for (color, c) in zip(cols, Contours.levels(contours)) for elem in Contours.lines(c) append!(points, elem.vertices) - push!(points, Point2f(NaN32)) + push!(points, Point2{FT}(NaN)) append!(colors, fill(color, length(elem.vertices) + 1)) labels && push!(lev_pos_col, label_info(c.level, elem.vertices, color)) end end - points, colors, lev_pos_col + return points, colors, lev_pos_col end -function contourlines(::Type{<: Contour3d}, contours, cols, labels) - points = Point3f[] +function contourlines(::Type{<: Contour3d}, contours, cols, labels, FT::Type) + points = Point3{FT}[] colors = RGBA{Float32}[] - lev_pos_col = Tuple{Float32,NTuple{3,Point3f},RGBA{Float32}}[] + lev_pos_col = Tuple{FT, NTuple{3, Point3{FT}}, RGBA{Float32}}[] for (color, c) in zip(cols, Contours.levels(contours)) for elem in Contours.lines(c) for p in elem.vertices - push!(points, to_ndim(Point3f, p, c.level)) + push!(points, to_ndim(Point3{FT}, p, c.level)) end - push!(points, Point3f(NaN32)) + push!(points, Point3{FT}(NaN)) append!(colors, fill(color, length(elem.vertices) + 1)) labels && push!(lev_pos_col, label_info(c.level, elem.vertices, color)) end end - points, colors, lev_pos_col + return points, colors, lev_pos_col end to_levels(x::AbstractVector{<: Number}, cnorm) = x @@ -207,15 +207,16 @@ function plot!(plot::T) where T <: Union{Contour, Contour3d} @extract plot (labels, labelsize, labelfont, labelcolor, labelformatter) args = @extract plot (color, colormap, colorrange, alpha) level_colors = lift(color_per_level, plot, args..., levels) + FT = floattype(x, y, z, levels) + cont_lines = lift(plot, x, y, z, levels, level_colors, labels) do x, y, z, levels, level_colors, labels - t = eltype(z) # Compute contours - xv, yv = to_vector(x, size(z, 1), t), to_vector(y, size(z, 2), t) - contours = Contours.contours(xv, yv, z, convert(Vector{t}, levels)) - contourlines(T, contours, level_colors, labels) + xv, yv = to_vector(x, size(z, 1), FT), to_vector(y, size(z, 2), FT) + contours = Contours.contours(xv, yv, z, convert(Vector{FT}, levels)) + contourlines(T, contours, level_colors, labels, FT) end - P = T <: Contour ? Point2f : Point3f + P = T <: Contour ? Point2{FT} : Point3{FT} scene = parent_scene(plot) space = plot.space[] @@ -238,7 +239,7 @@ function plot!(plot::T) where T <: Union{Contour, Contour3d} col = texts.color.val; empty!(col) lbl = texts.text.val; empty!(lbl) for (lev, (p1, p2, p3), color) in lev_pos_col - rot_from_horz::Float32 = angle(project(scene, p1), project(scene, p3)) + rot_from_horz = Float32(angle(project(scene, p1), project(scene, p3))) # transition from an angle from horizontal axis in [-π; π] # to a readable text with a rotation from vertical axis in [-π / 2; π / 2] rot_from_vert::Float32 = if abs(rot_from_horz) > 0.5f0 * π @@ -270,7 +271,7 @@ function plot!(plot::T) where T <: Union{Contour, Contour3d} bb = bboxes[n] nlab = length(bboxes) masked = copy(segments) - nan = P(NaN32) + nan = P(NaN) for (i, p) in enumerate(segments) if isnan(p) && n < nlab bb = bboxes[n += 1] # next segment is materialized by a NaN, thus consider next label @@ -305,8 +306,8 @@ end function point_iterator(x::Contour{<: Tuple{X, Y, Z}}) where {X, Y, Z} axes = (x[1], x[2]) extremata = map(extrema∘to_value, axes) - minpoint = Point2f(first.(extremata)...) + minpoint = Point2(first.(extremata)...) widths = last.(extremata) .- first.(extremata) - rect = Rect2f(minpoint, Vec2f(widths)) + rect = Rect2(minpoint, Vec2(widths)) return unique(decompose(Point, rect)) end diff --git a/src/basic_recipes/error_and_rangebars.jl b/src/basic_recipes/error_and_rangebars.jl index edb5fd6564e..8b7c759eb1a 100644 --- a/src/basic_recipes/error_and_rangebars.jl +++ b/src/basic_recipes/error_and_rangebars.jl @@ -63,48 +63,48 @@ end function Makie.convert_arguments(::Type{<:Errorbars}, x, y, error_both) xyerr = broadcast(x, y, error_both) do x, y, e - Vec4f(x, y, e, e) + Vec4(x, y, e, e) end (xyerr,) end function Makie.convert_arguments(::Type{<:Errorbars}, x, y, error_low, error_high) - xyerr = broadcast(Vec4f, x, y, error_low, error_high) + xyerr = broadcast(Vec4, x, y, error_low, error_high) (xyerr,) end function Makie.convert_arguments(::Type{<:Errorbars}, x, y, error_low_high::AbstractVector{<:VecTypes{2}}) xyerr = broadcast(x, y, error_low_high) do x, y, (el, eh) - Vec4f(x, y, el, eh) + Vec4(x, y, el, eh) end (xyerr,) end function Makie.convert_arguments(::Type{<:Errorbars}, xy::AbstractVector{<:VecTypes{2}}, error_both) xyerr = broadcast(xy, error_both) do (x, y), e - Vec4f(x, y, e, e) + Vec4(x, y, e, e) end (xyerr,) end function Makie.convert_arguments(::Type{<:Errorbars}, xy::AbstractVector{<:VecTypes{2}}, error_low, error_high) xyerr = broadcast(xy, error_low, error_high) do (x, y), el, eh - Vec4f(x, y, el, eh) + Vec4(x, y, el, eh) end (xyerr,) end function Makie.convert_arguments(::Type{<:Errorbars}, xy::AbstractVector{<:VecTypes{2}}, error_low_high::AbstractVector{<:VecTypes{2}}) xyerr = broadcast(xy, error_low_high) do (x, y), (el, eh) - Vec4f(x, y, el, eh) + Vec4(x, y, el, eh) end (xyerr,) end function Makie.convert_arguments(::Type{<:Errorbars}, xy_error_both::AbstractVector{<:VecTypes{3}}) xyerr = broadcast(xy_error_both) do (x, y, e) - Vec4f(x, y, e, e) + Vec4(x, y, e, e) end (xyerr,) end @@ -112,13 +112,13 @@ end ### conversions for rangebars function Makie.convert_arguments(::Type{<:Rangebars}, val, low, high) - val_low_high = broadcast(Vec3f, val, low, high) + val_low_high = broadcast(Vec3, val, low, high) (val_low_high,) end function Makie.convert_arguments(::Type{<:Rangebars}, val, low_high) val_low_high = broadcast(val, low_high) do val, (low, high) - Vec3f(val, low, high) + Vec3(val, low, high) end (val_low_high,) end @@ -143,8 +143,8 @@ function Makie.plot!(plot::Errorbars{T}) where T <: Tuple{AbstractVector{<:VecTy linesegpairs = lift(plot, x_y_low_high, is_in_y_direction) do x_y_low_high, in_y return map(x_y_low_high) do (x, y, l, h) in_y ? - (Point2f(x, y - l), Point2f(x, y + h)) : - (Point2f(x - l, y), Point2f(x + h, y)) + (Point2(x, y - l), Point2(x, y + h)) : + (Point2(x - l, y), Point2(x + h, y)) end end @@ -169,8 +169,8 @@ function Makie.plot!(plot::Rangebars{T}) where T <: Tuple{AbstractVector{<:VecTy linesegpairs = lift(plot, val_low_high, is_in_y_direction) do vlh, in_y return map(vlh) do (v, l, h) in_y ? - (Point2f(v, l), Point2f(v, h)) : - (Point2f(l, v), Point2f(h, v)) + (Point2(v, l), Point2(v, h)) : + (Point2(l, v), Point2(h, v)) end end @@ -234,32 +234,21 @@ function _plot_bars!(plot, linesegpairs, is_in_y_direction) plot end -function scene_to_screen(pts, scene) - p4 = to_ndim.(Vec4f, to_ndim.(Vec3f, pts, 0.0), 1.0) - p1m1 = Ref(scene.camera.projectionview[]) .* p4 - projected = Ref(inv(scene.camera.pixel_space[])) .* p1m1 - [Point2.(p[Vec(1, 2)]...) for p in projected] -end - -function screen_to_scene(pts, scene) - p4 = to_ndim.(Vec4f, to_ndim.(Vec3f, pts, 0.0), 1.0) - p1m1 = Ref(scene.camera.pixel_space[]) .* p4 - projected = Ref(inv(scene.camera.projectionview[])) .* p1m1 - [Point2.(p[Vec(1, 2)]...) for p in projected] -end +scene_to_screen(pts::AbstractArray, scene) = scene_to_screen.(pts, (scene,)) +screen_to_scene(pts::AbstractArray, scene) = screen_to_scene.(pts, (scene,)) -function scene_to_screen(p::T, scene) where T <: Point - p4 = to_ndim(Vec4f, to_ndim(Vec3f, p, 0.0), 1.0) +function scene_to_screen(p::Point{N, T}, scene) where {N, T <: NativeFloat} + p4 = to_ndim(Vec4{T}, to_ndim(Vec3{T}, p, 0.0), 1.0) p1m1 = scene.camera.projectionview[] * p4 projected = inv(scene.camera.pixel_space[]) * p1m1 - T(projected[Vec(1, 2)]...) + return Point{2, T}(projected[1], projected[2]) end -function screen_to_scene(p::T, scene) where T <: Point - p4 = to_ndim(Vec4f, to_ndim(Vec3f, p, 0.0), 1.0) +function screen_to_scene(p::Point{N, T}, scene) where {N, T <: NativeFloat} + p4 = to_ndim(Vec4{T}, to_ndim(Vec3{T}, p, 0.0), 1.0) p1m1 = scene.camera.pixel_space[] * p4 projected = inv(scene.camera.projectionview[]) * p1m1 - T(projected[Vec(1, 2)]...) + return Point{2, T}(projected[1], projected[2]) end # ignore whiskers when determining data limits diff --git a/src/basic_recipes/hvlines.jl b/src/basic_recipes/hvlines.jl index a7ead9e9d09..c4ef760c508 100644 --- a/src/basic_recipes/hvlines.jl +++ b/src/basic_recipes/hvlines.jl @@ -41,8 +41,8 @@ end function projview_to_2d_limits(pv) xmin, xmax = minmax((((-1, 1) .- pv[1, 4]) ./ pv[1, 1])...) ymin, ymax = minmax((((-1, 1) .- pv[2, 4]) ./ pv[2, 2])...) - origin = Vec2f(xmin, ymin) - return Rect2f(origin, Vec2f(xmax, ymax) - origin) + origin = Vec2(xmin, ymin) + return Rect2(origin, Vec2(xmax, ymax) - origin) end function Makie.plot!(p::Union{HLines, VLines}) @@ -50,9 +50,10 @@ function Makie.plot!(p::Union{HLines, VLines}) transf = transform_func_obs(scene) limits = lift(projview_to_2d_limits, p, scene.camera.projectionview) - - points = Observable(Point2f[]) - + + ET = floattype(p[1]) + points = Observable(Point2{ET}[]) + mi = p isa HLines ? p.xmin : p.ymin ma = p isa HLines ? p.xmax : p.ymax @@ -67,15 +68,15 @@ function Makie.plot!(p::Union{HLines, VLines}) x_ma = min_x + (max_x - min_x) * ma x_mi = _apply_x_transform(inv, x_mi) x_ma = _apply_x_transform(inv, x_ma) - push!(points[], Point2f(x_mi, val)) - push!(points[], Point2f(x_ma, val)) + push!(points[], Point2{ET}(x_mi, val)) + push!(points[], Point2{ET}(x_ma, val)) elseif p isa VLines y_mi = min_y + (max_y - min_y) * mi y_ma = min_y + (max_y - min_y) * ma y_mi = _apply_y_transform(inv, y_mi) y_ma = _apply_y_transform(inv, y_ma) - push!(points[], Point2f(val, y_mi)) - push!(points[], Point2f(val, y_ma)) + push!(points[], Point2{ET}(val, y_mi)) + push!(points[], Point2{ET}(val, y_ma)) end end notify(points) diff --git a/src/basic_recipes/hvspan.jl b/src/basic_recipes/hvspan.jl index 18ac06bdae4..c038981596b 100644 --- a/src/basic_recipes/hvspan.jl +++ b/src/basic_recipes/hvspan.jl @@ -44,8 +44,9 @@ function Makie.plot!(p::Union{HSpan, VSpan}) limits = lift(projview_to_2d_limits, scene.camera.projectionview) - rects = Observable(Rect2f[]) - + ET = floattype(p[1], p[2]) + rects = Observable(Rect2{ET}[]) + mi = p isa HSpan ? p.xmin : p.ymin ma = p isa HSpan ? p.xmax : p.ymax @@ -60,13 +61,13 @@ function Makie.plot!(p::Union{HSpan, VSpan}) x_ma = min_x + (max_x - min_x) * ma x_mi = _apply_x_transform(inv, x_mi) x_ma = _apply_x_transform(inv, x_ma) - push!(rects[], Rect2f(Point2f(x_mi, low), Vec2f(x_ma - x_mi, high - low))) + push!(rects[], Rect2{ET}(Point2(x_mi, low), Vec2(x_ma - x_mi, high - low))) elseif p isa VSpan y_mi = min_y + (max_y - min_y) * mi y_ma = min_y + (max_y - min_y) * ma y_mi = _apply_y_transform(inv, y_mi) y_ma = _apply_y_transform(inv, y_ma) - push!(rects[], Rect2f(Point2f(low, y_mi), Vec2f(high - low, y_ma - y_mi))) + push!(rects[], Rect2{ET}(Point2(low, y_mi), Vec2(high - low, y_ma - y_mi))) end end notify(rects) diff --git a/src/basic_recipes/pie.jl b/src/basic_recipes/pie.jl index e13033d39e9..44346080d10 100644 --- a/src/basic_recipes/pie.jl +++ b/src/basic_recipes/pie.jl @@ -22,7 +22,7 @@ $(ATTRIBUTES) ) end -function plot!(plot::Pie) +function Makie.plot!(plot::Pie) values = plot[1] @@ -46,18 +46,18 @@ function plot!(plot::Pie) # curve points points = map(LinRange(sta, en, nvertices)) do rad - Point2f(cos(rad + offset), sin(rad + offset)) .* radius + Point2(radius * cos(rad + offset), radius * sin(rad + offset)) end # add inner points (either curve or one point) if inner_radius != 0 inner_points = map(LinRange(en, sta, nvertices)) do rad - Point2f(cos(rad + offset), sin(rad + offset)) .* inner_radius + Point2(inner_radius * cos(rad + offset), inner_radius * sin(rad + offset)) end append!(points, inner_points) else - push!(points, Point2f(0, 0)) + push!(points, eltype(points)(0, 0)) end points diff --git a/src/basic_recipes/poly.jl b/src/basic_recipes/poly.jl index efd57008854..463379201b7 100644 --- a/src/basic_recipes/poly.jl +++ b/src/basic_recipes/poly.jl @@ -33,19 +33,22 @@ function plot!(plot::Poly{<: Tuple{Union{GeometryBasics.Mesh, GeometryPrimitive} end # Poly conversion +function _triangle_mesh(geom::GeometryBasics.Meshable{N, T}) where {N, T} + GeometryBasics.mesh(geom; pointtype = Point{N, T}, facetype=GeometryBasics.GLTriangleFace) +end function poly_convert(geometries) isempty(geometries) && return typeof(GeometryBasics.Mesh(Point2f[], GLTriangleFace[]))[] - return triangle_mesh.(geometries) + return _triangle_mesh.(geometries) end poly_convert(meshes::AbstractVector{<:AbstractMesh}) = meshes -poly_convert(polys::AbstractVector{<:Polygon}) = triangle_mesh.(polys) +poly_convert(polys::AbstractVector{<:Polygon}) = _triangle_mesh.(polys) function poly_convert(multipolygons::AbstractVector{<:MultiPolygon}) - return [merge(triangle_mesh.(multipoly.polygons)) for multipoly in multipolygons] + return [merge(_triangle_mesh.(multipoly.polygons)) for multipoly in multipolygons] end poly_convert(mesh::GeometryBasics.Mesh) = mesh -poly_convert(polygon::Polygon) = triangle_mesh(polygon) +poly_convert(polygon::Polygon) = _triangle_mesh(polygon) function poly_convert(polygon::AbstractVector{<: VecTypes}) return poly_convert([convert_arguments(Scatter, polygon)[1]]) @@ -64,21 +67,19 @@ to_lines(polygon) = convert_arguments(Lines, polygon)[1] to_lines(polygon::GeometryBasics.Mesh) = convert_arguments(PointBased(), polygon)[1] function to_lines(meshes::AbstractVector) - line = Point2f[] - for (i, mesh) in enumerate(meshes) + # TODO: handle empty inputs better + line = isempty(meshes) ? Point2f[] : to_lines(meshes[1]) + PT = eltype(line) + for mesh in view(meshes, 2:length(meshes)) points = to_lines(mesh) + push!(line, PT(NaN)) append!(line, points) - # push!(line, points[1]) - # dont need to separate the last line segment - if i != length(meshes) - push!(line, Point2f(NaN)) - end end return line end -function to_lines(polygon::AbstractVector{<: VecTypes}) - result = Point2f.(polygon) +function to_lines(polygon::AbstractVector{<: VecTypes{2, T}}) where T + result = Point2{T}.(polygon) push!(result, polygon[1]) return result end @@ -172,7 +173,7 @@ function plot!(plot::Mesh{<: Tuple{<: AbstractVector{P}}}) where P <: Union{Abst if isempty(meshes) return GeometryBasics.Mesh(Point2f[], GLTriangleFace[]) else - return merge(GeometryBasics.triangle_mesh.(meshes)) + return merge(_triangle_mesh.(meshes)) end end mesh!(plot, attributes, bigmesh) diff --git a/src/basic_recipes/series.jl b/src/basic_recipes/series.jl index a0375a0790a..9e441de2465 100644 --- a/src/basic_recipes/series.jl +++ b/src/basic_recipes/series.jl @@ -44,13 +44,13 @@ end function convert_arguments(::Type{<: Series}, x::AbstractVector, ys::AbstractMatrix) return (map(1:size(ys, 1)) do i - Point2f.(replace_missing.(x), replace_missing.(view(ys, i, :))) + Point2.(replace_missing.(x), replace_missing.(view(ys, i, :))) end,) end function convert_arguments(::Type{<: Series}, arg::AbstractVector{<: Tuple{X, Y}}) where {X, Y} return (map(arg) do (x, y) - Point2f.(replace_missing.(x), replace_missing.(y)) + Point2.(replace_missing.(x), replace_missing.(y)) end,) end @@ -60,7 +60,7 @@ end function convert_arguments(::Type{<: Series}, arg::AbstractVector{<: AbstractVector{<:Point2}}) return (map(arg) do points - Point2f.(replace_missing.(first.(points)), replace_missing.(last.(points))) + Point2.(replace_missing.(first.(points)), replace_missing.(last.(points))) end,) end diff --git a/src/basic_recipes/spy.jl b/src/basic_recipes/spy.jl index 199867dd9fc..e57649df328 100644 --- a/src/basic_recipes/spy.jl +++ b/src/basic_recipes/spy.jl @@ -36,7 +36,7 @@ end function calculated_attributes!(::Type{<: Spy}, plot) end -function plot!(p::Spy) +function Makie.plot!(p::Spy) rect = lift(p, p.x, p.y) do x, y xe = extrema(x) ye = extrema(y) @@ -56,7 +56,7 @@ function plot!(p::Spy) xycol = lift(p, rect, p.z, markersize) do rect, z, markersize x, y, color = SparseArrays.findnz(z) points = map(x, y) do x, y - (((Point2f(x, y) .- 1) ./ Point2f(size(z) .- 1)) .* + (((Point2(x, y) .- 1) ./ Point2(size(z) .- 1)) .* widths(rect) .+ minimum(rect)) end points, convert(Vector{Float32}, color) diff --git a/src/basic_recipes/stairs.jl b/src/basic_recipes/stairs.jl index 4d74024c9b1..6693be909a5 100644 --- a/src/basic_recipes/stairs.jl +++ b/src/basic_recipes/stairs.jl @@ -22,45 +22,43 @@ end conversion_trait(::Type{<:Stairs}) = PointBased() -function plot!(p::Stairs{<:Tuple{<:AbstractVector{<:Point2}}}) +function Makie.plot!(p::Stairs{<:Tuple{<:AbstractVector{<:Point2}}}) points = p[1] steppoints = lift(p, points, p.step) do points, step + if !(step in (:pre, :post, :center)) + error("Invalid step $step. Valid options are :pre, :post and :center") + end + + s_points = Vector{eltype(points)}(undef, length(points) * 2 - (step !== :center)) + s_points[1] = point = points[1] + if step === :pre - s_points = Vector{Point2f}(undef, length(points) * 2 - 1) - s_points[1] = point = points[1] for i in 1:length(points)-1 nextpoint = points[i + 1] - s_points[2i] = Point2f(point[1], nextpoint[2]) + s_points[2i] = Point2(point[1], nextpoint[2]) s_points[2i + 1] = nextpoint point = nextpoint end - s_points elseif step === :post - s_points = Vector{Point2f}(undef, length(points) * 2 - 1) - s_points[1] = point = points[1] for i in 1:length(points)-1 - nextpoint = points[i+1] - s_points[2i] = Point2f(nextpoint[1], point[2]) + nextpoint = points[i + 1] + s_points[2i] = Point2(nextpoint[1], point[2]) s_points[2i + 1] = nextpoint point = nextpoint end - s_points elseif step === :center - s_points = Vector{Point2f}(undef, length(points) * 2) - s_points[1] = point = points[1] for i in 1:length(points)-1 nextpoint = points[i+1] halfx = (point[1] + nextpoint[1]) / 2 - s_points[2i] = Point2f(halfx, point[2]) - s_points[2i + 1] = Point2f(halfx, nextpoint[2]) + s_points[2i] = Point2(halfx, point[2]) + s_points[2i + 1] = Point2(halfx, nextpoint[2]) point = nextpoint end s_points[end] = point - s_points - else - error("Invalid step $step. Valid options are :pre, :post and :center") end + + return s_points end lines!(p, steppoints; [x for x in pairs(p.attributes) if x[1] !== :step]...) diff --git a/src/basic_recipes/streamplot.jl b/src/basic_recipes/streamplot.jl index f26b4b9a9e6..c2d92a3872f 100644 --- a/src/basic_recipes/streamplot.jl +++ b/src/basic_recipes/streamplot.jl @@ -36,20 +36,22 @@ end function convert_arguments(::Type{<: StreamPlot}, f::Function, xrange, yrange) xmin, xmax = extrema(xrange) ymin, ymax = extrema(yrange) - return (f, Rect(xmin, ymin, xmax - xmin, ymax - ymin)) + FT = floattype(xmin, xmax, ymin, ymax) + return (f, Rect{2, FT}(xmin, ymin, xmax - xmin, ymax - ymin)) end function convert_arguments(::Type{<: StreamPlot}, f::Function, xrange, yrange, zrange) xmin, xmax = extrema(xrange) ymin, ymax = extrema(yrange) zmin, zmax = extrema(zrange) - mini = Vec3f(xmin, ymin, zmin) - maxi = Vec3f(xmax, ymax, zmax) - return (f, Rect(mini, maxi .- mini)) + mini = Vec3(xmin, ymin, zmin) + maxi = Vec3(xmax, ymax, zmax) + FT = floattype(mini, maxi) + return (f, Rect{3, FT}(mini, maxi .- mini)) end -function convert_arguments(::Type{<: StreamPlot}, f::Function, limits::Rect) - return (f, limits) +function convert_arguments(::Type{<: StreamPlot}, f::Function, limits::Rect{N, T}) where {N, T} + return (f, Rect{N, floattype(T)}(limits)) end scatterfun(N) = N == 2 ? scatter! : meshscatter! @@ -76,9 +78,9 @@ Links: function streamplot_impl(CallType, f, limits::Rect{N, T}, resolutionND, stepsize, maxsteps=500, dens=1.0) where {N, T} resolution = to_ndim(Vec{N, Int}, resolutionND, last(resolutionND)) mask = trues(resolution...) # unvisited squares - arrow_pos = Point{N, Float32}[] + arrow_pos = Point{N, T}[] arrow_dir = Vec{N, Float32}[] - line_points = Point{N, Float32}[] + line_points = Point{N, T}[] colors = Float64[] line_colors = Float64[] dt = Point{N, Float32}(stepsize) @@ -121,7 +123,7 @@ function streamplot_impl(CallType, f, limits::Rect{N, T}, resolutionND, stepsize n_linepoints = 1 x = x0 ccur = c - push!(line_points, Point{N, Float32}(NaN), x) + push!(line_points, Point{N, T}(NaN), x) push!(line_colors, 0.0, pnorm) while x in limits && n_linepoints < maxsteps point = apply_f(x, CallType) @@ -158,9 +160,9 @@ function streamplot_impl(CallType, f, limits::Rect{N, T}, resolutionND, stepsize ) end -function plot!(p::StreamPlot) +function Makie.plot!(p::StreamPlot) data = lift(p, p.f, p.limits, p.gridsize, p.stepsize, p.maxsteps, p.density) do f, limits, resolution, stepsize, maxsteps, density - P = if applicable(f, Point2f(0)) || applicable(f, Point3f(0)) + P = if any(p -> applicable(f, p), (Point2f(0), Point3f(0), Point2e(0), Point3e(0))) Point else Number diff --git a/src/basic_recipes/text.jl b/src/basic_recipes/text.jl index 4441dd082a9..70fe5c1b552 100644 --- a/src/basic_recipes/text.jl +++ b/src/basic_recipes/text.jl @@ -141,13 +141,13 @@ function plot!(plot::Text{<:Tuple{<:AbstractArray{<:AbstractString}}}) end # overload text plotting for a vector of tuples of a string and a point each -function plot!(plot::Text{<:Tuple{<:AbstractArray{<:Tuple{<:Any, <:Point}}}}) +function plot!(plot::Text{<:Tuple{<:AbstractArray{<:Tuple{<:Any, <:Point{N, T}}}}}) where {N, T} strings_and_positions = plot[1] strings = Observable{Vector{Any}}(first.(strings_and_positions[])) positions = Observable( - Point3f[to_ndim(Point3f, last(x), 0) for x in strings_and_positions[]] # avoid Any for zero elements + Point3{T}[to_ndim(Point3{T}, last(x), 0) for x in strings_and_positions[]] # avoid Any for zero elements ) attrs = plot.attributes @@ -158,7 +158,7 @@ function plot!(plot::Text{<:Tuple{<:AbstractArray{<:Tuple{<:Any, <:Point}}}}) # update both text and positions together on(strings_and_positions) do str_pos strs = first.(str_pos) - poss = to_ndim.(Ref(Point3f), last.(str_pos), 0) + poss = to_ndim.(Ref(Point3{T}), last.(str_pos), 0) strings.val != strs && (strings[] = strs) positions.val != poss && (positions[] = poss) diff --git a/src/basic_recipes/timeseries.jl b/src/basic_recipes/timeseries.jl index 7e7fc9ca8ed..ab9cf240d2a 100644 --- a/src/basic_recipes/timeseries.jl +++ b/src/basic_recipes/timeseries.jl @@ -27,7 +27,7 @@ end ) end -signal2point(signal::Number, start) = Point2f(time() - start, signal) +signal2point(signal::Number, start) = Point2(time() - start, signal) signal2point(signal::Point2, start) = signal signal2point(signal, start) = error(""" Signal needs to be of type Number or Point. Found: $(typeof(signal)) @@ -37,7 +37,7 @@ Found: $(typeof(signal)) function Makie.plot!(plot::TimeSeries) # normal plotting code, building on any previously defined recipes # or atomic plotting operations, and adding to the combined `plot`: - points = Observable(fill(Point2f(NaN), plot.history[])) + points = Observable(fill(Point2e(NaN), plot.history[])) buffer = copy(points[]) lines!(plot, points) start = time() diff --git a/src/basic_recipes/tooltip.jl b/src/basic_recipes/tooltip.jl index ae0a516f04c..83d33d86f75 100644 --- a/src/basic_recipes/tooltip.jl +++ b/src/basic_recipes/tooltip.jl @@ -70,8 +70,8 @@ Creates a tooltip pointing at `position` displaying the given `string` ) end -convert_arguments(::Type{<: Tooltip}, x::Real, y::Real, str::AbstractString) = (Point2f(x, y), str) -convert_arguments(::Type{<: Tooltip}, x::Real, y::Real) = (Point2f(x, y),) +convert_arguments(::Type{<: Tooltip}, x::Real, y::Real, str::AbstractString) = (Point2(x, y), str) +convert_arguments(::Type{<: Tooltip}, x::Real, y::Real) = (Point2(x, y),) function plot!(plot::Tooltip{<:Tuple{<:VecTypes, <:AbstractString}}) plot.attributes[:text] = plot[2] tooltip!(plot, plot[1]; plot.attributes...) diff --git a/src/basic_recipes/tricontourf.jl b/src/basic_recipes/tricontourf.jl index 9b98a876cbb..748e3e949cd 100644 --- a/src/basic_recipes/tricontourf.jl +++ b/src/basic_recipes/tricontourf.jl @@ -46,7 +46,7 @@ $(ATTRIBUTES) end function Makie.convert_arguments(::Type{<:Tricontourf}, x::AbstractVector{<:Real}, y::AbstractVector{<:Real}, z::AbstractVector{<:Real}) - map(x -> elconvert(Float32, x), (x, y, z)) + return map(convert_single_argument, (x, y, z)) end function compute_contourf_colormap(levels, cmap, elow, ehigh) @@ -112,12 +112,13 @@ function Makie.plot!(c::Tricontourf{<:Tuple{<:AbstractVector{<:Real},<:AbstractV c.attributes[:_computed_extendhigh] = highcolor is_extended_high = lift(!isnothing, c, c.extendhigh) - PolyType = typeof(Polygon(Point2f[], [Point2f[]])) + FT = floattype(xs, ys, zs) + PolyType = typeof(Polygon(Point2{FT}[], [Point2{FT}[]])) polys = Observable(PolyType[]) colors = Observable(Float64[]) - function calculate_polys(xs, ys, zs, levels::Vector{Float32}, is_extended_low, is_extended_high, triangulation) + function calculate_polys(xs, ys, zs, levels::Vector{<:AbstractFloat}, is_extended_low, is_extended_high, triangulation) empty!(polys[]) empty!(colors[]) @@ -138,7 +139,7 @@ function Makie.plot!(c::Tricontourf{<:Tuple{<:AbstractVector{<:Real},<:AbstractV for (fc, lc) in zip(filledcontours, levelcenters) pointvecs = map(fc.polylines) do vecs - map(Point2f, vecs) + map(Point2{FT}, vecs) end if isempty(pointvecs) continue diff --git a/src/basic_recipes/waterfall.jl b/src/basic_recipes/waterfall.jl index 0d83e40221f..52aa3cd2b6a 100644 --- a/src/basic_recipes/waterfall.jl +++ b/src/basic_recipes/waterfall.jl @@ -47,8 +47,8 @@ function Makie.plot!(p::Waterfall) for (grp, inds) in StructArrays.finduniquesorted(groupby) fromto = stack_from_to_final(i_stack[inds], y[inds]) fillto[inds] .= fromto.from - xy[inds] .= Point2f.(x[inds], fromto.to) - final[inds] .= Point2f.(x[inds], fromto.final) + xy[inds] .= Point2.(x[inds], fromto.to) + final[inds] .= Point2.(x[inds], fromto.final) end return (xy=xy, fillto=fillto, final=final) end diff --git a/src/basic_recipes/wireframe.jl b/src/basic_recipes/wireframe.jl index bbf6d271e0d..97acdf2a01f 100644 --- a/src/basic_recipes/wireframe.jl +++ b/src/basic_recipes/wireframe.jl @@ -29,7 +29,7 @@ yvector(x::AbstractMatrix, len) = x function plot!(plot::Wireframe{<: Tuple{<: Any, <: Any, <: AbstractMatrix}}) points_faces = lift(plot, plot[1:3]...) do x, y, z M, N = size(z) - points = vec(Point3f.(xvector(x, M), yvector(y, N), z)) + points = vec(Point3.(xvector(x, M), yvector(y, N), z)) # Connect the vetices with faces, as one would use for a 2D Rectangle # grid with M,N grid points faces = decompose(LineFace{GLIndex}, Tesselation(Rect2(0, 0, 1, 1), (M, N))) diff --git a/src/camera/camera.jl b/src/camera/camera.jl index 48d63063fa7..67584c5c61c 100644 --- a/src/camera/camera.jl +++ b/src/camera/camera.jl @@ -69,13 +69,13 @@ end function Camera(px_area) pixel_space = lift(px_area) do window_size - nearclip = -10_000f0 - farclip = 10_000f0 - w, h = Float32.(widths(window_size)) - return orthographicprojection(0f0, w, 0f0, h, nearclip, farclip) + nearclip = -10_000.0 + farclip = 10_000.0 + w, h = Float64.(widths(window_size)) + return orthographicprojection(0.0, w, 0.0, h, nearclip, farclip) end - view = Observable(Mat4f(I)) - proj = Observable(Mat4f(I)) + view = Observable(Mat4{Float64}(I)) + proj = Observable(Mat4{Float64}(I)) proj_view = map(*, proj, view) return Camera( pixel_space, @@ -83,7 +83,7 @@ function Camera(px_area) proj, proj_view, lift(a-> Vec2f(widths(a)), px_area), - Observable(Vec3f(1)), + Observable(Vec3e(1)), ObserverFunction[] ) end diff --git a/src/camera/camera2d.jl b/src/camera/camera2d.jl index ff276348d94..29ea0c1bd88 100644 --- a/src/camera/camera2d.jl +++ b/src/camera/camera2d.jl @@ -1,9 +1,9 @@ struct Camera2D <: AbstractCamera - area::Observable{Rect2f} - zoomspeed::Observable{Float32} + area::Observable{Rect2{Float64}} + zoomspeed::Observable{Float64} zoombutton::Observable{ButtonTypes} panbutton::Observable{Union{ButtonTypes, Vector{ButtonTypes}}} - padding::Observable{Float32} + padding::Observable{Float64} last_area::Observable{Vec{2, Int}} update_limits::Observable{Bool} end @@ -16,8 +16,8 @@ Creates a 2D camera for the given Scene. function cam2d!(scene::SceneLike; kw_args...) cam_attributes = merged_get!(:cam2d, scene, Attributes(kw_args)) do Attributes( - area = Observable(Rectf(0, 0, 1, 1)), - zoomspeed = 0.10f0, + area = Observable(Rect2{Float64}(0, 0, 1, 1)), + zoomspeed = 0.10, zoombutton = nothing, panbutton = Mouse.right, selectionbutton = (Keyboard.space, Mouse.left), @@ -55,7 +55,7 @@ Useful when using the `Observable` pipeline. update_cam!(scene::SceneLike) = update_cam!(scene, cameracontrols(scene), data_limits(scene)) function update_cam!(scene::Scene, cam::Camera2D, area3d::Rect) - area = Rect2f(area3d) + area = Rect2{Float64}(area3d) area = positive_widths(area) # ignore rects with width almost 0 any(x-> x ≈ 0.0, widths(area)) && return @@ -71,18 +71,18 @@ function update_cam!(scene::Scene, cam::Camera2D, area3d::Rect) # so we make the minimum 1.0, and grow in the other dimension s = ratio ./ minimum(ratio) newwh = s .* widths(area) - cam.area[] = Rectf(minimum(area), newwh) + cam.area[] = Rect2{Float64}(minimum(area), newwh) end update_cam!(scene, cam) end function update_cam!(scene::SceneLike, cam::Camera2D) x, y = minimum(cam.area[]) - w, h = widths(cam.area[]) ./ 2f0 + w, h = widths(cam.area[]) ./ 2.0 # These observables should be final, no one should do map(cam.projection), # so we don't push! and just update the value in place - view = translationmatrix(Vec3f(-x - w, -y - h, 0)) - projection = orthographicprojection(-w, w, -h, h, -10_000f0, 10_000f0) + view = translationmatrix(Vec3e(-x - w, -y - h, 0)) + projection = orthographicprojection(-w, w, -h, h, -10_000.0, 10_000.0) set_proj_view!(camera(scene), projection, view) cam.last_area[] = Vec(size(scene)) return @@ -94,7 +94,7 @@ function correct_ratio!(scene, cam) change = neww .- cam.last_area[] if !(change ≈ Vec(0.0, 0.0)) s = 1.0 .+ (change ./ cam.last_area[]) - camrect = Rectf(minimum(cam.area[]), widths(cam.area[]) .* s) + camrect = Rect2{Float64}(minimum(cam.area[]), widths(cam.area[]) .* s) cam.area[] = camrect update_cam!(scene, cam) end @@ -124,7 +124,7 @@ function add_pan!(scene::SceneLike, cam::Camera2D) startpos[] = mp area = cam.area[] diff = Vec(diff) .* wscale(pixelarea(scene)[], area) - cam.area[] = Rectf(minimum(area) .+ diff, widths(area)) + cam.area[] = Rect2{Float64}(minimum(area) .+ diff, widths(area)) update_cam!(scene, cam) active[] = false return Consume(true) @@ -142,7 +142,7 @@ function add_pan!(scene::SceneLike, cam::Camera2D) startpos[] = pos area = cam.area[] diff = Vec(diff) .* wscale(pixelarea(scene)[], area) - cam.area[] = Rectf(minimum(area) .+ diff, widths(area)) + cam.area[] = Rect2{Float64}(minimum(area) .+ diff, widths(area)) update_cam!(scene, cam) return Consume(true) end @@ -154,17 +154,17 @@ function add_zoom!(scene::SceneLike, cam::Camera2D) e = events(scene) on(camera(scene), e.scroll) do x @extractvalue cam (zoomspeed, zoombutton, area) - zoom = Float32(x[2]) + zoom = Float64(x[2]) if zoom != 0 && ispressed(scene, zoombutton) && is_mouseinside(scene) pa = pixelarea(scene)[] - z = (1f0 - zoomspeed)^zoom - mp = Vec2f(e.mouseposition[]) - minimum(pa) + z = (1.0 - zoomspeed)^zoom + mp = Vec2e(e.mouseposition[]) - minimum(pa) mp = (mp .* wscale(pa, area)) + minimum(area) p1, p2 = minimum(area), maximum(area) p1, p2 = p1 - mp, p2 - mp # translate to mouse position p1, p2 = z * p1, z * p2 p1, p2 = p1 + mp, p2 + mp - cam.area[] = Rectf(p1, p2 - p1) + cam.area[] = Rect2{Float64}(p1, p2 - p1) update_cam!(scene, cam) return Consume(true) end @@ -182,13 +182,13 @@ function absrect(rect) xy = ntuple(Val(2)) do i wh[i] < 0 ? xy[i] + wh[i] : xy[i] end - return Rectf(Vec2f(xy), Vec2f(abs.(wh))) + return Rect2{Float64}(Vec2e(xy), Vec2e(abs.(wh))) end function selection_rect!(scene, cam, key) - rect = RefValue(Rectf(NaN, NaN, NaN, NaN)) - lw = 2f0 + rect = RefValue(Rect2{Float64}(NaN, NaN, NaN, NaN)) + lw = 2.0 scene_unscaled = Scene( scene, transformation = Transformation(), cam = copy(camera(scene)), clear = false @@ -198,7 +198,7 @@ function selection_rect!(scene, cam, key) scene_unscaled, rect[], linestyle = :dot, - linewidth = 2f0, + linewidth = 2.0, color = (:black, 0.4), visible = false ) @@ -209,7 +209,7 @@ function selection_rect!(scene, cam, key) if event.action == Mouse.press && !waspressed[] waspressed[] = true rect_vis[:visible] = true # start displaying - rect[] = Rectf(mp, 0, 0) + rect[] = Rect2{Float64}(mp, Vec2e(0)) rect_vis[1] = rect[] return Consume(true) end @@ -221,7 +221,7 @@ function selection_rect!(scene, cam, key) if w > 0.0 && h > 0.0 update_cam!(scene, cam, r) end - rect[] = Rectf(NaN, NaN, NaN, NaN) + rect[] = Rect2{Float64}(NaN, NaN, NaN, NaN) rect_vis[1] = rect[] return Consume(true) end @@ -237,7 +237,7 @@ function selection_rect!(scene, cam, key) if ispressed(scene, key) && is_mouseinside(scene) mp = camspace(scene, cam, mp) mini = minimum(rect[]) - rect[] = Rectf(mini, mp - mini) + rect[] = Rect2{Float64}(mini, mp - mini) rect_vis[1] = rect[] return Consume(true) end @@ -256,14 +256,14 @@ function reset!(cam, boundingbox, preserveratio = true) ratio = w2 ./ w1 w1 = if ratio[1] > ratio[2] s = w2[1] ./ w2[2] - Vec2f(s * w1[2], w1[2]) + Vec2e(s * w1[2], w1[2]) else s = w2[2] ./ w2[1] - Vec2f(w1[1], s * w1[1]) + Vec2e(w1[1], s * w1[1]) end end p = minimum(w1) .* 0.001 # 2mm padding - update_cam!(cam, Rectf(-p, -p, w1 .+ 2p)) + update_cam!(cam, Rect2{Float64}(-p, -p, w1 .+ 2p)) return end @@ -272,7 +272,7 @@ function add_restriction!(cam, window, rarea::Rect2, minwidths::Vec) restrict_action = paused_action(1.0) do t o = lerp(origin(area_ref[]), origin(cam[Area]), t) wh = lerp(widths(area_ref[]), widths(cam[Area]), t) - update_cam!(cam, Rectf(o, wh)) + update_cam!(cam, Rect2{Float64}(o, wh)) end on(window, Mouse.Drag) do drag if drag == Mouse.up && !isplaying(restrict_action) @@ -284,13 +284,13 @@ function add_restriction!(cam, window, rarea::Rect2, minwidths::Vec) maxi = maxi - newmax newo = newo - maxi newwh = newmax - newo - scale = 1f0 + scale = 1.0 for (w1, w2) in zip(minwidths, newwh) - stmp = w1 > w2 ? w1 / w2 : 1f0 + stmp = w1 > w2 ? w1 / w2 : 1.0 scale = max(scale, stmp) end newwh = newwh * scale - area_ref[] = Rectf(newo, newwh) + area_ref[] = Rect2{Float64}(newo, newwh) if area_ref[] != cam[Area] play!(restrict_action) end @@ -305,22 +305,22 @@ struct PixelCamera <: AbstractCamera end struct UpdatePixelCam camera::Camera - near::Float32 - far::Float32 + near::Float64 + far::Float64 end function (cam::UpdatePixelCam)(window_size) - w, h = Float32.(widths(window_size)) - projection = orthographicprojection(0f0, w, 0f0, h, cam.near, cam.far) + w, h = Float64.(widths(window_size)) + projection = orthographicprojection(0.0, w, 0.0, h, cam.near, cam.far) set_proj_view!(cam.camera, projection, Mat4f(I)) end """ - campixel!(scene; nearclip=-1000f0, farclip=1000f0) + campixel!(scene; nearclip=-1000.0, farclip=1000.0) Creates a pixel-level camera for the `Scene`. No controls! """ -function campixel!(scene::Scene; nearclip=-10_000f0, farclip=10_000f0) +function campixel!(scene::Scene; nearclip=-10_000.0, farclip=10_000.0) disconnect!(camera(scene)) update_once = Observable(false) closure = UpdatePixelCam(camera(scene), nearclip, farclip) @@ -340,8 +340,8 @@ struct RelativeCamera <: AbstractCamera end Creates a pixel-level camera for the `Scene`. No controls! """ -function cam_relative!(scene::Scene; nearclip=-10_000f0, farclip=10_000f0) - projection = orthographicprojection(0f0, 1f0, 0f0, 1f0, nearclip, farclip) +function cam_relative!(scene::Scene; nearclip=-10_000.0, farclip=10_000.0) + projection = orthographicprojection(0.0, 1.0, 0.0, 1.0, nearclip, farclip) set_proj_view!(camera(scene), projection, Mat4f(I)) cam = RelativeCamera() cameracontrols!(scene, cam) diff --git a/src/camera/camera3d.jl b/src/camera/camera3d.jl index d7a8b6dace2..6f1f0bfb6b5 100644 --- a/src/camera/camera3d.jl +++ b/src/camera/camera3d.jl @@ -1,12 +1,12 @@ struct Camera3D <: AbstractCamera - eyeposition::Observable{Vec3f} - lookat::Observable{Vec3f} - upvector::Observable{Vec3f} - - zoom_mult::Observable{Float32} - fov::Observable{Float32} # WGLMakie compat - near::Observable{Float32} - far::Observable{Float32} + eyeposition::Observable{Vec3e} + lookat::Observable{Vec3e} + upvector::Observable{Vec3e} + + zoom_mult::Observable{Float64} + fov::Observable{Float64} # WGLMakie compat + near::Observable{Float64} + far::Observable{Float64} pulser::Observable{Float64} attributes::Attributes @@ -19,7 +19,7 @@ Creates a 3d camera with a lot of controls. The 3D camera is (or can be) unrestricted in terms of rotations and translations. Both `cam3d!(scene)` and `cam3d_cad!(scene)` create this camera type. Unlike the 2D camera, settings and controls are stored in the `cam.attributes` field rather than in the struct directly, but can still be passed as keyword arguments. The general camera settings include -- `fov = 45f0` sets the "neutral" field of view, i.e. the fov corresponding to no zoom. This is irrelevant if the camera uses an orthographic projection. +- `fov = 45.0` sets the "neutral" field of view, i.e. the fov corresponding to no zoom. This is irrelevant if the camera uses an orthographic projection. - `near = automatic` sets the value of the near clip. By default this will be chosen based on the scenes bounding box. The final value is in `cam.near`. - `far = automatic` sets the value of the far clip. By default this will be chosen based on the scenes bounding box. The final value is in `cam.far`. - `rotation_center = :lookat` sets the default center for camera rotations. Currently allows `:lookat` or `:eyeposition`. @@ -28,7 +28,7 @@ The 3D camera is (or can be) unrestricted in terms of rotations and translations - `zoom_shift_lookat = true`: If true attempts to keep data under the cursor in view when zooming. - `cad = false`: If true rotates the view around `lookat` when zooming off-center. -The camera view follows from the position of the camera `eyeposition`, the point which the camera focuses `lookat` and the up direction of the camera `upvector`. These can be accessed as `cam.eyeposition` etc and adjusted via `update_cam!(scene, cameracontrols(scene), eyeposition, lookat[, upvector = Vec3f(0, 0, 1)])`. They can also be passed as keyword arguments when the camera is constructed. +The camera view follows from the position of the camera `eyeposition`, the point which the camera focuses `lookat` and the up direction of the camera `upvector`. These can be accessed as `cam.eyeposition` etc and adjusted via `update_cam!(scene, cameracontrols(scene), eyeposition, lookat[, upvector = Vec3e(0, 0, 1)])`. They can also be passed as keyword arguments when the camera is constructed. The camera can be controlled by keyboard and mouse. The keyboard has the following available attributes @@ -51,9 +51,9 @@ The camera can be controlled by keyboard and mouse. The keyboard has the followi - `roll_clockwise_key = Keyboard.e` sets the key for rotations of the screen. - `roll_counterclockwise_key = Keyboard.q` sets the key for rotations of the screen. -- `keyboard_rotationspeed = 1f0` sets the speed of keyboard based rotations. -- `keyboard_translationspeed = 0.5f0` sets the speed of keyboard based translations. -- `keyboard_zoomspeed = 1f0` sets the speed of keyboard based zooms. +- `keyboard_rotationspeed = 1.0` sets the speed of keyboard based rotations. +- `keyboard_translationspeed = 0.5` sets the speed of keyboard based translations. +- `keyboard_zoomspeed = 1.0` sets the speed of keyboard based zooms. - `update_rate = 1/30` sets the rate at which keyboard based camera updates are evaluated. and mouse interactions are controlled by @@ -62,9 +62,9 @@ and mouse interactions are controlled by - `scroll_mod = true` sets an additional modifier button for scroll-based zoom. (true being neutral) - `rotation_button = Mouse.left` sets the mouse button for drag-rotations. (pan, tilt) -- `mouse_rotationspeed = 1f0` sets the speed of mouse rotations. -- `mouse_translationspeed = 0.5f0` sets the speed of mouse translations. -- `mouse_zoomspeed = 1f0` sets the speed of mouse zooming (mousewheel). +- `mouse_rotationspeed = 1.0` sets the speed of mouse rotations. +- `mouse_translationspeed = 0.5` sets the speed of mouse translations. +- `mouse_zoomspeed = 1.0` sets the speed of mouse zooming (mousewheel). - `circular_rotation = (true, true, true)` enables circular rotations for (fixed x, fixed y, fixed z) rotation axis. (This means drawing a circle with your mouse around the center of the scene will result in a continuous rotation.) There are also a few generally applicable controls: @@ -72,12 +72,12 @@ There are also a few generally applicable controls: - `fix_x_key = Keyboard.x` sets the key for fixing translations and rotations to the (world/plot) x-axis. - `fix_y_key = Keyboard.y` sets the key for fixing translations and rotations to the (world/plot) y-axis. - `fix_z_key = Keyboard.z` sets the key for fixing translations and rotations to the (world/plot) z-axis. -- `reset = Keyboard.home` sets the key for fully resetting the camera. This equivalent to setting `lookat = Vec3f(0)`, `upvector = Vec3f(0, 0, 1)`, `eyeposition = Vec3f(3)` and then calling `center!(scene)`. +- `reset = Keyboard.home` sets the key for fully resetting the camera. This equivalent to setting `lookat = Vec3e(0)`, `upvector = Vec3e(0, 0, 1)`, `eyeposition = Vec3e(3)` and then calling `center!(scene)`. You can also make adjustments to the camera position, rotation and zoom by calling relevant functions: - `translate_cam!(scene, v)` will translate the camera by the given world/plot space vector `v`. -- `rotate_cam!(scene, angles)` will rotate the camera around its axes with the corresponding angles. The first angle will rotate around the cameras "right" that is the screens horizontal axis, the second around the up vector/vertical axis or `Vec3f(0, 0, +-1)` if `fixed_axis = true`, and the third will rotate around the view direction i.e. the axis out of the screen. The rotation respects the current `rotation_center` of the camera. +- `rotate_cam!(scene, angles)` will rotate the camera around its axes with the corresponding angles. The first angle will rotate around the cameras "right" that is the screens horizontal axis, the second around the up vector/vertical axis or `Vec3e(0, 0, +-1)` if `fixed_axis = true`, and the third will rotate around the view direction i.e. the axis out of the screen. The rotation respects the current `rotation_center` of the camera. - `zoom!(scene, zoom_step)` will change the zoom level of the scene without translating or rotating the scene. `zoom_step` applies multiplicatively to `cam.zoom_mult` which is used as a multiplier to the fov (perspective projection) or width and height (orthographic projection). """ function Camera3D(scene::Scene; kwargs...) @@ -113,14 +113,14 @@ function Camera3D(scene::Scene; kwargs...) fix_z_key = Keyboard.z, reset = Keyboard.home, # Settings - keyboard_rotationspeed = 1f0, - keyboard_translationspeed = 0.5f0, - keyboard_zoomspeed = 1f0, - mouse_rotationspeed = 1f0, - mouse_translationspeed = 1f0, - mouse_zoomspeed = 1f0, + keyboard_rotationspeed = 1.0, + keyboard_translationspeed = 0.5, + keyboard_zoomspeed = 1.0, + mouse_rotationspeed = 1.0, + mouse_translationspeed = 1.0, + mouse_zoomspeed = 1.0, circular_rotation = (true, true, true), - fov = 45f0, # base fov + fov = 45.0, # base fov near = automatic, far = automatic, rotation_center = :lookat, @@ -135,14 +135,14 @@ function Camera3D(scene::Scene; kwargs...) end cam = Camera3D( - pop!(attr, :eyeposition, Vec3f(3)), - pop!(attr, :lookat, Vec3f(0)), - pop!(attr, :upvector, Vec3f(0, 0, 1)), + pop!(attr, :eyeposition, Vec3e(3)), + pop!(attr, :lookat, Vec3e(0)), + pop!(attr, :upvector, Vec3e(0, 0, 1)), - Observable(1f0), + Observable(1.0), Observable(attr[:fov][]), - Observable(attr[:near][] === automatic ? 0.1f0 : attr[:near][]), - Observable(attr[:far][] === automatic ? 100f0 : attr[:far][]), + Observable(attr[:near][] === automatic ? 0.1 : attr[:near][]), + Observable(attr[:far][] === automatic ? 100.0 : attr[:far][]), Observable(-1.0), attr @@ -154,7 +154,7 @@ function Camera3D(scene::Scene; kwargs...) # ticks every so often to get consistent position updates. on(cam.pulser) do prev_time current_time = time() - active = on_pulse(scene, cam, Float32(current_time - prev_time)) + active = on_pulse(scene, cam, Float64(current_time - prev_time)) @async if active && attr.selected[] sleep(attr.update_rate[]) cam.pulser[] = current_time @@ -214,9 +214,9 @@ function Camera3D(scene::Scene; kwargs...) # center keeps the rotation of the camera so we reset that here # might make sense to keep user set lookat, upvector, eyeposition # around somewhere for this? - cam.lookat[] = Vec3f(0) - cam.upvector[] = Vec3f(0,0,1) - cam.eyeposition[] = Vec3f(3) + cam.lookat[] = Vec3e(0) + cam.upvector[] = Vec3e(0,0,1) + cam.eyeposition[] = Vec3e(3) center!(scene) return Consume(true) end @@ -256,12 +256,12 @@ function add_translation!(scene, cam::Camera3D) function compute_diff(delta) if cam.attributes[:projectiontype][] == Orthographic - aspect = Float32((/)(widths(scene.px_area[])...)) - aspect_scale = Vec2f(1f0 + aspect, 1f0 + 1f0 / aspect) + aspect = Float64((/)(widths(scene.px_area[])...)) + aspect_scale = Vec2f(1.0 + aspect, 1.0 + 1.0 / aspect) return cam.zoom_mult[] * delta .* aspect_scale ./ widths(scene.px_area[]) else viewdir = cam.lookat[] - cam.eyeposition[] - return 0.002f0 * cam.zoom_mult[] * norm(viewdir) * delta + return 0.002 * cam.zoom_mult[] * norm(viewdir) * delta end end @@ -278,7 +278,7 @@ function add_translation!(scene, cam::Camera3D) diff = compute_diff(last_mousepos[] .- mousepos) last_mousepos[] = mousepos dragging[] = false - translate_cam!(scene, cam, translationspeed[] .* Vec3f(diff[1], diff[2], 0f0)) + translate_cam!(scene, cam, translationspeed[] .* Vec3e(diff[1], diff[2], 0.0)) return Consume(true) end return Consume(false) @@ -290,7 +290,7 @@ function add_translation!(scene, cam::Camera3D) mousepos = screen_relative(scene, mp) diff = compute_diff(last_mousepos[] .- mousepos) last_mousepos[] = mousepos - translate_cam!(scene, cam, translationspeed[] * Vec3f(diff[1], diff[2], 0f0)) + translate_cam!(scene, cam, translationspeed[] * Vec3e(diff[1], diff[2], 0.0)) return Consume(true) end return Consume(false) @@ -298,7 +298,7 @@ function add_translation!(scene, cam::Camera3D) on(camera(scene), scene.events.scroll) do scroll if is_mouseinside(scene) && ispressed(scene, scroll_mod[]) - zoom_step = (1f0 + 0.1f0 * zoomspeed[]) ^ -scroll[2] + zoom_step = (1.0 + 0.1 * zoomspeed[]) ^ -scroll[2] zoom!(scene, cam, zoom_step, shift_lookat[], cad[]) return Consume(true) end @@ -325,9 +325,9 @@ function add_rotation!(scene, cam::Camera3D) mousepos = mouseposition_px(scene) dragging[] = false rot_scaling = rotationspeed[] * (e.window_dpi[] * 0.005) - mp = (last_mousepos[] .- mousepos) .* 0.01f0 .* rot_scaling + mp = (last_mousepos[] .- mousepos) .* 0.01 .* rot_scaling last_mousepos[] = mousepos - rotate_cam!(scene, cam, Vec3f(-mp[2], mp[1], 0f0), true) + rotate_cam!(scene, cam, Vec3e(-mp[2], mp[1], 0.0), true) return Consume(true) end return Consume(false) @@ -338,9 +338,9 @@ function add_rotation!(scene, cam::Camera3D) if dragging[] && ispressed(scene, button[]) mousepos = screen_relative(scene, mp) rot_scaling = rotationspeed[] * (e.window_dpi[] * 0.005) - mp = (last_mousepos[] .- mousepos) * 0.01f0 * rot_scaling + mp = (last_mousepos[] .- mousepos) * 0.01 * rot_scaling last_mousepos[] = mousepos - rotate_cam!(scene, cam, Vec3f(-mp[2], mp[1], 0f0), true) + rotate_cam!(scene, cam, Vec3e(-mp[2], mp[1], 0.0), true) return Consume(true) end return Consume(false) @@ -363,7 +363,7 @@ function on_pulse(scene, cam, timestep) if translating # translation in camera space x/y/z direction translation = attr[:keyboard_translationspeed][] * timestep * - Vec3f(right - left, up - down, backward - forward) + Vec3e(right - left, up - down, backward - forward) viewdir = cam.lookat[] - cam.eyeposition[] _translate_cam!(scene, cam, cam.zoom_mult[] * norm(viewdir) * translation) end @@ -380,7 +380,7 @@ function on_pulse(scene, cam, timestep) if rotating # rotations around camera space x/y/z axes angles = attr[:keyboard_rotationspeed][] * timestep * - Vec3f(up - down, left - right, counterclockwise - clockwise) + Vec3e(up - down, left - right, counterclockwise - clockwise) _rotate_cam!(scene, cam, angles) end @@ -391,14 +391,14 @@ function on_pulse(scene, cam, timestep) zooming = zoom_out || zoom_in if zooming - zoom_step = (1f0 + attr[:keyboard_zoomspeed][] * timestep) ^ (zoom_out - zoom_in) + zoom_step = (1.0 + attr[:keyboard_zoomspeed][] * timestep) ^ (zoom_out - zoom_in) _zoom!(scene, cam, zoom_step, false) end stretch = ispressed(scene, attr[:stretch_view_key][]) contract = ispressed(scene, attr[:contract_view_key][]) if stretch || contract - zoom_step = (1f0 + attr[:keyboard_zoomspeed][] * timestep) ^ (stretch - contract) + zoom_step = (1.0 + attr[:keyboard_zoomspeed][] * timestep) ^ (stretch - contract) cam.eyeposition[] = cam.lookat[] + zoom_step * (cam.eyeposition[] - cam.lookat[]) end zooming = zooming || stretch || contract @@ -435,7 +435,7 @@ function _translate_cam!(scene, cam, t) fix_y = ispressed(scene, cam.attributes[:fix_y_key][]) fix_z = ispressed(scene, cam.attributes[:fix_z_key][]) if fix_x || fix_y || fix_z - trans = Vec3f(fix_x, fix_y, fix_z) .* trans + trans = Vec3e(fix_x, fix_y, fix_z) .* trans end cam.eyeposition[] = eyepos + trans @@ -459,7 +459,7 @@ function _rotate_cam!(scene, cam::Camera3D, angles::VecTypes, from_mouse=false) right = cross(viewdir, up) # +x x_axis = right - y_axis = cam.attributes[:fixed_axis][] ? Vec3f(0, 0, ifelse(up[3] < 0, -1, 1)) : up + y_axis = cam.attributes[:fixed_axis][] ? Vec3e(0, 0, ifelse(up[3] < 0, -1, 1)) : up z_axis = -viewdir fix_x = ispressed(scene, cam.attributes[:fix_x_key][]) @@ -478,14 +478,14 @@ function _rotate_cam!(scene, cam::Camera3D, angles::VecTypes, from_mouse=false) # recontextualize the (dy, dx, 0) from mouse rotations so that # drawing circles creates continuous rotations around the fixed axis mp = mouseposition_px(scene) - past_half = 0.5f0 .* widths(scene.px_area[]) .> mp - flip = 2f0 * past_half .- 1f0 + past_half = 0.5 .* widths(scene.px_area[]) .> mp + flip = 2.0 * past_half .- 1.0 angle = flip[1] * angles[1] + flip[2] * angles[2] - angles = Vec3f(-angle, angle, -angle) + angles = Vec3e(-angle, angle, -angle) # only one fix is true so this only rotates around one axis rotation *= qrotation( - Vec3f(fix_x, fix_z, fix_y) .* Vec3f(sign(right[1]), viewdir[2], sign(up[3])), - dot(Vec3f(fix_x, fix_y, fix_z), angles) + Vec3e(fix_x, fix_z, fix_y) .* Vec3e(sign(right[1]), viewdir[2], sign(up[3])), + dot(Vec3e(fix_x, fix_y, fix_z), angles) ) else # restrict total quaternion rotation to one axis @@ -534,9 +534,9 @@ function _zoom!(scene::Scene, cam::Camera3D, zoom_step, shift_lookat = false, ca viewdir = lookat - eyepos # -z right = cross(viewdir, up) # +x - rel_pos = 2f0 * mouseposition_px(scene) ./ widths(scene.px_area[]) .- 1f0 + rel_pos = 2.0 * mouseposition_px(scene) ./ widths(scene.px_area[]) .- 1.0 shift = rel_pos[1] * normalize(right) + rel_pos[2] * normalize(up) - shifted = eyepos + 0.1f0 * sign(1f0 - zoom_step) * norm(viewdir) * shift + shifted = eyepos + 0.1 * sign(1.0 - zoom_step) * norm(viewdir) * shift cam.eyeposition[] = lookat + norm(viewdir) * normalize(shifted - lookat) elseif shift_lookat lookat = cam.lookat[] @@ -551,19 +551,19 @@ function _zoom!(scene::Scene, cam::Camera3D, zoom_step, shift_lookat = false, ca # translate both eyeposition and lookat to more or less keep data # under the mouse in view fov = cam.attributes[:fov][] - before = tan(clamp(cam.zoom_mult[] * fov, 0.01f0, 175f0) / 360f0 * Float32(pi)) - after = tan(clamp(cam.zoom_mult[] * zoom_step * fov, 0.01f0, 175f0) / 360f0 * Float32(pi)) + before = tan(clamp(cam.zoom_mult[] * fov, 0.01, 175.0) / 360.0 * Float64(pi)) + after = tan(clamp(cam.zoom_mult[] * zoom_step * fov, 0.01, 175.0) / 360.0 * Float64(pi)) - aspect = Float32((/)(widths(scene.px_area[])...)) - rel_pos = 2f0 * mouseposition_px(scene) ./ widths(scene.px_area[]) .- 1f0 + aspect = Float64((/)(widths(scene.px_area[])...)) + rel_pos = 2.0 * mouseposition_px(scene) ./ widths(scene.px_area[]) .- 1.0 shift = rel_pos[1] * u_x + rel_pos[2] * u_y shift = -(after - before) * norm(viewdir) * normalize(aspect .* shift) else - mx, my = 2f0 * mouseposition_px(scene) ./ widths(scene.px_area[]) .- 1f0 - aspect = Float32((/)(widths(scene.px_area[])...)) - w = 0.5f0 * (1f0 + aspect) * cam.zoom_mult[] - h = 0.5f0 * (1f0 + 1f0 / aspect) * cam.zoom_mult[] - shift = (1f0 - zoom_step) * (mx * w * u_x + my * h * u_y) + mx, my = 2.0 * mouseposition_px(scene) ./ widths(scene.px_area[]) .- 1.0 + aspect = Float64((/)(widths(scene.px_area[])...)) + w = 0.5 * (1.0 + aspect) * cam.zoom_mult[] + h = 0.5 * (1.0 + 1.0 / aspect) * cam.zoom_mult[] + shift = (1.0 - zoom_step) * (mx * w * u_x + my * h * u_y) end cam.lookat[] = lookat + shift @@ -581,15 +581,15 @@ function update_cam!(scene::Scene, cam::Camera3D) @extractvalue cam (lookat, eyeposition, upvector) near = cam.near[]; far = cam.far[] - aspect = Float32((/)(widths(scene.px_area[])...)) + aspect = Float64((/)(widths(scene.px_area[])...)) if cam.attributes[:projectiontype][] == Perspective - fov = clamp(cam.zoom_mult[] * cam.attributes[:fov][], 0.01f0, 175f0) + fov = clamp(cam.zoom_mult[] * cam.attributes[:fov][], 0.01, 175.0) cam.fov[] = fov proj = perspectiveprojection(fov, aspect, near, far) else - w = 0.5f0 * (1f0 + aspect) * cam.zoom_mult[] - h = 0.5f0 * (1f0 + 1f0 / aspect) * cam.zoom_mult[] + w = 0.5 * (1.0 + aspect) * cam.zoom_mult[] + h = 0.5 * (1.0 + 1.0 / aspect) * cam.zoom_mult[] proj = orthographicprojection(-w, w, -h, h, near, far) end @@ -602,34 +602,34 @@ end function update_cam!(scene::Scene, camera::Camera3D, area3d::Rect) @extractvalue camera (lookat, eyeposition, upvector) - bb = Rect3f(area3d) + bb = Rect3{Float64}(area3d) width = widths(bb) - half_width = width ./ 2f0 + half_width = width ./ 2.0 middle = maximum(bb) - half_width old_dir = normalize(eyeposition .- lookat) camera.lookat[] = middle neweyepos = middle .+ (1.2*norm(width) .* old_dir) camera.eyeposition[] = neweyepos - camera.upvector[] = Vec3f(0,0,1) + camera.upvector[] = Vec3e(0,0,1) if camera.attributes[:near][] === automatic - camera.near[] = 0.1f0 * norm(widths(bb)) + camera.near[] = 0.1 * norm(widths(bb)) end if camera.attributes[:far][] === automatic - camera.far[] = 3f0 * norm(widths(bb)) + camera.far[] = 3.0 * norm(widths(bb)) end if camera.attributes[:projectiontype][] == Orthographic camera.zoom_mult[] = 0.6 * norm(width) else - camera.zoom_mult[] = 1f0 + camera.zoom_mult[] = 1.0 end update_cam!(scene, camera) return end -function update_cam!(scene::Scene, camera::Camera3D, eyeposition, lookat, up = Vec3f(0, 0, 1)) - camera.lookat[] = Vec3f(lookat) - camera.eyeposition[] = Vec3f(eyeposition) - camera.upvector[] = Vec3f(up) +function update_cam!(scene::Scene, camera::Camera3D, eyeposition, lookat, up = Vec3e(0, 0, 1)) + camera.lookat[] = Vec3e(lookat) + camera.eyeposition[] = Vec3e(eyeposition) + camera.upvector[] = Vec3e(up) update_cam!(scene, camera) return end diff --git a/src/camera/old_camera3d.jl b/src/camera/old_camera3d.jl index 2d5f424cccf..fde16ca4e8b 100644 --- a/src/camera/old_camera3d.jl +++ b/src/camera/old_camera3d.jl @@ -2,14 +2,14 @@ @enum ProjectionEnum Perspective Orthographic struct OldCamera3D <: AbstractCamera - rotationspeed::Observable{Float32} - translationspeed::Observable{Float32} - eyeposition::Observable{Vec3f} - lookat::Observable{Vec3f} - upvector::Observable{Vec3f} - fov::Observable{Float32} - near::Observable{Float32} - far::Observable{Float32} + rotationspeed::Observable{Float64} + translationspeed::Observable{Float64} + eyeposition::Observable{Vec3e} + lookat::Observable{Vec3e} + upvector::Observable{Vec3e} + fov::Observable{Float64} + near::Observable{Float64} + far::Observable{Float64} projectiontype::Observable{ProjectionEnum} pan_button::Observable{ButtonTypes} rotate_button::Observable{ButtonTypes} @@ -28,12 +28,12 @@ function old_cam3d_cad!(scene::Scene; kw_args...) Attributes( rotationspeed = 0.01, translationspeed = 1.0, - eyeposition = Vec3f(3), - lookat = Vec3f(0), - upvector = Vec3f(0, 0, 1), - fov = 45f0, - near = 0.01f0, - far = 100f0, + eyeposition = Vec3e(3), + lookat = Vec3e(0), + upvector = Vec3e(0, 0, 1), + fov = 45.0, + near = 0.01, + far = 100.0, projectiontype = Perspective, pan_button = Mouse.right, rotate_button = Mouse.left, @@ -64,12 +64,12 @@ function old_cam3d_turntable!(scene::Scene; kw_args...) Attributes( rotationspeed = 0.01, translationspeed = 1.0, - eyeposition = Vec3f(3), - lookat = Vec3f(0), - upvector = Vec3f(0, 0, 1), - fov = 45f0, - near = 0.01f0, - far = 100f0, + eyeposition = Vec3e(3), + lookat = Vec3e(0), + upvector = Vec3e(0, 0, 1), + fov = 45.0, + near = 0.01, + far = 100.0, projectiontype = Perspective, pan_button = Mouse.right, rotate_button = Mouse.left, @@ -151,7 +151,7 @@ function add_translation!(scene, cam, key, button, zoom_shift_lookat::Bool) dragging[] = false diff = (last_mousepos[] - mousepos) * cam.translationspeed[] last_mousepos[] = mousepos - translate_cam!(scene, cam, Vec3f(0f0, diff[1], diff[2])) + translate_cam!(scene, cam, Vec3e(0.0, diff[1], diff[2])) return Consume(true) end end @@ -163,7 +163,7 @@ function add_translation!(scene, cam, key, button, zoom_shift_lookat::Bool) mousepos = screen_relative(scene, mp) diff = (last_mousepos[] .- mousepos) * cam.translationspeed[] last_mousepos[] = mousepos - translate_cam!(scene, cam, Vec3f(0f0, diff[1], diff[2])) + translate_cam!(scene, cam, Vec3e(0.0, diff[1], diff[2])) return Consume(true) end return Consume(false) @@ -173,7 +173,7 @@ function add_translation!(scene, cam, key, button, zoom_shift_lookat::Bool) if ispressed(scene, button[]) && is_mouseinside(scene) cam_res = Vec2f(widths(scene.px_area[])) mouse_pos_normalized = mouseposition_px(scene) ./ cam_res - mouse_pos_normalized = 2*mouse_pos_normalized .- 1f0 + mouse_pos_normalized = 2*mouse_pos_normalized .- 1.0 zoom_step = scroll[2] zoom!(scene, mouse_pos_normalized, zoom_step, zoom_shift_lookat) return Consume(true) @@ -199,7 +199,7 @@ function add_rotation!(scene, cam, button, key, fixed_axis::Bool) rot_scaling = cam.rotationspeed[] * (e.window_dpi[] * 0.005) mp = (last_mousepos[] - mousepos) * rot_scaling last_mousepos[] = mousepos - rotate_cam!(scene, cam, Vec3f(mp[1], -mp[2], 0f0), fixed_axis) + rotate_cam!(scene, cam, Vec3e(mp[1], -mp[2], 0.0), fixed_axis) return Consume(true) end end @@ -212,7 +212,7 @@ function add_rotation!(scene, cam, button, key, fixed_axis::Bool) rot_scaling = cam.rotationspeed[] * (e.window_dpi[] * 0.005) mp = (last_mousepos[] .- mousepos) * rot_scaling last_mousepos[] = mousepos - rotate_cam!(scene, cam, Vec3f(mp[1], -mp[2], 0f0), fixed_axis) + rotate_cam!(scene, cam, Vec3e(mp[1], -mp[2], 0.0), fixed_axis) return Consume(true) end return Consume(false) @@ -226,15 +226,15 @@ Translate the camera by a translation vector given in camera space. """ translate_cam!(scene::Scene, translation::VecTypes) = translate_cam!(scene, cameracontrols(scene), translation) function translate_cam!(scene::Scene, cam::OldCamera3D, _translation::VecTypes) - translation = Vec3f(_translation) - translation == Vec3f(0) && return + translation = Vec3e(_translation) + translation == Vec3e(0) && return @extractvalue cam (projectiontype, lookat, eyeposition, upvector) dir = eyeposition - lookat dir_len = norm(dir) cam_res = Vec2f(widths(scene.px_area[])) z, x, y = translation - z *= 0.1f0 * dir_len + z *= 0.1 * dir_len x, y = (Vec2f(x, y) ./ cam_res) .* dir_len @@ -265,7 +265,7 @@ function zoom!(scene, point::VecTypes, zoom_step, shift_lookat::Bool) # the offset parallel to `eyeposition - lookat` ~ dir ray_eye = inv(scene.camera.projection[]) * Vec4f(point[1],point[2],0,0) ray_eye = Vec4f(ray_eye[Vec(1, 2)]...,0,0) - ray_dir = Vec3f((inv(scene.camera.view[]) * ray_eye)) + ray_dir = Vec3e((inv(scene.camera.view[]) * ray_eye)) dir = eyeposition - lookat @@ -274,13 +274,13 @@ function zoom!(scene, point::VecTypes, zoom_step, shift_lookat::Bool) if projectiontype == Perspective ray_dir *= norm(dir) end - cam.eyeposition[] = eyeposition + (ray_dir - dir) * (1f0 - 0.9f0 ^ zoom_step) - cam.lookat[] = lookat + (1f0 - 0.9f0 ^ zoom_step) * ray_dir + cam.eyeposition[] = eyeposition + (ray_dir - dir) * (1.0 - 0.9 ^ zoom_step) + cam.lookat[] = lookat + (1.0 - 0.9 ^ zoom_step) * ray_dir else # Rotations need more extreme eyeposition shifts step = zoom_step - while abs(step) > 0f0 - cam.eyeposition[] = cam.eyeposition[] + sign(zoom_step) * (ray_dir - dir * 0.1f0) + while abs(step) > 0.0 + cam.eyeposition[] = cam.eyeposition[] + sign(zoom_step) * (ray_dir - dir * 0.1) dir = cam.eyeposition[] - lookat step -= sign(step) end @@ -299,14 +299,14 @@ the camera according to the Euler angles (α, β, γ). rotate_cam!(scene::Scene, theta_v::Number...) = rotate_cam!(scene, cameracontrols(scene), theta_v) rotate_cam!(scene::Scene, theta_v::VecTypes) = rotate_cam!(scene, cameracontrols(scene), theta_v) function rotate_cam!(scene::Scene, cam::OldCamera3D, _theta_v::VecTypes, fixed_axis::Bool = true) - theta_v = Vec3f(_theta_v) - theta_v == Vec3f(0) && return #nothing to do! + theta_v = Vec3e(_theta_v) + theta_v == Vec3e(0) && return #nothing to do! @extractvalue cam (eyeposition, lookat, upvector) dir = normalize(eyeposition - lookat) right_v = normalize(cross(upvector, dir)) upvector = normalize(cross(dir, right_v)) - axis = fixed_axis ? Vec3f(0, 0, sign(upvector[3])) : upvector + axis = fixed_axis ? Vec3e(0, 0, sign(upvector[3])) : upvector rotation = rotate_cam(theta_v, right_v, axis, dir) r_eyepos = lookat + rotation * (eyeposition - lookat) r_up = normalize(rotation * upvector) @@ -322,7 +322,7 @@ function update_cam!(scene::Scene, cam::OldCamera3D) zoom = norm(lookat - eyeposition) # TODO this means you can't set FarClip... SAD! # TODO use boundingbox(scene) for optimal far/near - far = max(zoom * 5f0, 30f0) + far = max(zoom * 5.0, 30.0) proj = projection_switch(scene.px_area[], fov, near, far, projectiontype, zoom) view = Makie.lookat(eyeposition, lookat, upvector) set_proj_view!(camera(scene), proj, view) @@ -331,32 +331,32 @@ end function update_cam!(scene::Scene, camera::OldCamera3D, area3d::Rect) @extractvalue camera (fov, near, lookat, eyeposition, upvector) - bb = Rect3f(area3d) + bb = Rect3{Float64}(area3d) width = widths(bb) - half_width = width/2f0 + half_width = width/2.0 middle = maximum(bb) - half_width old_dir = normalize(eyeposition .- lookat) camera.lookat[] = middle neweyepos = middle .+ (1.2*norm(width) .* old_dir) camera.eyeposition[] = neweyepos - camera.upvector[] = Vec3f(0,0,1) - camera.near[] = 0.1f0 * norm(widths(bb)) - camera.far[] = 3f0 * norm(widths(bb)) + camera.upvector[] = Vec3e(0,0,1) + camera.near[] = 0.1 * norm(widths(bb)) + camera.far[] = 3.0 * norm(widths(bb)) update_cam!(scene, camera) return end """ - update_cam!(scene::Scene, eyeposition, lookat, up = Vec3f(0, 0, 1)) + update_cam!(scene::Scene, eyeposition, lookat, up = Vec3e(0, 0, 1)) Updates the camera's controls to point to the specified location. """ -update_cam!(scene::Scene, eyeposition, lookat, up = Vec3f(0, 0, 1)) = update_cam!(scene, cameracontrols(scene), eyeposition, lookat, up) +update_cam!(scene::Scene, eyeposition, lookat, up = Vec3e(0, 0, 1)) = update_cam!(scene, cameracontrols(scene), eyeposition, lookat, up) -function update_cam!(scene::Scene, camera::OldCamera3D, eyeposition, lookat, up = Vec3f(0, 0, 1)) - camera.lookat[] = Vec3f(lookat) - camera.eyeposition[] = Vec3f(eyeposition) - camera.upvector[] = Vec3f(up) +function update_cam!(scene::Scene, camera::OldCamera3D, eyeposition, lookat, up = Vec3e(0, 0, 1)) + camera.lookat[] = Vec3e(lookat) + camera.eyeposition[] = Vec3e(eyeposition) + camera.upvector[] = Vec3e(up) update_cam!(scene, camera) return end diff --git a/src/camera/projection_math.jl b/src/camera/projection_math.jl index 717224c6a6a..5d34b9dd80a 100644 --- a/src/camera/projection_math.jl +++ b/src/camera/projection_math.jl @@ -240,14 +240,9 @@ end function to_world(scene::Scene, point::T) where T <: StaticVector cam = scene.camera - x = to_world( - point, - inv(transformationmatrix(scene)[]) * - inv(cam.view[]) * - inv(cam.projection[]), - T(widths(pixelarea(scene)[])) - ) - Point2f(x[1], x[2]) + pvm = cam.projectionview[] * transformationmatrix(scene)[] + x = to_world(point, inv(pvm), widths(pixelarea(scene)[])) + return Point2{eltype(point)}(x[1], x[2]) end w_component(x::Point) = 1.0 @@ -266,7 +261,7 @@ function to_world( T(0), w_component(p) ) ws = prj_view_inv * pix_space - ws ./ ws[4] + return ws ./ ws[4] end function to_world( @@ -291,18 +286,18 @@ function project(scene::Scene, point::T) where T<:StaticVector ) end -function project(matrix::Mat4f, p::T, dim4 = 1.0) where T <: VecTypes - p = to_ndim(Vec4f, to_ndim(Vec3f, p, 0.0), dim4) +function project(matrix::Mat4, p::VT, dim4 = 1.0) where {N, T, VT <: VecTypes{N, T}} + p = to_ndim(Vec4{T}, to_ndim(Vec3{T}, p, 0.0), dim4) p = matrix * p - to_ndim(T, p, 0.0) + to_ndim(VT, p, 0.0) end -function project(proj_view::Mat4f, resolution::Vec2, point::Point) - p4d = to_ndim(Vec4f, to_ndim(Vec3f, point, 0f0), 1f0) +function project(proj_view::Mat4, resolution::Vec2, point::Point{N, T}) where {N, T} + p4d = to_ndim(Vec4{T}, to_ndim(Vec3{T}, point, 0.0), 1.0) clip = proj_view * p4d p = (clip ./ clip[4])[Vec(1, 2)] - p = Vec2f(p[1], p[2]) - return (((p .+ 1f0) ./ 2f0) .* (resolution .- 1f0)) .+ 1f0 + p = Vec2{T}(p[1], p[2]) + return (((p .+ 1) ./ 2) .* (resolution .- 1)) .+ 1 end function project_point2(mat4::Mat4, point2::Point2) diff --git a/src/conversions.jl b/src/conversions.jl index f2846e73c35..150a3f88ef7 100644 --- a/src/conversions.jl +++ b/src/conversions.jl @@ -1,17 +1,37 @@ ################################################################################ # Type Conversions # ################################################################################ + const RangeLike = Union{AbstractRange, AbstractVector, ClosedInterval} +const NativeFloat = Union{Float64, Float32} +const NativePoint = Point{N, T} where {N, T <: NativeFloat} + +floattype(::Type{Float64}) = Float64 +floattype(::Type{<: Real}) = Float32 +floattype(::T) where T <: Real = floattype(T) +floattype(::VecTypes{N, T}) where {N, T <: Real} = floattype(T) +floattype(::AbstractArray{T}) where T <: Real = floattype(T) +floattype(::AbstractArray{VT}) where {N, T <: Real, VT <: VecTypes{N, T}} = floattype(T) +floattype(::Rect{N, T}) where {N, T <: Real} = floattype(T) +floattype(x::Observable) = floattype(x[]) +function floattype(a, others...) + if floattype(a) === Float64 + return Float64 + else + return floattype(others...) + end +end + # if no plot type based conversion is defined, we try using a trait function convert_arguments(T::PlotFunc, args...; kw...) ct = conversion_trait(T) try - convert_arguments(ct, args...; kw...) + return convert_arguments(ct, args...; kw...) catch e if e isa MethodError try - convert_arguments_individually(T, args...) + return convert_arguments_individually(T, args...) catch ee if ee isa MethodError error( @@ -48,15 +68,15 @@ function convert_arguments_individually(T::PlotFunc, args...) end # otherwise we try converting our newly single-converted args again because # now a normal conversion method might work again - convert_arguments(T, single_converted...) + return convert_arguments(T, single_converted...) end function recursively_convert_argument(x) newx = convert_single_argument(x) if typeof(newx) == typeof(x) - x + return x else - recursively_convert_argument(newx) + return recursively_convert_argument(newx) end end @@ -68,13 +88,21 @@ end convert_single_argument(x) = x # replace missings with NaNs +function convert_single_argument(a::AbstractArray{<:Union{Missing, T}}) where {T <: NativeFloat} + nan = T(NaN) + return [ismissing(x) ? nan : x for x in a] +end function convert_single_argument(a::AbstractArray{<:Union{Missing, <:Real}}) - [ismissing(x) ? NaN32 : convert(Float32, x) for x in a] + return [ismissing(x) ? NaN32 : convert(Float32, x) for x in a] end # same for points +function convert_single_argument(a::AbstractArray{<:Union{Missing, T}}) where {T <: NativePoint} + nan = T(NaN) + return [ismissing(x) ? nan : T(x) for x in a] +end function convert_single_argument(a::AbstractArray{<:Union{Missing, <:Point{N}}}) where N - [ismissing(x) ? Point{N, Float32}(NaN32) : Point{N, Float32}(x) for x in a] + return [ismissing(x) ? Point{N, Float32}(NaN32) : Point{N, Float32}(x) for x in a] end ################################################################################ @@ -85,24 +113,24 @@ end Wrap a single point or equivalent object in a single-element array. """ function convert_arguments(::PointBased, x::Real, y::Real) - ([Point2f(x, y)],) + return ([native_type(x, y)],) end function convert_arguments(::PointBased, x::Real, y::Real, z::Real) - ([Point3f(x, y, z)],) + return ([native_type(x, y, z)],) end -function convert_arguments(::PointBased, position::VecTypes{N, <: Number}) where N - ([convert(Point{N, Float32}, position)],) +function convert_arguments(::PointBased, position::VecTypes{N, T}) where {T <: Real, N} + return ([native_type(position)],) end -function convert_arguments(::PointBased, positions::AbstractVector{<: VecTypes{N, <: Number}}) where N - (elconvert(Point{N, Float32}, positions),) +function convert_arguments(::PointBased, positions::AbstractVector{<: VecTypes{N}}) where N + return (native_type.(positions),) end function convert_arguments(::PointBased, positions::SubArray{<: VecTypes, 1}) # TODO figure out a good subarray solution - (positions,) + return (positions,) end """ @@ -110,7 +138,7 @@ Enables to use scatter like a surface plot with x::Vector, y::Vector, z::Matrix spanning z over the grid spanned by x y """ function convert_arguments(::PointBased, x::AbstractVector, y::AbstractVector, z::AbstractMatrix) - (vec(Point3f.(x, y', z)),) + return (vec(native_type.(x, y', z)),) end """ convert_arguments(P, x, y, z)::(Vector) @@ -119,7 +147,7 @@ Takes vectors `x`, `y`, and `z` and turns it into a vector of 3D points of the v from `x`, `y`, and `z`. `P` is the plot Type (it is optional). """ -convert_arguments(::PointBased, x::RealVector, y::RealVector, z::RealVector) = (Point3f.(x, y, z),) +convert_arguments(::PointBased, x::RealVector, y::RealVector, z::RealVector) = (native_type.(x, y, z),) """ convert_arguments(P, x)::(Vector) @@ -127,15 +155,15 @@ convert_arguments(::PointBased, x::RealVector, y::RealVector, z::RealVector) = ( Takes an input GeometryPrimitive `x` and decomposes it to points. `P` is the plot Type (it is optional). """ -convert_arguments(p::PointBased, x::GeometryPrimitive) = convert_arguments(p, decompose(Point, x)) +convert_arguments(p::PointBased, x::GeometryPrimitive) = convert_arguments(p, decompose(Point3f, x)) -function convert_arguments(::PointBased, pos::AbstractMatrix{<: Number}) - (to_vertices(pos),) +function convert_arguments(::PointBased, pos::AbstractMatrix{<: Real}) + return (to_vertices(pos),) # NOTE: This currently ends up as Float32 end -convert_arguments(P::PointBased, x::AbstractVector{<:Real}, y::AbstractVector{<:Real}) = (Point2f.(x, y),) - -convert_arguments(P::PointBased, x::AbstractVector{<:Real}, y::AbstractVector{<:Real}, z::AbstractVector{<:Real}) = (Point3f.(x, y, z),) +function convert_arguments(P::PointBased, x::AbstractVector{<:Real}, y::AbstractVector{<:Real}) + return (native_type.(x, y),) +end """ convert_arguments(P, y)::Vector @@ -144,7 +172,7 @@ an arbitrary `x` axis. `P` is the plot Type (it is optional). """ -convert_arguments(P::PointBased, y::RealVector) = convert_arguments(P, keys(y), y) +convert_arguments(P::PointBased, y::AbstractVector{<: Number}) = convert_arguments(P, keys(y), y) """ convert_arguments(P, x, y)::(Vector) @@ -154,9 +182,12 @@ from `x` and `y`. `P` is the plot Type (it is optional). """ -#convert_arguments(::PointBased, x::RealVector, y::RealVector) = (Point2f.(x, y),) -convert_arguments(P::PointBased, x::ClosedInterval, y::RealVector) = convert_arguments(P, LinRange(extrema(x)..., length(y)), y) -convert_arguments(P::PointBased, x::RealVector, y::ClosedInterval) = convert_arguments(P, x, LinRange(extrema(y)..., length(x))) +function convert_arguments(P::PointBased, x::ClosedInterval, y::AbstractVector{<: Number}) + return convert_arguments(P, LinRange(extrema(x)..., length(y)), y) +end +function convert_arguments(P::PointBased, x::AbstractVector{<: Number}, y::ClosedInterval) + return convert_arguments(P, x, LinRange(extrema(y)..., length(x))) +end """ @@ -166,12 +197,12 @@ Takes an input `Rect` `x` and decomposes it to points. `P` is the plot Type (it is optional). """ -function convert_arguments(P::PointBased, x::Rect2) +function convert_arguments(P::PointBased, x::Rect2{T}) where T # TODO fix the order of decompose - return convert_arguments(P, decompose(Point2f, x)[[1, 2, 4, 3]]) + return convert_arguments(P, decompose(Point2{T}, x)[[1, 2, 4, 3]]) end -function convert_arguments(P::PointBased, mesh::AbstractMesh) +function convert_arguments(P::PointBased, mesh::AbstractMesh) # TODO return convert_arguments(P, decompose(Point3f, mesh)) end @@ -180,19 +211,19 @@ function convert_arguments(PB::PointBased, linesegments::FaceView{<:Line, P}) wh return convert_arguments(PB, collect(reinterpret(P, linesegments))) end -function convert_arguments(P::PointBased, rect::Rect3) - return (decompose(Point3f, rect),) +function convert_arguments(P::PointBased, rect::Rect3{T}) where T + return (decompose(Point3{T}, rect),) end -function convert_arguments(P::Type{<: LineSegments}, rect::Rect3) +function convert_arguments(P::Type{<: LineSegments}, rect::Rect3{T}) where T f = decompose(LineFace{Int}, rect) - p = connect(decompose(Point3f, rect), f) + p = connect(decompose(Point3{T}, rect), f) return convert_arguments(P, p) end -function convert_arguments(::Type{<: Lines}, rect::Rect3) - points = unique(decompose(Point3f, rect)) - push!(points, Point3f(NaN)) # use to seperate linesegments +function convert_arguments(::Type{<: Lines}, rect::Rect3{T}) where T + points = unique(decompose(Point3{T}, rect)) + push!(points, Point3{T}(NaN)) # use to seperate linesegments return (points[[1, 2, 3, 4, 1, 5, 6, 2, 9, 6, 8, 3, 9, 5, 7, 4, 9, 7, 8]],) end """ @@ -211,12 +242,12 @@ end Takes an input `Array{LineString}` or a `MultiLineString` and decomposes it to points. """ function convert_arguments(PB::PointBased, linestring::Union{Array{<:LineString}, MultiLineString}) - arr = Point2f[]; n = length(linestring) - for idx in 1:n + n = length(linestring) + arr = n > 0 ? convert_arguments(PB, linestring[1])[1] : Point2f[] + nan = eltype(arr)(NaN) + for idx in 2:n + push!(arr, nan) append!(arr, convert_arguments(PB, linestring[idx])[1]) - if idx != n # don't add NaN at the end - push!(arr, Point2f(NaN)) - end end return (arr,) end @@ -233,8 +264,9 @@ function convert_arguments(PB::PointBased, pol::Polygon) if !isempty(arr) && arr[1] != arr[end] push!(arr, arr[1]) # close exterior end + nan = eltype(arr)(NaN) for interior in pol.interiors - push!(arr, Point2f(NaN)) + push!(arr, nan) inter = convert_arguments(PB, interior)[1] # this should always be a Tuple{<: Vector{Point}} append!(arr, inter) if !isempty(inter) && inter[1] != inter[end] @@ -251,14 +283,13 @@ end Takes an input `Array{Polygon}` or a `MultiPolygon` and decomposes it to points. """ function convert_arguments(PB::PointBased, mp::Union{Array{<:Polygon}, MultiPolygon}) - arr = Point2f[] n = length(mp) - for idx in 1:n + arr = n > 0 ? convert_arguments(PB, mp[1])[1] : Point2f[] + nan = eltype(arr)(NaN) + for idx in 2:n + push!(arr, nan) converted = convert_arguments(PB, mp[idx])[1] # this should always be a Tuple{<: Vector{Point}} append!(arr, converted) - if idx != n # don't add NaN at the end - push!(arr, Point2f(NaN)) - end end return (arr,) end @@ -320,7 +351,7 @@ function edges(v::AbstractVector) end end -function adjust_axes(::DiscreteSurface, x::AbstractVector{<:Number}, y::AbstractVector{<:Number}, z::AbstractMatrix) +function adjust_axes(::DiscreteSurface, x::RealVector, y::RealVector, z::AbstractMatrix) x̂, ŷ = map((x, y), size(z)) do v, sz return length(v) == sz ? edges(v) : v end @@ -337,11 +368,9 @@ whether they represent edges or centers of the heatmap bins. If they are centers, convert to edges. Convert eltypes to `Float32` and return outputs as a `Tuple`. """ -function convert_arguments(SL::SurfaceLike, x::AbstractVecOrMat{<: Number}, y::AbstractVecOrMat{<: Number}, z::AbstractMatrix{<: Union{Number, Colorant}}) - return map(el32convert, adjust_axes(SL, x, y, z)) -end -function convert_arguments(SL::SurfaceLike, x::AbstractVecOrMat{<: Number}, y::AbstractVecOrMat{<: Number}, z::AbstractMatrix{<:Number}) - return map(el32convert, adjust_axes(SL, x, y, z)) +function convert_arguments(SL::SurfaceLike, x::AbstractVecOrMat{<: Real}, y::AbstractVecOrMat{<: Real}, z::AbstractMatrix{<: Union{Real, Colorant}}) + _x, _y, _z = adjust_axes(SL, x, y, z) + return convert_single_argument(_x), convert_single_argument(_y), el32convert(_z) # TODO convert_single_argument for z too? end convert_arguments(sl::SurfaceLike, x::AbstractMatrix, y::AbstractMatrix) = convert_arguments(sl, x, y, zeros(size(y))) @@ -354,7 +383,7 @@ linspaces with size(z, 1/2) `P` is the plot Type (it is optional). """ function convert_arguments(P::SurfaceLike, x::ClosedInterval, y::ClosedInterval, z::AbstractMatrix) - convert_arguments(P, to_linspace(x, size(z, 1)), to_linspace(y, size(z, 2)), z) + return convert_arguments(P, to_linspace(x, size(z, 1)), to_linspace(y, size(z, 2)), z) end """ @@ -366,16 +395,16 @@ and stores the `ClosedInterval` to `n` and `m`, plus the original matrix in a Tu `P` is the plot Type (it is optional). """ function convert_arguments(sl::SurfaceLike, data::AbstractMatrix) - n, m = Float32.(size(data)) - convert_arguments(sl, 0f0 .. n, 0f0 .. m, el32convert(data)) + n, m = size(data) + return convert_arguments(sl, 0 .. n, 0 .. m, el32convert(data)) end function convert_arguments(ds::DiscreteSurface, data::AbstractMatrix) n, m = Float32.(size(data)) - convert_arguments(ds, edges(1:n), edges(1:m), el32convert(data)) + return convert_arguments(ds, edges(1:n), edges(1:m), el32convert(data)) end -function convert_arguments(SL::SurfaceLike, x::AbstractVector{<:Number}, y::AbstractVector{<:Number}, z::AbstractVector{<:Number}) +function convert_arguments(SL::SurfaceLike, x::AbstractVector{<: Real}, y::AbstractVector{<: Real}, z::AbstractVector{<: Real}) if !(length(x) == length(y) == length(z)) error("x, y and z need to have the same length. Lengths are $(length.((x, y, z)))") end @@ -397,7 +426,7 @@ function convert_arguments(SL::SurfaceLike, x::AbstractVector{<:Number}, y::Abst j = searchsortedfirst(y_centers, yi) @inbounds zs[i, j] = zi end - convert_arguments(SL, x_centers, y_centers, zs) + return convert_arguments(SL, x_centers, y_centers, zs) end @@ -431,7 +460,7 @@ and stores the `ClosedInterval` to `n`, `m` and `k`, plus the original array in `P` is the plot Type (it is optional). """ function convert_arguments(::VolumeLike, data::AbstractArray{T, 3}) where T - n, m, k = Float32.(size(data)) + n, m, k = T.(size(data)) return (0f0 .. n, 0f0 .. m, 0f0 .. k, el32convert(data)) end @@ -446,7 +475,7 @@ Takes 3 `AbstractVector` `x`, `y`, and `z` and the `AbstractMatrix` `i`, and put `P` is the plot Type (it is optional). """ function convert_arguments(::VolumeLike, x::AbstractVector, y::AbstractVector, z::AbstractVector, i::AbstractArray{T, 3}) where T - (x, y, z, el32convert(i)) + return (x, y, z, el32convert(i)) end @@ -473,9 +502,9 @@ end # <:Lines # ################################################################################ -function convert_arguments(::Type{<: Lines}, x::Rect2) +function convert_arguments(::Type{<: Lines}, x::Rect2{T}) where T # TODO fix the order of decompose - points = decompose(Point2f, x) + points = decompose(Point2{T}, x) return (points[[1, 2, 4, 3, 1]],) end @@ -487,13 +516,14 @@ end Accepts a Vector of Pair of Points (e.g. `[Point(0, 0) => Point(1, 1), ...]`) to encode e.g. linesegments or directions. """ -function convert_arguments(::Type{<: LineSegments}, positions::AbstractVector{E}) where E <: Union{Pair{A, A}, Tuple{A, A}} where A <: VecTypes{N, T} where {N, T} - (elconvert(Point{N, Float32}, reinterpret(Point{N, T}, positions)),) +function convert_arguments(::Type{<: LineSegments}, positions::AbstractVector{E}) where + E <: Union{Pair{A, A}, Tuple{A, A}} where A <: VecTypes{N, T} where {N, T} + return (reinterpret(Point{N, T}, positions),) end -function convert_arguments(::Type{<: LineSegments}, x::Rect2) +function convert_arguments(::Type{<: LineSegments}, x::Rect2{T}) where T # TODO fix the order of decompose - points = decompose(Point2f, x) + points = decompose(Point2{T}, x) return (points[[1, 2, 2, 4, 4, 3, 3, 1]],) end @@ -523,7 +553,7 @@ function convert_arguments( T::Type{<:Mesh}, x::RealVector, y::RealVector, z::RealVector ) - convert_arguments(T, Point3f.(x, y, z)) + return convert_arguments(T, Point3.(x, y, z)) end """ convert_arguments(Mesh, xyz::AbstractVector)::GLNormalMesh @@ -549,6 +579,7 @@ function convert_arguments(::Type{<:Mesh}, mesh::GeometryBasics.Mesh{N}) where { mesh = GeometryBasics.pointmeta(mesh, decompose(Vec3f, n)) end end + # TODO only convert face type? # If already correct eltypes for GL, we can pass the mesh through as is if eltype(metafree(coordinates(mesh))) == Point{N, Float32} && eltype(faces(mesh)) == GLTriangleFace return (mesh,) @@ -567,12 +598,12 @@ end function convert_arguments( MT::Type{<:Mesh}, - xyz::Union{AbstractPolygon, AbstractVector{<: AbstractPoint{2}}} - ) + xyz::Union{AbstractPolygon{2, T}, AbstractVector{<: AbstractPoint{2, T}}} + ) where T return convert_arguments(MT, triangle_mesh(xyz)) end -function convert_arguments(MT::Type{<:Mesh}, geom::GeometryPrimitive) +function convert_arguments(MT::Type{<:Mesh}, geom::GeometryPrimitive{N, T}) where {N, T} # we convert to UV mesh as default, because otherwise the uv informations get lost # - we can still drop them, but we can't add them later on return (GeometryBasics.uv_normal_mesh(geom),) @@ -589,7 +620,7 @@ function convert_arguments( x::RealVector, y::RealVector, z::RealVector, indices::AbstractVector ) - return convert_arguments(T, Point3f.(x, y, z), indices) + return convert_arguments(T, Point3.(x, y, z), indices) end """ @@ -599,13 +630,17 @@ Takes `vertices` and `indices`, and creates a triangle mesh out of those. See [`to_vertices`](@ref) and [`to_triangles`](@ref) for more information about accepted types. """ +function convert_arguments(MT::Type{<:Mesh}, vertices::AbstractArray, indices::AbstractArray) + return convert_arguments(MT, to_vertices(vertices), to_triangles(indices)) +end + function convert_arguments( - ::Type{<:Mesh}, - vertices::AbstractArray, - indices::AbstractArray - ) - m = normal_mesh(to_vertices(vertices), to_triangles(indices)) - (m,) + ::Type{<:Mesh}, pos::AbstractVector{VT}, faces::AbstractVector{GLTriangleFace} + ) where {N, T, VT <: VecTypes{N, T}} + _points = to_ndim.(Point{3, T}, pos, T(0)) + return (GeometryBasics.Mesh(GeometryBasics.meta( + _points; normals = GeometryBasics.normals(_points, faces) + ), faces), ) end ################################################################################ @@ -614,13 +649,13 @@ end function convert_arguments(P::PlotFunc, r::AbstractVector, f::Function) ptype = plottype(P, Lines) - to_plotspec(ptype, convert_arguments(ptype, r, f.(r))) + return to_plotspec(ptype, convert_arguments(ptype, r, f.(r))) end function convert_arguments(P::PlotFunc, i::AbstractInterval, f::Function) x, y = PlotUtils.adapted_grid(f, endpoints(i)) ptype = plottype(P, Lines) - to_plotspec(ptype, convert_arguments(ptype, x, y)) + return to_plotspec(ptype, convert_arguments(ptype, x, y)) end # The following `tryrange` code was copied from Plots.jl @@ -631,7 +666,7 @@ function tryrange(F::AbstractArray, vec) rets = [tryrange(f, vec) for f in F] # get the preferred for each maxind = maximum(indexin(rets, vec)) # get the last attempt that succeeded (most likely to fit all) rets .= [tryrange(f, vec[maxind:maxind]) for f in F] # ensure that all functions compute there - rets[1] + return rets[1] end function tryrange(F, vec) @@ -665,12 +700,14 @@ to_linspace(interval, N) = range(minimum(interval), stop = maximum(interval), le Converts the elemen array type to `T1` without making a copy if the element type matches """ elconvert(::Type{T1}, x::AbstractArray{T2, N}) where {T1, T2, N} = convert(AbstractArray{T1, N}, x) -float32type(x::Type) = Float32 +float32type(::Type) = Float32 float32type(::Type{<: RGB}) = RGB{Float32} float32type(::Type{<: RGBA}) = RGBA{Float32} float32type(::Type{<: Colorant}) = RGBA{Float32} -float32type(x::AbstractArray{T}) where T = float32type(T) -float32type(x::T) where T = float32type(T) +float32type(::Type{<: Point{N}}) where {N} = Point{N, Float32} +float32type(::Type{<: Vec{N}}) where {N} = Vec{N, Float32} +float32type(::AbstractArray{T}) where T = float32type(T) +float32type(::T) where T = float32type(T) el32convert(x::AbstractArray) = elconvert(float32type(x), x) el32convert(x::AbstractArray{Float32}) = x el32convert(x::Observable) = lift(el32convert, x) @@ -681,6 +718,27 @@ function el32convert(x::AbstractArray{T, N}) where {T<:Union{Missing, <: Number} return (ismissing(elem) ? NaN32 : convert(Float32, elem))::Float32 end::Array{Float32, N} end + +function el32convert(mesh::GeometryBasics.Mesh, positions = mesh.position) + points = el32convert(positions) + attr = GeometryBasics.attributes(mesh) + delete!(attr, :position) + for key in keys(attr) + attr[key] = el32convert(attr[key]) + end + return GeometryBasics.Mesh(meta(points; attr...), faces(mesh)) +end + + +native_type(x::NativeFloat) = x +# native_type(x::VecTypes{N, T}) where {N, T <: NativeFloat} = reinterpret(Point{N, T}, x) # crashes precompile? +native_type(x::VecTypes{N, T}) where {N, T <: NativeFloat} = Point{N, T}(x) +native_type(x::Real) = Float32(x) +native_type(x::VecTypes{N}) where N = Point{N, Float32}(x) +native_type(x::Real, y::Real) = Point2(native_type(x), native_type(y)) +native_type(x::Real, y::Real, z::Real) = Point3(native_type(x), native_type(y), native_type(z)) + + """ to_triangles(indices) @@ -727,15 +785,14 @@ Converts a representation of vertices `v` to its canonical representation as a - otherwise if `v` has 2 or 3 columns, it will treat each row as a vertex. """ function to_vertices(verts::AbstractVector{<: VecTypes{3, T}}) where T - vert3f0 = T != Float32 ? Point3f.(verts) : verts - return reinterpret(Point3f, vert3f0) + return T != Float32 ? Point3f.(verts) : reinterpret(Point3f, verts) end function to_vertices(verts::AbstractVector{<: VecTypes}) - to_vertices(to_ndim.(Point3f, verts, 0.0)) + to_ndim.(Point3f, verts, 0.0) end -function to_vertices(verts::AbstractMatrix{<: Number}) +function to_vertices(verts::AbstractMatrix{<: Real}) if size(verts, 1) in (2, 3) to_vertices(verts, Val(1)) elseif size(verts, 2) in (2, 3) @@ -745,10 +802,10 @@ function to_vertices(verts::AbstractMatrix{<: Number}) end end -function to_vertices(verts::AbstractMatrix{T}, ::Val{1}) where T <: Number +function to_vertices(verts::AbstractMatrix{T}, ::Val{1}) where T <: Real N = size(verts, 1) if T == Float32 && N == 3 - reinterpret(Point{N, T}, elconvert(T, vec(verts))) + reinterpret(Point3f, elconvert(T, vec(verts))) else let N = Val(N), lverts = verts broadcast(1:size(verts, 2), N) do vidx, n @@ -758,7 +815,7 @@ function to_vertices(verts::AbstractMatrix{T}, ::Val{1}) where T <: Number end end -function to_vertices(verts::AbstractMatrix{T}, ::Val{2}) where T <: Number +function to_vertices(verts::AbstractMatrix{T}, ::Val{2}) where T <: Real let N = Val(size(verts, 2)), lverts = verts broadcast(1:size(verts, 1), N) do vidx, n to_ndim(Point3f, ntuple(i-> lverts[vidx, i], n), 0.0) diff --git a/src/interaction/interactive_api.jl b/src/interaction/interactive_api.jl index 93aff3479d6..bdf18977dec 100644 --- a/src/interaction/interactive_api.jl +++ b/src/interaction/interactive_api.jl @@ -214,7 +214,7 @@ By default uses the `scene` that the mouse is currently hovering over. mouseposition(x) = mouseposition(get_scene(x)) function mouseposition(scene::Scene = hovered_scene()) - return to_world(scene, mouseposition_px(scene)) + return to_world(scene, Float64.(mouseposition_px(scene))) end mouseposition_px(x) = mouseposition_px(get_scene(x)) diff --git a/src/interfaces.jl b/src/interfaces.jl index bc159b80cd0..ae597f02dc0 100644 --- a/src/interfaces.jl +++ b/src/interfaces.jl @@ -329,7 +329,7 @@ function plot!(scene::Union{Combined, SceneLike}, P::PlotFunc, attributes::Attri FinalType, argsconverted = apply_convert!(PreType, attributes, converted) converted_node = Observable(argsconverted) - input_nodes = convert.(Observable, args) + input_nodes = convert.(Observable, args) obs_funcs = onany(kw_signal, input_nodes...) do kwargs, args... # do the argument conversion inside a lift result = convert_arguments(FinalType, args...; kwargs...) diff --git a/src/layouting/boundingbox.jl b/src/layouting/boundingbox.jl index 18757dcb7a5..a0942dc8aa6 100644 --- a/src/layouting/boundingbox.jl +++ b/src/layouting/boundingbox.jl @@ -1,6 +1,6 @@ function parent_transform(x) p = parent(transformation(x)) - isnothing(p) ? Mat4f(I) : p.model[] + isnothing(p) ? Mat4{Float64}(I) : Mat4{Float64}(p.model[]) end function boundingbox(x, exclude = (p)-> false) @@ -13,9 +13,9 @@ function project_widths(matrix, vec) return pr - zero end -function rotate_bbox(bb::Rect3f, rot) - points = decompose(Point3f, bb) - Rect3f(Ref(rot) .* points) +function rotate_bbox(bb::Rect3, rot) + points = decompose(Point3e, bb) + Rect3{Float64}(Ref(rot) .* points) end function gl_bboxes(gl::GlyphCollection) @@ -23,10 +23,9 @@ function gl_bboxes(gl::GlyphCollection) map(gl.glyphs, gl.extents, scales) do c, ext, scale hi_bb = height_insensitive_boundingbox_with_advance(ext) # TODO c != 0 filters out all non renderables, which is not always desired - Rect2f( - Makie.origin(hi_bb) * scale, - (c != 0) * widths(hi_bb) * scale - ) + o = Makie.origin(hi_bb) * scale + w = (c != 0) * widths(hi_bb) * scale + Rect3{Float64}(Point3{Float64}(o[1], o[2], 0.0), Vec3{Float64}(w[1], w[2], 0)) end end @@ -35,7 +34,7 @@ function height_insensitive_boundingbox(ext::GlyphExtent) w = ext.ink_bounding_box.widths[1] b = ext.descender h = ext.ascender - return Rect2f((l, b), (w, h - b)) + return Rect2{Float64}((l, b), (w, h - b)) end function height_insensitive_boundingbox_with_advance(ext::GlyphExtent) @@ -43,26 +42,26 @@ function height_insensitive_boundingbox_with_advance(ext::GlyphExtent) r = ext.hadvance b = ext.descender h = ext.ascender - return Rect2f((l, b), (r - l, h - b)) + return Rect2{Float64}((l, b), (r - l, h - b)) end _inkboundingbox(ext::GlyphExtent) = ext.ink_bounding_box -function boundingbox(glyphcollection::GlyphCollection, position::Point3f, rotation::Quaternion) +function boundingbox(glyphcollection::GlyphCollection, position::Point3, rotation::Quaternion) return boundingbox(glyphcollection, rotation) + position end function boundingbox(glyphcollection::GlyphCollection, rotation::Quaternion) if isempty(glyphcollection.glyphs) - return Rect3f(Point3f(0), Vec3f(0)) + return Rect3(Point3e(0), Vec3e(0)) end glyphorigins = glyphcollection.origins glyphbbs = gl_bboxes(glyphcollection) - bb = Rect3f() + bb = Rect3{Float64}() for (charo, glyphbb) in zip(glyphorigins, glyphbbs) - charbb = rotate_bbox(Rect3f(glyphbb), rotation) + charo + charbb = rotate_bbox(Rect3{Float64}(glyphbb), rotation) + charo if !isfinite_rect(bb) bb = charbb else @@ -75,9 +74,9 @@ end function boundingbox(layouts::AbstractArray{<:GlyphCollection}, positions, rotations) if isempty(layouts) - return Rect3f((0, 0, 0), (0, 0, 0)) + return Rect3{Float64}((0, 0, 0), (0, 0, 0)) else - bb = Rect3f() + bb = Rect3{Float64}() broadcast_foreach(layouts, positions, rotations) do layout, pos, rot if !isfinite_rect(bb) bb = boundingbox(layout, pos, rot) @@ -92,7 +91,7 @@ end function boundingbox(x::Text{<:Tuple{<:GlyphCollection}}) if x.space[] == x.markerspace[] - pos = to_ndim(Point3f, x.position[], 0) + pos = to_ndim(Point3e, x.position[], 0) else cam = parent_scene(x).camera transformed = apply_transform(x.transformation.transform_func[], x.position[]) @@ -103,7 +102,7 @@ end function boundingbox(x::Text{<:Tuple{<:AbstractArray{<:GlyphCollection}}}) if x.space[] == x.markerspace[] - pos = to_ndim.(Point3f, x.position[], 0) + pos = to_ndim.(Point3e, x.position[], 0) else cam = (parent_scene(x).camera,) transformed = apply_transform(x.transformation.transform_func[], x.position[]) @@ -113,7 +112,7 @@ function boundingbox(x::Text{<:Tuple{<:AbstractArray{<:GlyphCollection}}}) end function boundingbox(plot::Text) - bb = Rect3f() + bb = Rect3{Float64}() for p in plot.plots _bb = boundingbox(p) if !isfinite_rect(bb) diff --git a/src/layouting/data_limits.jl b/src/layouting/data_limits.jl index df81ae151dc..34fe74ee9eb 100644 --- a/src/layouting/data_limits.jl +++ b/src/layouting/data_limits.jl @@ -95,7 +95,7 @@ function point_iterator(x::Volume) extremata = map(extrema∘to_value, axes) minpoint = Point3f(first.(extremata)...) widths = last.(extremata) .- first.(extremata) - rect = Rect3f(minpoint, Vec3f(widths)) + rect = Rect3(minpoint, Vec3(widths)) return unique(decompose(Point, rect)) end @@ -144,12 +144,15 @@ function iterate_transformed(plot) end function iterate_transformed(points, model, space, trans_func) - (to_ndim(Point3f, project(model, apply_transform(trans_func, point, space)), 0f0) for point in points) + Iterators.map(points) do point + p = apply_transform(trans_func, Point{length(point), Float64}(point), space) + to_ndim(Point3e, project(model, p), 0.0) + end end function update_boundingbox!(bb_ref, point) if all(isfinite, point) - vec = to_ndim(Vec3f, point, 0.0) + vec = to_ndim(Vec3{Float64}, point, 0.0) bb_ref[] = update(bb_ref[], vec) end end @@ -157,7 +160,7 @@ end function update_boundingbox!(bb_ref, bb::Rect) # ref is uninitialized, so just set it to the first bb if !isfinite_rect(bb_ref[]) - bb_ref[] = bb + bb_ref[] = Rect3{Float64}(bb) # TODO check when this avoids an error # hexbin scale, hexbin threshold return end # don't update if not finite @@ -175,7 +178,8 @@ function _update_rect(rect::Rect{N, T}, point::Point{N, T}) where {N, T} mi = minimum(rect) ma = maximum(rect) mis_mas = map(mi, ma, point) do _mi, _ma, _p - (isnan(_mi) ? _p : _p < _mi ? _p : _mi), (isnan(_ma) ? _p : _p > _ma ? _p : _ma) + (isnan(_mi) ? _p : _p < _mi ? _p : _mi), + (isnan(_ma) ? _p : _p > _ma ? _p : _ma) end new_o = map(first, mis_mas) new_w = map(mis_mas) do (mi, ma) @@ -185,14 +189,14 @@ function _update_rect(rect::Rect{N, T}, point::Point{N, T}) where {N, T} end function limits_from_transformed_points(points_iterator) - isempty(points_iterator) && return Rect3f() + isempty(points_iterator) && return Rect3{Float64}() first, rest = Iterators.peel(points_iterator) - bb = foldl(_update_rect, rest, init = Rect3f(first, zero(first))) + bb = foldl(_update_rect, rest, init = Rect3{Float64}(first, zero(first))) return bb end function data_limits(scenelike, exclude=(p)-> false) - bb_ref = Base.RefValue(Rect3f()) + bb_ref = Base.RefValue(Rect3{Float64}()) foreach_plot(scenelike) do plot if !exclude(plot) update_boundingbox!(bb_ref, data_limits(plot)) @@ -206,19 +210,19 @@ function data_limits(plot::Surface) mini_maxi = extrema_nan.((plot.x[], plot.y[], plot.z[])) mini = first.(mini_maxi) maxi = last.(mini_maxi) - return Rect3f(mini, maxi .- mini) + return Rect3{Float64}(mini, maxi .- mini) end function data_limits(plot::Heatmap) mini_maxi = extrema_nan.((plot.x[], plot.y[])) - mini = Vec3f(first.(mini_maxi)..., 0) - maxi = Vec3f(last.(mini_maxi)..., 0) - return Rect3f(mini, maxi .- mini) + mini = Vec3(first.(mini_maxi)..., 0) + maxi = Vec3(last.(mini_maxi)..., 0) + return Rect3{Float64}(mini, maxi .- mini) end function data_limits(plot::Image) mini_maxi = extrema_nan.((plot.x[], plot.y[])) - mini = Vec3f(first.(mini_maxi)..., 0) - maxi = Vec3f(last.(mini_maxi)..., 0) - return Rect3f(mini, maxi .- mini) + mini = Vec3(first.(mini_maxi)..., 0) + maxi = Vec3(last.(mini_maxi)..., 0) + return Rect3{Float64}(mini, maxi .- mini) end diff --git a/src/layouting/layouting.jl b/src/layouting/layouting.jl index d71fe598d4e..8c4f4d4f608 100644 --- a/src/layouting/layouting.jl +++ b/src/layouting/layouting.jl @@ -302,9 +302,9 @@ _offset_to_vec(o::Vector) = to_ndim.(Vec3f, o, 0) Base.getindex(x::ScalarOrVector, i) = x.sv isa Vector ? x.sv[i] : x.sv Base.lastindex(x::ScalarOrVector) = x.sv isa Vector ? length(x.sv) : 1 -function text_quads(atlas::TextureAtlas, position::VecTypes, gc::GlyphCollection, offset, transfunc, space) +function text_quads(atlas::TextureAtlas, position::VecTypes{N, T}, gc::GlyphCollection, offset, transfunc, space) where {N, T} p = apply_transform(transfunc, position, space) - pos = [to_ndim(Point3f, p, 0) for _ in gc.origins] + pos = [to_ndim(Point3{T}, p, 0) for _ in gc.origins] pad = atlas.glyph_padding / atlas.pix_per_glyph off = _offset_to_vec(offset) @@ -325,6 +325,7 @@ function text_quads(atlas::TextureAtlas, position::VecTypes, gc::GlyphCollection end # pos is the (space) position given to text (with transfunc applied) + # (keep float type for further processing in the backend) # char_offsets are 3D offsets in marker space, including: # - offsets passed to text # - character origins (relative to the string origin pos) @@ -335,9 +336,9 @@ function text_quads(atlas::TextureAtlas, position::VecTypes, gc::GlyphCollection return pos, char_offsets, quad_offsets, uvs, scales end -function text_quads(atlas::TextureAtlas, position::Vector, gcs::Vector{<: GlyphCollection}, offset, transfunc, space) +function text_quads(atlas::TextureAtlas, position::Vector{<: VecTypes{N, T}}, gcs::Vector{<: GlyphCollection}, offset, transfunc, space) where {N, T} ps = apply_transform(transfunc, position, space) - pos = [to_ndim(Point3f, p, 0) for (p, gc) in zip(ps, gcs) for _ in gc.origins] + pos = [to_ndim(Point3{T}, p, 0) for (p, gc) in zip(ps, gcs) for _ in gc.origins] pad = atlas.glyph_padding / atlas.pix_per_glyph off = _offset_to_vec(offset) diff --git a/src/makielayout/blocks/axis.jl b/src/makielayout/blocks/axis.jl index 59a97731ce8..2d4c8b9c441 100644 --- a/src/makielayout/blocks/axis.jl +++ b/src/makielayout/blocks/axis.jl @@ -73,11 +73,11 @@ function register_events!(ax, scene) end function update_axis_camera(camera::Camera, t, lims, xrev::Bool, yrev::Bool) - nearclip = -10_000f0 - farclip = 10_000f0 + nearclip = -10_000.0 + farclip = 10_000.0 # we are computing transformed camera position, so this isn't space dependent - tlims = Makie.apply_transform(t, lims) + tlims = Makie.apply_transform(t, lims) left, bottom = minimum(tlims) right, top = maximum(tlims) @@ -86,11 +86,11 @@ function update_axis_camera(camera::Camera, t, lims, xrev::Bool, yrev::Bool) bottomtop = yrev ? (top, bottom) : (bottom, top) projection = Makie.orthographicprojection( - Float32, + Float64, leftright..., bottomtop..., nearclip, farclip) - Makie.set_proj_view!(camera, projection, Makie.Mat4f(Makie.I)) + Makie.set_proj_view!(camera, projection, Makie.Mat4{Float64}(Makie.I)) return end @@ -171,8 +171,8 @@ function initialize_block!(ax::Axis; palette = nothing) # initialize either with user limits, or pick defaults based on scales # so that we don't immediately error - targetlimits = Observable{Rect2f}(defaultlimits(ax.limits[], ax.xscale[], ax.yscale[])) - finallimits = Observable{Rect2f}(targetlimits[]; ignore_equal_values=true) + targetlimits = Observable{Rect2{Float64}}(defaultlimits(ax.limits[], ax.xscale[], ax.yscale[])) + finallimits = Observable{Rect2{Float64}}(targetlimits[]; ignore_equal_values=true) setfield!(ax, :targetlimits, targetlimits) setfield!(ax, :finallimits, finallimits) @@ -585,7 +585,7 @@ function reset_limits!(ax; xauto = true, yauto = true, zauto = true) (lo, hi) end else - convert(Tuple{Float32, Float32}, tuple(mxlims...)) + convert(Tuple{Float64, Float64}, tuple(mxlims...)) end ylims = if isnothing(mylims) || mylims[1] === nothing || mylims[2] === nothing l = if yauto @@ -601,7 +601,7 @@ function reset_limits!(ax; xauto = true, yauto = true, zauto = true) (lo, hi) end else - convert(Tuple{Float32, Float32}, tuple(mylims...)) + convert(Tuple{Float64, Float64}, tuple(mylims...)) end if ax isa Axis3 @@ -619,7 +619,7 @@ function reset_limits!(ax; xauto = true, yauto = true, zauto = true) (lo, hi) end else - convert(Tuple{Float32, Float32}, tuple(mzlims...)) + convert(Tuple{Float64, Float64}, tuple(mzlims...)) end end @@ -635,15 +635,14 @@ function reset_limits!(ax; xauto = true, yauto = true, zauto = true) end end - tlims = if ax isa Axis - BBox(xlims..., ylims...) + if ax isa Axis + ax.targetlimits[] = BBox64(xlims[1], xlims[2], ylims[1], ylims[2]) elseif ax isa Axis3 - Rect3f( - Vec3f(xlims[1], ylims[1], zlims[1]), - Vec3f(xlims[2] - xlims[1], ylims[2] - ylims[1], zlims[2] - zlims[1]), + ax.targetlimits[] = Rect3( + Vec3(xlims[1], ylims[1], zlims[1]), + Vec3(xlims[2] - xlims[1], ylims[2] - ylims[1], zlims[2] - zlims[1]), ) end - ax.targetlimits[] = tlims nothing end @@ -912,7 +911,7 @@ function update_linked_limits!(block_limit_linking, xaxislinks, yaxislinks, tlim otherylims = limits(otherlims, 2) if thisxlims != otherxlims xlink.block_limit_linking[] = true - xlink.targetlimits[] = BBox(thisxlims[1], thisxlims[2], otherylims[1], otherylims[2]) + xlink.targetlimits[] = BBox64(thisxlims[1], thisxlims[2], otherylims[1], otherylims[2]) xlink.block_limit_linking[] = false end end @@ -923,7 +922,7 @@ function update_linked_limits!(block_limit_linking, xaxislinks, yaxislinks, tlim otherylims = limits(otherlims, 2) if thisylims != otherylims ylink.block_limit_linking[] = true - ylink.targetlimits[] = BBox(otherxlims[1], otherxlims[2], thisylims[1], thisylims[2]) + ylink.targetlimits[] = BBox64(otherxlims[1], otherxlims[2], thisylims[1], thisylims[2]) ylink.block_limit_linking[] = false end end @@ -1030,7 +1029,7 @@ function adjustlimits!(la) ylims = expandlimits(ylims, (((1 / correction_factor) - 1) .* ratios)..., identity) # don't use scale here? end - bbox = BBox(xlims[1], xlims[2], ylims[1], ylims[2]) + bbox = BBox64(xlims[1], xlims[2], ylims[1], ylims[2]) la.finallimits[] = bbox return end @@ -1332,7 +1331,7 @@ Makie.transform_func(ax::Axis) = Makie.transform_func(ax.scene) # these functions pick limits for different x and y scales, so that # we don't pick values that are invalid, such as 0 for log etc. function defaultlimits(userlimits::Tuple{Real, Real, Real, Real}, xscale, yscale) - BBox(userlimits...) + BBox64(userlimits...) end defaultlimits(l::Tuple{Any, Any, Any, Any}, xscale, yscale) = defaultlimits(((l[1], l[2]), (l[3], l[4])), xscale, yscale) @@ -1340,7 +1339,7 @@ defaultlimits(l::Tuple{Any, Any, Any, Any}, xscale, yscale) = defaultlimits(((l[ function defaultlimits(userlimits::Tuple{Any, Any}, xscale, yscale) xl = defaultlimits(userlimits[1], xscale) yl = defaultlimits(userlimits[2], yscale) - BBox(xl..., yl...) + BBox64(xl..., yl...) end defaultlimits(limits::Nothing, scale) = defaultlimits(scale) diff --git a/src/makielayout/blocks/axis3d.jl b/src/makielayout/blocks/axis3d.jl index 874beff7572..7e630dee0cd 100644 --- a/src/makielayout/blocks/axis3d.jl +++ b/src/makielayout/blocks/axis3d.jl @@ -9,7 +9,7 @@ function initialize_block!(ax::Axis3) end notify(ax.protrusions) - finallimits = Observable(Rect3f(Vec3f(0f0, 0f0, 0f0), Vec3f(100f0, 100f0, 100f0))) + finallimits = Observable(Rect3(Vec3(0.0), Vec3(100.0))) setfield!(ax, :finallimits, finallimits) scenearea = lift(round_to_IRect2D, blockscene, ax.layoutobservables.computedbbox) @@ -219,10 +219,10 @@ function calculate_matrices(limits, px_area, elev, azim, perspectiveness, aspect view_matrix = lookat_matrix * scale_matrix projection_matrix = projectionmatrix(view_matrix, limits, eyepos, radius, azim, elev, angle, w, h, scales, viewmode) - + # for eyeposition dependent algorithms, we need to present the position as if # there was no scaling applied - eyeposition = Vec3f(inv(scale_matrix) * Vec4f(eyepos..., 1)) + eyeposition = Vec3{Float64}(inv(scale_matrix) * Vec4(eyepos..., 1.0)) view_matrix, projection_matrix, eyeposition end @@ -241,8 +241,8 @@ function projectionmatrix(viewmatrix, limits, eyepos, radius, azim, elev, angle, pm = Makie.perspectiveprojection(Float64, angle, aspect_ratio, near, far) if viewmode in (:fitzoom, :stretch) - points = decompose(Point3f, limits) - projpoints = Ref(pm * viewmatrix) .* to_ndim.(Point4f, points, 1) + points = decompose(Point3{Float64}, limits) + projpoints = Ref(pm * viewmatrix) .* to_ndim.(Point4{Float64}, points, 1) maxx = maximum(x -> abs(x[1] / x[4]), projpoints) maxy = maximum(x -> abs(x[2] / x[4]), projpoints) @@ -303,15 +303,15 @@ function autolimits!(ax::Axis3) ylims = getlimits(ax, 2) zlims = getlimits(ax, 3) - ori = Vec3f(xlims[1], ylims[1], zlims[1]) - widths = Vec3f(xlims[2] - xlims[1], ylims[2] - ylims[1], zlims[2] - zlims[1]) + ori = Vec3(xlims[1], ylims[1], zlims[1]) + widths = Vec3(xlims[2] - xlims[1], ylims[2] - ylims[1], zlims[2] - zlims[1]) enlarge_factor = 0.1 nori = ori .- (0.5 * enlarge_factor) * widths nwidths = widths .* (1 + enlarge_factor) - lims = Rect3f(nori, nwidths) + lims = Rect3(nori, nwidths) ax.finallimits[] = lims nothing @@ -454,10 +454,10 @@ end # small z value function to_topscene_z_2d(p3d, scene) o = scene.px_area[].origin - p2d = Point2f(o + Makie.project(scene, p3d)) + p2d = Point2{Float64}(o + Makie.project(scene, p3d)) # -10000 is an arbitrary weird constant that in preliminary testing didn't seem # to clip into plot objects anymore - Point3f(p2d..., -10000) + return Point3(p2d..., -10000.0) end function add_ticks_and_ticklabels!(topscene, scene, ax, dim::Int, limits, ticknode, miv, min1, min2, azimuth) @@ -519,7 +519,7 @@ function add_ticks_and_ticklabels!(topscene, scene, ax, dim::Int, limits, tickno tick_segments, ticklabels, attr(:ticklabelpad)) do pxa, pv, ticksegs, ticklabs, pad o = pxa.origin - + points = map(ticksegs) do (tstart, tend) tstartp = Point2f(o + Makie.project(scene, tstart)) tendp = Point2f(o + Makie.project(scene, tend)) @@ -551,7 +551,7 @@ function add_ticks_and_ticklabels!(topscene, scene, ax, dim::Int, limits, tickno translate!(ticklabels, 0, 0, 1000) - label_position = Observable(Point2f(0)) + label_position = Observable(Point2(0.0)) label_rotation = Observable(0f0) label_align = Observable((:center, :top)) @@ -570,8 +570,8 @@ function add_ticks_and_ticklabels!(topscene, scene, ax, dim::Int, limits, tickno p2 = dpoint(maximum(lims)[dim], f1, f2) # project them into screen space - pp1 = Point2f(o + Makie.project(scene, p1)) - pp2 = Point2f(o + Makie.project(scene, p2)) + pp1 = Point2e(o + Makie.project(scene, p1)) + pp2 = Point2e(o + Makie.project(scene, p2)) # find the midpoint midpoint = (pp1 + pp2) ./ 2 diff --git a/src/makielayout/blocks/scene.jl b/src/makielayout/blocks/scene.jl index 8ecbad040c6..fd517e476c7 100644 --- a/src/makielayout/blocks/scene.jl +++ b/src/makielayout/blocks/scene.jl @@ -29,16 +29,17 @@ function initialize_block!(ls::LScene; scenekw = NamedTuple()) # Add axis on first plot!, if requested # update limits when scene limits change limits = lift(blockscene, ls.scene.theme.limits) do lims - if lims === automatic + out = if lims === automatic dl = data_limits(ls.scene, p -> Makie.isaxis(p) || Makie.not_in_data_space(p)) if any(isinf, widths(dl)) || any(isinf, Makie.origin(dl)) - Rect3f((0f0, 0f0, 0f0), (1f0, 1f0, 1f0)) + Rect3((0.0, 0.0, 0.0), (1.0, 1.0, 1.0)) else dl end else lims end + Rect3{Float64}(out) end Makie.axis3d!(ls.scene, limits) # Make sure axis is always in pos 1 diff --git a/src/makielayout/helpers.jl b/src/makielayout/helpers.jl index b222d029c17..b2b826f25ba 100644 --- a/src/makielayout/helpers.jl +++ b/src/makielayout/helpers.jl @@ -432,3 +432,9 @@ end Makie.get_scene(ax::Axis) = ax.scene Makie.get_scene(ax::Axis3) = ax.scene Makie.get_scene(ax::LScene) = ax.scene + +function BBox64(left::Number, right::Number, bottom::Number, top::Number) + mini = (left, bottom) + maxi = (right, top) + return Rect2{Float64}(mini, maxi .- mini) +end \ No newline at end of file diff --git a/src/makielayout/interactions.jl b/src/makielayout/interactions.jl index f94641d69b9..db4c4189124 100644 --- a/src/makielayout/interactions.jl +++ b/src/makielayout/interactions.jl @@ -108,15 +108,16 @@ end ############################################################################ function _chosen_limits(rz, ax) - r = positivize(Rect2f(rz.from, rz.to .- rz.from)) + + r = positivize(Rect2{Float64}(rz.from, rz.to .- rz.from)) lims = ax.finallimits[] # restrict to y change if rz.restrict_x || !ax.xrectzoom[] - r = Rect2f(lims.origin[1], r.origin[2], widths(lims)[1], widths(r)[2]) + r = Rect2{Float64}(lims.origin[1], r.origin[2], widths(lims)[1], widths(r)[2]) end # restrict to x change if rz.restrict_y || !ax.yrectzoom[] - r = Rect2f(r.origin[1], lims.origin[2], widths(r)[1], widths(lims)[2]) + r = Rect2{Float64}(r.origin[1], lims.origin[2], widths(r)[1], widths(lims)[2]) end return r end @@ -244,9 +245,9 @@ function process_interaction(s::ScrollZoom, event::ScrollEvent, ax::Axis) if zoom != 0 pa = pixelarea(scene)[] - z = (1f0 - s.speed)^zoom + z = (1.0 - s.speed)^zoom - mp_axscene = Vec4f((e.mouseposition[] .- pa.origin)..., 0, 1) + mp_axscene = Vec4e((e.mouseposition[] .- pa.origin)..., 0, 1) # first to normal -1..1 space mp_axfraction = (cam.pixel_space[] * mp_axscene)[Vec(1, 2)] .* @@ -276,11 +277,11 @@ function process_interaction(s::ScrollZoom, event::ScrollEvent, ax::Axis) timed_ticklabelspace_reset(ax, s.reset_timer, s.prev_xticklabelspace, s.prev_yticklabelspace, s.reset_delay) newrect_trans = if ispressed(scene, xzoomkey[]) - Rectf(newxorigin, yorigin, newxwidth, ywidth) + Rect2(newxorigin, yorigin, newxwidth, ywidth) elseif ispressed(scene, yzoomkey[]) - Rectf(xorigin, newyorigin, xwidth, newywidth) + Rect2(xorigin, newyorigin, xwidth, newywidth) else - Rectf(newxorigin, newyorigin, newxwidth, newywidth) + Rect2(newxorigin, newyorigin, newxwidth, newywidth) end inv_transf = Makie.inverse_transform(transf) @@ -308,8 +309,8 @@ function process_interaction(dp::DragPan, event::MouseEvent, ax) cam = camera(scene) pa = pixelarea(scene)[] - mp_axscene = Vec4f((event.px .- pa.origin)..., 0, 1) - mp_axscene_prev = Vec4f((event.prev_px .- pa.origin)..., 0, 1) + mp_axscene = Vec4e((event.px .- pa.origin)..., 0, 1) + mp_axscene_prev = Vec4e((event.prev_px .- pa.origin)..., 0, 1) mp_axfraction, mp_axfraction_prev = map((mp_axscene, mp_axscene_prev)) do mp # first to normal -1..1 space @@ -347,7 +348,7 @@ function process_interaction(dp::DragPan, event::MouseEvent, ax) timed_ticklabelspace_reset(ax, dp.reset_timer, dp.prev_xticklabelspace, dp.prev_yticklabelspace, dp.reset_delay) inv_transf = Makie.inverse_transform(transf) - newrect_trans = Rectf(Vec2f(xori, yori), widths(tlimits_trans)) + newrect_trans = Rect2(Vec2e(xori, yori), widths(tlimits_trans)) tlimits[] = Makie.apply_transform(inv_transf, newrect_trans) return Consume(true) diff --git a/src/makielayout/lineaxis.jl b/src/makielayout/lineaxis.jl index 5bbb30d29be..0fc1442db34 100644 --- a/src/makielayout/lineaxis.jl +++ b/src/makielayout/lineaxis.jl @@ -185,7 +185,7 @@ end function update_tickpos_string(closure_args, tickvalues_labels_unfiltered, reversed::Bool, scale) tickstrings, tickpositions, tickvalues, pos_extents_horizontal, limits_obs = closure_args - limits = limits_obs[]::NTuple{2, Float32} + limits = limits_obs[]::NTuple{2, Float64} tickvalues_unfiltered, tickstrings_unfiltered = tickvalues_labels_unfiltered @@ -226,7 +226,7 @@ function update_tickpos_string(closure_args, tickvalues_labels_unfiltered, rever return end -function update_minor_ticks(minortickpositions, limits::NTuple{2, Float32}, pos_extents_horizontal, minortickvalues, scale, reversed::Bool) +function update_minor_ticks(minortickpositions, limits::NTuple{2, Float64}, pos_extents_horizontal, minortickvalues, scale, reversed::Bool) position::Float32, extents_uncorrected::NTuple{2, Float32}, horizontal::Bool = pos_extents_horizontal extents = reversed ? reverse(extents_uncorrected) : extents_uncorrected @@ -266,8 +266,8 @@ function LineAxis(parent::Scene, attrs::Attributes) pos_extents_horizontal = lift(calculate_horizontal_extends, parent, endpoints; ignore_equal_values=true) horizontal = lift(x -> x[3], parent, pos_extents_horizontal) # Tuple constructor converts more than `convert(NTuple{2, Float32}, x)` but we still need the conversion to Float32 tuple: - limits = lift(x -> convert(NTuple{2,Float32}, Tuple(x)), parent, attrs.limits; ignore_equal_values=true) - flipped = lift(x -> convert(Bool, x), parent, attrs.flipped; ignore_equal_values=true) + limits = lift(x-> convert(NTuple{2, Float64}, Tuple(x)), parent, attrs.limits; ignore_equal_values=true) + flipped = lift(x-> convert(Bool, x), parent, attrs.flipped; ignore_equal_values=true) ticksnode = Observable(Point2f[]; ignore_equal_values=true) ticklines = linesegments!( @@ -411,11 +411,11 @@ function LineAxis(parent::Scene, attrs::Attributes) decorations[:labeltext] = labeltext - tickvalues = Observable(Float32[]; ignore_equal_values=true) + tickvalues = Observable(Float64[]; ignore_equal_values=true) - tickvalues_labels_unfiltered = Observable{Tuple{Vector{Float32},Vector{Any}}}() - map!(parent, tickvalues_labels_unfiltered, pos_extents_horizontal, limits, ticks, tickformat, - attrs.scale) do (position, extents, horizontal), + tickvalues_labels_unfiltered = Observable{Tuple{Vector{Float64},Vector{Any}}}() + map!(parent, tickvalues_labels_unfiltered, pos_extents_horizontal, limits, ticks, tickformat, + attrs.scale) do (position, extents, horizontal), limits, ticks, tickformat, scale get_ticks(ticks, scale, tickformat, limits...) end @@ -427,7 +427,7 @@ function LineAxis(parent::Scene, attrs::Attributes) Observable((tickstrings, tickpositions, tickvalues, pos_extents_horizontal, limits)), tickvalues_labels_unfiltered, reversed, attrs.scale) - minortickvalues = Observable(Float32[]; ignore_equal_values=true) + minortickvalues = Observable(Float64[]; ignore_equal_values=true) minortickpositions = Observable(Point2f[]; ignore_equal_values=true) onany(parent, tickvalues, minorticks) do tickvalues, minorticks diff --git a/src/makielayout/mousestatemachine.jl b/src/makielayout/mousestatemachine.jl index 0fdd41e3bfe..741bd07b739 100644 --- a/src/makielayout/mousestatemachine.jl +++ b/src/makielayout/mousestatemachine.jl @@ -47,10 +47,10 @@ Fields: struct MouseEvent type::MouseEventType t::Float64 - data::Point2f + data::Point2e px::Point2f prev_t::Float64 - prev_data::Point2f + prev_data::Point2e prev_px::Point2f end @@ -127,7 +127,7 @@ function _addmouseevents!(scene, is_mouse_over_relevant_area, priority) dblclick_max_interval = 0.2 mouseevent = Observable{MouseEvent}( - MouseEvent(MouseEventTypes.out, 0.0, Point2f(0, 0), Point2f(0, 0), 0.0, Point2f(0, 0), Point2f(0, 0)) + MouseEvent(MouseEventTypes.out, 0.0, Point2e(0, 0), Point2f(0, 0), 0.0, Point2e(0, 0), Point2f(0, 0)) ) # initialize state variables last_mouseevent = Ref{Mouse.Action}(Mouse.release) diff --git a/src/makielayout/types.jl b/src/makielayout/types.jl index f0a22f98c5c..2842dbb2160 100644 --- a/src/makielayout/types.jl +++ b/src/makielayout/types.jl @@ -125,10 +125,10 @@ mutable struct LineAxis attributes::Attributes elements::Dict{Symbol, Any} tickpositions::Observable{Vector{Point2f}} - tickvalues::Observable{Vector{Float32}} + tickvalues::Observable{Vector{Float64}} ticklabels::Observable{Vector{Any}} minortickpositions::Observable{Vector{Point2f}} - minortickvalues::Observable{Vector{Float32}} + minortickvalues::Observable{Vector{Float64}} end struct LimitReset end @@ -138,15 +138,15 @@ mutable struct RectangleZoom active::Observable{Bool} restrict_x::Bool restrict_y::Bool - from::Union{Nothing, Point2f} - to::Union{Nothing, Point2f} - rectnode::Observable{Rect2f} + from::Union{Nothing, Point2e} + to::Union{Nothing, Point2e} + rectnode::Observable{Rect2{Float64}} modifier::Any # e.g. Keyboard.left_alt, or some other button that needs to be pressed to start rectangle... Defaults to `true`, which means no modifier needed end function RectangleZoom(callback::Function; restrict_x=false, restrict_y=false, modifier=true) return RectangleZoom(callback, Observable(false), restrict_x, restrict_y, - nothing, nothing, Observable(Rect2f(0, 0, 1, 1)), modifier) + nothing, nothing, Observable(Rect2{Float64}(0, 0, 1, 1)), modifier) end struct ScrollZoom @@ -189,8 +189,8 @@ end scene::Scene xaxislinks::Vector{Axis} yaxislinks::Vector{Axis} - targetlimits::Observable{Rect2f} - finallimits::Observable{Rect2f} + targetlimits::Observable{Rect2{Float64}} + finallimits::Observable{Rect2{Float64}} cycler::Cycler palette::Attributes block_limit_linking::Observable{Bool} @@ -1327,7 +1327,7 @@ end @Block Axis3 begin scene::Scene - finallimits::Observable{Rect3f} + finallimits::Observable{Rect3{Float64}} mouseeventhandle::MouseEventHandle scrollevents::Observable{ScrollEvent} keysevents::Observable{KeysEvent} @@ -1578,7 +1578,7 @@ end "Controls if the xz panel is visible" xzpanelvisible = true "The limits that the axis tries to set given other constraints like aspect. Don't set this directly, use `xlims!`, `ylims!` or `limits!` instead." - targetlimits = Rect3f(Vec3f(0, 0, 0), Vec3f(1, 1, 1)) + targetlimits = Rect3(Vec3(0.0), Vec3(1.0)) "The limits that the user has manually set. They are reinstated when calling `reset_limits!` and are set to nothing by `autolimits!`. Can be either a tuple (xlow, xhigh, ylow, high, zlow, zhigh) or a tuple (nothing_or_xlims, nothing_or_ylims, nothing_or_zlims). Are set by `xlims!`, `ylims!`, `zlims!` and `limits!`." limits = (nothing, nothing, nothing) "The relative margins added to the autolimits in x direction." diff --git a/src/scenes.jl b/src/scenes.jl index c992e2970fb..8d9b697a280 100644 --- a/src/scenes.jl +++ b/src/scenes.jl @@ -574,10 +574,10 @@ end function center!(scene::Scene, padding=0.01, exclude = not_in_data_space) bb = boundingbox(scene, exclude) - bb = transformationmatrix(scene)[] * bb + bb = Mat4{Float64}(transformationmatrix(scene)[]) * bb w = widths(bb) padd = w .* padding - bb = Rect3f(minimum(bb) .- padd, w .+ 2padd) + bb = Rect3{Float64}(minimum(bb) .- padd, w .+ 2padd) update_cam!(scene, bb) scene end diff --git a/src/stats/boxplot.jl b/src/stats/boxplot.jl index 33d11eeeefc..f58849e037a 100644 --- a/src/stats/boxplot.jl +++ b/src/stats/boxplot.jl @@ -75,12 +75,13 @@ conversion_trait(x::Type{<:BoxPlot}) = SampleBased() _cycle(v::AbstractVector, idx::Integer) = v[mod1(idx, length(v))] _cycle(v, idx::Integer) = v -flip_xy(p::Point2f) = reverse(p) +flip_xy(p::Point2) = reverse(p) flip_xy(r::Rect{2,T}) where {T} = Rect{2,T}(reverse(r.origin), reverse(r.widths)) function Makie.plot!(plot::BoxPlot) args = @extract plot (weights, width, range, show_outliers, whiskerwidth, show_notch, orientation, gap, dodge, n_dodge, dodge_gap) + FT = floattype(plot[1], plot[2]) signals = lift( plot, plot[1], @@ -93,14 +94,14 @@ function Makie.plot!(plot::BoxPlot) error("whiskerwidth must be :match or a positive number. Found: $whiskerwidth") end ww = whiskerwidth === :match ? boxwidth : whiskerwidth * boxwidth - outlier_points = Point2f[] - centers = Float32[] - medians = Float32[] - boxmin = Float32[] - boxmax = Float32[] - notchmin = Float32[] - notchmax = Float32[] - t_segments = Point2f[] + outlier_points = Point2{FT}[] + centers = FT[] + medians = FT[] + boxmin = FT[] + boxmax = FT[] + notchmin = FT[] + notchmax = FT[] + t_segments = Point2{FT}[] outlier_indices = Int[] T = color isa AbstractVector ? eltype(color) : typeof(color) boxcolor = T[] diff --git a/src/stats/crossbar.jl b/src/stats/crossbar.jl index 6bcd61abb03..f6768b538b8 100644 --- a/src/stats/crossbar.jl +++ b/src/stats/crossbar.jl @@ -53,6 +53,7 @@ end function Makie.plot!(plot::CrossBar) args = @extract plot (width, dodge, n_dodge, gap, dodge_gap, show_notch, notchmin, notchmax, notchwidth, orientation) + FT = floattype(plot[1], plot[2], plot[3], plot[4]) signals = lift( plot, plot[1], @@ -65,7 +66,7 @@ function Makie.plot!(plot::CrossBar) show_notch = show_notch && (nmin !== automatic && nmax !== automatic) # for horizontal crossbars just flip all components - fpoint, frect = Point2f, Rectf + fpoint, frect = Point2{FT}, Rect{2, FT} if orientation === :horizontal fpoint, frect = flip_xy ∘ fpoint, flip_xy ∘ frect end diff --git a/src/stats/density.jl b/src/stats/density.jl index 2d667196268..ae9685afe91 100644 --- a/src/stats/density.jl +++ b/src/stats/density.jl @@ -4,10 +4,11 @@ function convert_arguments(P::PlotFunc, d::KernelDensity.UnivariateKDE) end function convert_arguments(::Type{<:Poly}, d::KernelDensity.UnivariateKDE) - points = Vector{Point2f}(undef, length(d.x) + 2) - points[1] = Point2f(d.x[1], 0) - points[2:end-1] .= Point2f.(d.x, d.density) - points[end] = Point2f(d.x[end], 0) + # d.density is always Float64 + points = Vector{Point2e}(undef, length(d.x) + 2) + points[1] = Point2e(d.x[1], 0) + points[2:end-1] .= Point2e.(d.x, d.density) + points[end] = Point2e(d.x[end], 0) (points,) end @@ -53,7 +54,7 @@ $(ATTRIBUTES) ) end -function plot!(plot::Density{<:Tuple{<:AbstractVector}}) +function Makie.plot!(plot::Density{<:Tuple{<:AbstractVector}}) x = plot[1] lowerupper = lift(plot, x, plot.direction, plot.boundary, plot.offset, @@ -67,11 +68,11 @@ function plot!(plot::Density{<:Tuple{<:AbstractVector}}) ) if dir === :x - lowerv = Point2f.(k.x, offs) - upperv = Point2f.(k.x, offs .+ k.density) + lowerv = Point2.(k.x, offs) + upperv = Point2.(k.x, offs .+ k.density) elseif dir === :y - lowerv = Point2f.(offs, k.x) - upperv = Point2f.(offs .+ k.density, k.x) + lowerv = Point2.(offs, k.x) + upperv = Point2.(offs .+ k.density, k.x) else error("Invalid direction $dir, only :x or :y allowed") end @@ -90,14 +91,13 @@ function plot!(plot::Density{<:Tuple{<:AbstractVector}}) end end - lower = Observable(Point2f[]) - upper = Observable(Point2f[]) + lower = Observable(first(lowerupper[])) + upper = Observable(last(lowerupper[])) on(plot, lowerupper) do (l, u) lower.val = l upper[] = u end - notify(lowerupper) colorobs = Observable{RGBColors}() map!(plot, colorobs, plot.color, lowerupper, plot.direction) do c, lu, dir diff --git a/src/stats/distributions.jl b/src/stats/distributions.jl index 0e219fb0bd9..ceaed6d290e 100644 --- a/src/stats/distributions.jl +++ b/src/stats/distributions.jl @@ -90,8 +90,8 @@ function fit_qqplot(x, y; qqline = :none) throw(ArgumentError(msg)) end h = qqbuild(x, y) - points = Point2f.(h.qx, h.qy) - qqline === :none && return points, Point2f[] + points = Point2.(h.qx, h.qy) + qqline === :none && return points, eltype(points)[] xs = collect(extrema(h.qx)) if qqline === :identity ys = xs @@ -103,7 +103,7 @@ function fit_qqplot(x, y; qqline = :none) slp = (quanty[2] - quanty[1]) / (quantx[2] - quantx[1]) ys = @. quanty + slp * (xs - quantx) end - return points, Point2f.(xs, ys) + return points, eltype(points).(xs, ys) end # Fit distribution type, otherwise leave first argument unchanged diff --git a/src/stats/ecdf.jl b/src/stats/ecdf.jl index 6494ca58df9..f5ab9e22a39 100644 --- a/src/stats/ecdf.jl +++ b/src/stats/ecdf.jl @@ -19,11 +19,13 @@ function convert_arguments(P::PlotFunc, ecdf::StatsBase.ECDF; npoints=10_000) end return to_plotspec(ptype, convert_arguments(ptype, x, ecdf(x)); kwargs...) end + function convert_arguments(P::PlotFunc, x::AbstractVector, ecdf::StatsBase.ECDF) ptype = plottype(P, Stairs) kwargs = ptype <: Stairs ? (; step=:post) : NamedTuple() return to_plotspec(ptype, convert_arguments(ptype, x, ecdf(x)); kwargs...) end + function convert_arguments(P::PlotFunc, x0::AbstractInterval, ecdf::StatsBase.ECDF) xmin, xmax = extrema(x0) z = ecdf_xvalues(ecdf, Inf) @@ -47,16 +49,19 @@ If `weights` for the values are provided, a weighted ECDF is plotted. $(ATTRIBUTES) """ @recipe(ECDFPlot) do scene - default_theme(scene, Stairs) + merge!( + default_theme(scene, Stairs), + Attributes( + npoints = 10_000, + weights = StatsBase.Weights(Float64[]) + ) + ) end -used_attributes(::Type{<:ECDFPlot}, ::AbstractVector) = (:npoints, :weights) -function convert_arguments( - ::Type{<:ECDFPlot}, - x::AbstractVector; - npoints=10_000, - weights=StatsBase.Weights(Float64[]), -) - ecdf = StatsBase.ecdf(x; weights=weights) - return convert_arguments(Stairs, ecdf; npoints=npoints) -end +function plot!(p::ECDFPlot) + attr = copy(p.attributes) + weights = pop!(attr, :weights) + ecdf = map((x, w) -> StatsBase.ecdf(x; weights=w), p[1], weights) + stairs!(p, attr, ecdf) + return p +end \ No newline at end of file diff --git a/src/stats/hexbin.jl b/src/stats/hexbin.jl index 47150e0c9e9..27b16812e22 100644 --- a/src/stats/hexbin.jl +++ b/src/stats/hexbin.jl @@ -58,21 +58,26 @@ end Makie.conversion_trait(::Type{<:Hexbin}) = PointBased() function data_limits(hb::Hexbin) - bb = Rect3f(hb.plots[1][1][]) - fn(num::Real) = Float32(num) - fn(tup::Union{Tuple,Vec2}) = Vec2f(tup...) + data = hb.plots[1][1][] + FT = floattype(data) + bb = Rect3{FT}(data) + + fn(num::Real) = Float64(num) + fn(tup::Union{Tuple,Vec2}) = Vec2(tup...) ms = 2 .* fn(hb.plots[1].markersize[]) - nw = widths(bb) .+ (ms..., 0.0f0) - no = bb.origin .- ((ms ./ 2.0f0)..., 0.0f0) + nw = widths(bb) .+ (ms..., 0) + no = bb.origin .- ((ms ./ 2)..., 0) - return Rect3f(no, nw) + r = Rect3(no, nw) + return r end function Makie.plot!(hb::Hexbin{<:Tuple{<:AbstractVector{<:Point2}}}) xy = hb[1] - points = Observable(Point2f[]) + FT = floattype(xy) + points = Observable(Point2{FT}[]) count_hex = Observable(Float64[]) markersize = Observable(Vec2f(1, 1)) @@ -142,7 +147,7 @@ function Makie.plot!(hb::Hexbin{<:Tuple{<:AbstractVector{<:Point2}}}) _x = xoff + 2 * ix * xspacing + (isodd(iy) * xspacing) _y = yoff + iy * yspacing c = get(d, (ix, iy), 0) - push!(points[], Point2f(_x, _y)) + push!(points[], Point2{FT}(_x, _y)) push!(count_hex[], scale(c)) end end @@ -152,7 +157,7 @@ function Makie.plot!(hb::Hexbin{<:Tuple{<:AbstractVector{<:Point2}}}) if value >= threshold _x = xoff + 2 * ix * xspacing + (isodd(iy) * xspacing) _y = yoff + iy * yspacing - push!(points[], Point2f(_x, _y)) + push!(points[], Point2{FT}(_x, _y)) push!(count_hex[], scale(value)) end end diff --git a/src/stats/hist.jl b/src/stats/hist.jl index bf5cd7e5bf8..f0a5f58e49e 100644 --- a/src/stats/hist.jl +++ b/src/stats/hist.jl @@ -63,7 +63,7 @@ function Makie.plot!(plot::StepHist) edges = vcat(edges, phantomedge) z = zero(eltype(weights)) heights = vcat(z, weights, z) - return Point2f.(edges, heights) + return Point2.(edges, heights) end color = lift(plot, plot.color) do color if color === :values @@ -165,7 +165,7 @@ function Makie.plot!(plot::Hist) points = lift(plot, edges, plot.normalization, plot.scale_to, plot.weights) do edges, normalization, scale_to, wgts centers, weights = _hist_center_weights(values, edges, normalization, scale_to, wgts) - return Point2f.(centers, weights) + return Point2.(centers, weights) end widths = lift(diff, plot, edges) color = lift(plot, plot.color) do color diff --git a/src/stats/violin.jl b/src/stats/violin.jl index ef6e6f5ff99..08c3e1bb76d 100644 --- a/src/stats/violin.jl +++ b/src/stats/violin.jl @@ -47,17 +47,18 @@ function getuniquevalue(v::AbstractVector, idxs) return f end -function plot!(plot::Violin) +function Makie.plot!(plot::Violin) x, y = plot[1], plot[2] args = @extract plot (width, side, color, show_median, npoints, boundary, bandwidth, weights, datalimits, max_density, dodge, n_dodge, gap, dodge_gap, orientation) + FT = floattype(x, y) signals = lift(plot, x, y, args...) do x, y, width, vside, color, show_median, n, bound, bw, w, limits, max_density, dodge, n_dodge, gap, dodge_gap, orientation x̂, violinwidth = compute_x_and_width(x, width, gap, dodge, n_dodge, dodge_gap) # for horizontal violin just flip all componentes - point_func = Point2f + point_func = Point2{FT} if orientation === :horizontal point_func = flip_xy ∘ point_func end @@ -93,8 +94,8 @@ function plot!(plot::Violin) max_density end - vertices = Vector{Point2f}[] - lines = Pair{Point2f, Point2f}[] + vertices = Vector{Point2{FT}}[] + lines = Pair{Point2{FT}, Point2{FT}}[] colors = RGBA{Float32}[] for spec in specs diff --git a/src/types.jl b/src/types.jl index c28e74df6a8..a657da6ebc2 100644 --- a/src/types.jl +++ b/src/types.jl @@ -210,17 +210,17 @@ struct Camera """ View matrix is usually used to rotate, scale and translate the scene """ - view::Observable{Mat4f} + view::Observable{Mat4{Float64}} """ Projection matrix is used for any perspective transformation """ - projection::Observable{Mat4f} + projection::Observable{Mat4{Float64}} """ just projection * view """ - projectionview::Observable{Mat4f} + projectionview::Observable{Mat4{Float64}} """ resolution of the canvas this camera draws to @@ -230,7 +230,7 @@ struct Camera """ Eye position of the camera, sued for e.g. ray tracing. """ - eyeposition::Observable{Vec3f} + eyeposition::Observable{Vec3f} # TODO Should this be Float64? """ To make camera interactive, steering observables are connected to the different matrices. diff --git a/src/utilities/quaternions.jl b/src/utilities/quaternions.jl index bcae57f50de..278468be9bc 100644 --- a/src/utilities/quaternions.jl +++ b/src/utilities/quaternions.jl @@ -107,9 +107,6 @@ function Mat4{ET}(q::Quaternion{T}) where {T, ET} ) end -concrete_type(::Type{Any}, ::Type{T}) where T = T -concrete_type(::Type{T}, x) where T = T - function Mat3{ET}(q::Quaternion{T}) where {T, ET} sx, sy, sz = 2q[4]*q[1], 2q[4]*q[2], 2q[4]*q[3] xx, xy, xz = 2q[1]^2, 2q[1]*q[2], 2q[1]*q[3] diff --git a/src/utilities/utilities.jl b/src/utilities/utilities.jl index 3be79b92cd3..2d07c53e3f6 100644 --- a/src/utilities/utilities.jl +++ b/src/utilities/utilities.jl @@ -344,7 +344,7 @@ Allows to supply `f`, which gets applied to every point. """ function matrix_grid(f, x::AbstractArray, y::AbstractArray, z::AbstractMatrix) g = map(CartesianIndices(z)) do i - return f(Point3f(get_dim(x, i, 1, size(z)), get_dim(y, i, 2, size(z)), z[i])) + return f(Point3(get_dim(x, i, 1, size(z)), get_dim(y, i, 2, size(z)), z[i])) end return vec(g) end @@ -364,3 +364,64 @@ end # Scalar - Vector getindex sv_getindex(v::Vector, i::Integer) = v[i] sv_getindex(x, i::Integer) = x + + +# For tracing function call order, probably delete later? + +macro trace(expr) + if expr.head in (Symbol("="), :function) + name = _to_typed_name(expr.args[1]) + file = " in " * string(__source__.file) * ':' + line = string(__source__.line) * '\n' + code = quote + begin + printstyled($name, bold = true) + printstyled($file, color = :light_black) + printstyled($line, bold = true) + $(expr.args[2]) + end + end + out = Expr( + expr.head, # function or = + esc(expr.args[1]), # function name w/ args + esc(code) + ) + return out + end + return expr +end + +function _to_typed_name(e::Expr) + if e.head == :where + _to_typed_name(e.args[1]) + elseif e.head == :call + if length(e.args) > 1 && e.args[2] isa Expr && e.args[2].head == :parameters + args = join(_to_type.(e.args[3:end]), ", ") + kwargs = join(_to_type.(e.args[2].args), ", ") + return string(e.args[1]) * "(" * args * "; " * kwargs * ")" + else + args = join(_to_type.(e.args[2:end]), ", ") + return string(e.args[1]) * "(" * args * ")" + end + else + dump(e) + return "ERROR" + end +end + +_to_type(s::Symbol) = "::Any" +function _to_type(e::Expr) + if e.head == Symbol("::") + return "::" * string(e.args[end]) + elseif e.head == Symbol("...") + return _to_type(e.args[1]) * "..." + elseif e.head == :parameters # keyword args + return _to_type(e.args[1]) + elseif e.head == :kw # default value + return _to_type(e.args[1]) + else + dump(e) + error("Failed to parse expression.") + return "" + end +end \ No newline at end of file diff --git a/test/conversions.jl b/test/conversions.jl index 881062c02c3..327a5c9102c 100644 --- a/test/conversions.jl +++ b/test/conversions.jl @@ -21,7 +21,7 @@ end @testset "changing input types" begin input = Observable{Any}(decompose(Point2f, Circle(Point2f(0), 2f0))) f, ax, pl = mesh(input) - m = Makie.triangle_mesh(Circle(Point2f(0), 1f0)) + m = Makie._triangle_mesh(Circle(Point2f(0), 1f0)) input[] = m @test pl[1][] == m end diff --git a/test/makielayout.jl b/test/makielayout.jl index df8614a2ce6..2e728304427 100644 --- a/test/makielayout.jl +++ b/test/makielayout.jl @@ -54,65 +54,86 @@ end end @testset "Axis limits basics" begin + using Makie: BBox64 + f = Figure() ax = Axis(f[1, 1], limits = (nothing, nothing)) - ax.targetlimits[] = BBox(0, 10, 0, 20) - @test ax.finallimits[] == BBox(0, 10, 0, 20) + + ax.targetlimits[] = BBox64(0, 10, 0, 20) + @test ax.finallimits[] == BBox64(0, 10, 0, 20) @test ax.limits[] == (nothing, nothing) + xlims!(ax, -10, 10) @test ax.limits[] == ((-10, 10), nothing) - @test ax.finallimits[] == BBox(-10, 10, 0, 20) + @test ax.finallimits[] == BBox64(-10, 10, 0, 20) + ylims!(ax, -20, 30) @test ax.limits[] == ((-10, 10), (-20, 30)) - @test ax.finallimits[] == BBox(-10, 10, -20, 30) + @test ax.finallimits[] == BBox64(-10, 10, -20, 30) + + ylims!(ax, 1 - 0.5e-9, 1 + 1.5e-9) + @test ax.limits[] == ((-10, 10), (0.9999999995, 1.0000000015)) + @test ax.finallimits[] == BBox64(-10, 10, 0.9999999995, 1.0000000015) + limits!(ax, -5, 5, -10, 10) - @test ax.finallimits[] == BBox(-5, 5, -10, 10) + @test ax.finallimits[] == BBox64(-5, 5, -10, 10) @test ax.limits[] == ((-5, 5), (-10, 10)) + ax.limits[] = (nothing, nothing) ax.xautolimitmargin = (0, 0) ax.yautolimitmargin = (0, 0) scatter!(Point2f[(0, 0), (1, 2)]) reset_limits!(ax) @test ax.limits[] == (nothing, nothing) - @test ax.targetlimits[] == BBox(0, 1, 0, 2) - @test ax.finallimits[] == BBox(0, 1, 0, 2) + @test ax.targetlimits[] == BBox64(0, 1, 0, 2) + @test ax.finallimits[] == BBox64(0, 1, 0, 2) + scatter!(Point2f(3, 4)) reset_limits!(ax) @test ax.limits[] == (nothing, nothing) - @test ax.targetlimits[] == BBox(0, 3, 0, 4) - @test ax.finallimits[] == BBox(0, 3, 0, 4) + @test ax.targetlimits[] == BBox64(0, 3, 0, 4) + @test ax.finallimits[] == BBox64(0, 3, 0, 4) + limits!(ax, -1, 1, 0, 2) @test ax.limits[] == ((-1, 1), (0, 2)) - @test ax.targetlimits[] == BBox(-1, 1, 0, 2) - @test ax.finallimits[] == BBox(-1, 1, 0, 2) + @test ax.targetlimits[] == BBox64(-1, 1, 0, 2) + @test ax.finallimits[] == BBox64(-1, 1, 0, 2) + scatter!(Point2f(5, 6)) reset_limits!(ax) @test ax.limits[] == ((-1, 1), (0, 2)) - @test ax.targetlimits[] == BBox(-1, 1, 0, 2) - @test ax.finallimits[] == BBox(-1, 1, 0, 2) + @test ax.targetlimits[] == BBox64(-1, 1, 0, 2) + @test ax.finallimits[] == BBox64(-1, 1, 0, 2) + autolimits!(ax) @test ax.limits[] == (nothing, nothing) - @test ax.targetlimits[] == BBox(0, 5, 0, 6) - @test ax.finallimits[] == BBox(0, 5, 0, 6) + @test ax.targetlimits[] == BBox64(0, 5, 0, 6) + @test ax.finallimits[] == BBox64(0, 5, 0, 6) + xlims!(ax, [-10, 10]) @test ax.limits[] == ([-10, 10], nothing) - @test ax.targetlimits[] == BBox(-10, 10, 0, 6) - @test ax.finallimits[] == BBox(-10, 10, 0, 6) + @test ax.targetlimits[] == BBox64(-10, 10, 0, 6) + @test ax.finallimits[] == BBox64(-10, 10, 0, 6) + scatter!(Point2f(11, 12)) reset_limits!(ax) @test ax.limits[] == ([-10, 10], nothing) - @test ax.targetlimits[] == BBox(-10, 10, 0, 12) - @test ax.finallimits[] == BBox(-10, 10, 0, 12) + @test ax.targetlimits[] == BBox64(-10, 10, 0, 12) + @test ax.finallimits[] == BBox64(-10, 10, 0, 12) + autolimits!(ax) ylims!(ax, [5, 7]) @test ax.limits[] == (nothing, [5, 7]) - @test ax.targetlimits[] == BBox(0, 11, 5, 7) - @test ax.finallimits[] == BBox(0, 11, 5, 7) + @test ax.targetlimits[] == BBox64(0, 11, 5, 7) + @test ax.finallimits[] == BBox64(0, 11, 5, 7) + scatter!(Point2f(-5, -7)) reset_limits!(ax) @test ax.limits[] == (nothing, [5, 7]) - @test ax.targetlimits[] == BBox(-5, 11, 5, 7) - @test ax.finallimits[] == BBox(-5, 11, 5, 7) + @test ax.targetlimits[] == BBox64(-5, 11, 5, 7) + @test ax.finallimits[] == BBox64(-5, 11, 5, 7) + + end @testset "Colorbar plot object kwarg clash" begin