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

原文地址:https://www.cnblogs.com/HelloQLQ/p/12347229.html

时间: 2024-10-12 15:59:03

objectarx 多段线自交检查的相关文章

ObjectARX2010 学习笔记004:复制多段线点生成新多段线

static void swtArxProject5plcopy(void) { // Add your code for command swtArxProject5.plcopy here //定义对象名和点 ads_name ename;ads_point pt; //如果没有选择到实体 if(acedEntSel(NULL,ename,pt)!=RTNORM) { return; } //定义并获取ID AcDbObjectId id; acdbGetObjectId(id,ename)

多段线动态切割闭合区域

#include "StdAfx.h"#include "StdArx.h"#include <dbpl.h>#include "..\..\Common\Others\ConvertUtil.h"#include "..\..\Common\Document\DwgDatabaseUtil.h"#include <dbents.h>#include <dbregion.h>#include

Cesium实现文字、点、多段线、多边形的实时绘制

背景知识 点.线.面以及文字的实时绘制是GIS很重要的一个功能,是用户对感兴趣区域标注的业务需要.同时Cesium提供了点.线(多段线).面及文字(label)绘制的接口,绘制方式总共有两种,一种是通过Entity实体的方式,一种是通过Primitives的方式.第一种使用较为简单,是在Primitives基础上进行了封装:第二种则更加贴近WebGL底层,语法更复杂但是绘制效率更高效率.鉴于实时绘制数据量并不大,不需要使用复杂高效的方法,第一种方法完全适用. Cesium通过ScreenSpac

CAD参数绘制多段线(网页版)

多段线又被称为多义线,表示一起画的都是连在一起的一个复合对象,可以是直线也可以是圆弧并且它们还可以加不同的宽度. 主要用到函数说明: _DMxDrawX::PathLineTo 把路径下一个点移到指定位置.详细说明如下: 参数 说明 DOUBLE dX 点的X坐标 DOUBLE dY 点的Y坐标 _DMxDrawX::DrawPathToPolyline 把路径变成一个Polyline. js中实现代码说明: function DrawPolyline() { //Polyline 又称多义线,

CAD参数绘制多段线(安卓版)

多段线又被称为多义线,表示一起画的都是连在一起的一个复合对象,可以是直线也可以是圆弧并且它们还可以加不同的宽度. 主要用到函数说明: MxLibDraw.pathMoveTo 把路径的开始位置移动指定的点.详细说明如下: 参数 说明 double dX 点的X坐标 double dY 点的Y坐标 MxLibDraw.pathLineTo 把路径下一个点移到指定位置.详细说明如下: 参数 说明 double dX 点的X坐标 double dY 点的Y坐标 MxLibDraw.drawPathTo

4、c++ Arx二次开发创建多段线

一.本节课程 c++ Arx二次开发创建多段线 二.本节要讲解的知识点 如何应用C++ ARX二次开发创建多段线(AcDbPolyline.AcDb2dPolyLine.AcDb3dPolyline的使用) 三.具体内容 1.ARX提供了三种多段线相关的类:AcDbPolyline.AcDb2dPolyLine.AcDb3dPolyline.PLINE 创建的是AcDbPolyline,3DPOLY创建AcDb3dPolyline.创建一般的轻量多段线只需要调用AcDbPolyline的构造函数

ObjectARX中三维多段线转二维多段线的方法

Acad::ErrorStatus AcDb3dPolylineToAcDb2dPolyline(AcDbObjectId objId, int flag /* =0 */) { Acad::ErrorStatus es; AcDbEntity *pEnt = NULL; double elev = 0.0; es = acdbOpenObject(pEnt, objId, AcDb::kForWrite); int i = 0; if (pEnt->isKindOf(AcDb3dPolylin

修改多段线的凸度

static void zffObjectARX_MyCommand5(void) { ads_point pick; ads_name name; if (acedEntSel(NULL,name,pick)!=RTNORM) { return; } AcGePoint3d ptClosest; AcDbObjectId polyId; double param; AcDbPolyline* pPoly=NULL; acdbGetObjectId(polyId,name); acdbOpenO

散线转化成多段线

std::vector<entStruct> vecInfo; AcDbObjectIdArray idarr=CDwgDatabaseUtil::GetAllEntityIds(); int iLen = idarr.length(); for (int i = 0; i < iLen;i++) { entStruct eTemp; AcDbObjectId idTemp = idarr[i]; AcDbEntity *pEnt = NULL; Acad::ErrorStatus es