Just another update
This commit is contained in:
parent
a25938f123
commit
00a190b0a6
6591 changed files with 94363 additions and 23227 deletions
|
|
@ -0,0 +1,105 @@
|
|||
#SingleInstance, Force
|
||||
#NoEnv
|
||||
SetBatchLines, -1
|
||||
|
||||
pToken := Gdip_Startup()
|
||||
global pBitmap := Gdip_CreateBitmap(500, 500)
|
||||
drawLine(100,50,400,400)
|
||||
Gdip_SaveBitmapToFile(pBitmap, A_ScriptDir "\linetest.png")
|
||||
Gdip_DisposeImage(pBitmap)
|
||||
Gdip_Shutdown(pToken)
|
||||
Run, % A_ScriptDir "\linetest.png"
|
||||
ExitApp
|
||||
|
||||
plot(x, y, c) {
|
||||
A := DecToBase(255 * c, 16)
|
||||
Gdip_SetPixel(pBitmap, x, y, "0x" A "000000")
|
||||
}
|
||||
|
||||
; integer part of x
|
||||
ipart(x) {
|
||||
return x // 1
|
||||
}
|
||||
|
||||
rnd(x) {
|
||||
return ipart(x + 0.5)
|
||||
}
|
||||
|
||||
; fractional part of x
|
||||
fpart(x) {
|
||||
if (x < 0)
|
||||
return 1 - (x - floor(x))
|
||||
return x - floor(x)
|
||||
}
|
||||
|
||||
rfpart(x) {
|
||||
return 1 - fpart(x)
|
||||
}
|
||||
|
||||
drawLine(x0,y0,x1,y1) {
|
||||
steep := abs(y1 - y0) > abs(x1 - x0)
|
||||
|
||||
if (steep) {
|
||||
temp := x0, x0 := y0, y0 := temp
|
||||
temp := x1, x1 := y1, y1 := temp
|
||||
}
|
||||
if (x0 > x1 then) {
|
||||
temp := x0, x0 := x1, x1 := temp
|
||||
temp := y0, y0 := y1, y1 := temp
|
||||
}
|
||||
|
||||
dx := x1 - x0
|
||||
dy := y1 - y0
|
||||
gradient := dy / dx
|
||||
|
||||
; handle first endpoint
|
||||
xend := rnd(x0)
|
||||
yend := y0 + gradient * (xend - x0)
|
||||
xgap := rfpart(x0 + 0.5)
|
||||
xpxl1 := xend ; this will be used in the main loop
|
||||
ypxl1 := ipart(yend)
|
||||
if (steep) {
|
||||
plot(ypxl1, xpxl1, rfpart(yend) * xgap)
|
||||
plot(ypxl1+1, xpxl1, fpart(yend) * xgap)
|
||||
}
|
||||
else {
|
||||
plot(xpxl1, ypxl1 , rfpart(yend) * xgap)
|
||||
plot(xpxl1, ypxl1+1, fpart(yend) * xgap)
|
||||
}
|
||||
intery := yend + gradient ; first y-intersection for the main loop
|
||||
|
||||
; handle second endpoint
|
||||
xend := rnd(x1)
|
||||
yend := y1 + gradient * (xend - x1)
|
||||
xgap := fpart(x1 + 0.5)
|
||||
xpxl2 := xend ;this will be used in the main loop
|
||||
ypxl2 := ipart(yend)
|
||||
if (steep) {
|
||||
plot(ypxl2 , xpxl2, rfpart(yend) * xgap)
|
||||
plot(ypxl2+1, xpxl2, fpart(yend) * xgap)
|
||||
}
|
||||
else {
|
||||
plot(xpxl2, ypxl2, rfpart(yend) * xgap)
|
||||
plot(xpxl2, ypxl2+1, fpart(yend) * xgap)
|
||||
}
|
||||
|
||||
; main loop
|
||||
while (x := xpxl1 + A_Index) < xpxl2 {
|
||||
if (steep) {
|
||||
plot(ipart(intery) , x, rfpart(intery))
|
||||
plot(ipart(intery)+1, x, fpart(intery))
|
||||
}
|
||||
else {
|
||||
plot(x, ipart (intery), rfpart(intery))
|
||||
plot(x, ipart (intery)+1, fpart(intery))
|
||||
}
|
||||
intery := intery + gradient
|
||||
}
|
||||
}
|
||||
|
||||
DecToBase(n, Base) {
|
||||
static U := A_IsUnicode ? "w" : "a"
|
||||
VarSetCapacity(S,65,0)
|
||||
DllCall("msvcrt\_i64to" U, "Int64",n, "Str",S, "Int",Base)
|
||||
return, S
|
||||
}
|
||||
|
|
@ -4,17 +4,19 @@ import std.math, std.algorithm, grayscale_image;
|
|||
void aaLine(Color)(ref Image!Color img,
|
||||
double x1, double y1,
|
||||
double x2, double y2,
|
||||
in Color color) /*pure*/ nothrow {
|
||||
in Color color) pure nothrow @safe @nogc {
|
||||
// Straight translation of Wikipedia pseudocode.
|
||||
static double round(in double x) pure nothrow {
|
||||
|
||||
// std.math.round is not pure. **
|
||||
static double round(in double x) pure nothrow @safe @nogc {
|
||||
return floor(x + 0.5);
|
||||
}
|
||||
|
||||
static double fpart(in double x) pure nothrow {
|
||||
static double fpart(in double x) pure nothrow @safe @nogc {
|
||||
return x - x.floor;
|
||||
}
|
||||
|
||||
static double rfpart(in double x) pure nothrow {
|
||||
static double rfpart(in double x) pure nothrow @safe @nogc {
|
||||
return 1 - fpart(x);
|
||||
}
|
||||
|
||||
|
|
@ -24,7 +26,7 @@ void aaLine(Color)(ref Image!Color img,
|
|||
immutable ay = dy.abs;
|
||||
|
||||
static Color mixColors(in Color c1, in Color c2, in double p)
|
||||
pure nothrow {
|
||||
pure nothrow @safe @nogc {
|
||||
static if (is(Color == RGB))
|
||||
return Color(cast(ubyte)(c1.r * p + c2.r * (1 - p)),
|
||||
cast(ubyte)(c1.g * p + c2.g * (1 - p)),
|
||||
|
|
@ -35,23 +37,23 @@ void aaLine(Color)(ref Image!Color img,
|
|||
}
|
||||
|
||||
// Plot function set here to handle the two cases of slope.
|
||||
void delegate(ref Image!Color img, in int, in int, in double)
|
||||
pure nothrow plot;
|
||||
void function(ref Image!Color, in int, in int, in double, in Color)
|
||||
pure nothrow @safe @nogc plot;
|
||||
|
||||
if (ax < ay) {
|
||||
swap(x1, y1);
|
||||
swap(x2, y2);
|
||||
swap(dx, dy);
|
||||
//plot = (img, x, y, p) {
|
||||
plot = (ref Image!Color img, x, y, p) {
|
||||
//plot = (img, x, y, p, col) {
|
||||
plot = (ref img, x, y, p, col) {
|
||||
assert(p >= 0.0 && p <= 1.0);
|
||||
img[y, x] = mixColors(color, img[y, x], p);
|
||||
img[y, x] = mixColors(col, img[y, x], p);
|
||||
};
|
||||
} else {
|
||||
//plot = (img, x, y, p) {
|
||||
plot = (ref Image!Color img, x, y, p) {
|
||||
//plot = (img, x, y, p, col) {
|
||||
plot = (ref img, x, y, p, col) {
|
||||
assert(p >= 0.0 && p <= 1.0);
|
||||
img[x, y] = mixColors(color, img[x, y], p);
|
||||
img[x, y] = mixColors(col, img[x, y], p);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -62,31 +64,31 @@ void aaLine(Color)(ref Image!Color img,
|
|||
immutable gradient = dy / dx;
|
||||
|
||||
// Handle first endpoint.
|
||||
auto xEnd = x1.round; // Not pure.
|
||||
auto xEnd = round(x1);
|
||||
auto yEnd = y1 + gradient * (xEnd - x1);
|
||||
auto xGap = rfpart(x1 + 0.5);
|
||||
// This will be used in the main loop.
|
||||
immutable xpxl1 = cast(int)xEnd;
|
||||
immutable ypxl1 = cast(int)yEnd.floor;
|
||||
plot(img, xpxl1, ypxl1, rfpart(yEnd) * xGap);
|
||||
plot(img, xpxl1, ypxl1 + 1, fpart(yEnd) * xGap);
|
||||
plot(img, xpxl1, ypxl1, rfpart(yEnd) * xGap, color);
|
||||
plot(img, xpxl1, ypxl1 + 1, fpart(yEnd) * xGap, color);
|
||||
// First y-intersection for the main loop.
|
||||
auto yInter = yEnd + gradient;
|
||||
|
||||
// Handle second endpoint.
|
||||
xEnd = x2.round;
|
||||
xEnd = round(x2);
|
||||
yEnd = y2 + gradient * (xEnd - x2);
|
||||
xGap = fpart(x2 + 0.5);
|
||||
// This will be used in the main loop.
|
||||
immutable xpxl2 = cast(int)xEnd;
|
||||
immutable ypxl2 = cast(int)yEnd.floor;
|
||||
plot(img, xpxl2, ypxl2, rfpart(yEnd) * xGap);
|
||||
plot(img, xpxl2, ypxl2 + 1, fpart(yEnd) * xGap);
|
||||
plot(img, xpxl2, ypxl2, rfpart(yEnd) * xGap, color);
|
||||
plot(img, xpxl2, ypxl2 + 1, fpart(yEnd) * xGap, color);
|
||||
|
||||
// Main loop.
|
||||
foreach (immutable x; xpxl1 + 1 .. xpxl2) {
|
||||
plot(img, x, cast(int)yInter.floor, rfpart(yInter));
|
||||
plot(img, x, cast(int)yInter.floor + 1, fpart(yInter));
|
||||
plot(img, x, cast(int)yInter.floor, rfpart(yInter), color);
|
||||
plot(img, x, cast(int)yInter.floor + 1, fpart(yInter), color);
|
||||
yInter += gradient;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
wd'pc win closeok; xywh 0 0 300 200;cc g isigraph; pas 0 0; pshow;' NB. J6 or earlier
|
||||
wd'pc win closeok; minwh 600 400;cc g isigraph; pas 0 0; pshow;' NB. J8 or later
|
||||
wd'pc win closeok; minwh 600 400;cc g isidraw flush; pshow;' NB. J802 or later
|
||||
glpaint glclear ''
|
||||
glpaint drawLine 10 10 590 390
|
||||
|
|
|
|||
|
|
@ -0,0 +1,122 @@
|
|||
program wu;
|
||||
uses
|
||||
SDL2,
|
||||
math;
|
||||
|
||||
const
|
||||
FPS = 1000 div 60;
|
||||
SCALE = 6;
|
||||
|
||||
var
|
||||
win: PSDL_Window;
|
||||
ren: PSDL_Renderer;
|
||||
mouse_x, mouse_y: longint;
|
||||
origin: TSDL_Point;
|
||||
event: TSDL_Event;
|
||||
line_alpha: byte = 255;
|
||||
|
||||
procedure SDL_RenderDrawWuLine(renderer: PSDL_Renderer; x1, y1, x2, y2: longint);
|
||||
var
|
||||
r, g, b, a, a_new: Uint8;
|
||||
gradient, iy: real;
|
||||
x, y: longint;
|
||||
px, py: plongint;
|
||||
|
||||
procedure swap(var a, b: longint);
|
||||
var
|
||||
tmp: longint;
|
||||
begin
|
||||
tmp := a;
|
||||
a := b;
|
||||
b := tmp;
|
||||
end;
|
||||
|
||||
begin
|
||||
if a = 0 then
|
||||
exit;
|
||||
SDL_GetRenderDrawColor(renderer, @r, @g, @b, @a);
|
||||
if abs(y2 - y1) > abs(x2 - x1) then
|
||||
begin
|
||||
swap(x1, y1);
|
||||
swap(x2, y2);
|
||||
px := @y;
|
||||
py := @x;
|
||||
end
|
||||
else
|
||||
begin
|
||||
px := @x;
|
||||
py := @y;
|
||||
end;
|
||||
if x1 > x2 then
|
||||
begin
|
||||
swap(x1, x2);
|
||||
swap(y1, y2);
|
||||
end;
|
||||
x := x2 - x1;
|
||||
if x = 0 then
|
||||
x := 1;
|
||||
gradient := (y2 - y1) / x;
|
||||
iy := y1;
|
||||
for x := x1 to x2 do
|
||||
begin
|
||||
a_new := round(a * frac(iy));
|
||||
y := floor(iy);
|
||||
SDL_SetRenderDrawColor(renderer, r, g, b, a-a_new);
|
||||
SDL_RenderDrawPoint(renderer, px^, py^);
|
||||
inc(y);
|
||||
SDL_SetRenderDrawColor(renderer, r, g, b, a_new);
|
||||
SDL_RenderDrawPoint(renderer, px^, py^);
|
||||
iy := iy + gradient;
|
||||
end;
|
||||
SDL_SetRenderDrawColor(renderer, r, g, b, a);
|
||||
end;
|
||||
|
||||
begin
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
win := SDL_CreateWindow('Xiaolin Wu''s line algorithm', SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
|
||||
640, 480, SDL_WINDOW_RESIZABLE);
|
||||
ren := SDL_CreateRenderer(win, -1, 0);
|
||||
if ren = NIL then
|
||||
begin
|
||||
writeln(SDL_GetError);
|
||||
halt;
|
||||
end;
|
||||
SDL_SetRenderDrawBlendMode(ren, SDL_BLENDMODE_BLEND);
|
||||
SDL_RenderSetScale(ren, SCALE, SCALE);
|
||||
SDL_SetCursor(SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_CROSSHAIR));
|
||||
|
||||
mouse_x := 0;
|
||||
mouse_y := 0;
|
||||
origin.x := 0;
|
||||
origin.y := 0;
|
||||
repeat
|
||||
while SDL_PollEvent(@event) = 1 do
|
||||
case event.type_ of
|
||||
SDL_KEYDOWN:
|
||||
if event.key.keysym.sym = SDLK_ESCAPE then
|
||||
halt;
|
||||
SDL_MOUSEBUTTONDOWN:
|
||||
begin
|
||||
origin.x := mouse_x;
|
||||
origin.y := mouse_y;
|
||||
end;
|
||||
SDL_MOUSEMOTION:
|
||||
with event.motion do
|
||||
begin
|
||||
mouse_x := x div SCALE;
|
||||
mouse_y := y div SCALE;
|
||||
end;
|
||||
SDL_MOUSEWHEEL:
|
||||
line_alpha := EnsureRange(line_alpha + event.wheel.y * 20, 0, 255);
|
||||
SDL_QUITEV:
|
||||
halt;
|
||||
end;
|
||||
|
||||
SDL_SetRenderDrawColor(ren, 35, 35, 35, line_alpha);
|
||||
SDL_RenderDrawWuLine(ren, origin.x, origin.y, mouse_x, mouse_y);
|
||||
SDL_RenderPresent(ren);
|
||||
SDL_SetRenderDrawColor(ren, 255, 255, 255, 255);
|
||||
SDL_RenderClear(ren);
|
||||
SDL_Delay(FPS);
|
||||
until false;
|
||||
end.
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
import java.awt.Color
|
||||
import math.{floor => ipart, round, abs}
|
||||
|
||||
case class Point(x: Double, y: Double) {def swap = Point(y, x)}
|
||||
|
||||
def plotter(bm: RgbBitmap, c: Color)(x: Double, y: Double, v: Double) = {
|
||||
val X = round(x).toInt
|
||||
val Y = round(y).toInt
|
||||
val V = v.toFloat
|
||||
// tint the existing pixels
|
||||
val c1 = c.getRGBColorComponents(null)
|
||||
val c2 = bm.getPixel(X, Y).getRGBColorComponents(null)
|
||||
val c3 = (c1 zip c2).map{case (n, o) => n * V + o * (1 - V)}
|
||||
bm.setPixel(X, Y, new Color(c3(0), c3(1), c3(2)))
|
||||
}
|
||||
|
||||
def drawLine(plotter: (Double,Double,Double) => _)(p1: Point, p2: Point) {
|
||||
def fpart(x: Double) = x - ipart(x)
|
||||
def rfpart(x: Double) = 1 - fpart(x)
|
||||
def avg(a: Float, b: Float) = (a + b) / 2
|
||||
|
||||
val steep = abs(p2.y - p1.y) > abs(p2.x - p1.x)
|
||||
val (p3, p4) = if (steep) (p1.swap, p2.swap) else (p1, p2)
|
||||
val (a, b) = if (p3.x > p4.x) (p4, p3) else (p3, p4)
|
||||
val dx = b.x - a.x
|
||||
val dy = b.y - a.y
|
||||
val gradient = dy / dx
|
||||
var intery = 0.0
|
||||
|
||||
def endpoint(xpxl: Double, yend: Double, xgap: Double) {
|
||||
val ypxl = ipart(yend)
|
||||
if (steep) {
|
||||
plotter(ypxl, xpxl, rfpart(yend) * xgap)
|
||||
plotter(ypxl+1, xpxl, fpart(yend) * xgap)
|
||||
} else {
|
||||
plotter(xpxl, ypxl , rfpart(yend) * xgap)
|
||||
plotter(xpxl, ypxl+1, fpart(yend) * xgap)
|
||||
}
|
||||
}
|
||||
|
||||
// handle first endpoint
|
||||
var xpxl1 = round(a.x);
|
||||
{
|
||||
val yend = a.y + gradient * (xpxl1 - a.x)
|
||||
val xgap = rfpart(a.x + 0.5)
|
||||
endpoint(xpxl1, yend, xgap)
|
||||
intery = yend + gradient
|
||||
}
|
||||
|
||||
// handle second endpoint
|
||||
val xpxl2 = round(b.x);
|
||||
{
|
||||
val yend = b.y + gradient * (xpxl2 - b.x)
|
||||
val xgap = fpart(b.x + 0.5)
|
||||
endpoint(xpxl2, yend, xgap)
|
||||
}
|
||||
|
||||
// main loop
|
||||
for (x <- (xpxl1 + 1) to (xpxl2 - 1)) {
|
||||
if (steep) {
|
||||
plotter(ipart(intery) , x, rfpart(intery))
|
||||
plotter(ipart(intery)+1, x, fpart(intery))
|
||||
} else {
|
||||
plotter(x, ipart (intery), rfpart(intery))
|
||||
plotter(x, ipart (intery)+1, fpart(intery))
|
||||
}
|
||||
intery = intery + gradient
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
val r = 120
|
||||
val img = new RgbBitmap(r*2+1, r*2+1)
|
||||
val line = drawLine(plotter(img, Color.GRAY)_)_
|
||||
img.fill(Color.WHITE)
|
||||
for (angle <- 0 to 360 by 30; θ = math toRadians angle; θ2 = θ + math.Pi) {
|
||||
val a = Point(r + r * math.sin(θ), r + r * math.cos(θ))
|
||||
val b = Point(r + r * math.sin(θ2), r + r * math.cos(θ2))
|
||||
line(a, b)
|
||||
}
|
||||
javax.imageio.ImageIO.write(img.image, "png", new java.io.File("XiaolinWuLineAlgorithm.png"))
|
||||
Loading…
Add table
Add a link
Reference in a new issue