I Like Algebra
I Like Algebra

Reputation: 25

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?

Upvotes: 1

Views: 130

Answers (1)

kirklong
kirklong

Reputation: 570

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

Upvotes: 0

Related Questions