描述
碰到一道算法题,把我写的代码记录在这里
代码
#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