找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 1127|回复: 2

[ARX程序]:求闭合的无自交的pline的并集

[复制链接]
发表于 2005-9-9 11:55:03 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
合并两闭合的无自交的pline。
CAD本身也提供了域合并的功能,但是速度非常的慢。所以偶就自己写了试试,但是很多地方不好处理,如重线的处理还有漏洞,对于多个pline
的合并不好实现,因为对每两个返回的结果不知道怎么和其它的求交,而CAD的域合并返回的结果不管有多少的区域都作为一个处理.而且就算能完全正确,
速度也不会比CAD快, 求交点和判断点在区域的操作比较慢.各位如果有同样需求的不妨讨论一下,或者已有此类算法的高人请不吝赐教!


typedef CArray(AcGePoint3dArray,AcGePoint3dArray&) TPtArrArr;
typedef CArray(AcGeLineSeg3d,AcGeLineSeg3d&) TArrLineSeg3d;
"(" 为"<",显示不出来;

//点是否在区域内,bEdage--是否考虑边界
bool ptInArea(AcGePoint3d pt, AcGePoint3dArray& ptArr, bool bEdage = false);

//点表排序
bool sortPtb(AcGePoint3dArray & ptArr);

//取点距
double getDist(AcGePoint3d sp,AcGePoint3d ep);

//取中点
bool getMidPt(AcGePoint3d sp,AcGePoint3d ep,AcGePoint3d & midPt);

bool uniteSub(AcGePoint3dArray & ptArr1,AcGePoint3dArray & ptArr2,TPtArrArr & ptArrArr)
{
        register int i,j,k;
        int nLen1,nLen2;
        AcGePoint3d pt,pt1;
        AcGeLineSeg3d seg;
        TArrLineSeg3d segArr,segArr1,segArr2;

        ptArrArr.RemoveAll();
        nLen1 = ptArr1.length();
        nLen2 = ptArr2.length();
        if((nLen1 < 3) || (nLen2 < 3))
                return false;

                   //构造几何线段
        for(i=1;i<nLen1;i++)
        {
                seg.set(ptArr1[i-1],ptArr1);
                segArr1.Add(seg);
        }
        if (!ptArr1.first().isEqualTo(ptArr1.last()))
        {
                seg.set(ptArr1.last(),ptArr1.first());
                segArr1.Add(seg);
        }
        for(i=1;i<nLen2;i++)
        {
                seg.set(ptArr2[i-1],ptArr2);
                segArr2.Add(seg);
        }
        if (!ptArr2.first().isEqualTo(ptArr2.last()))
        {
                seg.set(ptArr2.last(),ptArr2.first());
                segArr2.Add(seg);
        }

        bool bIn1,bIn2;
        AcGePoint3dArray tmpArr;
        //裁剪线段
        bool bFlag;
        for(k=0;k<2;k++)
        {
          //k==0用segArr2裁剪segArr1的各线段,k==1用segArr1裁剪segArr2的各线段
                if (k == 1)
                {
                        //互换顺序
                        segArr.RemoveAll();
                        segArr.Append(segArr1);
                        segArr1.RemoveAll();
                        segArr1.Append(segArr2);
                        segArr2.RemoveAll();
                        segArr2.Append(segArr);
                        if (tmpArr.length() > 0)
                                tmpArr.removeSubArray(0,tmpArr.length()-1);
                        tmpArr.append(ptArr1);
                        ptArr1.removeSubArray(0,ptArr1.length()-1);
                        ptArr1.append(ptArr2);
                        ptArr2.removeSubArray(0,ptArr2.length()-1);
                        ptArr2.append(tmpArr);
                }

                for(i=0;i<segArr1.GetSize();i++)
                {
                        bIn1 = false;
                        bIn2 = false;
                        if(ptInArea(segArr1.startPoint(),ptArr2,false))
                                bIn1 = true;
                        if(ptInArea(segArr1.endPoint(),ptArr2,false))
                                bIn2 = true;
                       
                        if(tmpArr.length() > 0)
                                tmpArr.removeSubArray(0,tmpArr.length()-1);
                       
                        for(j=0;j<segArr2.GetSize();j++)
                        {
                                //相交线
                                if (segArr1.intersectWith(segArr2[j],pt))
                                {
                                        //滤除交点是端点的情况
        if(pt.isEqualTo(segArr1.startPoint()) || pt.isEqualTo(segArr1.endPoint()))
                        continue;
                                tmpArr.append(pt);
        }
        else//重合线
                {
          //对重合线的各种情况进行合并,考虑到效率,省略的函数和变量,写的比较累赘.
          //这一部分对重合线的处理存在漏洞
       if (segArr1.isOn(segArr2[j].startPoint()))
                          {
                        if (segArr1.isOn(segArr2[j].endPoint()))
                        {
                                                bFlag = true;
                                                        if (getDist(segArr1.startPoint(),segArr2[j].startPoint()) < getDist(segArr1.startPoint(),segArr2[j].endPoint()))
                                                        {
                                                                seg.set(segArr2[j].endPoint(),segArr1.endPoint());
                                                                if(getDist(segArr1.startPoint(),segArr2[j].startPoint()) > 1.0E-7)
                                                                {
                                                                        bFlag = false;
                                                                        segArr1.set(segArr1.startPoint(),segArr2[j].startPoint());
                                                                }
                                                                if(seg.length() > 1.0E-7)
                                                                {
                                                                        bFlag = false;
                                                                        segArr1.Add(seg);
                                                                }
                                                        }
                                                        else
                                                        {
                                                                seg.set(segArr2[j].startPoint(),segArr1.endPoint());
                                                                if(getDist(segArr1.startPoint(),segArr2[j].endPoint()) > 1.0E-7)
                                                                {
                                                                        bFlag = false;
                                                                        segArr1.set(segArr1.startPoint(),segArr2[j].endPoint());
                                                                }
                                                                if(seg.length() > 1.0E-7)
                                                                {
                                                                        bFlag = false;
                                                                        segArr1.Add(seg);
                                                                }
                                                        }
                                                        segArr2.RemoveAt(j--);
                                                        if(bFlag)
                                                        {
                                                                segArr1.RemoveAt(i--);
                                                                break;
                                                        }
                                                }
                                                else if (segArr2[j].isOn(segArr1.startPoint()))
                                                {
                                                        pt = segArr1.startPoint();
                                                        if(getDist(segArr1.endPoint(),segArr2[j].startPoint()) > 1.0E-7)
                                                                segArr1.set(segArr1.endPoint(),segArr2[j].startPoint());
                                                        if(getDist(pt,segArr2[j].endPoint()) > 1.0E-7)
                                                                segArr2[j].set(pt,segArr2[j].endPoint());
                                                }
                                                else if (segArr2[j].isOn(segArr1.endPoint()))
                                                {
                                                        pt = segArr1.endPoint();
                                                        if(getDist(segArr1.startPoint(),segArr2[j].startPoint()) > 1.0E-7)
                                                                segArr1.set(segArr1.startPoint(),segArr2[j].startPoint());
                                                        if(getDist(pt,segArr2[j].endPoint()) > 1.0E-7)
                                                                segArr2[j].set(pt,segArr2[j].endPoint());
                                                }
                                        }
                                        else if (segArr1.isOn(segArr2[j].endPoint()))
                                        {
                                                if (segArr2[j].isOn(segArr1.startPoint()))
                                                {
                                                        pt = segArr1.startPoint();
                                                        if(getDist(segArr1.endPoint(),segArr2[j].endPoint()) > 1.0E-7)
                                                                segArr1.set(segArr1.endPoint(),segArr2[j].endPoint());
                                                        if(getDist(pt,segArr2[j].startPoint()) > 1.0E-7)
                                                                segArr2[j].set(pt,segArr2[j].startPoint());
                                                }
                                                else if (segArr2[j].isOn(segArr1.endPoint()))
                                                {
                                                        pt = segArr1.endPoint();
                                                        if(getDist(segArr1.startPoint(),segArr2[j].endPoint()) > 1.0E-7)
                                                                segArr1.set(segArr1.startPoint(),segArr2[j].endPoint());
                                                        if(getDist(pt,segArr2[j].startPoint()) > 1.0E-7)
                                                                segArr2[j].set(pt,segArr2[j].startPoint());
                                                }
                                        }
                                        else if (segArr2[j].isOn(segArr1.startPoint()) && segArr2[j].isOn(segArr1.endPoint()))
                                        {
                                                if (getDist(segArr2[j].startPoint(),segArr1.startPoint()) < getDist(segArr2[j].startPoint(),segArr1.endPoint()))
                                                {
                                                        seg.set(segArr1.endPoint(),segArr2[j].endPoint());
                                                        if(getDist(segArr2[j].startPoint(),segArr1.startPoint()) > 1.0E-7)
                                                                segArr2[j].set(segArr2[j].startPoint(),segArr1.startPoint());
                                                        if(seg.length() > 1.0E-7)
                                                                segArr2.Add(seg);
                                                }
                                                else
                                                {
                                                        seg.set(segArr1.startPoint(),segArr2[j].endPoint());
                                                        if(getDist(segArr2[j].startPoint(),segArr1.endPoint()) > 1.0E-7)
                                                                segArr2[j].set(segArr2[j].startPoint(),segArr1.endPoint());
                                                        if(seg.length() > 1.0E-7)
                                                                segArr2.Add(seg);
                                                }
                                                segArr1.RemoveAt(i--);
                                                break;
                                        }
                                }
                        }
                       
                        //没有交点且该线段两端点不在另一区域中,删除该线段
                        if((tmpArr.length() <= 0) && bIn1 && bIn2)
                        {
                                segArr1.RemoveAt(i--);
                                continue;
                        }
                        else if (tmpArr.length() == 1)
                        {
                          //只有一的交点,分别裁剪两端
                                if (!bIn1)
                                {
                                        if(getDist(segArr1.startPoint(),tmpArr.first()) > 1.0E-7)
                                                segArr1.set(segArr1.startPoint(),tmpArr.first());
                                }
                                else if(!bIn2)
                                {
                                        if(getDist(tmpArr.first(),segArr1.endPoint()) > 1.0E-7)
                                                segArr1.set(tmpArr.first(),segArr1.endPoint());
                                }
                        }
                        else if (tmpArr.length() >= 2)
                        {
                          //有多个交点时,先裁剪两端,然后裁剪各段
                          //对交点排序
                                sortPtb(tmpArr);
                                //确定线段两端点与交点的点序
                                if(getDist(segArr1.startPoint(),tmpArr.first()) < getDist(segArr1.startPoint(),tmpArr.last()))
                                {
                                        seg.set(tmpArr.last(),segArr1.endPoint());
                                        if (!bIn1 && (getDist(segArr1.startPoint(),tmpArr.first()) > 1.0E-7))
                                                segArr1.set(segArr1.startPoint(),tmpArr.first());
                                        if (!bIn2 && (seg.length() > 1.0E-7))
                                                segArr1.Add(seg);
                                }
                                else
                                {
                                        seg.set(tmpArr.first(),segArr1.endPoint());
                                        if (!bIn1 && (getDist(segArr1.startPoint(),tmpArr.last()) > 1.0E-7))
                                                segArr1.set(segArr1.startPoint(),tmpArr.last());
                                        if (!bIn2 && (seg.length() > 1.0E-7))
                                                segArr1.Add(seg);
                                }
                                for(j=1;j<tmpArr.length();j++)
                                {
                                        getMidPt(tmpArr[j-1],tmpArr[j],pt);
                                        if (!ptInArea(pt,ptArr2,false))
                                        {
                                                seg.set(tmpArr[j-1],tmpArr[j]);
                                                segArr1.Add(seg);
                                        }
                                }
                        }
                }
        }

        //构造闭合点组
        bool bEqual,bClose;
        segArr.RemoveAll();
        segArr.Append(segArr1);
        segArr.Append(segArr2);

        while (segArr.GetSize() > 0)
        {
                if(tmpArr.length() > 0)
                        tmpArr.removeSubArray(0,tmpArr.length()-1);
                tmpArr.append(segArr[0].startPoint());
                tmpArr.append(segArr[0].endPoint());
                segArr.RemoveAt(0);
                bClose = false;
                while (segArr.GetSize() > 0)
                {
                        bEqual = false;
                        for(i=0;i<segArr.GetSize();i++)
                        {
                                if (tmpArr.last().isEqualTo(segArr.startPoint()))
                                {
                                        bEqual = true;
                                        tmpArr.append(segArr.endPoint());
                                        segArr.RemoveAt(i--);
                                        if (tmpArr.first().isEqualTo(tmpArr.last()))
                                        {
                                                bClose = true;
                                                ptArrArr.Add(tmpArr);
                                        }
                                        break;
                                }
                                else if (tmpArr.last().isEqualTo(segArr.endPoint()))
                                {
                                        bEqual = true;
                                        tmpArr.append(segArr.startPoint());
                                        segArr.RemoveAt(i--);
                                        if (tmpArr.first().isEqualTo(tmpArr.last()))
                                        {
                                                bClose = true;
                                                ptArrArr.Add(tmpArr);
                                        }
                                        break;
                                }
                        }

                        if(!bEqual || bClose)
                                break;
                }
                if(!bClose)
                        break;
        }

        if(ptArrArr.GetSize() <= 0)
        {
                ptArrArr.Add(ptArr1);
                ptArrArr.Add(ptArr2);
        }

        return true;
}


bool sortPtb(AcGePoint3dArray & ptArr)
{
        if (ptArr.isEmpty())
                return false;
        register int i,j,nLen;
        nLen = ptArr.length();
        for (i=0;i < nLen-1;i++)
        {
                for (j = i+1; j < nLen; j++)
                {
                        if ((ptArr.x > ptArr[j].x) || ((fabs(ptArr.x-ptArr[j].x) < 1.0E-7) && (ptArr.y>ptArr[j].y)))
                                ptArr.swap(i,j);
                }
        }

        return true;
}
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

已领礼包: 194个

财富等级: 日进斗金

发表于 2005-9-9 12:18:31 | 显示全部楼层
真的好强,自己编写的程序?
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-9-9 12:37:05 | 显示全部楼层
最初由 shuaier 发布
[B]真的好强,自己编写的程序? [/B]



是啊,前几天写的,不过还有漏洞,请指正!
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2024-5-5 11:17 , Processed in 0.445086 second(s), 35 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表