• 计算机图形学|两道习题


    1.    设空间有两条线段AB和CD,其端点坐标分别为,怎样判断它们是否相交?若相交,求出交点坐标。

    解法1解答:

    由端点坐标可知线段AB和CD的参数方程分别为:

     

    如果线段AB和CD相交,则存在和,使下面的方程组:

     

    由(1)式,(2)式即可求出和:

    将求得的和代入(3)式,若满足(3)式,则线段AB和CD所在的直线相交。此时如果有:

     

    则线段AB和CD相交,否则不相交。令代入线段AB的参数方程中或者令代入线段CD的参数方程即可求出交点坐标。

    解法2解答:

    由端点坐标可知线段AB和CD的参数方程分别为:

     

    线段AB和CD在z=0平面上的正投影线段A’B’和C’D’端点坐标分别为

    根据书中第一节介绍的方法(本答案不再重复该方法)可以判断出A’B’和C’D’是否有交点,如果没有交点,则线段AB和CD也没有交点。

    如果有交点,假设交点坐标为。因为做的是正投影,所以该交点对应的线段上的被投影点的x、y坐标值相同。假设线段AB和CD上对应该交点的点的坐标分别为。将坐标值分别代入线段AB和CD的参数方程中,可以分别计算出,如果=,则线段AB和CD相交,且交点坐标为,否则不相交。

    2. 写一个算法,能迅速地判断一条直线与一个凸多边形是否相交,若相交求出交点。

    解答:

    设直线由两点确定,凸多边形由顶点序列、···(共n个顶点)确定。

    算法的基本思想是:取多边形一条边,判断该边的两个端点是否在直线的同侧,如果在同侧,则该边与直线无交点;如果两个端点在直线的异侧,则线段与直线有交点,计算交点。依次检查多边形的所有边即可求出多边形与直线的所有交点,因为是凸多边形,所以交点最多有两个,算法可以在求出两个交点后就停止。判断点在直线的哪一侧可使用第四节第二部分中介绍的方法,计算交点采用第一节中介绍的线段求交点中使用的方法。

    算法具体过程如下:

    (1)    首先计算A=y2-y1;B=x1-x2;C=x2y1-x1y2

    (2)    取多边形的P0点为P1,计算d1=A*P1.x+B*p1.y+C

    (3)    for (i=1; i<=n; i++)

    {

      1)       取多边形的下标为i%n的点为P2(这样可以在i=n时取P0点);

      2)       计算d2=A*p2.x+B*p2.y+C

      3)       if (d1==0),表明P1点在直线上,P1点是一个交点;

      4)       else if (d1*d2<0),表明P1和P2点在直线的异侧,该边与直线有交点,计算交点:

      delta = (p2.x - p1.x) * (y1 - y2) - (x1 - x2) * (p2.y - p1.y);

      t = ((x1 - p1.x) * (y1 - y2) - (y1 - p1.y) * (x1 - x2)) / delta;

      交点jdp的x,y坐标值分别为:

      x = p1.x + (p2.x - p1.x) * t;

      y = p1.y + (p2.y - p1.y) * t

      5)       如果已经求得两个交点,则算法结束,否则令p1=p2,d1=d2;

     }

    (4)    如果没有求出交点,则直线与多边形不相交。

    该算法当直线与多边形的一条边重合时,将该边的两个端点作为交点。

    算法实现代码如下:

    void CHW1View::GetJD(CArray<CPoint,CPoint>* points, int x1, int y1, int x2, int y2, CArray<CPoint,CPoint>* jd)

    {

             int d1,d2;

             int a = y2 - y1;

             int b = x1 - x2;

             int c = x2*y1 - x1*y2;

             CPoint p1 = (CPoint)points->GetAt(0);

             CPoint p2;

             d1 = a * p1.x + b * p1.y + c;

             int n = points->GetSize();

             for (int i=1;i<=n;i++)

             {

                       p2 = (CPoint)points->GetAt(i%n);

                       d2 = a * p2.x + b * p2.y + c;

                       if (d1 == 0)

                       {

                                jd->Add(p1);

                       }

                       else if ((d1<0 && d2>0) || (d1>0 && d2<0))

                       {

                                double delta = (p2.x - p1.x) * (y1 - y2) - (x1 - x2) * (p2.y - p1.y);

                                double t = ((x1 - p1.x) * (y1 - y2) - (y1 - p1.y) * (x1 - x2)) / delta;

                                CPoint jdp;

                                jdp.x = (int)(p1.x + (p2.x - p1.x) * t);

                                jdp.y = (int)(p1.y + (p2.y - p1.y) * t);

                                jd->Add(jdp);

                       }

                       if (jd->GetSize() == 2) return;

                       p1 = p2;d1 = d2;

             }

    }

    代码中points存放多边形顶点坐标,jd存放计算得到的交点坐标,x1,y1,x2,y2为直线上的两点坐标。

  • 相关阅读:
    HDOJ1267 下沙的沙子2[DP或卡特兰数]
    HDOJ1711 Number Sequence[KMP模版]
    HDOJ2546 饭卡[DP01背包问题]
    寻找必败态——一类博弈问题的快速解法
    kmp 模版
    网络流题目
    HDOJ1261 字串数[组合+大数]
    传说中效率最高的最大流算法(Dinic) [转]
    ACM博弈论
    HDOJ1061 Rightmost Digit[简单数学题]
  • 原文地址:https://www.cnblogs.com/qq1337822982/p/10810256.html
Copyright © 2020-2023  润新知