求三角形是否重叠

描述

碰到一道算法题,把我写的代码记录在这里

代码

#include <stdio.h>
#include <opencv2/opencv.hpp>
#include <vector>

int min(int x, int y){
    return x < y ? x : y;
}

int max(int x, int y){
    return x > y ? x : y;
}

// 判断两条直线是否相交
bool is_lines_cross (int line1_x1, int line1_y1, int line1_x2, int line1_y2,
                     int line2_x1, int line2_y1, int line2_x2, int line2_y2) {
    // 首先简单从线段边界来判断是否根本不可能相交 
    if ( (max(line1_x1, line1_x2) < min(line2_x1, line2_x2)) 
        || (max(line1_y1, line1_y2) < min(line2_y1, line2_y2)) 
        || (max(line2_x1, line2_x2) < min(line1_x1, line1_x2))
        || (max(line2_y1, line2_y2) < min(line1_y1, line1_y2)) ){
        return false;
    }
    // 两个线段向量做叉乘,判断是否相交
    // 假设line1的两个点是A和B,line2的两个点是C和D
    // 不失一般性,向量CA和CB应该分别在CD的两侧,向量AC和AD应该在AB的两侧
    // 因此如果相交会有: (CA×CD)*(CB×CD)<=0 && (AC×AB)*(AD×AB)<=0
    // 所以不想交会有: (CA×CD)*(CB×CD)>0 || (BC×BA)*(BD×BA)>0
    int CA_x = line1_x1 - line2_x1;
    int CA_y = line1_y1 - line2_y1;
    int CB_x = line1_x2 - line2_x1;
    int CB_y = line1_y2 - line2_y1; 
    int CD_x = line2_x2 - line2_x1;
    int CD_y = line2_y2 - line2_y1;

    int AC_x = line2_x1 - line1_x1;
    int AC_y = line2_y1 - line1_y1;
    int AD_x = line2_x2 - line1_x1;
    int AD_y = line2_y2 - line1_y1;
    int AB_x = line1_x2 - line1_x1;
    int AB_y = line1_y2 - line1_y1;

    if ( ((CA_x*CD_y - CD_x*CA_y) * (CB_x*CD_y - CD_x*CB_y) > 0)
    ||  ((AC_x*AB_y - AB_x*AC_y) * (AD_x*AB_y - AB_x*AD_y) > 0) ) {
        return false;
    }
    return true;
}

// 用于显示三角形
void show_proj1(int triangle1[6], int triangle2[6]){
    int project1_show_size = 500;
	cv::Mat img_proj1 = cv::Mat::zeros(cv::Size(project1_show_size, project1_show_size), CV_8UC3);
    img_proj1.setTo(255);

    
    cv::Point l1_p1(0 + triangle1[0], project1_show_size - triangle1[1]);
    cv::Point l1_p2(0 + triangle1[2], project1_show_size - triangle1[3]);
    cv::Point l1_p3(0 + triangle1[4], project1_show_size - triangle1[5]);
  
    cv::Point l2_p1(0 + triangle2[0], project1_show_size - triangle2[1]);
    cv::Point l2_p2(0 + triangle2[2], project1_show_size - triangle2[3]);
    cv::Point l2_p3(0 + triangle2[4], project1_show_size - triangle2[5]);
    
	cv::circle(img_proj1, l1_p1, 1, cv::Scalar(0, 255, 0), -1);
    cv::circle(img_proj1, l1_p2, 1, cv::Scalar(0, 255, 0), -1);
    cv::circle(img_proj1, l1_p3, 1, cv::Scalar(0, 255, 0), -1);
    cv::circle(img_proj1, l2_p1, 1, cv::Scalar(255, 0, 0), -1);
    cv::circle(img_proj1, l2_p2, 1, cv::Scalar(255, 0, 0), -1);
    cv::circle(img_proj1, l2_p3, 1, cv::Scalar(255, 0, 0), -1);
    
    cv::line(img_proj1, l1_p1, l1_p2, cv::Scalar(0, 255, 0), 1);
	cv::line(img_proj1, l1_p1, l1_p3, cv::Scalar(0, 255, 0), 1);
    cv::line(img_proj1, l1_p2, l1_p3, cv::Scalar(0, 255, 0), 1);
    cv::line(img_proj1, l2_p1, l2_p2, cv::Scalar(255, 0, 0), 1);
	cv::line(img_proj1, l2_p1, l2_p3, cv::Scalar(255, 0, 0), 1);
    cv::line(img_proj1, l2_p2, l2_p3, cv::Scalar(255, 0, 0), 1);

    cv::namedWindow( "Display window", cv::WINDOW_AUTOSIZE ); // Create a window for display.
    cv::imshow( "Display window", img_proj1 );       
    cv::waitKey(0);
}

// 两个三角形是否有重叠区域
bool has_overlap(int triangle1[6], int triangle2[6])
{
    int choose[3][4] = {{0, 1, 2, 3}, {0, 1, 4, 5}, { 2, 3, 4, 5}};
    // i和j代表:三角形1和2各有三条线段
    for (int i = 0; i < 3; i++){
        for (int j = 0; j < 3; j++){
            // 三角形1和2的线段是否相交
            if ( is_lines_cross( triangle1[choose[i][0]], triangle1[choose[i][1]],
                                       triangle1[choose[i][2]], triangle1[choose[i][3]], 
                                       triangle2[choose[j][0]], triangle2[choose[j][1]],
                                       triangle2[choose[j][2]], triangle2[choose[j][3]] )) {
               return true; // 线段相交即为重叠
           } 
        }
    }
    return false;
}

int main(int argc, char **argv)
{
    // 三角形的3个顶点坐标:[x1, y1, x2, y2, x3, y3]
    int tri[5][6] = {
        {100, 200, 305, 105, 100, 25},  
        {86, 192, 100, 150, 102, 75},
        {200, 260, 160, 100, 201, 300},
        {150, 100, 50, 60, 300, 60},
        {260, 200, 150, 60, 80, 100}
    };
    
    for (int i = 0; i < 5; i++)
    {
        for (int j = i+1; j < 5; j++)
        {
            printf("Overlap [%d][%d] = %d\n", i, j, has_overlap(tri[i], tri[j]));
            show_proj1(tri[i], tri[j]);
        }        
    }

    return 0;
}

参考

完成上述代码时,下面的文章给了我很大的帮助,贴出链接
https://blog.csdn.net/HelloZEX/article/details/80880385

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值