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;
    }

  • 相关阅读:
    git创建分支与合并分支
    web实现点击左侧导航,右侧加载不同的网页(这种布局多用于后台管理系统)
    小程序通过用户授权获取手机号之getPhoneNumber
    git 本地仓库与远程仓库建立连接
    multipartUpload上传图片到阿里云
    5月23日——SPA单页面应用的原理
    5月23日——谈谈对BFC规范的理解
    5月11日——IOS下如何检测用户是否安装微信
    5月10日——华为内置虚拟键问题
    移动端WEB开发,click,touch,tap事件浅析
  • 原文地址:https://www.cnblogs.com/mazhenyu/p/1757230.html
Copyright © 2011-2022 走看看