Just another update

This commit is contained in:
Ingy döt Net 2015-02-20 00:35:01 -05:00
parent a25938f123
commit 00a190b0a6
6591 changed files with 94363 additions and 23227 deletions

View file

@ -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
}

View file

@ -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;
}
}

View file

@ -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

View file

@ -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.

View file

@ -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
}
}

View file

@ -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"))