Liang-Barsky裁剪算法+中点画线法光栅画法

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
// 光栅化中点画线算法
void drawPatch(Mat image, int x1, int y1, int x2, int y2)
{
    // 计算直线参数
    int a = y1 - y2;
    int b = x2 - x1;
    int c = x1 * y2 - x2 * y1;
    // 计算斜率
    float slope = (y2 * 1.0 - y1 * 1.0) / (x2 * 1.0 - x1 * 1.0);
    float slope_abs = abs(slope);
    int x, y, end_x, end_y;
    if (a == 0)
    {
        for (int i = min(x1, x2); i <= max(x1, x2); i = i + 10)
        {
            int xn = (i / 10) * 10;
            int yn = (y1 / 10) * 10;
            for (int k = xn; k < xn + 10; k++)
                for (int j = yn; j < yn + 10; j++)
                    image.at<Vec3b>(Point(k, j)) = Vec3b(200, 200, 200); // 浅灰色
        }
        return;
    }
    if (b == 0)
    {
        for (int i = min(y1, y2); i < max(y1, y2); i = i + 10)
        {
            int xn = (x1 / 10) * 10;
            int yn = (i / 10) * 10;
            for (int k = xn; k < xn + 10; k++)
                for (int j = yn; j < yn + 10; j++)
                    image.at<Vec3b>(Point(k, j)) = Vec3b(200, 200, 200); // 浅灰色
        }
        return;
    }
    if (x1 < x2)
    {
        x = x1;
        y = y1;
        end_y = y2;
        end_x = x2;
    }
    else
    {
        x = x2;
        y = y2;
        end_y = y1;
        end_x = x1;
    }
    int d, d1, d2;
    if (slope <= -1)
    {
        d = 2 * (a * (x + 0.5) + b * (y - 1) + c);
        d1 = 2 * (a - b);
        d2 = 2 * b * (-1);
    }
    else if (slope <= 0)
    {
        d = 2 * (a * (x + 1) + b * (y - 0.5) + c);
        d1 = 2 * (a - b);
        d2 = 2 * a;
    }
    else if (slope <= 1)
    {
        d = 2 * (a * (x + 1) + b * (y + 0.5) + c);
        d1 = 2 * (a + b);
        d2 = 2 * a;
    }
    else
    {
        d = 2 * (a * (x + 0.5) + b * (y + 1) + c);
        d1 = 2 * (a + b);
        d2 = 2 * b;
    }
    int min_d, max_d, d3;
    min_d = min(d1, d2);
    max_d = max(d1, d2);
    int flag = (slope > 0) ? 1 : -1;
    int con = 0;
    if (slope_abs >= 1)
    {
        for (; y != end_y;)
        {
            int xn = (x / 10) * 10;
            int yn = (y / 10) * 10;
            if (con > 4)
                for (int i = xn; i < xn + 10; i++)
                    for (int j = yn; j < yn + 10; j++)
                        image.at<Vec3b>(Point(i, j)) = Vec3b(200, 200, 200); // 浅灰色
            do
            {
                if (y == end_y)
                    return;
                con++;
                if (d > 0)
                {
                    y = y + flag;
                    d3 = min_d;
                    d += min_d;
                }
                else
                {
                    y = y + flag;
                    d3 = max_d;
                    d += max_d;
                }
                if (d3 == d1)
                    x += 1;
                image.at<Vec3b>(Point(x, y)) = Vec3b(0, 255, 0);
            } while (y % 10 != 5);
        }
    }
    else
    {
        for (; x != end_x;)
        {
            int xn = (x / 10) * 10;
            int yn = (y / 10) * 10;
            if (con > 4)
                for (int i = xn; i < xn + 10; i++)
                    for (int j = yn; j < yn + 10; j++)
                        image.at<Vec3b>(Point(i, j)) = Vec3b(200, 200, 200); // 浅灰色
            do
            {
                if (x == end_x)
                    return;
                con++;
                if (d > 0)
                {
                    x = x + 1;
                    d3 = min_d;
                    d += min_d;
                }
                else
                {
                    x = x + 1;
                    d3 = max_d;
                    d += max_d;
                }
                if (d3 == d1)
                    y += flag;
                image.at<Vec3b>(Point(x, y)) = Vec3b(0, 255, 0);
            } while (x % 10 != 5);
        }
    }
}
void drawLine(Mat image, int x1, int y1, int x2, int y2)
{
    // 计算直线参数
    int a = y1 - y2;
    int b = x2 - x1;
    int c = x1 * y2 - x2 * y1;
    // 计算斜率
    float slope = (y2 * 1.0 - y1 * 1.0) / (x2 * 1.0 - x1 * 1.0);
    float slope_abs = abs(slope);
    int x, y, end_x, end_y;
    if (a == 0)
    {
        for (int i = min(x1, x2); i <= max(x1, x2); i++)
            image.at<Vec3b>(Point(i, y1)) = Vec3b(0, 255, 0);
        return;
    }
    if (b == 0)
    {
        for (int i = min(y1, y2); i <= max(y1, y2); i++)
            image.at<Vec3b>(Point(x1, i)) = Vec3b(0, 255, 0);
        return;
    }
    if (x1 < x2)
    {
        x = x1;
        y = y1;
        end_y = y2;
        end_x = x2;
    }
    else
    {
        x = x2;
        y = y2;
        end_y = y1;
        end_x = x1;
    }
    int d, d1, d2;
    if (slope <= -1)
    {
        d = 2 * (a * (x + 0.5) + b * (y - 1) + c);
        d1 = 2 * (a - b);
        d2 = 2 * b * (-1);
    }
    else if (slope <= 0)
    {
        d = 2 * (a * (x + 1) + b * (y - 0.5) + c);
        d1 = 2 * (a - b);
        d2 = 2 * a;
    }
    else if (slope <= 1)
    {
        d = 2 * (a * (x + 1) + b * (y + 0.5) + c);
        d1 = 2 * (a + b);
        d2 = 2 * a;
    }
    else
    {
        d = 2 * (a * (x + 0.5) + b * (y + 1) + c);
        d1 = 2 * (a + b);
        d2 = 2 * b;
    }
    int min_d, max_d, d3;
    min_d = min(d1, d2);
    max_d = max(d1, d2);
    int flag = (slope > 0) ? 1 : -1;
    if (slope_abs >= 1)
    {
        for (; y != end_y;)
        {
            if (d > 0)
            {
                y = y + flag;
                d3 = min_d;
                d += min_d;
            }
            else
            {
                y = y + flag;
                d3 = max_d;
                d += max_d;
            }
            if (d3 == d1)
                x += 1;
            image.at<Vec3b>(Point(x, y)) = Vec3b(0, 255, 0);
        }
    }
    else
    {
        for (; x != end_x;)
        {
            if (d > 0)
            {
                x = x + 1;
                d3 = min_d;
                d += min_d;
            }
            else
            {
                x = x + 1;
                d3 = max_d;
                d += max_d;
            }
            if (d3 == d1)
                y += flag;
            image.at<Vec3b>(Point(x, y)) = Vec3b(0, 255, 0);
        }
    }
}
// Liang-Barsky裁剪算法
bool LiangBarsky(float x1, float y1, float x2, float y2, float &u1, float &u2, float xmin, float xmax, float ymin, float ymax)
{
    float p[4] = {-(x2 - x1), x2 - x1, -(y2 - y1), y2 - y1};
    float q[4] = {x1 - xmin, xmax - x1, y1 - ymin, ymax - y1};
    u1 = 0, u2 = 1;
    for (int i = 0; i < 4; i++)
    {
        if (p[i] == 0)
        {
            if (q[i] < 0)
                return false; // 线段平行于裁剪窗口的边界且在窗口之外
        }
        else
        {
            float u = q[i] / p[i];
            if (p[i] < 0 && u1 < u) // 入边
                u1 = u;
            else if (p[i] > 0 && u2 > u) // 出边
                u2 = u;
        }
    }
    if (u1 > u2)
        return false; // 线段在窗口之外
    return true;
}
int main()
{
    int x1, y1, x2, y2;
    cin >> x1 >> y1 >> x2 >> y2;
    // 创建画布
    Mat canvas(500, 500, CV_8UC3, Scalar(255, 255, 255));
    // 绘制矩形
    rectangle(canvas, Point(100, 100), Point(400, 400), Scalar(0, 0, 0), 2);
    // 绘制线段
    x1 = x1 * 10;
    y1 = y1 * 10;
    x2 = x2 * 10;
    y2 = y2 * 10;
    Point line_start(x1, y1);
    Point line_end(x2, y2);
    line(canvas, line_start, line_end, Scalar(0, 0, 255), 1);
    // 显示画布
    imshow("Canvas", canvas);
    while (true)
    {
        int key = waitKey(0);
        if (key == 27) // 按下Esc键
        {
            float u1, u2;
            if (LiangBarsky(x1, y1, x2, y2, u1, u2, 100, 400, 100, 400))
            {
                // 裁剪线段
                Point clipped_start(x1 + u1 * (x2 - x1), y1 + u1 * (y2 - y1));
                Point clipped_end(x1 + u2 * (x2 - x1), y1 + u2 * (y2 - y1));
                // drawPatch(canvas, clipped_start.x, clipped_start.y, clipped_end.x, clipped_end.y);
                for (int i = 10; i < 40; i++)
                    rectangle(canvas, Point(i * 10, 100), Point(i * 10, 400), Scalar(0, 0, 0), 0.5);
                for (int i = 10; i < 40; i++)
                    rectangle(canvas, Point(100, i * 10), Point(400, i * 10), Scalar(0, 0, 0), 0.5);
                // drawLine(canvas, clipped_start.x, clipped_start.y, clipped_end.x, clipped_end.y);
                line(canvas, clipped_start, clipped_end, Scalar(0, 255, 0), 2);
                imshow("Canvas", canvas);
            }
        }
        if (key == 'a')
            break;
    }
    return 0;
}

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值