plotgraphicsjuliapixelline-plot

Plotting points in a pixel grid on Julia


I am using this algorithm to check if it gives sequential pixel-points while plotting a line between the points (1,1) and (4,13):

using Plots
function plotline(x1,y1,x2,y2)
    a=(x2-x1)/(y2-y1)
    c=(x2*y1-x1*y2)/(y2-y1)
    y=collect(y1:y2)
    x=y.*a
    x=round.(x.-c)
    display(plot(x,y,label="plotline",shape=:circle, color=:red,))
    #println(x)

end

plotline(1,1,4,13)

The plot command gives me a continous line which is not really helpful. I am wondering if there is a way to plot the points somewhat like this: Grid Example

My first idea was if I could somehow turn it into a kind of heatmap but I am not really used to them. Any ideas?


Solution

  • You can indeed use heatmap to visualize -- how about this? Haven't fully checked all edge cases (i.e. this assumes x2>x1 and y2>y1) but it should be a good starting point...fun problem! Seems like the kind of thing computer graphics do under the hood all the time to figure out which pixels to light up.

    using Plots
    x1 = 1; y1 = 1; x2 = 4; y2 = 13; pixSize=1
    function genPixelLine(x1,y1,x2,y2,pixSize=1)
        m = (y2-y1)/(x2-x1); b = y2-m*x2 #slope and intercept of line
        xline = x1:x2; line = m.*xline.+b #line itself
        xpix = x1:pixSize:x2; ypix = y1:pixSize:y2 #pixel centers
        pixels = zeros(length(xpix),length(ypix)) #initialize pixel grid
        xMins = xpix.-(pixSize/2); xMaxs = xpix.+(pixSize/2) #bounding edges in x
        for (yBin,yp) in enumerate(ypix) #go through bounding horizontal lines
            yMin = yp-pixSize/2; yMax = yp+pixSize/2 #top and bottom bounds
            xMin = (yMin-b)/m; xMax = (yMax-b)/m #x values at top and bottom bounds
            xBins = (xMax.>xMins) .&& (xMin.<=xMaxs) #we want the maximum x to greater than the minimum bounding line in x and vice versa
            pixels[xBins,yBin] .= 1.0 #light pixel up where conditions are satisfied
        end
        return (xpix,ypix,pixels),(xline,line)
    end
            
    pix,l = genPixelLine(x1,y1,x2,y2,pixSize)
    heatmap(pix[1],pix[2],pix[3]',colorbar=false) #note have to plot transpose because of how heatmap works internally, pix[1] and pix[2] are the 1D x and y arrays of pixel centers
    plot!(l[1],l[2],lw=2,label="line")
    vline!([pix[1].-pixSize/2,pix[1].+pixSize/2],label="",c=:purple) #visualize the bounding boxes the function calculated to determine which cells to light up
    hline!([pix[2].-pixSize/2,pix[2].+pixSize/2],c=:purple,label="pixel edges")
    plot!(widen=false,tickdirection=:out,aspect_ratio=:equal,
        xlims=(x1-pixSize/2,x2+pixSize/2),ylims=(y1-pixSize/2,y2+pixSize/2),
        legend=:outerright,xlabel="x",ylabel="y",size=(600,800))
    

    Outputs the following plot: pixelated line