| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 3394 人关注过本帖
标题:如何用C语言解出多条线段的交点坐标?求大师赐教!
只看楼主 加入收藏
书生等待
Rank: 7Rank: 7Rank: 7
等 级:黑侠
威 望:8
帖 子:280
专家分:689
注 册:2013-2-22
收藏
得分:0 
楼主,你都有思路了啊
已知直线两点(a1,b1)  (a2,b2)
把直线表示成y=kx+b的形式,不是有公式吗:   k=b2-b1/a2-a1       至于a1=a2的情况另行判断吧
同理求出  b

得到两条直线的(k1,b1) (k2,b2),再求交点,不过又是求解二元一次方程组的问题

简而言之,一句话:把求解二元一次方程的过程变成直接用公式在代码里求解

同是新手,个人思路
2014-05-08 15:55
宇宙规律
Rank: 3Rank: 3
等 级:论坛游侠
威 望:1
帖 子:232
专家分:128
注 册:2014-5-7
收藏
得分:0 
我是自学的C语言,几何代数知道怎么算,编写大型程序自己功夫不够啊!

其实,很有难度的!在网上搜索了两天,仅找到了一个类似程序!
2014-05-08 16:20
宇宙规律
Rank: 3Rank: 3
等 级:论坛游侠
威 望:1
帖 子:232
专家分:128
注 册:2014-5-7
收藏
得分:0 
找到了心剑菩提的帖子,解读揣摩几天再说!
我编写的是预测金融价格的程序,这个问题难了我快一个月了!很难找啊!


(一)问题2001年第10期擂台赛的问题是: 给定n条线段,请编一程序,给出所有的交点坐标。
(二)一般解法该问题的解决并不难: 遍历该组线段中的任意一对求出交点即可。具体两线段交点的求法为:(1)先对应两线段分别对它们所在的直线写出相应的两点式方程,即设一线段两端点坐标分别为(xi,yi)与(xj,yj),则对应直线方程为: (y-yi)/(x-xi)=(y-yj)/(x-xj);(2)求两直线交点坐标,即联合两直线方程得一个一元二次方程组,求解之;(3)如方程组有解,判断解是否在两线段的两端点之间或端点上。是则方程组之解即是两线段的交点;否则两线段无交点。当然,在求两线段交点前还可以用一些条件式加以过滤,如对两线段所对应矩形无相交部分的情况,可直接判断两线段无交点等等。
(三)编程实例参赛程序有许多采用了上述方法,这里选载一个比较典型的程序设计
/* 程序说明
程序中的几个变量:
*x1棗线段初始点横坐标*y1棗线段初始点纵坐标
*x2棗线段终止点横坐标*y2棗线段终止点纵坐标
*a棗线段所在直线解析式中x项系数*b棗线段所在直线解析式中y项系数
*c棗线段所在直线解析式中常数项jx棗两条线段所在直线交点横坐标
jy棗两条线段所在直线交点纵坐标程序结构:
读出变量, 分配内存。用解析几何中计算两直线交点的公式两两计算两条线段所在直线交点。
用函数between判断两条线段所在直线交点是否
在线段上,若是,则输出结果。*/
#include <stdio.h>
#include <stdlib.h>
// 此函数判断交点坐标是否在线段坐标范围内,即判断交点是否落在线段上
int between(float u, float v, float w)
{ float max,min;
  max=(v>w)?v:w;
  min=(v<w)?v:w;
  return ((u<=max&&u>=min)?1:0);
}
int main()
{
  int n,i,j,num; //n为线段条数
  float x1[100],y1[100],x2[100],y2[100],a[100],b[100],c[100],jx,jy;
  while(scanf("%d",&n)&&n!=0)
  {   
   num=0;   
   for(i=0;i<n;++i)
   { scanf("%f%f%f%f",&x1[i],&y1[i],&x2[i],&y2[i]);
     if(x1[i]==x2[i])
     {
       a[i]=1;b[i]=0;c[i]=-x1[i];
     }
     else
     {
       a[i]=(y2[i]-y1[i])/(x1[i]-x2[i]);b[i]=1;
       c[i]=(x1[i]*y2[i]-x2[i]*y1[i])/(x2[i]-x1[i]);
     }
   }
   for(i=0;i<n;++i)
   {
      for(j=i+1;j<n;++j)
      {
         if(a[i]*b[j]-a[j]*b[i]!=0)
        {
          jx=(b[i]*c[j]-b[j]*c[i])/(a[i]*b[j]-a[j]*b[i]);
          jy=(c[i]*a[j]-c[j]*a[i])/(a[i]*b[j]-a[j]*b[i]);
          if(between(jx,x1[i],x2[i])&&between(jx,x1[j],x2[j])&&between(jy,y1[i],y2[i])&&between(jy,y1[j],y2[j]))
          //printf("(%f,%f)\n ",jx,jy);
          num++;
       }
      }
   }
   printf("%d\n",num);
  }
  return 0;
}
(四)另一算法设计这里再给出一种求解算法。首先,对给定的n条边的2n个端点按X坐标由小到大的次序进行排序,并在每一端点处作一平行Y轴的辅助虚线。一个实例如图所示, 共有5条线段,分别编号为:第1,2..5 号线段,共2 × 5=10 个端点。对每一辅助线,将有一些线段与之相交,将能与之相交的边的序号按交点Y坐标由大到小排序,由上向下记录。例如,图中每条虚线下面对应记录的一组边序号:{1},{1,2},{2,1},{2,3}..等。对两虚线,显然一对线段要相交的充分必要条件是在两虚线处对应边序号序列中两边序号都存在,且两边序号正好排序相反。例如: 图中:第1虚线{1}与第2虚线{1,2}没有共同两边序号,故其间无线段相交;第2虚线{1,2}与第3虚线{2,1}有共同两边序号1与2, 且第2虚线处排序为1->2, 第3虚线处排序为2->1,两者反序, 故其间线段2 必与线段3 相交;第3虚线{2,1}与第4虚线{2,3}没有共同两边序号,只有一个共同边序号2,故其间无线段相交;第4虚线{2,3}与第5虚线{2,3}虽有共同两边序号2与3, 但排序同为2->3,故其间无线段相交;第5虚线{2,3}与第6虚线{3,5}没有共同两边序号, 只有一个共同边序号3,故其间无线段相交;第6虚线{3,5}与第7虚线{4,3,5}虽有共同两边序号3与5, 但排序同为3->5,故其间无线段相交;第7虚线{4,3,5}与第8虚线{3,4,5}有共同三边序号3,4与5, 但排序不同的只有一对:3->4与4->3,故其间有一对线段3 与4 相交;第8虚线{3,4,5}与第9虚线{5,4}有共同两边序号4与5, 且第8虚线处排序为4->5, 第9虚线处排序为5->4,两者反序, 故其间线段4必与线段5相交;第9虚线{5,4}与第10虚线{4}没有共同两边序号,故其间无线段相交;由以上讨论可自然导出下列算法。
算法:(1)对n条线段的2n个端点按X坐标升序排序;
(2)依次给出每一端点Y坐标辅助虚线处按Y坐标排序的边序号序列;其中如两边Y坐标同,则直接判断在虚线处有相应交点;序列中边序列号的确定按X坐标从小到大,碰到左端点加相应边边序号,碰到右端点删去相应边边序号方法进行。
(3) 扫描每一虚线区间,如前后虚线处对应边序列共同边超过1 条,则遍查所有前后逆序线对,并求出交点坐标输出。
设A   (Ax,Ay)   B(Bx,By)   C(Cx,Cy)   D(Dx,Dy)四点坐标   
  #define   Max(X,Y)   (X)>=(Y)?(X):(Y);   
  #define   Min(X,Y)   (X)>=(Y)?(Y):(X);   
   
  只要   (Ax<=Max(Cx,Dx)&&Ax>=Min(Cx,Dx))   &&   (Bx<=Max(Cx,Dx)&&Bx>=Min(Cx,Dx))     
  就有交点
定义:平面上的三点P1(x1,y1),P2(x2,y2),P3(x3,y3)的面积量:   
                            |x1     x2     x3|   
          S(P1,P2,P3)   =   |y1     y2     y3|   =   (x1-x3)*(y2-y3) - (y1-y3)(x2-x3)   
                            |1      1       1|   
   
  已知一条线段的两个端点为A(x1,y1),B(x2,y2),另一条线段的两个端点为C(x3,y3),D(x4,y4),要判断AB与CD是否有交点,若有求出.   
   
  首先判断d   =   (y2-y1)(x4-x3)-(y4-y3)(x2-x1),   
    若d=0,则直线AB与CD平行或重合,   
    若d!=0,则直线AB与CD有交点,设交点为E(x0,y0):   
          则有:CE/ED   =   S(A,C,B)   /   S(A,B,D)   
          所以:CE/CD   =   S(A,C,B)   /   (S(A,C,B)   +   S(A,B,D))   
             x0   =   C.x   +   (D.x   -   C.x)   *   S(A,C,B)   /   (S(A,C,B)   +   S(A,B,D));   
                y0   =   C.y   +   (D.y   -   C.y)   *   S(A,C,B)   /   (S(A,C,B)   +   S(A,B,D));   
   
  也可以直接求   
                x0   =   [(x2-x1)*(x4-x3)*(y3-y1)+(y2-y1)*(x4-x3)*x1-(y4-y3)*(x2-x1)*x3]/d   
                y0   =   [(y2-y1)*(y4-y3)*(x3-x1)+(x2-x1)*(y4-y3)*y1-(x4-x3)*(y2-y1)*y3]/(-d)   
   
   
  求出交点后在判断交点是否在线段上,即判断以下的式子:   
          (x0-x1)*(x0-x2)<=0   
          (x0-x3)*(x0-x4)<=0   
          (y0-y1)*(y0-y2)<=0   
          (y0-y3)*(y0-y4)<=0   
  只有上面的四个式子都成立才可判定(x0,y0)是线段AB与CD的交点,否则两线段无交点
2014-05-08 16:42
黑色萌王
Rank: 1
等 级:新手上路
帖 子:1
专家分:0
注 册:2014-5-8
收藏
得分:0 
其实能不能直接先写个两条直线求交点的程序,然后将每两条线段的相应的值依次带入进行计算,最后判断点是否相同,这样可以吧?
2014-05-08 16:44
宇宙规律
Rank: 3Rank: 3
等 级:论坛游侠
威 望:1
帖 子:232
专家分:128
注 册:2014-5-7
收藏
得分:0 
你的思路是对的!我自己编写程序的时候,思路也是对的,但程序运行不了,自己也不知道错到哪里了!
2014-05-08 16:48
书生等待
Rank: 7Rank: 7Rank: 7
等 级:黑侠
威 望:8
帖 子:280
专家分:689
注 册:2013-2-22
收藏
得分:0 
回复 15 楼 宇宙规律
程序贴上来,会有人帮你的
2014-05-08 17:26
top398
Rank: 8Rank: 8
等 级:蝙蝠侠
威 望:2
帖 子:427
专家分:857
注 册:2014-5-2
收藏
得分:0 
每一条线段表达为 y=kx+b, 可用结构
struct LINE {
    double k,b;
};
表示,n条线段用数组
struct LINE lines[n];
表示。则剩下的工作只是循环求相邻两数组元素表达的线段的交点而已(最后一个元素与第一个元素求交点)。二元一次方程组求解不是问题吧。
2014-05-08 18:29
ditg
Rank: 10Rank: 10Rank: 10
等 级:贵宾
威 望:16
帖 子:852
专家分:1937
注 册:2014-4-10
收藏
得分:0 
可用于股票价格预测? (可怕的想法……)

梦想拥有一台龙芯3A-4000
2014-05-08 18:38
宇宙规律
Rank: 3Rank: 3
等 级:论坛游侠
威 望:1
帖 子:232
专家分:128
注 册:2014-5-7
收藏
得分:0 
求出线段的交点后(x1,y1),(x2,y2),(x3,y3),...(xn,yn),还需要按照 x1,x2,x3,...xn的大小排序,如果x1>x3>xn>x2,要求输出顺序是(x1,y1),(x3,y3),(xn,yn),(x2,y2);
同时,每条线段ab的长度取值范围是:N*ab ;
2014-05-08 18:49
宇宙规律
Rank: 3Rank: 3
等 级:论坛游侠
威 望:1
帖 子:232
专家分:128
注 册:2014-5-7
收藏
得分:0 
N是一个有小数点的常数
2014-05-08 18:51
快速回复:如何用C语言解出多条线段的交点坐标?求大师赐教!
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.045273 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved