82 lines
2.2 KiB
Nim
82 lines
2.2 KiB
Nim
import math
|
|
import imageman
|
|
|
|
template ipart(x: float): float = floor(x)
|
|
template fpart(x: float): float = x - ipart(x)
|
|
template rfpart(x: float): float = 1 - fpart(x)
|
|
|
|
const
|
|
BG = ColorRGBF64([0.0, 0.0, 0.0])
|
|
FG = ColorRGBF64([1.0, 1.0, 1.0])
|
|
|
|
func plot(img: var Image; x, y: int; c: float) =
|
|
## Draw a point with brigthness c.
|
|
let d = 1 - c
|
|
img[x, y] = ColorRGBF64([BG.r * d + FG.r * c, BG.g * d + FG.g * c, BG.b * d + FG.b * c])
|
|
|
|
|
|
func drawLine(img: var Image; x0, y0, x1, y1: float) =
|
|
## Draw an anti-aliased line from (x0, y0) to (x1, y1).
|
|
|
|
var (x0, y0, x1, y1) = (x0, y0, x1, y1)
|
|
let steep = abs(y1 - y0) > abs(x1 - x0)
|
|
if steep:
|
|
swap x0, y0
|
|
swap x1, y1
|
|
if x0 > x1:
|
|
swap x0, x1
|
|
swap y0, y1
|
|
|
|
let dx = x1 - x0
|
|
let dy = y1 - y0
|
|
var gradient = dy / dx
|
|
if dx == 0:
|
|
gradient = 1
|
|
|
|
# Handle first endpoint.
|
|
var xend = round(x0)
|
|
var yend = y0 + gradient * (xend - x0)
|
|
var xgap = rfpart(x0 + 0.5)
|
|
let xpxl1 = xend.toInt
|
|
let ypxl1 = yend.toInt
|
|
if steep:
|
|
img.plot(ypxl1, xpxl1, rfpart(yend) * xgap)
|
|
img.plot(ypxl1 + 1, xpxl1, fpart(yend) * xgap)
|
|
else:
|
|
img.plot(xpxl1, ypxl1, rfpart(yend) * xgap)
|
|
img.plot(xpxl1, ypxl1 + 1, fpart(yend) * xgap)
|
|
var intery = yend + gradient # First y-intersection for the main loop.
|
|
|
|
# Handle second endpoint.
|
|
xend = round(x1)
|
|
yend = y1 + gradient * (xend - x1)
|
|
xgap = fpart(x1 + 0.5)
|
|
let xpxl2 = xend.toInt
|
|
let ypxl2 = yend.toInt
|
|
if steep:
|
|
img.plot(ypxl2, xpxl2, rfpart(yend) * xgap)
|
|
img.plot(ypxl2 + 1, xpxl2, fpart(yend) * xgap)
|
|
else:
|
|
img.plot(xpxl2, ypxl2, rfpart(yend) * xgap)
|
|
img.plot(xpxl2, ypxl2 + 1, fpart(yend) * xgap)
|
|
|
|
# Main loop.
|
|
if steep:
|
|
for x in (xpxl1 + 1)..(xpxl2 - 1):
|
|
img.plot(intery.int, x, rfpart(intery))
|
|
img.plot(intery.int + 1, x, fpart(intery))
|
|
intery += gradient
|
|
else:
|
|
for x in (xpxl1 + 1)..(xpxl2 - 1):
|
|
img.plot(x, intery.int, rfpart(intery))
|
|
img.plot(x, intery.int + 1, fpart(intery))
|
|
intery += gradient
|
|
|
|
|
|
when isMainModule:
|
|
var img = initImage[ColorRGBF64](800, 800)
|
|
img.fill(BG)
|
|
for x1 in countup(100, 700, 60):
|
|
img.drawLine(400, 700, x1.toFloat, 100)
|
|
img.savePNG("xiaoling_wu.png", compression = 9)
|