106 lines
3.0 KiB
PHP
106 lines
3.0 KiB
PHP
|
|
/*adapted from :
|
|||
|
|
* http://rosettacode.org/wiki/Xiaolin_Wu%27s_line_algorithm#C
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
#define plot_(X, Y, D) \
|
|||
|
|
p.x = (X); \
|
|||
|
|
p.y = (Y); \
|
|||
|
|
if (p.x >= xmin && p.x <= xmax && p.y >= ymin && p.y <= ymax) { \
|
|||
|
|
color->rgba.a = (D)*0xff; \
|
|||
|
|
lcd_draw_points(lcd, &p, 1); \
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#define ipart_(X) ((int)(X))
|
|||
|
|
#define round_(X) ((int)(((double)(X)) + 0.5))
|
|||
|
|
#define fpart_(X) (((double)(X)) - (double)ipart_(X))
|
|||
|
|
#define rfpart_(X) (1.0 - fpart_(X))
|
|||
|
|
#define fabs(xx) ((xx) < 0 ? -(xx) : (xx))
|
|||
|
|
|
|||
|
|
#define swap_(a, b) \
|
|||
|
|
do { \
|
|||
|
|
unsigned int tmp = a; \
|
|||
|
|
a = b; \
|
|||
|
|
b = tmp; \
|
|||
|
|
} while (0)
|
|||
|
|
|
|||
|
|
void draw_line(canvas_t* c, int x1, int y1, int x2, int y2) {
|
|||
|
|
rect_t r;
|
|||
|
|
point_t p;
|
|||
|
|
lcd_t* lcd = c->lcd;
|
|||
|
|
xy_t xmin, xmax, ymin, ymax;
|
|||
|
|
color_t* color = &(c->lcd->stroke_color);
|
|||
|
|
double dx = (double)x2 - (double)x1;
|
|||
|
|
double dy = (double)y2 - (double)y1;
|
|||
|
|
canvas_get_clip_rect(c, &r);
|
|||
|
|
xmin = r.x;
|
|||
|
|
xmax = r.x + r.w - 1;
|
|||
|
|
ymin = r.y;
|
|||
|
|
ymax = r.y + r.h - 1;
|
|||
|
|
|
|||
|
|
if (fabs(dx) > fabs(dy)) {
|
|||
|
|
if (x2 < x1) {
|
|||
|
|
swap_(x1, x2);
|
|||
|
|
swap_(y1, y2);
|
|||
|
|
}
|
|||
|
|
double gradient = dy / dx;
|
|||
|
|
double xend = round_(x1);
|
|||
|
|
double yend = y1 + gradient * (xend - x1);
|
|||
|
|
double xgap = rfpart_(x1 + 0.5);
|
|||
|
|
int xpxl1 = xend;
|
|||
|
|
int ypxl1 = ipart_(yend);
|
|||
|
|
plot_(xpxl1, ypxl1, rfpart_(yend) * xgap);
|
|||
|
|
plot_(xpxl1, ypxl1 + 1, fpart_(yend) * xgap);
|
|||
|
|
double intery = yend + gradient;
|
|||
|
|
|
|||
|
|
xend = round_(x2);
|
|||
|
|
yend = y2 + gradient * (xend - x2);
|
|||
|
|
xgap = fpart_(x2 + 0.5);
|
|||
|
|
int xpxl2 = xend;
|
|||
|
|
int ypxl2 = ipart_(yend);
|
|||
|
|
plot_(xpxl2, ypxl2, rfpart_(yend) * xgap);
|
|||
|
|
plot_(xpxl2, ypxl2 + 1, fpart_(yend) * xgap);
|
|||
|
|
|
|||
|
|
int x;
|
|||
|
|
for (x = xpxl1 + 1; x <= (xpxl2 - 1); x++) {
|
|||
|
|
plot_(x, ipart_(intery), rfpart_(intery));
|
|||
|
|
plot_(x, ipart_(intery) + 1, fpart_(intery));
|
|||
|
|
intery += gradient;
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
if (y2 < y1) {
|
|||
|
|
swap_(x1, x2);
|
|||
|
|
swap_(y1, y2);
|
|||
|
|
}
|
|||
|
|
double gradient = dx / dy;
|
|||
|
|
double yend = round_(y1);
|
|||
|
|
double xend = x1 + gradient * (yend - y1);
|
|||
|
|
double ygap = rfpart_(y1 + 0.5);
|
|||
|
|
int ypxl1 = yend;
|
|||
|
|
int xpxl1 = ipart_(xend);
|
|||
|
|
plot_(xpxl1, ypxl1, rfpart_(xend) * ygap);
|
|||
|
|
plot_(xpxl1, ypxl1 + 1, fpart_(xend) * ygap);
|
|||
|
|
double interx = xend + gradient;
|
|||
|
|
|
|||
|
|
yend = round_(y2);
|
|||
|
|
xend = x2 + gradient * (yend - y2);
|
|||
|
|
ygap = fpart_(y2 + 0.5);
|
|||
|
|
int ypxl2 = yend;
|
|||
|
|
int xpxl2 = ipart_(xend);
|
|||
|
|
plot_(xpxl2, ypxl2, rfpart_(xend) * ygap);
|
|||
|
|
plot_(xpxl2, ypxl2 + 1, fpart_(xend) * ygap);
|
|||
|
|
|
|||
|
|
int y;
|
|||
|
|
for (y = ypxl1 + 1; y <= (ypxl2 - 1); y++) {
|
|||
|
|
plot_(ipart_(interx), y, rfpart_(interx));
|
|||
|
|
plot_(ipart_(interx) + 1, y, fpart_(interx));
|
|||
|
|
interx += gradient;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
#undef swap_
|
|||
|
|
#undef plot_
|
|||
|
|
#undef ipart_
|
|||
|
|
#undef fpart_
|
|||
|
|
#undef round_
|
|||
|
|
#undef rfpart_
|