LineBlog
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "Line.h" | |
#include <cmath> | |
#include <iostream> | |
inline int max(int a, int b) { | |
if (a > b) { | |
return a; | |
} | |
return b; | |
} | |
inline void swap(int& a, int& b) { | |
int tmp = a; | |
a = b; | |
b = tmp; | |
} | |
void PutPixel(MonoImage& image, int x, int y, unsigned char val) { | |
#if _DEBUG | |
if (y * image.width + x > image.width * image.height) { | |
std::cout << "About to break\n"; | |
} | |
#endif | |
image.data[y * image.width + x] = val; | |
} | |
void DrawLine_Reference(MonoImage& image, int x0, int y0, int x1, int y1, unsigned char val) { | |
int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1; | |
int dy = abs(y1 - y0), sy = y0 < y1 ? 1 : -1; | |
int err = (dx > dy ? dx : -dy); | |
while (PutPixel(image, x0, y0, val), x0 != x1 || y0 != y1) { | |
int e2 = err; | |
if (e2 > -dx << 1) { err -= dy; x0 += sx; } | |
if (e2 < dy << 1) { err += dx; y0 += sy; } | |
} | |
} | |
void DrawLine_Implicit_Real(MonoImage& image, int x0, int y0, int x1, int y1, unsigned char val) { | |
if (x0 == x1 && y0 == y1) { | |
PutPixel(image, x0, y0, val); | |
return; | |
} | |
float m = (x0 == x1) ? 0.0f : (float(y1 - y0) / float(x1 - x0)); | |
float b = float(y0) - m * float(x0); | |
int xStep = x0 < x1 ? 1 : -1; | |
int yStep = y0 < y1 ? 1 : -1; | |
if (abs(x1 - x0) > abs(y1 - y0)) { | |
for (int x = x0; x != x1 + xStep; x += xStep) { | |
float y = m * float(x) + b; | |
PutPixel(image, x, int(y + 0.5f), val); | |
} | |
} | |
else { | |
for (int y = y0; y != y1 + yStep; y += yStep) { | |
float x = (x0 == x1) ? float(x0) : ((float(y) - b) / m); | |
PutPixel(image, int(x + 0.5f), y, val); | |
} | |
} | |
} | |
void DrawLine_Incremental_Real(MonoImage& image, int x0, int y0, int x1, int y1, unsigned char val) { | |
if (x0 == x1 && y0 == y1) { | |
PutPixel(image, x0, y0, val); | |
return; | |
} | |
float m = (x0 == x1) ? 0.0f : (float(y1 - y0) / float(x1 - x0)); | |
float changeX = (y0 == y1) ? 0.0f : (float(x1 - x0) / float(y1 - y0)); | |
int xStep = x0 < x1 ? 1 : -1; | |
int yStep = y0 < y1 ? 1 : -1; | |
if (abs(x1 - x0) > abs(y1 - y0)) { | |
float y = float(y0); | |
for (int x = x0; x != x1 + xStep; x += xStep) { | |
PutPixel(image, x, int(y), val); | |
y += m * xStep; | |
} | |
} | |
else { | |
float x = float(x0); | |
for (int y = y0; y != y1 + yStep; y += yStep) { | |
PutPixel(image, int(x), y, val); | |
x += changeX * yStep; | |
} | |
} | |
} | |
void DrawLine_DDA_Real(MonoImage& image, int x0, int y0, int x1, int y1, unsigned char val) { | |
if (x0 == x1 && y0 == y1) { | |
PutPixel(image, x0, y0, val); | |
return; | |
} | |
float xDelta = float(x1 - x0); | |
float yDelta = float(y1 - y0); | |
int steps = max(abs(x1 - x0), abs(y1 - y0)); | |
float xStep = xDelta / float(steps); | |
float yStep = yDelta / float(steps); | |
float x = float(x0); | |
float y = float(y0); | |
for (int i = 0; i <= steps; ++i) { | |
PutPixel(image, (int)(x), (int)(y), val); | |
y += yStep; | |
x += xStep; | |
} | |
} | |
void DrawLine_DDA_Int(MonoImage& image, int x0, int y0, int x1, int y1, unsigned char val) { | |
if (x0 == x1 && y0 == y1) { | |
PutPixel(image, x0, y0, val); | |
return; | |
} | |
int xDelta = x1 - x0; | |
int yDelta = y1 - y0; | |
int steps = max(abs(x1 - x0), abs(y1 - y0)); | |
// rational number x | |
int xWhole = x0; | |
int xNumerator = 0; | |
int xDenominator = steps; | |
// rational number y | |
int yWhole = y0; | |
int yNumerator = 0; | |
int yDenominator = steps; | |
for (int i = 0; i <= steps; ++i) { | |
PutPixel(image, xWhole, yWhole, val); | |
xNumerator += xDelta; | |
if (xNumerator >= xDenominator) { | |
xWhole += 1; | |
xNumerator -= xDenominator; | |
} | |
else if (xNumerator < 0) { | |
xWhole -= 1; | |
xNumerator += xDenominator; | |
} | |
yNumerator += yDelta; | |
if (yNumerator >= yDenominator) { | |
yWhole += 1; | |
yNumerator -= yDenominator; | |
} | |
else if (yNumerator < 0) { | |
yWhole -= 1; | |
yNumerator += yDenominator; | |
} | |
} | |
} | |
void DrawLine_DDA_Int_Shorter(MonoImage& image, int x0, int y0, int x1, int y1, unsigned char val) { | |
if (x0 == x1 && y0 == y1) { | |
PutPixel(image, x0, y0, val); | |
return; | |
} | |
int absXDelta = abs(x1 - x0); | |
int absYDelta = abs(y1 - y0); | |
int steps = max(absXDelta, absYDelta); | |
int xDir = x0 < x1 ? 1 : -1; | |
int yDir = y0 < y1 ? 1 : -1; | |
int x = x0, xNumerator = 0; | |
int y = y0, yNumerator = 0; | |
for (int i = 0; i <= steps; ++i) { | |
PutPixel(image, x, y, val); | |
xNumerator += absXDelta; | |
if (xNumerator >= steps) { | |
x += xDir; | |
xNumerator -= steps; | |
} | |
yNumerator += absYDelta; | |
if (yNumerator >= steps) { | |
y += yDir; | |
yNumerator -= steps; | |
} | |
} | |
} | |
void DrawLine_Error_Real(MonoImage& image, int x0, int y0, int x1, int y1, unsigned char val) { | |
float abs_m = (x0 == x1) ? 0.0f : fabsf(float(y1 - y0) / float(x1 - x0)); | |
float abs_cx = (y0 == y1) ? 0.0f : fabsf(float(x1 - x0) / float(y1 - y0)); | |
int xStep = x0 < x1 ? 1 : -1; | |
int yStep = y0 < y1 ? 1 : -1; | |
float error = 0.0f; | |
#if 1 | |
if (abs(x1 - x0) > abs(y1 - y0)) { | |
float y = float(y0); | |
for (int x = x0; x != x1 + xStep; x += xStep) { | |
PutPixel(image, x, int(y + 0.5f), val); | |
error += abs_m; | |
if (error >= 0.5f) { | |
y += float(yStep); | |
error -= 1.0f; | |
} | |
} | |
} | |
else { | |
float x = float(x0); | |
for (int y = y0; y != y1 + yStep; y += yStep) { | |
PutPixel(image, int(x + 0.5f), y, val); | |
error += abs_cx; | |
if (error >= 0.5f) { | |
x += float(xStep); | |
error -= 1.0f; | |
} | |
} | |
} | |
#else | |
bool steep = abs(x1 - x0) > abs(y1 - y0); | |
int steps = max(abs(x1 - x0), abs(y1 - y0)); | |
float y = float(y0); | |
float x = float(x0); | |
for (int step = 0; step <= steps; ++step) { | |
PutPixel(image, int(x + 0.5f), int(y + 0.5f), val); | |
if (steep) { | |
x += float(xStep); | |
error += abs_m; | |
if (error >= 0.5f) { | |
y += float(yStep); | |
error -= 1.0f; | |
} | |
} | |
else { | |
y += float(yStep); | |
error += abs_cx; | |
if (error >= 0.5f) { | |
x += float(xStep); | |
error -= 1.0f; | |
} | |
} | |
} | |
#endif | |
} | |
void DrawLine_Error_Int(MonoImage& image, int x0, int y0, int x1, int y1, unsigned char val) { | |
int dx = abs(x1 - x0); | |
int dy = abs(y1 - y0); | |
int xStep = x0 < x1 ? 1 : -1; | |
int yStep = y0 < y1 ? 1 : -1; | |
int error = 0; | |
#if 1 | |
if (dx > dy) { | |
int m = 2 * dy; | |
int scale = 2 * dx; | |
for (int x = x0, y = y0; x != x1 + xStep; x += xStep) { | |
PutPixel(image, x, y, val); | |
error += m; | |
if (error >= dx) { | |
y += yStep; | |
error -= scale; | |
} | |
} | |
} | |
else { | |
int m = 2 * dx; | |
int scale = 2 * dy; | |
for (int y = y0, x = x0; y != y1 + yStep; y += yStep) { | |
PutPixel(image, x, y, val); | |
error += m; | |
if (error >= dy) { | |
x += xStep; | |
error -= scale; | |
} | |
} | |
} | |
#else | |
bool steep = dx > dy; | |
int steps = max(dx, dy); | |
int y = y0; | |
int x = x0; | |
int m = 2 * dx; | |
int scale = 2 * dy; | |
if (steep) { | |
m = 2 * dy; | |
scale = 2 * dx; | |
} | |
for (int step = 0; step <= steps; ++step) { | |
PutPixel(image, x, y, val); | |
if (steep) { | |
x += xStep; | |
error += m; | |
if (error >= dx) { | |
y += yStep; | |
error -= scale; | |
} | |
} | |
else { | |
y += yStep; | |
error += m; | |
if (error >= dy) { | |
x += xStep; | |
error -= scale; | |
} | |
} | |
} | |
#endif | |
} | |
void DrawLine_Midpoint_Implicit_Real(MonoImage& image, int x0, int y0, int x1, int y1, unsigned char val) { | |
#if 0 | |
float m = (x0 == x1) ? 0.0f : (float(y1 - y0) / float(x1 - x0)); | |
float b = float(y0) - m * float(x0); | |
float A = float(y1 - y0); | |
float B = -float(x1 - x0); | |
float C = b * float(x1 - x0); | |
int y = y0; | |
for (int x = x0; x <= x1; x += 1) { | |
PutPixel(image, x, y, val); | |
float d = A * float(x + 1) + B * (float(y) + 0.5f) + C; | |
if (d >= 0) { | |
y += 1; | |
} | |
} | |
#else | |
bool steep = abs(y1 - y0) >= abs(x1 - x0); | |
if (!steep && x1 < x0) { | |
swap(x1, x0); | |
swap(y1, y0); | |
} | |
else if (steep && y1 < y0) { | |
swap(x1, x0); | |
swap(y1, y0); | |
} | |
float m = (x0 == x1) ? 0.0f : (float(y1 - y0) / float(x1 - x0)); | |
float b = float(y0) - m * float(x0); | |
float A = float(y1 - y0); | |
float B = -float(x1 - x0); | |
float C = b * float(x1 - x0); | |
int yStep = y1 < y0 ? -1 : 1; | |
int xStep = x1 < x0 ? -1 : 1; | |
if (!steep) { | |
float yHalf = y1 < y0 ? -0.5f : 0.5f; | |
for (int x = x0, y = y0; x <= x1; x += 1) { | |
PutPixel(image, x, y, val); | |
float d = A * float(x + 1) + B * (float(y) + yHalf) + C; | |
if (d * float(yStep) >= 0.0f) { | |
y += yStep; | |
} | |
} | |
} | |
else { | |
float xHalf = x1 < x0 ? -0.5f : 0.5f; | |
for (int x = x0, y = y0; y <= y1; y += 1) { | |
PutPixel(image, x, y, val); | |
float d = A * (float(x) + xHalf) + B * float(y + 1) + C; | |
if (d * float(xStep) < 0.0f) { | |
x += xStep; | |
} | |
} | |
} | |
#endif | |
} | |
void DrawLine_Thick(MonoImage& image, int x0, int y0, int x1, int y1, unsigned char val) { | |
int dx = abs(x1 - x0); | |
int dy = abs(y1 - y0); | |
int xStep = x0 < x1 ? 1 : -1; | |
int yStep = y0 < y1 ? 1 : -1; | |
int error = 0; | |
if (dx > dy) { | |
int m = 2 * dy; | |
int scale = 2 * dx; | |
for (int x = x0, y = y0; x != x1 + xStep; x += xStep) { | |
PutPixel(image, x, y, val); | |
PutPixel(image, x, y + yStep, val); | |
error += m; | |
if (error >= dx) { | |
y += yStep; | |
error -= scale; | |
} | |
} | |
} | |
else { | |
int m = 2 * dx; | |
int scale = 2 * dy; | |
for (int y = y0, x = x0; y != y1 + yStep; y += yStep) { | |
PutPixel(image, x, y, val); | |
PutPixel(image, x + xStep, y, val); | |
error += m; | |
if (error >= dy) { | |
x += xStep; | |
error -= scale; | |
} | |
} | |
} | |
} | |
void DrawLine_Thick_Brush(MonoImage& image, int x0, int y0, int x1, int y1, unsigned char val) { | |
if (x0 == x1 && y0 == y1) { | |
PutPixel(image, x0, y0, val); | |
return; | |
} | |
int absXDelta = abs(x1 - x0); | |
int absYDelta = abs(y1 - y0); | |
int steps = max(absXDelta, absYDelta); | |
int xDir = x0 < x1 ? 1 : -1; | |
int yDir = y0 < y1 ? 1 : -1; | |
int x = x0, xNumerator = 0; | |
int y = y0, yNumerator = 0; | |
for (int i = 0; i <= steps; ++i) { | |
PutPixel(image, x, y, val); | |
PutPixel(image, x + 1, y, val); | |
PutPixel(image, x + 1, y + 1, val); | |
PutPixel(image, x, y + 1, val); | |
PutPixel(image, x + 1, y, val); | |
PutPixel(image, x + 2, y, val); | |
PutPixel(image, x + 1, y + 1, val); | |
PutPixel(image, x + 1, y + 2, val); | |
PutPixel(image, x + 2, y + 2, val); | |
PutPixel(image, x, y + 1, val); | |
PutPixel(image, x, y + 2, val); | |
xNumerator += absXDelta; | |
if (xNumerator >= steps) { | |
x += xDir; | |
xNumerator -= steps; | |
} | |
yNumerator += absYDelta; | |
if (yNumerator >= steps) { | |
y += yDir; | |
yNumerator -= steps; | |
} | |
} | |
} | |
void DrawLine_Wu_Real(MonoImage& image, int x0, int y0, int x1, int y1, unsigned char val) { | |
float abs_m = (x0 == x1) ? 0.0f : fabsf(float(y1 - y0) / float(x1 - x0)); | |
float abs_cx = (y0 == y1) ? 0.0f : fabsf(float(x1 - x0) / float(y1 - y0)); | |
int xStep = x0 < x1 ? 1 : -1; | |
int yStep = y0 < y1 ? 1 : -1; | |
float error = 0.0f; | |
if (abs(x1 - x0) > abs(y1 - y0)) { | |
float y = float(y0); | |
for (int x = x0; x != x1 + xStep; x += xStep) { | |
float scale1 = 1.0f - fabsf(error); | |
float scale2 = 1.0f - scale1; | |
int errorStep = (error < 0.0f ? -1 : 1) * yStep; | |
PutPixel(image, x, int(y + 0.5f), (unsigned char)(float(val) * scale1)); | |
PutPixel(image, x, int(y + 0.5f) + errorStep, (unsigned char)(float(val) * scale2)); | |
error += abs_m; | |
if (error >= 0.5f) { | |
y += float(yStep); | |
error -= 1.0f; | |
} | |
} | |
} | |
else { | |
float x = float(x0); | |
for (int y = y0; y != y1 + yStep; y += yStep) { | |
float scale1 = 1.0f - fabsf(error); | |
float scale2 = 1.0f - scale1; | |
int errorStep = (error < 0.0f ? -1 : 1) * xStep; | |
PutPixel(image, int(x + 0.5f), y, (unsigned char)(float(val) * scale1)); | |
PutPixel(image, int(x + 0.5f) + errorStep, y, (unsigned char)(float(val) * scale2)); | |
error += abs_cx; | |
if (error >= 0.5f) { | |
x += float(xStep); | |
error -= 1.0f; | |
} | |
} | |
} | |
} | |
inline unsigned char GetClipCode(const Point& p, const Point& min, const Point& max) { | |
return ( | |
(p.x < min.x? 8 : 0) | (p.x > max.x? 4 : 0) | | |
(p.y < min.y? 2 : 0) | (p.y > max.y? 1 : 0) | |
); | |
} | |
// Returns true if the line is visible, false if it's outside of clip rect. | |
bool Clip_Line(Point& a, Point& b, const Point& min, const Point& max) { | |
unsigned char clipA = GetClipCode(a, min, max); | |
unsigned char clipB = GetClipCode(b, min, max); | |
float deltaX, deltaY; | |
while ((clipA | clipB) != 0) { // Loop until clipped | |
// Trivial reject case if both points are on | |
// the same side of a clip plane, we can reject them | |
if ((clipA & clipB) != 0) { | |
return false; | |
} | |
deltaX = b.x - a.x; | |
deltaY = b.y - a.y; | |
if (clipA != 0) { | |
if ((clipA & 8) == 8) { | |
a.y += (min.x - a.x) * deltaY / deltaX; | |
a.x = min.x; | |
} | |
else if ((clipA & 4) == 4) { | |
a.y += (max.x - a.x) * deltaY / deltaX; | |
a.x = max.x; | |
} | |
else if ((clipA & 2) == 2) { | |
a.x += (min.y - a.y) * deltaX / deltaY; | |
a.y = min.y; | |
} | |
else if ((clipA & 1) == 1) { | |
a.x += (max.y - a.y) * deltaX / deltaY; | |
a.y = max.y; | |
} | |
clipA = GetClipCode(a, min, max); | |
} | |
else if (clipB != 0) { | |
if ((clipB & 8) == 8) { | |
b.y += (min.x - b.x) * deltaY / deltaX; | |
b.x = min.x; | |
} | |
else if ((clipB & 4) == 4) { | |
b.y += (max.x - b.x) * deltaY / deltaX; | |
b.x = max.x; | |
} | |
else if ((clipB & 2) == 2) { | |
b.x += (min.y - b.y) * deltaX / deltaY; | |
b.y = min.y; | |
} | |
else if ((clipB & 1) == 1) { | |
b.x += (max.y - b.y) * deltaX / deltaY; | |
b.y = max.y; | |
} | |
clipB = GetClipCode(b, min, max); | |
} | |
} | |
return true; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
struct MonoImage { | |
unsigned char* data; | |
int width; | |
int height; | |
inline MonoImage() : data(0), width(0), height(0) { } | |
}; | |
struct Point { | |
float x; | |
float y; | |
inline Point() : x(0.0f), y(0.0f) { } | |
inline Point(float _x, float _y) : x(_x), y(_y) { } | |
inline Point(int _x, int _y) : x(_x), y(_y) { } | |
inline int xAsInt() { return x; } | |
inline int yAsInt() { return y; } | |
}; | |
typedef void (*fnDrawLine)(MonoImage& image, int x0, int y0, int x1, int y1, unsigned char val); | |
void PutPixel(MonoImage& image, int x, int y, unsigned char val); | |
void DrawLine_Reference(MonoImage& image, int x0, int y0, int x1, int y1, unsigned char val); | |
void DrawLine_Implicit_Real(MonoImage& image, int x0, int y0, int x1, int y1, unsigned char val); | |
void DrawLine_Incremental_Real(MonoImage& image, int x0, int y0, int x1, int y1, unsigned char val); | |
void DrawLine_DDA_Real(MonoImage& image, int x0, int y0, int x1, int y1, unsigned char val); | |
void DrawLine_DDA_Int(MonoImage& image, int x0, int y0, int x1, int y1, unsigned char val); | |
void DrawLine_DDA_Int_Shorter(MonoImage& image, int x0, int y0, int x1, int y1, unsigned char val); | |
void DrawLine_Error_Real(MonoImage& image, int x0, int y0, int x1, int y1, unsigned char val); | |
void DrawLine_Error_Int(MonoImage& image, int x0, int y0, int x1, int y1, unsigned char val); | |
void DrawLine_Midpoint_Implicit_Real(MonoImage& image, int x0, int y0, int x1, int y1, unsigned char val); | |
void DrawLine_Thick(MonoImage& image, int x0, int y0, int x1, int y1, unsigned char val); | |
void DrawLine_Thick_Brush(MonoImage& image, int x0, int y0, int x1, int y1, unsigned char val); | |
void DrawLine_Wu_Real(MonoImage& image, int x0, int y0, int x1, int y1, unsigned char val); | |
// Returns true if the line is visible, false if it's outside of clip rect. | |
bool Clip_Line(Point& a, Point& b, const Point& min, const Point& max); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define PI 3.14159265359f | |
#define STB_IMAGE_WRITE_IMPLEMENTATION | |
#include <Windows.h> | |
#include <iostream> | |
#include <limits> | |
#include <cmath> | |
#include "Line.h" | |
#include "stb_image_write.h" | |
#undef max | |
double ProfileDrawingMethod(fnDrawLine DrawLine, const char* output) { | |
LARGE_INTEGER timerFrequency; | |
if (!QueryPerformanceFrequency(&timerFrequency)) { | |
std::cout << "WinMain: QueryPerformanceFrequency failed\n"; | |
return 0.0; | |
} | |
MonoImage image; | |
image.width = 512; | |
image.height = 512; | |
image.data = new unsigned char[image.width * image.height]; | |
for (int x = 0; x < image.width; ++x) { | |
for (int y = 0; y < image.height; ++y) { | |
PutPixel(image, x, y, 42); | |
} | |
} | |
int val = 116; | |
LARGE_INTEGER timerStart = { 0 }; | |
LARGE_INTEGER timerStop = { 0 }; | |
QueryPerformanceCounter(&timerStart); | |
Point lineA, lineB; | |
Point clipMin = Point(150, 150); | |
Point clipMax = Point(image.width - 150, image.height - 150); | |
for (int angle = 0; angle < 360; angle += 1) { | |
float radians = float(angle) * 0.01745329; | |
float s = sinf(radians); | |
float c = cosf(radians); | |
if (angle % 10 == 0) { | |
lineA = Point(20.0f * s + 256.0f, 20.0f * c + 256.0f); | |
lineB = Point(60.0f * s + 256.0f, 60.0f * c + 256.0f); | |
if (Clip_Line(lineA, lineB, clipMin, clipMax)) { | |
DrawLine(image, lineA.xAsInt(), lineA.yAsInt(), lineB.xAsInt(), lineB.yAsInt(), val); | |
} | |
} | |
if (angle % 7 == 0) { | |
lineA = Point(70.0f * s + 256.0f, 70.0f * c + 256.0f); | |
lineB = Point(110.0f * s + 256.0f, 110.0f * c + 256.0f); | |
if (Clip_Line(lineA, lineB, clipMin, clipMax)) { | |
DrawLine(image, lineA.xAsInt(), lineA.yAsInt(), lineB.xAsInt(), lineB.yAsInt(), val); | |
} | |
} | |
if (angle % 4 == 0) { | |
lineA = Point(120.0f * s + 256.0f, 120.0f * c + 256.0f); | |
lineB = Point(160.0f * s + 256.0f, 160.0f * c + 256.0f); | |
if (Clip_Line(lineA, lineB, clipMin, clipMax)) { | |
DrawLine(image, lineA.xAsInt(), lineA.yAsInt(), lineB.xAsInt(), lineB.yAsInt(), val); | |
} | |
} | |
if (angle % 2 == 0) { | |
lineA = Point(170.0f * s + 256.0f, 170.0f * c + 256.0f); | |
lineB = Point(210.0f * s + 256.0f, 210.0f * c + 256.0f); | |
if (Clip_Line(lineA, lineB, clipMin, clipMax)) { | |
DrawLine(image, lineA.xAsInt(), lineA.yAsInt(), lineB.xAsInt(), lineB.yAsInt(), val); | |
} | |
} | |
lineA = Point(220.0f * s + 256.0f, 220.0f * c + 256.0f); | |
lineB = Point(250.0f * s + 256.0f, 250.0f * c + 256.0f); | |
if (Clip_Line(lineA, lineB, clipMin, clipMax)) { | |
DrawLine(image, lineA.xAsInt(), lineA.yAsInt(), lineB.xAsInt(), lineB.yAsInt(), val); | |
} | |
} | |
lineA = Point(256 - 15, 256); | |
lineB = Point(256 + 15, 256); | |
if (Clip_Line(lineA, lineB, clipMin, clipMax)) { | |
DrawLine(image, lineA.xAsInt(), lineA.yAsInt(), lineB.xAsInt(), lineB.yAsInt(), val); | |
} | |
lineA = Point(256, 256 - 15); | |
lineB = Point(256, 256 + 15); | |
if (Clip_Line(lineA, lineB, clipMin, clipMax)) { | |
DrawLine(image, lineA.xAsInt(), lineA.yAsInt(), lineB.xAsInt(), lineB.yAsInt(), val); | |
} | |
QueryPerformanceCounter(&timerStop); | |
LONGLONG timerDiff = timerStop.QuadPart - timerStart.QuadPart; | |
double ms = (double)timerDiff * 1000.0 / (double)timerFrequency.QuadPart; | |
int write_result = stbi_write_png(output, image.width, image.height, 1, image.data, 0); | |
if (write_result == 0) { | |
std::cout << "Error writing file: " << output << "\n"; | |
} | |
delete[] image.data; | |
return ms; | |
} | |
int main(int argc, char** argv) { | |
double time = ProfileDrawingMethod(DrawLine_Reference, "Line_Reference.png"); | |
std::cout << "DrawLine_Reference: " << time << " ms.\n"; | |
time = ProfileDrawingMethod(DrawLine_Implicit_Real, "Line_Implicit_Real.png"); | |
std::cout << "DrawLine_SlopeIntercept_Real: " << time << " ms.\n"; | |
time = ProfileDrawingMethod(DrawLine_Incremental_Real, "Line_Incremental_Real.png"); | |
std::cout << "Line_Incremental_Real: " << time << " ms.\n"; | |
time = ProfileDrawingMethod(DrawLine_DDA_Real, "Line_DDA_Real.png"); | |
std::cout << "DrawLine_DDA_Real: " << time << " ms.\n"; | |
time = ProfileDrawingMethod(DrawLine_DDA_Int_Shorter, "Line_DDA_Int_Shorter.png"); | |
std::cout << "DrawLine_DDA_Int: " << time << " ms.\n"; | |
time = ProfileDrawingMethod(DrawLine_Error_Real, "Line_Error_Real.png"); | |
std::cout << "DrawLine_Error_Real: " << time << " ms.\n"; | |
time = ProfileDrawingMethod(DrawLine_Error_Int, "Line_Error_Int.png"); | |
std::cout << "DrawLine_Error_Int: " << time << " ms.\n"; | |
time = ProfileDrawingMethod(DrawLine_Midpoint_Implicit_Real, "Line_Midpoint_Implicit_Real.png"); | |
std::cout << "DrawLine_Midpoint_Real: " << time << " ms.\n"; | |
time = ProfileDrawingMethod(DrawLine_Thick, "Line_Thick.png"); | |
std::cout << "DrawLine_Thick: " << time << " ms.\n"; | |
time = ProfileDrawingMethod(DrawLine_Thick_Brush, "Line_Thick_Brush.png"); | |
std::cout << "DrawLine_Thick_Brush: " << time << " ms.\n"; | |
time = ProfileDrawingMethod(DrawLine_Wu_Real, "Line_Wu_Real.png"); | |
std::cout << "DrawLine_Wu_Real: " << time << " ms.\n"; | |
std::cout << "Press ENTER to continue... " << std::flush; | |
std::cin.ignore(std::numeric_limits <std::streamsize> ::max(), '\n'); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment