In Julia, drawing and manipulating shapes is primarily accomplished through two popular ecosystems depending on your end goal: Plots.jl for data-driven geometric shapes or Luxor.jl for procedural 2D vector graphics. 1. Data-Driven Shapes with Plots.jl
Plots.jl uses a Shape object defined by a set of (x, y) vertices. This is ideal if you want your shapes to live inside a coordinate system alongside mathematical data. Drawing Basic Shapes
You create custom geometry by passing a list of X and Y coordinates to Shape.
using Plots # Define a rectangle function using the Shape object # The dot (x .+) broadcasts operations element-wise across arrays rectangle(w, h, x, y) = Shape(x .+ [0, w, w, 0], y .+ [0, 0, h, h]) # Draw a static canvas line plot, then overlay the shape plot(0:10, 0:10, legend=false) plot!(rectangle(4, 2, 2, 3), opacity=0.5, color=:blue) Use code with caution. Shape Manipulation (Translation & Scaling)
Because a Plots.jl shape is essentially a collection of coordinate arrays, you manipulate it by broadcasting arithmetic translations directly to its properties:
# Create a base shape my_shape = rectangle(2, 2, 0, 0) # Translate (shift) the shape by adding scalars to its x and y fields shifted_shape = Shape(my_shape.x .+ 3, my_shape.y .+ 5) # Scale (resize) the shape by multiplying its vectors scaled_shape = Shape(my_shape.x .2, my_shape.y .* 2) # Plot the mutated results plot!([shifted_shape, scaled_shape], color=[:red :green]) Use code with caution. 2. Procedural Vector Graphics with Luxor.jl
For graphic design, diagrams, and precise vector layouts, Luxor.jl provides a cleaner, faster procedural workflow over standard wrappers like Cairo. Drawing Shapes
Luxor uses macros like @draw or @drawsvg to render shapes instantly inside coding tools like VS Code or Pluto notebooks.
using Luxor # Render a simple 400x400 SVG image @drawsvg begin background(“white”) origin() # Moves coordinate system (0,0) to center of canvas setcolor(“purple”) circle(Point(0, 0), 50, action=:fill) # Fills a circle at center setcolor(“orange”) setline(4) # Sets border stroke thickness box(Point(60, 60), 80, 80, action=:stroke) # Draws a square outline end 400 400 Use code with caution. Native Matrix Manipulations (Transforms)
Luxor provides powerful, low-level affine coordinate transformations (translate, scale, and rotate), meaning you manipulate the underlying canvas frame rather than manually calculating the point arithmetic.
@drawsvg begin background(“black”) origin() setcolor(“cyan”) # Manipulation loop for i in 1:6 scale(0.85) # Shrinks the coordinate grid cumulatively rotate(π/6) # Rotates the grid by 30 degrees translate(20, 10) # Shifts the grid forward box(O, 100, 100, action=:stroke) # Draws a square at the mutated frame origin end end 500 500 Use code with caution. Core Syntax Comparison
Leave a Reply