找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: 活动 交友 discuz
查看: 264|回复: 2

计算几何-求线段交点算法和代码(C++语言)

[复制链接]

1

主题

0

回帖

37

积分

管理员

积分
37
发表于 2024-6-21 17:02:47 | 显示全部楼层 |阅读模式
  1. //跨立判断
  2. bool isLineSegmentCross(const Point &P1,const Point &P2,const Point &Q1,const Point &Q2)
  3. {
  4.     if(
  5.         ((Q1.x-P1.x)*(Q1.y-Q2.y)-(Q1.y-P1.y)*( Q1.x-Q2.x)) * ((Q1.x-P2.x)*(Q1.y-Q2.y)-(Q1.y-P2.y)*(Q1.x-Q2.x)) < 0 &&
  6.         ((P1.x-Q1.x)*(P1.y-P2.y)-(P1.y-Q1.y)*(P1.x-P2.x)) * ((P1.x-Q2.x)*(P1.y-P2.y)-(P1.y-Q2.y)*( P1.x-P2.x)) < 0
  7.     )
  8.         return true;
  9.     else
  10.        return false;
  11. }
复制代码

  1. #include<stdio.h>
  2. #define N 10002
  3. /**
  4. 算法适用于整形点,不适用于浮点型
  5. **/
  6. typedef struct Point
  7. {
  8.     int x;
  9.     int y;
  10. }Point;
  11. double min(int x, int y)
  12. {
  13.     return x<y?x:y;
  14. }
  15. double max(int x, int y)
  16. {
  17.     return x>y?x:y;
  18. }
  19. //排斥实验
  20. bool IsRectCross(const Point &p1,const Point &p2,const Point &q1,const Point &q2)
  21. {
  22.     bool ret = min(p1.x,p2.x) <= max(q1.x,q2.x)    &&
  23.                 min(q1.x,q2.x) <= max(p1.x,p2.x) &&
  24.                 min(p1.y,p2.y) <= max(q1.y,q2.y) &&
  25.                 min(q1.y,q2.y) <= max(p1.y,p2.y);
  26.     return ret;
  27. }
  28. /**这段代码不能得到正确答案,故注释
  29. //跨立判断
  30. bool IsLineSegmentCross(const Point &pFirst1,const Point &pFirst2,const Point &pSecond1,const Point &pSecond2)
  31. {
  32.     long line1,line2;
  33.     line1 = pFirst1.x * (pSecond1.y - pFirst2.y) +
  34.         pFirst2.x * (pFirst1.y - pSecond1.y) +
  35.         pSecond1.x * (pFirst2.y - pFirst1.y);
  36.     line2 = pFirst1.x * (pSecond2.y - pFirst2.y) +
  37.         pFirst2.x * (pFirst1.y - pSecond2.y) +
  38.         pSecond2.x * (pFirst2.y - pFirst1.y);
  39.     if (((line1 ^ line2) >= 0) && !(line1 == 0 && line2 == 0))
  40.         return false;
  41.     line1 = pSecond1.x * (pFirst1.y - pSecond2.y) +
  42.         pSecond2.x * (pSecond1.y - pFirst1.y) +
  43.         pFirst1.x * (pSecond2.y - pSecond1.y);
  44.     line2 = pSecond1.x * (pFirst2.y - pSecond2.y) +
  45.         pSecond2.x * (pSecond1.y - pFirst2.y) +
  46.         pFirst2.x * (pSecond2.y - pSecond1.y);
  47.     if (((line1 ^ line2) >= 0) && !(line1 == 0 && line2 == 0))
  48.         return false;
  49.     return true;
  50. }
  51. **/
  52. //跨立判断
  53. bool IsLineSegmentCross(const Point &P1,const Point &P2,const Point &Q1,const Point &Q2)
  54. {
  55.     if(
  56.         ((Q1.x-P1.x)*(Q1.y-Q2.y)-(Q1.y-P1.y)*( Q1.x-Q2.x)) * ((Q1.x-P2.x)*(Q1.y-Q2.y)-(Q1.y-P2.y)*(Q1.x-Q2.x)) < 0 ||
  57.         ((P1.x-Q1.x)*(P1.y-P2.y)-(P1.y-Q1.y)*(P1.x-P2.x)) * ((P1.x-Q2.x)*(P1.y-P2.y)-(P1.y-Q2.y)*( P1.x-P2.x)) < 0
  58.     )
  59.         return true;
  60.     else
  61.        return false;
  62. }
  63. /**
  64. 求线段P1P2与Q1Q2的交点。
  65. 先进行快速排斥实验和跨立实验确定有交点再进行计算。
  66. 交点(x,y)使用引用返回。
  67. 没有验证过
  68. **/
  69. bool GetCrossPoint(const Point &p1,const Point &p2,const Point &q1,const Point &q2,long &x,long &y)
  70. {
  71.     if(IsRectCross(p1,p2,q1,q2))
  72.     {
  73.         if (IsLineSegmentCross(p1,p2,q1,q2))
  74.         {
  75.             //求交点
  76.             long tmpLeft,tmpRight;
  77.             tmpLeft = (q2.x - q1.x) * (p1.y - p2.y) - (p2.x - p1.x) * (q1.y - q2.y);
  78.             tmpRight = (p1.y - q1.y) * (p2.x - p1.x) * (q2.x - q1.x) + q1.x * (q2.y - q1.y) * (p2.x - p1.x) - p1.x * (p2.y - p1.y) * (q2.x - q1.x);
  79.             x = (int)((double)tmpRight/(double)tmpLeft);
  80.             tmpLeft = (p1.x - p2.x) * (q2.y - q1.y) - (p2.y - p1.y) * (q1.x - q2.x);
  81.             tmpRight = p2.y * (p1.x - p2.x) * (q2.y - q1.y) + (q2.x- p2.x) * (q2.y - q1.y) * (p1.y - p2.y) - q2.y * (q1.x - q2.x) * (p2.y - p1.y);
  82.             y = (int)((double)tmpRight/(double)tmpLeft);
  83.             return true;
  84.         }
  85.     }
  86.     return false;
  87. }
复制代码


  1. #include <stdio.h>
  2. #include <math.h>
  3. const int N = 100010;
  4. int mark[N];
  5. struct Point
  6. {
  7.     double x,y;
  8. };
  9. struct stline
  10. {
  11.     Point a,b;
  12. } line1,line2, p[N];
  13. int dblcmp(double a,double b)
  14. {
  15.     if (fabs(a-b)<=1E-6) return 0;
  16.     if (a>b) return 1;
  17.     else return -1;
  18. }
  19. //***************点积判点是否在线段上***************
  20. double dot(double x1,double y1,double x2,double y2) //点积
  21. {
  22.     return x1*x2+y1*y2;
  23. }
  24. int point采用on采用line(Point a,Point b,Point c) //求a点是不是在线段bc上,>0不在,=0与端点重合,<0在。
  25. {
  26.     return dblcmp(dot(b.x-a.x,b.y-a.y,c.x-a.x,c.y-a.y),0);
  27. }
  28. //**************************************************
  29. double cross(double x1,double y1,double x2,double y2)
  30. {
  31.     return x1*y2-x2*y1;
  32. }
  33. double ab采用cross采用ac(Point a,Point b,Point c) //ab与ac的叉积
  34. {
  35.     return cross(b.x-a.x,b.y-a.y,c.x-a.x,c.y-a.y);
  36. }
  37. int ab采用cross采用cd (Point a,Point b,Point c,Point d) //求ab是否与cd相交,交点为p。1规范相交,0交点是一线段的端点,-1不相交。
  38. {
  39.     double s1,s2,s3,s4;
  40.     int d1,d2,d3,d4;
  41.     Point p;
  42.     d1=dblcmp(s1=ab采用cross采用ac(a,b,c),0);
  43.     d2=dblcmp(s2=ab采用cross采用ac(a,b,d),0);
  44.     d3=dblcmp(s3=ab采用cross采用ac(c,d,a),0);
  45.     d4=dblcmp(s4=ab采用cross采用ac(c,d,b),0);
  46. //如果规范相交则求交点
  47.     if ((d1^d2)==-2 && (d3^d4)==-2)
  48.     {
  49.         p.x=(c.x*s2-d.x*s1)/(s2-s1);
  50.         p.y=(c.y*s2-d.y*s1)/(s2-s1);
  51.         return 1;
  52.     }
  53. //如果不规范相交
  54.     if (d1==0 && point采用on采用line(c,a,b)<=0)
  55.     {
  56.         p=c;
  57.         return 0;
  58.     }
  59.     if (d2==0 && point采用on采用line(d,a,b)<=0)
  60.     {
  61.         p=d;
  62.         return 0;
  63.     }
  64.     if (d3==0 && point采用on采用line(a,c,d)<=0)
  65.     {
  66.         p=a;
  67.         return 0;
  68.     }
  69.     if (d4==0 && point采用on采用line(b,c,d)<=0)
  70.     {
  71.         p=b;
  72.         return 0;
  73.     }
  74. //如果不相交
  75.     return -1;
  76. }
复制代码

1

主题

0

回帖

37

积分

管理员

积分
37
 楼主| 发表于 2024-6-21 17:03:24 | 显示全部楼层
  1. Point getCrossPoint(Segment s1, Segment s2) {
  2.     Vector base = s2.p2 - s2.p1;
  3.     double d1 = abs(cross(base, s1.p1 - s2.p1));
  4.     double d2 = abs(cross(base, s1.p2 - s2.p1));
  5.     double t = d1 / (d1 + d2);
  6.     return s1.p1 + (s1.p2 - s1.p1) * t;
  7. }
复制代码

1

主题

0

回帖

37

积分

管理员

积分
37
 楼主| 发表于 2024-6-21 17:03:33 | 显示全部楼层
  1. #include<stdio.h>
  2. #include<iostream>
  3. #include<cmath>
  4. using namespace std;
  5. #define EPS (1e-10)
  6. #define equals(a, b) (fabs((a) - (b)) < EPS)
  7. class Point {//Point类,点
  8.     public:
  9.         double x, y;
  10.         
  11.         Point(double x = 0, double y = 0): x(x), y(y) {}
  12.         Point operator + (Point p) { return Point(x + p.x, y + p.y); }
  13.         Point operator - (Point p) { return Point(x - p.x, y - p.y); }
  14.         Point operator * (double a) { return Point(a * x, a * y); }
  15.         Point operator / (double a) { return Point(x / a, y / a); }
  16.         double abs() { return sqrt(norm()); }
  17.         double norm() { return x * x + y * y; }
  18.         
  19.         bool operator < (const Point &p) const {
  20.             return x != p.x ? x < p.x : y < p.y;
  21.         }
  22.         bool operator == (const Point &p) const {
  23.             return fabs(x - p.x) < EPS && fabs(y - p.y) < EPS;
  24.         }
  25. };
  26. typedef Point Vector;//Vector类,向量
  27. struct Segment{//Segment 线段
  28.     Point p1, p2;
  29. };
  30. double dot(Vector a, Vector b) {//内积
  31.     return a.x * b.x + a.y * b.y;
  32. }
  33. double cross(Vector a, Vector b) {//外积
  34.     return a.x*b.y - a.y*b.x;
  35. }
  36. Point getCrossPoint(Segment s1, Segment s2) {
  37.     Vector base = s2.p2 - s2.p1;
  38.     double d1 = abs(cross(base, s1.p1 - s2.p1));
  39.     double d2 = abs(cross(base, s1.p2 - s2.p1));
  40.     double t = d1 / (d1 + d2);
  41.     return s1.p1 + (s1.p2 - s1.p1) * t;
  42. }
  43. int main(){
  44.     int q;
  45.     cin>>q;
  46.    
  47.     Segment s1, s2;
  48.     Point p;
  49.    
  50.     while(q--){
  51.         cin>>s1.p1.x>>s1.p1.y>>s1.p2.x>>s1.p2.y>>s2.p1.x>>s2.p1.y>>s2.p2.x>>s2.p2.y;
  52.         p = getCrossPoint(s1, s2);
  53.         printf("%.10f %.10f\n", p.x, p.y);
  54.     }
  55. }
复制代码
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|膜结构网

GMT+8, 2025-1-6 16:56 , Processed in 0.122252 second(s), 20 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表