天气与日历 切换到窄版

 找回密码
 立即注册
中国膜结构网
十大进口膜材评选 十大国产膜材评选 十大膜结构设计评选 十大膜结构公司评选
查看: 58|回复: 0

ObjectARX_acedGrRead/acedDragGen动态拖动

[复制链接]

该用户从未签到

主题

0

回帖

2912

积分

管理员

积分
2912
发表于 2024-6-22 09:46:18 | 显示全部楼层 |阅读模式
参考ObjectARX(VC)开发基础与实例教程P254
        //************************************
        // Author:    WangHongFeng
        // Summary:   点与闭合多段线的位置关系
        // Method:    PtRelationToPoly
        // Access:    public
        // Returns:   int  -1表示在多段线外部,0表示在多段线上,1表示在多段线内部
        // Parameter: AcDbPolyline * pPoly
        // Parameter: const AcGePoint2d & pt
        // Parameter: double tol
        //************************************
        int PtRelationToPoly(AcDbPolyline *pPoly, const AcGePoint2d &pt, double tol = 1.0E-7);

        bool PointIsPolyVert(AcDbPolyline *pPoly, const AcGePoint2d &pt, double tol);
        void IntersectWithGeRay(AcDbPolyline *pPoly, const AcGeRay2d &geRay, AcGePoint3dArray &intPoints, double tol = 1.0E-7);
        void FilterEqualPoints(AcGePoint3dArray &points, double tol = 1.0E-7);
        void FilterEqualPoints(AcGePoint3dArray &points, const AcGePoint2d &pt, double tol = 1.0E-7);
        int FindPoint(const AcGePoint2dArray &points, const AcGePoint2d &point, double tol = 1.0E-7);
int PubFuc::PtRelationToPoly(AcDbPolyline *pPoly, const AcGePoint2d &pt, double tol /*= 1.0E-7*/)
{
        assert(pPoly);

        // 1.如果点到多段线的最近点和给定的点重合,表示点在多段线上
        AcGePoint3d closestPoint;
        pPoly->getClosestPointTo(ToPoint3d(pt, pPoly->elevation()), closestPoint);                // 多段线上与给定点距离最近的点       
        if (fabs(closestPoint.x - pt.x) < tol && fabs(closestPoint.y - pt.y) < tol)                        // 点在多段线上
        {
                return 0;
        }

        // 2.第一个射线的方向是从最近点到当前点,起点是当前点
        // 射线的起点是pt,方向为从最近点到pt,如果反向做判断,则最近点距离pt太近的时候,最近点也会被作为一个交点(这个交点不太容易被排除掉)
        // 此外,这样的射线方向很容易判断出点不在内部的情况
        AcGeVector3d vec(-(closestPoint[X] - pt[X]), -(closestPoint[Y] - pt[Y]), 0);
        AcGeRay2d geRay(AcGePoint2d(pt.x, pt.y), AcGePoint2d(pt.x + vec.x, pt.y + vec.y));

        // 3.射线与多段线计算交点
        AcGePoint3dArray intPoints;
        IntersectWithGeRay(pPoly, geRay, intPoints, 1.0E-4);
        // IntersectWith函数经常会得到很近的交点,这些点必须进行过滤
        PubFuc::FilterEqualPoints(intPoints, 1.0E-4);

        // 4.判断点和多段线的位置关系
RETRY:
        // 4.1 如果射线和多段线没有交点,表示点在多段线的外部
        if (intPoints.length() == 0)
        {
                return -1;
        }
        else
        {
                // 3.1 过滤掉由于射线被反向延长带来的影响
                PubFuc::FilterEqualPoints(intPoints, ToPoint2d(closestPoint));                // 2008-0907修订记录:当pt距离最近点比较近的时候,最近点竟然被作为一个交点!
                                                                                                                                                                                                // 3.2 如果某个交点与最近点在给定点的同一方向,要去掉这个点(这个点明显不是交点,还是由于intersectwith函数的Bug)       
                for (int i = intPoints.length() - 1; i >= 0; i--)
                {
                        if ((intPoints[i][X] - pt[X]) * (closestPoint[X] - pt[X]) >= 0 &&
                                (intPoints[i][Y] - pt[Y]) * (closestPoint[Y] - pt[Y]) >= 0)
                        {
                                intPoints.removeAt(i);
                        }
                }

                int count = intPoints.length();
                int i;
                for (i = 0; i < intPoints.length(); i++)
                {
                        if (PointIsPolyVert(pPoly, ToPoint2d(intPoints[i]), 1.0E-4))                // 只要有交点是多段线的顶点就重新进行判断
                        {
                                // 处理给定点很靠近多段线顶点的情况(如果与顶点距离很近,就认为这个点在多段线上,因为这种情况没有什么好的判断方法)
                                if (PointIsPolyVert(pPoly, AcGePoint2d(pt.x, pt.y), 1.0E-4))
                                {
                                        return 0;
                                }

                                // 将射线旋转一个极小的角度(2度)再次判断(假定这样不会再通过上次判断到的顶点)
                                vec = vec.rotateBy(0.035, AcGeVector3d::kZAxis);
                                geRay.set(AcGePoint2d(pt.x, pt.y), AcGePoint2d(pt.x + vec.x, pt.y + vec.y));
                                intPoints.setLogicalLength(0);
                                IntersectWithGeRay(pPoly, geRay, intPoints, 1.0E-4);
                                goto RETRY;                // 继续判断结果
                        }
                }

                if (count % 2 == 0)
                {
                        return -1;
                }
                else
                {
                        return 1;
                }
        }
}

bool PubFuc::PointIsPolyVert(AcDbPolyline *pPoly, const AcGePoint2d &pt, double tol)
{
        for (int i = 0; i < (int)pPoly->numVerts(); i++)
        {
                AcGePoint3d vert;
                pPoly->getPointAt(i, vert);

                AcGeTol gtol;
                gtol.setEqualPoint(tol);
                if (ToPoint2d(vert).isEqualTo(pt, gtol))
                {
                        return true;
                }
        }

        return false;
}


// 几何类射线和多段线计算交点
void PubFuc::IntersectWithGeRay(AcDbPolyline *pPoly, const AcGeRay2d &geRay, AcGePoint3dArray &intPoints, double tol /*= 1.0E-7*/)
{
        intPoints.setLogicalLength(0);
        AcGePoint2dArray intPoints2d;

        // 多段线的每一段分别与射线计算交点
        AcGeTol geTol;
        geTol.setEqualPoint(tol);
        for (int i = 0; i < pPoly->numVerts(); i++)
        {
                if (i < pPoly->numVerts() - 1 || pPoly->isClosed() == Adesk::kTrue)
                {
                        double bulge = 0;
                        pPoly->getBulgeAt(i, bulge);
                        if (fabs(bulge) < 1.0E-7)
                        {
                                // 构建几何类的线段来计算交点
                                AcGeLineSeg2d geLine;
                                Acad::ErrorStatus es = pPoly->getLineSegAt(i, geLine);
                                AcGePoint2d intPoint;
                                if (geLine.intersectWith(geRay, intPoint, geTol) == Adesk::kTrue)
                                {
                                        if (PubFuc::FindPoint(intPoints2d, intPoint, tol) < 0)
                                        {
                                                intPoints2d.append(intPoint);
                                        }
                                }
                        }
                        else
                        {
                                // 构建几何类的圆弧来计算交点
                                AcGeCircArc2d geArc;
                                pPoly->getArcSegAt(i, geArc);
                                AcGePoint2d pt1, pt2;
                                int count = 0;
                                if (geArc.intersectWith(geRay, count, pt1, pt2, geTol) == Adesk::kTrue)
                                {
                                        if (PubFuc::FindPoint(intPoints2d, pt1, tol) < 0)
                                        {
                                                intPoints2d.append(pt1);
                                        }
                                        if (count > 1 && PubFuc::FindPoint(intPoints2d, pt2, tol) < 0)
                                        {
                                                intPoints2d.append(pt2);
                                        }
                                }
                        }
                }
        }

        double z = pPoly->elevation();
        int i;
        for (i = 0; i < intPoints2d.length(); i++)
        {
                intPoints.append(AcGePoint3d(intPoints2d[i].x, intPoints2d[i].y, z));
        }
}

void PubFuc::FilterEqualPoints(AcGePoint3dArray &points, double tol /*= 1.0E-7*/)
{
        for (int i = points.length() - 1; i > 0; i--)
        {
                for (int j = 0; j < i; j++)
                {
                        if (MathUtils::IsEqual(points[i].x, points[j].x, tol) && MathUtils::IsEqual(points[i].y, points[j].y, tol))
                        {
                                points.removeAt(i);
                                break;
                        }
                }
        }
}

// 在数组中查找某个点,返回点在数组中的索引,未找到则返回-1
int PubFuc::FindPoint(const AcGePoint2dArray &points, const AcGePoint2d &point, double tol /*= 1.0E-7*/)
{
        for (int i = 0; i < points.length(); i++)
        {
                AcGeTol gtol;
                gtol.setEqualPoint(tol);
                if (points[i].isEqualTo(point, gtol))
                {
                        return i;
                }
        }

        return -1;
}

// 从数组中过滤掉重复点
void PubFuc::FilterEqualPoints(AcGePoint3dArray &points, const AcGePoint2d &pt, double tol /*= 1.0E-7*/)
{
        AcGePoint3dArray tempPoints;
        for (int i = 0; i < points.length(); i++)
        {
                if (ToPoint2d(points[i]).distanceTo(pt) > tol)
                {
                        tempPoints.append(points[i]);
                }
        }

        points = tempPoints;
}

 

 

 

 

ObjectARX_acedGrRead/acedDragGen动态拖动
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|中国膜结构网|中国膜结构协会|进口膜材|国产膜材|ETFE|PVDF|PTFE|设计|施工|安装|车棚|看台|污水池|中国膜结构网_中国空间膜结构协会

GMT+8, 2024-11-1 12:36 , Processed in 0.140294 second(s), 28 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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