Библиотека dlib на языке программирования D предоставляет мощные инструменты для работы с графикой, включая возможности для рисования различных примитивов, работы с изображениями и применения алгоритмов машинного обучения. В контексте создания векторной графики dlib позволяет рисовать линии, многоугольники, кривые и другие фигуры с помощью простого и понятного API.
Пример кода для рендеринга произвольного многоугольника
Для рендеринга произвольного многоугольника используется алгоритм, основанный на правиле четности-нечетности (even-odd rule). Этот алгоритм определяет, находится ли точка внутри многоугольника, проверяя, сколько раз горизонтальная линия от этой точки пересекает стороны многоугольника.
Пример кода
import dlib;
void main() {
// Создание изображения
auto img = new Image!(IntegerPixelFormat.RGB8)(800, 600);
// Определение вершин многоугольника
Vector2f[] vertices = [Vector2f(200.0f, 300.0f),
Vector2f(400.0f, 100.0f), Vector2f(600.0f, 300.0f),
Vector2f(500.0f, 500.0f), Vector2f(300.0f, 500.0f)];
bool vhodit;
foreach (y; 0 .. img.height) {
foreach (x; 0 .. img.width) {
vhodit = false;
ulong j = vertices.length - 1;
Vector2f point = Vector2f(x, y);
for (int i = 0; i < vertices.length; i++) {
if ( (vertices[i].y < point.y && vertices[j].y >= point.y || vertices[j].y < point.y && vertices[i].y >= point.y) &&
(vertices[i].x + (point.y - vertices[i].y) / (vertices[j].y - vertices[i].y) * (vertices[j].x - vertices[i].x) < point.x) )
vhodit = !vhodit;
j = i;
}
if (vhodit) {
img[x, y] = Color4f(255.0f, 0.0f, 0.0f, 255.0f); // RGBA format: red, green, blue, alpha
}
}
}
// Сохранение изображения
savePNG(img, "polygon.png");
}
В этом примере создается изображение размером 800×600 пикселей, определяются вершины многоугольника, и он рисуется на изображении. Результат сохраняется в файл polygon.png
.
Метод сглаживания: суперсэмплинг
Суперсэмплинг — это метод сглаживания, который улучшает качество изображения путем рендеринга его в более высоком разрешении, а затем уменьшения од исходного размера. Этот метод помогает избавиться от эффектов лестницы (aliasing).
Пример реализации кода
import dlib;
void main() {
// Создание изображения
auto img = new Image!(IntegerPixelFormat.RGB8)(3200, 2400);
// Определение вершин многоугольника
Vector2f[] vertices = [Vector2f(800.0f, 1200.0f),
Vector2f(1600.0f, 400.0f), Vector2f(2400.0f, 1200.0f),
Vector2f(2000.0f, 2000.0f), Vector2f(1200.0f, 2000.0f)];
// Рисование многоугольника
//img.drawPolygon(vertices, Color(0, 0, 0), true);
bool vhodit;
foreach (y; 0 .. img.height) {
foreach (x; 0 .. img.width) {
vhodit = false;
ulong j = vertices.length - 1;
Vector2f point = Vector2f(x, y);
for (int i = 0; i < vertices.length; i++) {
if ( (vertices[i].y < point.y && vertices[j].y >= point.y || vertices[j].y < point.y && vertices[i].y >= point.y) &&
(vertices[i].x + (point.y - vertices[i].y) / (vertices[j].y - vertices[i].y) * (vertices[j].x - vertices[i].x) < point.x) )
vhodit = !vhodit;
j = i;
}
if (vhodit) {
img[x, y] = Color4f(255.0f, 0.0f, 0.0f, 255.0f); // RGBA format: red, green, blue, alpha
}
}
}
auto resizedImg = resampleBicubic(img, 800, 600);
// Сохранение изображения
savePNG(resizedImg, "polygon_anti_aliased.png");
}
В этом примере изображение сначала создается в 4 раза большего размера, чем исходное, многоугольник рисуется на этом изображении в высоком разрешении, а затем изображение уменьшается методом бикубической интерполяции до нужного размера, что дает эффект сглаживания.
Рисование фигур на основе кривых Безье
Кривые Безье часто используются в компьютерной графике для создания гладких и плавных кривых. Для аппроксимации кривой Безье можно использовать последовательность коротких отрезков линии.
Пример кода для рисования кривой Безье
import dlib;
import std.math;
import std.conv:to;
void drawBezier(Image!(IntegerPixelFormat.RGB8) image,
Vector2f p0, Vector2f p1, Vector2f p2, Vector2f p3, Color4f color) {
int xr;
int yr;
for (double t = 0; t <= 1; t += 0.001) {
double x = pow(1-t, 3) * p0.x + 3 * t * pow(1-t, 2) * p1.x + 3 * pow(t, 2) * (1-t) * p2.x + pow(t, 3) * p3.x;
double y = pow(1-t, 3) * p0.y + 3 * t * pow(1-t, 2) * p1.y + 3 * pow(t, 2) * (1-t) * p2.y + pow(t, 3) * p3.y;
xr = to!int(floor(x));
yr = to!int(floor(y));
image[xr, yr] = color;
}
}
void main() {
// Создание изображения
auto img = new Image!(IntegerPixelFormat.RGB8)(800, 600);
// Определение контрольных точек кривой Безье
Vector2f p0 = Vector2f(100.0f, 500.0f);
Vector2f p1 = Vector2f(200.0f, 100.0f);
Vector2f p2 = Vector2f(600.0f, 100.0f);
Vector2f p3 = Vector2f(700.0f, 500.0f);
// Рисование кривой Безье
drawBezier(img, p0, p1, p2, p3, Color4f(255.0f, 0.0f, 0.0f, 255.0f));
// Сохранение изображения
savePNG(img, "bezier_curve.png");
}
В этом примере функция drawBezier
используется для рисования кривой Безье на изображении путем итерации параметра t
от 0 до 1 и вычисления координат точки на кривой.
Использование аффинных преобразований для трансформации фигур
Аффинные преобразования включают операции трансляции, масштабирования, вращения и отражения. Они полезны для изменения формы и положения фигур на плоскости.
Пример кода для поворота фигуры
import dlib;
import std.math;
import std.conv:to;
import std.algorithm;
import std.array;
Vector2f rotatePoint(Vector2f p, Vector2f center, double angle) {
double s = sin(angle);
double c = cos(angle);
// Перенос точки в начало координат
p.x -= center.x;
p.y -= center.y;
// Вращение точки
double xnew = p.x * c - p.y * s;
double ynew = p.x * s + p.y * c;
// Перенос точки обратно
p.x = xnew + center.x;
p.y = ynew + center.y;
return p;
}
void main() {
// Создание изображения
auto img = new Image!(IntegerPixelFormat.RGB8)(800, 600);
// Определение вершин многоугольника
Vector2f[] vertices = [Vector2f(200.0f, 300.0f), Vector2f(400.0f, 100.0f),
Vector2f(600.0f, 300.0f), Vector2f(500.0f, 500.0f), Vector2f(300.0f, 500.0f)];
// Определение центра вращения и угла
Vector2f center = Vector2f(200.0f, 150.0f);
double angle = PI / 4; // 45 градусов
// Вращение вершин многоугольника
Vector2f[] rotatedVertices = vertices.map!(p => rotatePoint(p, center, angle)).array;
// Рисование исходного многоугольника
bool vhodit;
foreach (y; 0 .. img.height) {
foreach (x; 0 .. img.width) {
vhodit = false;
ulong j = vertices.length - 1;
Vector2f point = Vector2f(x, y);
for (int i = 0; i < vertices.length; i++) {
if ( (vertices[i].y < point.y && vertices[j].y >= point.y || vertices[j].y < point.y && vertices[i].y >= point.y) &&
(vertices[i].x + (point.y - vertices[i].y) / (vertices[j].y - vertices[i].y) * (vertices[j].x - vertices[i].x) < point.x) )
vhodit = !vhodit;
j = i;
}
if (vhodit) {
img[x, y] = Color4f(0.0f, 0.0f, 255.0f, 255.0f); // RGBA format: red, green, blue, alpha
}
}
}
// Рисование исходного и повернутого многоугольников
foreach (y; 0 .. img.height) {
foreach (x; 0 .. img.width) {
vhodit = false;
ulong j = rotatedVertices.length - 1;
Vector2f point = Vector2f(x, y);
for (int i = 0; i < rotatedVertices.length; i++) {
if ( (rotatedVertices[i].y < point.y && rotatedVertices[j].y >= point.y || rotatedVertices[j].y < point.y && rotatedVertices[i].y >= point.y) &&
(rotatedVertices[i].x + (point.y - rotatedVertices[i].y) / (rotatedVertices[j].y - rotatedVertices[i].y) * (rotatedVertices[j].x - rotatedVertices[i].x) < point.x) )
vhodit = !vhodit;
j = i;
}
if (vhodit) {
img[x, y] = Color4f(255.0f, 0.0f, 0.0f, 255.0f); // RGBA format: red, green, blue, alpha
}
}
}
// Сохранение изображения
savePNG(img, "rotated_polygon.png");
}
В этом примере функция rotatePoint
используется для поворота точки вокруг заданного центра на определенный угол. Многоугольник рисуется дважды: в исходном положении и после поворота.
Автор статьи:
Обновлено:
Добавить комментарий