1. 程式人生 > >objectarx 多段線自交檢查

objectarx 多段線自交檢查

 

 只支援直線段的多段線檢查,因為主要用了初中的知識,一元一次方程求交點,詳細的說就是,把多段線上相鄰的兩個點構成一條直線段,然後每條直線段與剩餘的直線段求交點,一條直線段就代表一個一元一次方程,知道兩點就知道這個方程是什麼樣的。
求出交點之後得判斷這個點是否是多段線上本身的點,判斷方法是判斷求出來的交點與構成交點的兩條直線段的4個點做比較,如果點的誤差在1e-4之內,就認為這個交點是在多段線的端點上,不作為要求的交點。
除了這種可能之外,所求交點有可能是在直線段的延長線上,通過觀察可以知道,如果交點在任意一條直線段兩個端點之間,則可以知道這個交點到這條直線段兩個端點的距離都要小於這個直線段兩個端點的距離,如果交點到兩個端點的距離大於了兩個端點的距離,則說明這個交點是線上段的延長線上,也不作為要求的交點。

還需要注意的地方是,要考慮直線段垂直於x軸的情況,因為要求直線方程時的斜率時,分母不能為0,需要把直線垂直於x軸的情況單獨考慮。

除了這種思路外,還可以直接使用intersectwith函式來做,相交型別是都不延長,(不知是直接炸開這個多段線好,還是分割這個多段線好)。總之首先得得到兩個端點之間的線段。這樣作,不僅支援直線段的多段線,還支援帶凸度的,帶圓弧的多段線了。
下面放出使用到的函式:

static    bool IsEqual(const AcGePoint2d & firstPoint, const AcGePoint2d & secondPoint, double tol)
    {
        return (fabs(firstPoint.x - secondPoint.x) < tol&&
            fabs(firstPoint.y - secondPoint.y) < tol);
    }

 

struct StLine
{
	AcGePoint2d ptPre;

	AcGePoint2d ptNext;

};

 

static bool JiaoDian(StLine &l1, StLine &l2, AcGePoint3d& ptCenter) {

        double x0, y0, x1, y1, x2, y2, x3, y3;

        x0 = l1.ptPre.x;
        y0 = l1.ptPre.y;

        x1 = l1.ptNext.x;
        y1 = l1.ptNext.y;

        x2= l2.ptPre.x;
        y2 = l2.ptPre.y;

        x3 = l2.ptNext.x;
        y3 = l2.ptNext.y;


        if (x0 - x1 == 0) {
            if (x2 - x3 == 0)
            {
                if (IsEqual(l1.ptPre, l2.ptPre, 1e-4) ||
                    IsEqual(l1.ptPre, l2.ptNext, 1e-4) ||
                    IsEqual(l1.ptNext, l2.ptPre, 1e-4) ||
                    IsEqual(l1.ptNext, l2.ptNext, 1e-4)) {

                    acutPrintf(L"存在重疊的部分\n");
                    return false;
                }
                else {
                    acutPrintf(L"存在平行的部分\n");
                    return false;

                }
            }
            else {

                double k2 = (y3 - y2) / (x3 - x2);

                double b2 = (y2 - k2*x2);

                AcGePoint2d jd;

                jd.x = x0;
                jd.y = k2*x0 + b2;

                double distance = l1.ptPre.distanceTo(l1.ptNext);
                double dis1 = jd.distanceTo(l1.ptPre);
                double dis2 = jd.distanceTo(l1.ptNext);

                if (dis1 < distance&&dis2 < distance) {

                    if (IsEqual(l1.ptPre, jd, 1e-4) ||
                        IsEqual(jd, l2.ptNext, 1e-4) ||
                        IsEqual(l1.ptNext, jd, 1e-4) ||
                        IsEqual(jd, l2.ptPre, 1e-4)) {

                        return false;
                    }

                    ptCenter.x = jd.x;
                    ptCenter.y = jd.y;
                    ptCenter.z = 0;

                    return true;

                }
                else {
                    return false;
                }
            }
        }
        else if (x3 - x2 == 0) {
        if (x0 - x1 != 0)
        {
            double k2 = (y1 - y0) / (x1 - x0);

            double b2 = (y1 - k2*x1);

            AcGePoint2d jd;

            jd.x = x3;
            jd.y = k2*x3 + b2;

            double distance = l1.ptPre.distanceTo(l1.ptNext);
            double dis1 = jd.distanceTo(l1.ptPre);
            double dis2 = jd.distanceTo(l1.ptNext);

            if (dis1 < distance&&dis2 < distance) {

                if (IsEqual(l1.ptPre, jd, 1e-4) ||
                    IsEqual(jd, l2.ptNext, 1e-4) ||
                    IsEqual(l1.ptNext, jd, 1e-4) ||
                    IsEqual(jd, l2.ptPre, 1e-4)) {

                    return false;
                }

                ptCenter.x = jd.x;
                ptCenter.y = jd.y;
                ptCenter.z = 0;

                return true;

            }
            //交點在延長線上
            else {
                return false;
            }


        }
        else {
            if (IsEqual(l1.ptPre, l2.ptPre, 1e-4) ||
                IsEqual(l1.ptPre, l2.ptNext, 1e-4) ||
                IsEqual(l1.ptNext, l2.ptPre, 1e-4) ||
                IsEqual(l1.ptNext, l2.ptNext, 1e-4)) {

                acutPrintf(L"存在重疊的部分\n");
                return false;
            }
            else {
                acutPrintf(L"存在平行的部分\n");
                return false;
            }
        }
        }
        else {

            double k1 = (y1 - y0) / (x1 - x0);

            double b1 = (y1 - k1*x1);

            double k2 = (y3 - y2) / (x3 - x2);

            double b2 = (y2 - k2*x2);

            AcGePoint2d jd;

            if (k1 == k2) {
                return false;
            }

            double x0 = (b2 - b1) / (k1 - k2);
            jd.x = x0;

            jd.y = k1*x0 + b1;

            double distance = l1.ptPre.distanceTo(l1.ptNext);
            double dis1 = jd.distanceTo(l1.ptPre);
            double dis2 = jd.distanceTo(l1.ptNext);

            if (dis1 < distance&&dis2 < distance) {

                if (IsEqual(l1.ptPre, jd, 1e-4) ||
                    IsEqual(jd, l2.ptNext, 1e-4) ||
                    IsEqual(l1.ptNext, jd, 1e-4) ||
                    IsEqual(jd, l2.ptPre, 1e-4)) {

                    return false;
                }
                ptCenter.x = jd.x;
                ptCenter.y = jd.y;
                ptCenter.z = 0;

                return true;
            }
            else {
                return false;
            }
        }
  }