zoukankan      html  css  js  c++  java
  • 临时算法文件

    // 二维点转三维函数[核心]
    // 输入参数 : 转换平面上的点数组,二维点pt2DIn
    // 输出参数 : pt3DOut
    // 返回值 : 成功返回true,失败返回false
    bool CGMap2DTo3DDlg::Point2Dto3D_Ext2(CArray<POINT2D3D,POINT2D3D> &aryPlanePts,POINT2D pt2DIn,POINT3D &pt3DOut)
    {
        if(aryPlanePts.GetCount() < 3) return false;

        // 计算转换平面法向(ra,rb,rc)
        POINT3D A = aryPlanePts[0].pt3d;
        POINT3D B = aryPlanePts[1].pt3d;
        POINT3D C = aryPlanePts[2].pt3d;

        //方向矢量
        double bcx = B.X - C.X;
        double bcy = B.Y - C.Y;
        double bcz = B.Z - C.Z;

        double bax = B.X - A.X;
        double bay = B.Y - A.Y;
        double baz = B.Z - A.Z;

        //平面法矢量
        double ra,rb,rc;
        ra = bcy*baz - bay*bcz;
        rb = bax*bcz - bcx*baz;
        rc = bcx*bay - bax*bcy;   
        normalize(ra,rb,rc);

    #if 0
        double rd = -(ra*aryPlanePts[0].pt3d.X + rb*aryPlanePts[0].pt3d.Y + rc*aryPlanePts[0].pt3d.Z);
        // 转换
        Point2Dto3D_Ext2(ra,rb,rc,rd,pt2DIn,pt3DOut);
    #else// x,y成比例,z按照面法向与面上任意矢量点积为0来计算 2010.6.21
        double L_minx,L_maxx,L_miny,L_maxy;
        L_minx = L_maxx = aryPlanePts[0].pt2d.X;
        L_miny = L_maxy = aryPlanePts[0].pt2d.Y;
        double D_minx,D_maxx,D_miny,D_maxy;
        D_minx = D_maxx = aryPlanePts[0].pt3d.X;
        D_miny = D_maxy = aryPlanePts[0].pt3d.Y;
        double D_minz,D_maxz;
        D_minz = D_maxz = aryPlanePts[0].pt3d.Z;
        for (int i = 1; i < aryPlanePts.GetCount(); i++)
        {
            if (L_minx > aryPlanePts[i].pt2d.X)
            {
                L_minx = aryPlanePts[i].pt2d.X;
                D_minx = aryPlanePts[i].pt3d.X;
            }

            if (L_miny > aryPlanePts[i].pt2d.Y)
            {
                L_miny = aryPlanePts[i].pt2d.Y;       
                D_minz = aryPlanePts[i].pt3d.Z;
            }

            if (L_maxx < aryPlanePts[i].pt2d.X)
            {
                L_maxx = aryPlanePts[i].pt2d.X;
                D_maxx = aryPlanePts[i].pt3d.X;
            }

            if (L_maxy < aryPlanePts[i].pt2d.Y)
            {
                L_maxy = aryPlanePts[i].pt2d.Y;
                D_maxz = aryPlanePts[i].pt3d.Z;
            }

            if (D_miny > aryPlanePts[i].pt3d.Y)        
                D_miny = aryPlanePts[i].pt3d.Y;
            if (D_maxy < aryPlanePts[i].pt3d.Y)        
                D_maxy = aryPlanePts[i].pt3d.Y;
        }

        if ( (L_maxx - L_minx) != 0)
            pt3DOut.X = ( (pt2DIn.X-L_minx)/(L_maxx-L_minx) ) * (D_maxx-D_minx) + D_minx;
        else// 所有控制点X坐标一致
            pt3DOut.X = D_minx;

        double dy = L_maxy-L_miny;
        if ( dy != 0 )
            pt3DOut.Z = ( (pt2DIn.Y-L_miny)/(L_maxy-L_miny) ) * (D_maxz-D_minz) + D_minz;
        else
            pt3DOut.Z = A.Z;

        if (rb != 0)
        {
            pt3DOut.Y = (ra * (A.X - pt3DOut.X) + rc * (A.Z - pt3DOut.Z) + rb * A.Y)/rb;
        }
        else// 垂直Y轴
            pt3DOut.Y = A.Y;
        //if ( (L_maxy - L_miny) != 0)
        //    pt3DOut.Y = ( (pt2DIn.Y-L_miny)/(L_maxy-L_miny) ) * (D_maxy-D_miny) + D_miny;
        //else// 所有控制点Y坐标一致
        //    pt3DOut.Y = D_miny;

        //if(rc != 0)
        //{
        //    pt3DOut.Z = (ra*A.X + rb*A.Y + rc*A.Z - ra*pt3DOut.X - rb*pt3DOut.Y)/rc;
        //}
        ////垂直Z轴,不会出现 - 会出现
        //else
        //{
        //    //存在问题

        //    //距离不变性
        //    //pt3DOut.Z = sqrt( (pt2DIn.X - A.X)*(pt2DIn.X - A.X) + (pt2DIn.Y - A.Y)*(pt2DIn.Y - A.Y) ) - A.Z;

        //    // ml 改为直接使用某点的z值 2010.6.8
        //    //pt3DOut.Z = A.Z;
        //   
        //    // 沿Y轴方向进行Z值变化 - 针对向下的钻孔情况剖面
        //    double dy = D_maxy-D_miny;
        //    if ( dy != 0 )
        //        pt3DOut.Z = (pt3DOut.Y-D_miny)*(D_maxz-D_minz)/dy + D_minz;
        //    else
        //        pt3DOut.Z = A.Z;
        //}
    #endif
        return true;
    }

    // 二维线转三维函数[核心]
    // 输入参数 : 线的端点Ln_pt1,Ln_pt2,隐含参数控制点数组m_ctrlPointsArray
    // 输出参数 : 转换后的交点数组tempArray
    // 返回值 : 成功返回true,失败返回false
    bool CGMap2DTo3DDlg::Line2Dto3D_Ext(POINT2D Ln_pt1,POINT2D Ln_pt2,CArray<POINT2D3D,POINT2D3D> &tempArray)
    {
        //CArray<POINT2D3D,POINT2D3D> tempArray;
        // 如果tempArray数组内容不为空,清空之
        if (tempArray.GetSize() > 0)
            tempArray.RemoveAll();

        POINT2D3D ptInter;
        int polyid1,polyid2;
        POINT2D3D ln_node0,ln_node1;
        ln_node0.pt2d.X = Ln_pt1.X;
        ln_node0.pt2d.Y = Ln_pt1.Y;
        ln_node1.pt2d.X = Ln_pt2.X;
        ln_node1.pt2d.Y = Ln_pt2.Y;

        double l_minx = (Ln_pt1.X < Ln_pt2.X) ? Ln_pt1.X : Ln_pt2.X;
        double l_miny = (Ln_pt1.Y < Ln_pt2.Y) ? Ln_pt1.Y : Ln_pt2.Y;
        double l_maxx = (Ln_pt1.X > Ln_pt2.X) ? Ln_pt1.X : Ln_pt2.X;
        double l_maxy = (Ln_pt1.Y > Ln_pt2.Y) ? Ln_pt1.Y : Ln_pt2.Y;

        bool bSucc1 = PointInValidateRgn(ln_node0,polyid1);
        bool bSucc2 = PointInValidateRgn(ln_node1,polyid2);
        //if (bSucc1)    // 添加第一个点(起始点)
        // 首点必须添加做为排序基准点
        tempArray.Add(ln_node0);
        double maxx,maxy,minx,miny;
        maxx = maxy = -999999999999;
        minx = miny = 999999999999;
        if ( (polyid1 == polyid2) && (polyid1 != -1))
        {// 两点都在同一个poly中,并且不能都在可转换区域外
            // 由于判断点在多边形内PointInValidateRgn时已经将在转换范围内的点二维坐标转为三维,所以不必再次转换了
            // 对于两个点都落在转换区域外的line需要计算线与区域交点
        }
        else
        {// 两点不在一个转换平面内,需要计算一系列的交点,遍历所有的边计算交点
            CArray<POINT2D3D,POINT2D3D> poly;
            for (long i = 0; i < m_ctrlpolyIndexArray.GetSize(); i++)
            {
                int index = m_ctrlpolyIndexArray.GetAt(i);
                if (index != -1)
                {
                    poly.Add(m_ctrlPointsArray[index]);
                    if (minx > m_ctrlPointsArray[index].pt2d.X) minx = m_ctrlPointsArray[index].pt2d.X;
                    if (miny > m_ctrlPointsArray[index].pt2d.Y) miny = m_ctrlPointsArray[index].pt2d.Y;
                    if (maxx < m_ctrlPointsArray[index].pt2d.X) maxx = m_ctrlPointsArray[index].pt2d.X;
                    if (maxy < m_ctrlPointsArray[index].pt2d.Y) maxy = m_ctrlPointsArray[index].pt2d.Y;
                }
                else
                {// -1表示结束了一个poly定义
                    long count = poly.GetCount();               
                    double r_minx = max(minx, l_minx);
                    double r_miny = max(miny, l_miny);
                    double r_maxx = min(maxx, l_maxx);
                    double r_maxy = min(maxy, l_maxy);
                    if (r_minx <= r_maxx && r_miny <= r_maxy)
                    {//两矩形相交
                        for (long j = 0; j < count-1; j++)
                        {                       
                            if (IntersectLineLine(poly[j].pt2d,poly[j+1].pt2d,Ln_pt1,Ln_pt2,ptInter.pt2d) == 1)
                            {// 相交有交点ptInter ,当交点在poly区域内时,此点可以被添加到交点数组中
                                // 先用交点是否在线段ln_node0,ln_node1之间简单判断需不需要进一步判断点在poly多边形内,如果在则做进一步判断
                                // 这样做有助于加快判断速度,节约时间
                                double resX = (ptInter.pt2d.X-ln_node0.pt2d.X)*(ptInter.pt2d.X-ln_node1.pt2d.X);
                                double resY = (ptInter.pt2d.Y-ln_node0.pt2d.Y)*(ptInter.pt2d.Y-ln_node1.pt2d.Y);
                                if (resX <= ZERO && resY <= ZERO)
                                {// 交点在线段内,添加入交点数组并排序(注意不能将不在线段内得点加入交点集中)       
                                    //if (PointInValidateRgn(ptInter,polyid1) == true)//交点在转换区域内    错的bug,应该是在poly中    2010.6.23

                                    //resX = (ptInter.pt2d.X-minx)*(ptInter.pt2d.X-maxx);
                                    //resY = (ptInter.pt2d.Y-miny)*(ptInter.pt2d.Y-maxy);

                                    resX = (ptInter.pt2d.X-poly[j].pt2d.X)*(ptInter.pt2d.X-poly[j+1].pt2d.X);
                                    resY = (ptInter.pt2d.Y-poly[j].pt2d.Y)*(ptInter.pt2d.Y-poly[j+1].pt2d.Y);
                                    if (resX <= ZERO && resY <= ZERO)
                                    {
                                        //bool bIn = IsPointInPolygon(poly,ptInter.pt2d);
                                        //if (bIn) // 在多边形内,返回真值
                                        {                                       
                                            // 二维点转三维,直接存储再ptIn.pt3d中 - 如果poly的点不够3个返回失败
                                            if (Point2Dto3D_Ext2(poly,ptInter.pt2d,ptInter.pt3d))
                                                AddToSortArray(tempArray,ptInter);                               
                                        }
                                    }
                                }                       
                            }
                        }
                    }
                    poly.RemoveAll();

                    maxx = maxy = -999999999999;
                    minx = miny = 999999999999;
                }
            }
        }

        // 如果首点不在可转化区域内,移除首点
        if (!bSucc1) tempArray.RemoveAt(0);

        if (bSucc2)    // 如果尾点在可转化区域添加最后一个点(尾点)
            tempArray.Add(ln_node1);

        return true;
    }

    // 判断两POINT2D点是否同位置
    bool CGMap2DTo3DDlg::IsEqual(POINT2D pt1,POINT2D pt2)
    {
        if ( fabs(pt1.X-pt2.X) < ZERO && fabs(pt1.Y-pt2.Y) < ZERO)
            return true;
        return false;
    }

    bool CGMap2DTo3DDlg::IsEqual(IGNodePtr pNd1, IGNodePtr pNd2)
    {
        if (!pNd1 || !pNd2)
            return false;
        double x1,y1,z1,x2,y2,z2;
        pNd1->get_X(&x1);
        pNd1->get_Y(&y1);
        pNd1->get_Z(&z1);

        pNd2->get_X(&x2);
        pNd2->get_Y(&y2);
        pNd2->get_Z(&z2);

        if (fabs(x1-x2) < ZERO && fabs(y1-y2) < ZERO && fabs(z1-z2) < ZERO)
            return true;
        return false;
    }

    // 判断 点 是否在有效地转换区域,在则返回true,否则返回false
    bool CGMap2DTo3DDlg::PointInValidateRgn(POINT2D3D &ptIn, int &polyID)
    {
        int polyid = 0;
        CArray<POINT2D3D,POINT2D3D> poly;
        for (long i = 0; i < m_ctrlpolyIndexArray.GetSize(); i++)
        {
            int index = m_ctrlpolyIndexArray.GetAt(i);
            if (index != -1)
            {
                poly.Add(m_ctrlPointsArray[index]);
            }
            else
            {// -1表示结束了一个poly定义
                long count = poly.GetCount();
                if (count < 1) continue;
                // 如果poly是闭合的,则开始计算,如果没有闭合,程序进行闭合
                if (IsEqual(poly[0].pt2d,poly[count-1].pt2d) == false)
                    poly.Add(poly[0]);

                // 一个poly完毕,开始计算
                bool bIn = IsPointInPolygon(poly,ptIn.pt2d);
                if (bIn) // 在多边形内,返回真值
                {
                    polyID = polyid;               
                    // 二维点转三维,直接存储再ptIn.pt3d中 - 如果poly的点不够3个返回失败
                    Point2Dto3D_Ext2(poly,ptIn.pt2d,ptIn.pt3d);
                    return true;
                }
                polyid++;
                // 清除上一个poly,继续下一个poly
                poly.RemoveAll();
            }
        }   

        // 在区域外不转换,写入什么值合适???
        polyID = -1;
        return false;
    }

    void CGMap2DTo3DDlg::AddToSortArray(CArray<POINT2D3D,POINT2D3D> &aryPlanePts,POINT2D3D ptNew)
    {// 注: aryPlanPts中的元素是已经根据距离aryPlanPts[0]的二维距离排好序的,我们只要将ptNew添加到合适的位置即可
        int count = aryPlanePts.GetCount();
        if (count <= 0)
        {//  Error : aryPlanePts中必须不为空,它的第一个元素
            //aryPlanePts.Add(ptNew);
            return;
        }   

        double quater_dis = (aryPlanePts[0].pt2d.X - ptNew.pt2d.X)*(aryPlanePts[0].pt2d.X - ptNew.pt2d.X) +
            (aryPlanePts[0].pt2d.Y - ptNew.pt2d.Y) * (aryPlanePts[0].pt2d.Y - ptNew.pt2d.Y);

        double d1,d2;
        for (int i = 1; i < count-1; i++)
        {
            d1 = (aryPlanePts[0].pt2d.X - aryPlanePts[i].pt2d.X)*(aryPlanePts[0].pt2d.X - aryPlanePts[i].pt2d.X) +
                (aryPlanePts[0].pt2d.Y - aryPlanePts[i].pt2d.Y) * (aryPlanePts[0].pt2d.Y - aryPlanePts[i].pt2d.Y);
            d2 = (aryPlanePts[0].pt2d.X - aryPlanePts[i+1].pt2d.X)*(aryPlanePts[0].pt2d.X - aryPlanePts[i+1].pt2d.X) +
                (aryPlanePts[0].pt2d.Y - aryPlanePts[i+1].pt2d.Y) * (aryPlanePts[0].pt2d.Y - aryPlanePts[i+1].pt2d.Y);

            // 如果距离一样,说明点为重复点,不用添加
            if (IsEqual(ptNew.pt2d,aryPlanePts[i].pt2d) == true || IsEqual(ptNew.pt2d,aryPlanePts[i+1].pt2d) == true)
                return;
            if ( (quater_dis-d1)*(quater_dis-d2) < ZERO )
            {// 找到位置,应该将ptNew插入 i 后, i+1前的位置
                aryPlanePts.InsertAt(i+1,ptNew);
                return;
            }
        }

        aryPlanePts.Add(ptNew);
    }

     

    // 点P(pa,pb,pc)到平面A的垂直距离(平面方程Ax + By + Cz + D = 0)
    double PointDistancePlane(double pa,double pb,double pc, double aa,double ab,double ac, double ad)
    {       
        double dist = 1;
        double module = Module(aa,ab,ac);
        if (fabs(module) > 0.000001f)
        {
            dist = fabs(aa*pa + ab*pb + ac*pc + ad) /module;
        }
        return dist;
    }

    // 向量P绕任意轴A顺时针旋转theta(弧度值)结果Q
        void  AnyRotate(double &qa, double &qb, double &qc, double pa, double pb, double pc, double aa, double ab, double ac, double theta)
        {
            double temp[3];
            Cross(temp[0],temp[1],temp[2],pa,pb,pc,aa,ab,ac);
            double t = pa * aa + pb * ab + pc * ac;

            qa = pa*cos(theta) + temp[0]*sin(theta) + pa*t*(1-cos(theta));
            qb = pb*cos(theta) + temp[1]*sin(theta) + pb*t*(1-cos(theta));
            qc = pc*cos(theta) + temp[2]*sin(theta) + pc*t*(1-cos(theta));
        }

     

    void  normalize(double &x, double &y, double &z)
    {
        double module = sqrt(x*x + y*y + z*z);

        if (fabs(module) > 0.000001f)
        {
            x /= module;
            y /= module;
            z /= module;
        }
    }

    double Module(double x, double y, double z)
    {
        return sqrt(x*x + y*y + z*z);
    }

    double Dot( double x1,double y1,double z1, double x2,double y2, double z2)
    {
        return (x1*x2 + y1*y2 + z1*z2);
    }

    void Cross(double &x, double &y, double &z, double x1,double y1,double z1, double x2,double y2, double z2)
    {
        x = y1 * z2 - z1 * y2;
        y = z1 * x2 - x1 * z2;
        z = x1 * y2 - y1 * x2;
    }

    // 判断点是否在多边形内(包括凹多边形和凸多边形) - 二维平面
    // 定义判断,从点向水平(或垂直方向做延长线)计算交点,看在点右边的交点数目,奇数表示在poly内,偶数表示在poly外
    bool CGMap2DTo3DDlg::IsPointInPolygon(CArray<POINT2D3D,POINT2D3D> &poly,POINT2D pt2DIn)
    {
    #if 1 // 射线算法 - 适用于凹凸多边形
        long count=0;
        //float sub_count=0;
        for (long i = 0; i < poly.GetCount()-1; i++)
        {
            POINT2D Ln2_pt1 = poly.GetAt(i).pt2d;
            POINT2D Ln2_pt2 = poly.GetAt(i+1).pt2d;       
            if (Ln2_pt1.Y == Ln2_pt2.Y)
                continue;
            if ( (pt2DIn.Y < Ln2_pt1.Y) && (pt2DIn.Y < Ln2_pt2.Y))// 交点在p1p2延长线上
                continue;
            if ( (pt2DIn.Y >= Ln2_pt1.Y) && (pt2DIn.Y >= Ln2_pt2.Y))// 交点在p1p2延长线上
                continue;
            // 求交点的 X 坐标 --------------------------------------------------------------
            double x = (pt2DIn.Y - Ln2_pt1.Y) * (Ln2_pt2.X - Ln2_pt1.X) / (Ln2_pt2.Y - Ln2_pt1.Y) + Ln2_pt1.X;

            if ( x > pt2DIn.X )
                count++; // 只统计单边交点    
        }
        if (count%2==0)//有进有出,表示在点ptInter在poly外
            return false;
    #else// 叉乘算法只适用于凸多边形
        double res;
        bool bset = false;
        for (long i = 0; i < poly.GetCount()-1; i++)
        {
            POINT2D Ln2_pt1 = poly.GetAt(i).pt2d;
            POINT2D Ln2_pt2 = poly.GetAt(i+1).pt2d;

            double res2 = (Ln2_pt2.X-Ln2_pt1.X) * (pt2DIn.Y-Ln2_pt1.Y) - (Ln2_pt2.Y-Ln2_pt1.Y)*(pt2DIn.X-Ln2_pt1.X);
            if (res2 == 0)
            {
                if ( (pt2DIn.X-Ln2_pt1.X)*(pt2DIn.X-Ln2_pt2.X) <= ZERO && (pt2DIn.Y-Ln2_pt1.Y)*(pt2DIn.Y-Ln2_pt2.Y) <= ZERO )
                    return true;           
            }
            else
            {
                if (!bset)
                {
                    res = res2;
                    bset = true;
                }
                else
                {
                    if (res*res2 < 0)// 不在面内
                        return false;
                }           
            }
        }
    #endif
        return true;
    }

  • 相关阅读:
    BF算法和KMP算法
    Python课程笔记 (五)
    0268. Missing Number (E)
    0009. Palindrome Number (E)
    0008. String to Integer (atoi) (M)
    0213. House Robber II (M)
    0198. House Robber (E)
    0187. Repeated DNA Sequences (M)
    0007. Reverse Integer (E)
    0006. ZigZag Conversion (M)
  • 原文地址:https://www.cnblogs.com/mazhenyu/p/1757230.html
Copyright © 2011-2022 走看看