### Interactive Geometry and Paint Canvas with Tyler.jl Source: https://github.com/makieorg/makiedraw.jl/blob/main/README.md This example demonstrates setting up an interactive map using Tyler.jl and integrating multiple GeometryCanvas instances for points, lines, and polygons. It also shows how to save and reload polygon data to a GeoJSON file and then re-edit it. ```julia using MakieDraw using GLMakie using GeoJSON using GeometryBasics using GeoInterface using TileProviders using Tyler using Extents provider = Google(:satelite) figure = Figure() axis = Axis(figure[1, 1]) tyler = Tyler.Map(Extent(Y=(-27.0, 0.025), X=(0.04, 38.0)); figure, axis, provider=Google() ) categories = Observable(Int[]) point_canvas = GeometryCanvas{Point2}(; figure, axis, properties=(; categories), mouse_property=:categories, scatter_kw=(; color=categories, colorrange=(0, 2), colormap=:spring) ) line_canvas = GeometryCanvas{LineString}(; figure, axis) line_canvas.active[] = false point_canvas.active[] = true poly_canvas = GeometryCanvas{Polygon}(; figure, axis) layers = Dict( :point=>point_canvas, :line=>line_canvas, :poly=>poly_canvas, ) MakieDraw.CanvasSelect(figure[3, 1], axis; layers) # Write the polygons to JSON # Have to convert here because GeometryBasics `isgeometry` has a bug, see PR #193 polygons = GeoInterface.convert.(Ref(GeoInterface), poly_canvas.geoms[]) mp = GeoInterface.MultiPolygon(polygons) GeoJSON.write("multipolygon.json", mp) # Reload and edit again polygons = collect(GeoInterface.getgeom(GeoJSON.read(read("multipolygon.json")))) tyler = Tyler.Map(Extent(Y=(-27.0, 0.025), X=(0.04, 38.0)); provider) fig = tyler.figure; axis = tyler.axis; poly_canvas = GeometryCanvas(polygons; figure, axis) ``` -------------------------------- ### Setup CanvasSelect for Multiple Canvases Source: https://context7.com/makieorg/makiedraw.jl/llms.txt Demonstrates setting up CanvasSelect to manage multiple MakieDraw canvases (GeometryCanvas and PaintCanvas) with a dropdown menu for switching. ```julia using MakieDraw, GLMakie figure = Figure() axis = Axis(figure[1, 1]) # Create canvases point_canvas = GeometryCanvas{Point2}(; figure, axis) line_canvas = GeometryCanvas{LineString}(; figure, axis) poly_canvas = GeometryCanvas{Polygon}(; figure, axis) paint_canvas = PaintCanvas(zeros(100, 100); figure, axis) # Deactivate all except one before building selector line_canvas.active[] = false poly_canvas.active[] = false paint_canvas.active[] = false # CanvasSelect setup would follow here, typically involving a Menu widget ``` -------------------------------- ### Create Empty Polygon GeometryCanvas Source: https://context7.com/makieorg/makiedraw.jl/llms.txt Initializes an empty GeometryCanvas for drawing polygons. Click to add vertices, Shift+click to start a new polygon. ```julia using MakieDraw, GLMakie, GeoJSON, GeoInterface # --- Basic polygon canvas (empty) --- figure = Figure() axis = Axis(figure[1, 1]) poly_canvas = GeometryCanvas{Polygon}(; figure, axis) display(figure) # Interactive: click to add vertices, Shift+click starts a new polygon ``` -------------------------------- ### Manage Canvases with CanvasSelect Source: https://context7.com/makieorg/makiedraw.jl/llms.txt Demonstrates how to initialize and manage multiple GeometryCanvas instances using CanvasSelect. New canvases can be added, and existing ones can be replaced. ```julia layers = Dict( :point => point_canvas, # AbstractCanvas accepted directly :line => line_canvas.active, # Observable{Bool} also accepted :poly => poly_canvas, :paint => paint_canvas, ) cs = CanvasSelect(figure[2, 1]; layers) # Dynamically add a new canvas after creation new_canvas = GeometryCanvas{Polygon}(; figure, axis, name=:poly2) push!(cs, :poly2 => new_canvas) # Replace an existing entry replacement = GeometryCanvas{Point2}(; figure, axis) cs[:point] = replacement display(figure) ``` -------------------------------- ### Create Boolean Mask PaintCanvas Source: https://context7.com/makieorg/makiedraw.jl/llms.txt Initializes a PaintCanvas for boolean masks. Left-click fills with true, right-click with false. Requires GLMakie. ```julia using MakieDraw, GLMakie figure = Figure() axis = Axis(figure[1, 1]) # --- Boolean mask canvas (left click = true, right click = false) --- mask = falses(200, 200) paint_canvas = PaintCanvas(mask; figure, axis, fill_left = Observable(true), fill_right = Observable(false), ) display(figure) ``` -------------------------------- ### Create Float64 PaintCanvas with Custom Heatmap Renderer Source: https://context7.com/makieorg/makiedraw.jl/llms.txt Sets up a PaintCanvas for Float64 data with a custom heatmap rendering function. Allows interactive painting of continuous values. ```julia # --- Float64 canvas with custom heatmap renderer --- data = zeros(Float64, 100, 100) heatmap_canvas = PaintCanvas( (axis, xs, ys, v) -> heatmap!(axis, xs, ys, v; colormap=:viridis), data; figure, axis, fill_left = Observable(1.0), fill_right = Observable(0.0), fill_middle = Observable(0.5), ) ``` -------------------------------- ### Create RGB Color PaintCanvas Source: https://context7.com/makieorg/makiedraw.jl/llms.txt Initializes a PaintCanvas for RGB color painting. Allows interactive coloring of a matrix with specified fill colors. ```julia # --- RGB color painting --- using Colors color_data = fill(RGB(1.0, 1.0, 1.0), 100, 100) # white canvas color_canvas = PaintCanvas(color_data; figure, axis, fill_left = Observable(RGB(1.0, 0.0, 0.0)), # red fill_right = Observable(RGB(0.0, 0.0, 1.0)), # blue ) ``` -------------------------------- ### GeoInterface Integration with GeometryCanvas Source: https://context7.com/makieorg/makiedraw.jl/llms.txt Shows how GeometryCanvas implements GeoInterface.FeatureCollectionTrait, allowing it to be used with geo-aware packages. Features can be retrieved by index, and data can be round-tripped to GeoJSON. ```julia using MakieDraw, GLMakie, GeoInterface, GeoJSON figure = Figure(); axis = Axis(figure[1, 1]) labels = Observable(String[]) canvas = GeometryCanvas{Polygon}( figure, axis, properties = (; labels), propertynames = (:labels,) ) # GeoInterface trait inspection GeoInterface.isfeaturecollection(canvas) # true GeoInterface.nfeature(canvas) # number of drawn polygons # Retrieve feature i (geometry + properties) feature = GeoInterface.getfeature(GeoInterface.trait(canvas), canvas, 1) GeoInterface.geometry(feature) # the Polygon GeoInterface.properties(feature) # NamedTuple of properties # Round-trip to GeoJSON polygons = GeoInterface.convert.(Ref(GeoInterface), canvas.geoms[]) GeoJSON.write("drawn.geojson", GeoInterface.MultiPolygon(polygons)) # Reload from file and continue editing loaded = collect(GeoInterface.getgeom(GeoJSON.read(read("drawn.geojson")))) canvas2 = GeometryCanvas(loaded; figure, axis) ``` -------------------------------- ### Enable Arrow Key Navigation for Panning Source: https://context7.com/makieorg/makiedraw.jl/llms.txt Attaches keyboard arrow-key listeners to a figure for mouse-free axis panning. The pan step automatically scales with the current axis limits. ```julia using MakieDraw, GLMakie figure = Figure() axis = Axis(figure[1, 1]) # Draw some background data heatmap!(axis, rand(50, 50)) # Attach arrow-key panning MakieDraw.arrow_key_navigation(figure, axis) poly_canvas = GeometryCanvas{Polygon}(; figure, axis) display(figure) # Now use ← ↑ → ↓ to pan while drawing polygons ``` -------------------------------- ### Load and Edit Existing Geometries with GeometryCanvas Source: https://context7.com/makieorg/makiedraw.jl/llms.txt Loads existing geometries from a GeoJSON file into a GeometryCanvas for editing. Requires GeoJSON and GeoInterface packages. ```julia # --- Load existing geometries and edit them --- raw = GeoJSON.read(read("regions.geojson")) existing = collect(GeoInterface.getgeom(GeoJSON.read(read("regions.geojson")))) poly_canvas2 = GeometryCanvas(existing; figure, axis) ``` -------------------------------- ### Point Canvas with Per-Point Properties Source: https://context7.com/makieorg/makiedraw.jl/llms.txt Creates a GeometryCanvas for points with associated properties, such as categories. Properties are updated reactively using Observables and can be visualized using scatter plots. ```julia # --- Point canvas with per-point properties (category 0, 1, or 2 via mouse button) --- categories = Observable(Int[]) point_canvas = GeometryCanvas{Point2}(; figure, axis, properties = (; categories), mouse_property = :categories, scatter_kw = (; color=categories, colorrange=(0, 2), colormap=:spring), ) ``` -------------------------------- ### Access GeometryCanvas Data via Tables.jl Source: https://context7.com/makieorg/makiedraw.jl/llms.txt Demonstrates accessing geometry data from a GeometryCanvas using the Tables.jl interface. This allows compatibility with other Julia data packages. ```julia # --- Access via Tables.jl interface --- using Tables cols = Tables.columns(poly_canvas2) # :geometry column + any property columns geom_col = Tables.getcolumn(poly_canvas2, :geometry) ``` -------------------------------- ### Export Drawn Polygons to GeoJSON Source: https://context7.com/makieorg/makiedraw.jl/llms.txt Exports drawn polygons from a GeometryCanvas to a GeoJSON file. Requires GeoInterface.jl for conversion. ```julia # --- Export drawn polygons to GeoJSON --- polygons = GeoInterface.convert.(Ref(GeoInterface), poly_canvas.geoms[]) mp = GeoInterface.MultiPolygon(polygons) GeoJSON.write("output.geojson", mp) ``` -------------------------------- ### Read Painted Data from PaintCanvas Source: https://context7.com/makieorg/makiedraw.jl/llms.txt Retrieves the current state of the painted data from a PaintCanvas as a standard Julia Matrix. ```julia # --- Read painted data back --- result_matrix = heatmap_canvas.data[] # Plain Julia Matrix{Float64} ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.