#include #include #include "draw.h" int round (double x) { if ((x - (int) x) > 0.5) return (int) (x + 1); else return (int) x; } void findEdges (int x0, int y0, int x1, int y1, int* left, int* right, int bot) { int dx = abs(x1 - x0); int dy = abs(y1 - y0); if (dy == 0) return; if (dx == 0) { if (y1 < y0) { swapint(x0,x1); swapint(y0,y1); } for (int i = 0, y = y0; y <= y1; i++, y++) { if (right[y-bot] == -1) right[y-bot] = x0; else if (left[y-bot] == -1) left[y-bot] = x0; else if (x0 < left[y-bot]) left[y-bot] = x0; else if (x0 > right[y-bot]) right[y-bot] = x0; if (right[y-bot] < left[y-bot]) swapint(left[y-bot], right[y-bot]); } return; } double m = (y1 - y0) / (double) (x1 - x0); double b = y0 - m*x0; if (dx > dy) { if (x1 < x0) { swapint(x0,x1); swapint(y0,y1); } int y; for (int i = 0, x = x0; x <= x1; i++, x++) { y = round(m*x + b); if (right[y-bot] == -1) right[y-bot] = x; else if (left[y-bot] == -1) left[y-bot] = x; else if (x < left[y-bot]) left[y-bot] = x; else if (x > right[y-bot]) right[y-bot] = x; if (right[y-bot] < left[y-bot]) swapint(left[y-bot], right[y-bot]); } } else { if (y1 < y0) { swapint(x0,x1); swapint(y0,y1); } int x; for (int i = 0, y = y0; y <= y1; i++, y++) { x = round((y - b) / m); if (right[y-bot] == -1) right[y-bot] = x; else if (left[y-bot] == -1) left[y-bot] = x; else if (x < left[y-bot]) left[y-bot] = x; else if (x > right[y-bot]) right[y-bot] = x; if (right[y-bot] < left[y-bot]) swapint(left[y-bot], right[y-bot]); } } } void drawHLine (Image* dst, int y, int x0, int x1, Pixel& p) { if ((y < 0) || (y >= dst->getHeight())) return; if ((x0 < 0) || (x1 < 0) || (x0 >= dst->getWidth()) || (x1 >= dst->getWidth())) return; for (int x = x0; x <= x1; x++) dst->setPixel(x, y, p); } void drawQuad (Image* dst, point i, point j, point k, point l, Pixel& p) { int x0 = i.x; int y0 = i.y; int x1 = j.x; int y1 = j.y; int x2 = k.x; int y2 = k.y; int x3 = l.x; int y3 = l.y; int top = max4(y0,y1,y2,y3); int bot = min4(y0,y1,y2,y3); int height = top - bot + 1; int* left = new int[height]; int* right = new int[height]; for (int i = 0; i < height; i++) { left[i] = -1; right[i] = -1; } findEdges(x0, y0, x1, y1, left, right, bot); findEdges(x1, y1, x2, y2, left, right, bot); findEdges(x2, y2, x3, y3, left, right, bot); findEdges(x3, y3, x0, y0, left, right, bot); for (int i = 0; i < height; i++) drawHLine(dst, bot+i, left[i], right[i], p); delete[] left; delete[] right; } void drawPoly (Image* dst, point* pts, int n, Pixel& p) { int top = 0; int bot = 0; for (int i = 0; i < n; i++) { top = max(top, pts[i].y); bot = max(top, pts[i].y); } int height = top - bot + 1; int* left = new int[height]; int* right = new int[height]; for (int i = 0; i < height; i++) { left[i] = -1; right[i] = -1; } for (int i = 0; i < n; i++) findEdges(pts[i].x, pts[i].y, pts[(i+1)%n].x, pts[(i+1)%n].y, left, right, bot); for (int i = 0; i < height; i++) drawHLine(dst, bot+i, left[i], right[i], p); delete[] left; delete[] right; } void drawCircle(Image* img, int x, int y, int r, Pixel& p) { int left = x - r; int right = x + r; int top = y - r; int bottom = y + r; left = clamp(left, 0, img->getWidth() - 1); right = clamp(right, 0, img->getWidth() - 1); top = clamp(top, 0, img->getHeight() - 1); bottom = clamp(bottom, 0, img->getHeight() - 1); for (int i = left; i <= right; i++) for (int j = top; j <= bottom; j++) if (((i-x)*(i-x) + (j-y)*(j-y)) <= sqr(r)) img->setPixel(i,j,p); } void drawAntiAliasedCircle(Image* img, int x, int y, int r, Pixel& p) { double e = 0.7; int left = x - r; int right = x + r; int top = y - r; int bottom = y + r; left = clamp(left, 0, img->getWidth() - 1); right = clamp(right, 0, img->getWidth() - 1); top = clamp(top, 0, img->getHeight() - 1); bottom = clamp(bottom, 0, img->getHeight() - 1); for (int i = left; i <= right; i++) for (int j = top; j <= bottom; j++) if (((i-x)*(i-x) + (j-y)*(j-y)) <= sqr(r)) { img->setPixel(i,j,p); } else if (((i-x)*(i-x) + (j-y)*(j-y)) <= sqr(r+e)) { double a = (-r + sqrt(((double) (i-x)*(i-x) + (j-y)*(j-y)))) / e; Pixel q; img->getPixel(i,j,q); Pixel n; n.r = (1-a)*p.r + a*q.r; n.g = (1-a)*p.g + a*q.g; n.b = (1-a)*p.b + a*q.b; img->setPixel(i,j,n); } }