明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 217|回复: 3

分割所有的线段(自相交+与其他曲线交点+曲线顶点),不用 getSplitCurves 方法该...

[复制链接]
发表于 昨天 15:50 | 显示全部楼层 |阅读模式
本帖最后由 gzxl 于 2025-9-5 21:12 编辑

个人体会:
getSplitCurves 方法对自相交总之...,虽然折衷处理,但在某些特殊的情况下难以言表!




下面不以 getSplitCurves 分割的思路代码
  1. Acad::ErrorStatus es;
  2. // 分割点点集(自相交+两个曲线相交)
  3. AcGePoint3dArray pointsBreak;
  4. // 新建一个过滤掉孤立的曲线对象集合
  5. std::vector<AcDbCurve*> curvesCopy;
  6. // 曲线对象集合大小
  7. size_t nSize = curves.size();
  8. // 曲线自相交检测,将交点加入 pointsBreak 点集
  9. for (size_t i = 0; i < nSize; i++)
  10. {
  11.     AcDbCurve* pCurve = curves.at(i);
  12.     // 自相交
  13.     AcGePoint3dArray pointsOneselfInter;
  14.     if (GetCurveOneselfInter(pCurve, pointsOneselfInter))
  15.     {
  16.         int n = pointsOneselfInter.length();
  17.         for (int j = 0; j < n; j++)
  18.         {
  19.             AcGePoint3d pt = pointsOneselfInter.at(j);
  20.             pointsBreak.append(pt);
  21.         }
  22.         pointsOneselfInter.removeAll();
  23.     }
  24.     pCurve->close();
  25. }
  26. // 两条曲线相交
  27. for (size_t i = 0; i < nSize; i++)
  28. {
  29.     AcDbCurve* pCurve1 = curves.at(i);
  30.     // 起点和终点
  31.     AcGePoint3d ptStart1, ptEnd1;
  32.     pCurve1->getStartPoint(ptStart1);
  33.     pCurve1->getEndPoint(ptEnd1);
  34.     // 是否与其他曲线相交
  35.     bool bInters = false;
  36.     for (size_t j = 0; j < nSize; j++)
  37.     {
  38.         AcDbCurve* pCurve2 = curves.at(j);
  39.         if (pCurve2 == pCurve1)
  40.         {
  41.             pCurve2->close();
  42.             continue;
  43.         }
  44.         // 起点和终点
  45.         AcGePoint3d ptStart2, ptEnd2;
  46.         pCurve2->getStartPoint(ptStart2);
  47.         pCurve2->getEndPoint(ptEnd2);
  48.         // 两条曲线求交点
  49.         AcGePoint3dArray pointsInters;
  50.         if (GetCurvesInterPoints(pCurve2, pCurve1, pointsInters))
  51.         {
  52.             int n = pointsInters.length();
  53.             for (int k = 0; k < n; k++)
  54.             {
  55.                 // 交点不为曲线的起点或终点
  56.                 AcGePoint3d pt = pointsInters.at(k);
  57.                 if (!IsEqual(pt, ptStart1) || !IsEqual(pt, ptEnd1) ||
  58.                     !IsEqual(pt, ptStart2) || !IsEqual(pt, ptEnd2))
  59.                 {
  60.                     pointsBreak.append(pt);
  61.                 }
  62.             }
  63.             bInters = true;
  64.         }
  65.         pCurve2->close();
  66.     }
  67.     if (bInters)
  68.     {
  69.         curvesCopy.push_back(pCurve1);
  70.     }
  71.     pCurve1->close();
  72. }
  73. // 分割点点集过滤掉重复点
  74. if (pointsBreak.length() >= 2)
  75. {
  76.     CSplitCurves::FilterEqualPoints(pointsBreak);
  77. }
  78. // 曲线对象集合大小
  79. size_t nSizeCopy = curvesCopy.size();
  80. // 曲线前后顶点组成的线段插入交点处理
  81. for (size_t i = 0; i < nSizeCopy; i++)
  82. {
  83.     AcDbCurve* pCurveCopy = curvesCopy.at(i);
  84.     // 曲线的顶点点集
  85.     AcGePoint3dArray pointsVertex;
  86.     // 直线
  87.     if (pCurveCopy->isKindOf(AcDbLine::desc()))
  88.     {
  89.         AcDbLine *pLine = AcDbLine::cast(pCurveCopy);
  90.         // 起点和终点
  91.         AcGePoint3d ptStart, ptEnd;
  92.         pLine->getStartPoint(ptStart);
  93.         pLine->getEndPoint(ptEnd);
  94.         // 加入 pointsVertex 顶点点集
  95.         pointsVertex.append(ptStart);
  96.         pointsVertex.append(ptEnd);
  97.         pLine->close();
  98.     }
  99.     // 经量多段线
  100.     else if (pCurveCopy->isKindOf(AcDbPolyline::desc()))
  101.     {
  102.         AcDbPolyline *pPoly = AcDbPolyline::cast(pCurveCopy);
  103.         // 循环获取顶点加入 pointsVertex 顶点点集(将凸度值代入 Z 坐标)
  104.         int n = pPoly->numVerts();
  105.         for (int j = 0; j < n; j++)
  106.         {
  107.             AcGePoint3d pt;
  108.             pPoly->getPointAt(j, pt);
  109.             double dBulge = 0.0;
  110.             pPoly->getBulgeAt(j, dBulge);
  111.             pointsVertex.append(AcGePoint3d(pt.x, pt.y, dBulge));
  112.         }
  113.         // 如果是闭合的,则再将起点加入 pointVerts 顶点点集
  114.         if (pPoly->isClosed())
  115.         {
  116.             AcGePoint3d ptStart;
  117.             pPoly->getStartPoint(ptStart);
  118.             pointsVertex.append(AcGePoint3d(ptStart.x, ptStart.y, 0.0));
  119.         }
  120.         pPoly->close();
  121.     }
  122.     // 二维多段线
  123.     else if (pCurveCopy->isKindOf(AcDb2dPolyline::desc()))
  124.     {
  125.         AcDb2dPolyline *pPoly = AcDb2dPolyline::cast(pCurveCopy);
  126.         // 迭代器对象的指针
  127.         AcDbObjectIterator *pVertIter = pPoly->vertexIterator();
  128.         for (pVertIter->start(); !pVertIter->done(); pVertIter->step())
  129.         {
  130.             AcDbObjectId objId = pVertIter->objectId();
  131.             AcDb2dVertex *p2dVertex = NULL;
  132.             es = acdbOpenObject(p2dVertex, objId, AcDb::kForRead);
  133.             if (es != Acad::eOk)
  134.                 continue;
  135.             AcGePoint3d pt = p2dVertex->position();
  136.             pointsVertex.append(pt);
  137.             p2dVertex->close();
  138.         }
  139.         // 删除迭代器对象的指针
  140.         delete pVertIter;
  141.         // 如果是闭合的,则再将起点加入 pointVerts 顶点点集
  142.         if (pPoly->isClosed())
  143.         {
  144.             AcGePoint3d ptStart;
  145.             pPoly->getStartPoint(ptStart);
  146.             pointsVertex.append(AcGePoint3d(ptStart.x, ptStart.y, 0.0));
  147.         }
  148.         pPoly->close();
  149.     }
  150.     // 三维多段线
  151.     else if (pCurveCopy->isKindOf(AcDb3dPolyline::desc()))
  152.     {
  153.         AcDb3dPolyline *pPoly = AcDb3dPolyline::cast(pCurveCopy);
  154.         AcDbObjectIterator *pVertIter = pPoly->vertexIterator();
  155.         for (pVertIter->start(); !pVertIter->done(); pVertIter->step())
  156.         {
  157.             AcDbObjectId objId = pVertIter->objectId();
  158.             AcDb3dPolylineVertex *p3dVertex = NULL;
  159.             es = acdbOpenObject(p3dVertex, objId, AcDb::kForRead);
  160.             if (es != Acad::eOk)
  161.                 continue;
  162.             AcGePoint3d pt = p3dVertex->position();
  163.             pointsVertex.append(pt);
  164.             p3dVertex->close();
  165.         }
  166.         delete pVertIter;
  167.         pPoly->close();
  168.     }
  169.     // 圆弧
  170.     else if (pCurveCopy->isKindOf(AcDbArc::desc()))
  171.     {
  172.         AcDbArc *pArc = AcDbArc::cast(pCurveCopy);
  173.         // 起点和终点
  174.         AcGePoint3d ptStart, ptEnd;
  175.         pArc->getStartPoint(ptStart);
  176.         pArc->getEndPoint(ptEnd);
  177.         // 起始角度和结束角度
  178.         double dStartAngle = pArc->startAngle();
  179.         double dEndAngle = pArc->endAngle();
  180.         // 获取圆弧凸度
  181.         double dAlfa = dEndAngle - dStartAngle;
  182.         if (dAlfa < 0.0) // 如果终点角度小于起点角度
  183.         {
  184.             dAlfa = 2 * PI + dAlfa;
  185.         }
  186.         double dBulge = tan((dAlfa) / 4.0);
  187.         pointsVertex.append(AcGePoint3d(ptStart.x, ptStart.y, dBulge));
  188.         pointsVertex.append(ptEnd);
  189.         pArc->close();
  190.     }
  191.     // 圆
  192.     else if (pCurveCopy->isKindOf(AcDbCircle::desc()))
  193.     {
  194.         AcDbCircle *pCircle = AcDbCircle::cast(pCurveCopy);
  195.         // 圆的中心点
  196.         AcGePoint3d ptCenter;
  197.         ptCenter = pCircle->center();
  198.         // 圆的半径
  199.         double radius = 0.0;
  200.         radius = pCircle->radius();
  201.         // 获取圆上的四点
  202.         AcGePoint3dArray pointsTemp;
  203.         for (int j = 0; j <= 4; j++)
  204.         {
  205.             double x = ptCenter.x + radius * cos(j * 0.5 * PI);
  206.             double y = ptCenter.y + radius * sin(j * 0.5 * PI);
  207.             AcGePoint3d pt(x, y, 0.0);
  208.             pointsTemp.append(pt);
  209.         }
  210.         // 获取凸度
  211.         int nTemp = pointsTemp.length();
  212.         for (int j = 0; j < nTemp - 1; j++)
  213.         {
  214.             AcGePoint3d pt1 = pointsTemp.at(j);
  215.             AcGePoint3d pt2 = pointsTemp.at(j + 1);
  216.             // 重新计算设置 pt1 点的凸度
  217.             double dBulge1 = GetBulge(pt1, pt2, ptCenter);
  218.             pointsVertex.append(AcGePoint3d(pt1.x, pt1.y, dBulge1));
  219.             pointsVertex.append(AcGePoint3d(pt2.x, pt2.y, 0.0));
  220.         }
  221.         pCircle->close();
  222.     }
  223.     // 遍历曲线 pointVerts 顶点点集
  224.     // 如果交点在两顶点曲线上,则在两顶点曲线之间插入交点,且需重设对应顶点的凸度值
  225.     if (pointsBreak.length() > 0)
  226.     {
  227.         // 新建一个曲线顶点点集
  228.         AcGePoint3dArray pointsVertexNew;
  229.         // 原曲线顶点点集大小
  230.         int nVertex = pointsVertex.length();
  231.         // 原曲线前后顶点组成的线段是否存在交点
  232.         for (int j = 0; j < nVertex - 1; j++)
  233.         {
  234.             // 曲线当前顶点
  235.             AcGePoint3d ptCurrent = pointsVertex.at(j);
  236.             // 曲线下一个顶点
  237.             AcGePoint3d ptNext = pointsVertex.at(j + 1);
  238.             // 当前顶点 ptCurrent 加入 pointsVertexNew 点集中
  239.             pointsVertexNew.append(ptCurrent);
  240.             // 临时交点点集
  241.             AcGePoint3dArray pointsTemp;
  242.             // 遍历交点,交点是否在两顶点组成的曲线上(需考虑有多个交点)
  243.             int nBreak = pointsBreak.length();
  244.             for (int k = 0; k < nBreak; k++)
  245.             {
  246.                 AcGePoint3d ptBreak = pointsBreak.at(k);
  247.                 // 给定的交点 ptBreak 在由两个顶点 ptCurrent ptNext 组成的曲线上
  248.                 // 交点加入 pointsTemp 临时交点点集
  249.                 if (IsPointOnCurve(ptCurrent, ptNext, ptBreak))
  250.                 {
  251.                     pointsTemp.append(ptBreak);
  252.                 }
  253.             }
  254.             if (pointsTemp.length() > 0)
  255.             {
  256.                 // 计算曲线原前后两个顶点的中心点
  257.                 AcGePoint3d ptCenter = AcGePoint3d::kOrigin;
  258.                 if (fabs(ptCurrent.z) > 1.0E-4) // Z 值代表凸度值
  259.                 {
  260.                     ptCenter = GetCenterPoint(ptCurrent, ptNext, ptCurrent.z);
  261.                 }
  262.                 // 两个前后顶点之间有多个交点
  263.                 if (pointsTemp.length() > 1)
  264.                 {
  265.                     // 创建由当前顶点和下一个顶点组成的曲线
  266.                     AcGePoint3dArray points;
  267.                     points.append(ptCurrent);
  268.                     points.append(ptNext);
  269.                     int numVertices = points.length();
  270.                     AcDbPolyline *pPoly = new AcDbPolyline(numVertices);
  271.                     for (int i = 0; i < numVertices; i++)
  272.                     {
  273.                         AcGePoint3d pt3d = points.at(i);
  274.                         AcGePoint2d pt2d(pt3d.x, pt3d.y);
  275.                         double dBugle = pt3d.z;
  276.                         pPoly->addVertexAt(i, pt2d, dBugle, 0.0, 0.0);
  277.                     }
  278.                     // 强制转换为曲线类
  279.                     AcDbCurve* pCurveNew = static_cast<AcDbCurve*>(pPoly);
  280.                     // 点沿曲线排序
  281.                     SortPointsOnCurve(pCurveNew, pointsTemp, 0, pointsTemp.length() - 1);
  282.                     // 清理由当前顶点和下一个顶点组成的曲线
  283.                     pPoly->erase();
  284.                     pPoly->close();
  285.                     pCurveNew->erase();
  286.                     pCurveNew->close();
  287.                     // 对于有弧度的重新计算和设置交点的凸度值
  288.                     int nTemp = pointsTemp.length();
  289.                     for (int k = 0; k < nTemp - 1; k++)
  290.                     {
  291.                         AcGePoint3d ptTemp1 = pointsTemp.at(k);
  292.                         AcGePoint3d ptTemp2 = pointsTemp.at(k + 1);
  293.                         // Z 值代表是有凸度
  294.                         if (fabs(ptCurrent.z) > 1.0E-4)
  295.                         {
  296.                             // 计算重设 ptCurrent 新的凸度值
  297.                             double dBulge1 = GetBulge(ptCurrent, ptTemp1, ptCenter);
  298.                             int nCount = FindPoint(pointsVertexNew, ptCurrent);
  299.                             if (nCount > -1)
  300.                                 pointsVertexNew.at(nCount).z = dBulge1;

  301.                             // 计算交点的凸度值
  302.                             double dBulge2 = GetBulge(ptTemp1, ptTemp2, ptCenter);
  303.                             ptTemp1.set(ptTemp1.x, ptTemp1.y, dBulge2);
  304.                             pointsVertexNew.append(ptTemp1);
  305.                         }
  306.                         else
  307.                         {
  308.                             pointsVertexNew.append(ptTemp1);
  309.                         }
  310.                         ptCurrent = ptTemp1;
  311.                     }

  312.                     AcGePoint3d ptEnd = pointsTemp.at(pointsTemp.length() - 1);
  313.                     pointsVertexNew.append(ptEnd);
  314.                 }
  315.                 // 只有一个交点
  316.                 else
  317.                 {
  318.                     AcGePoint3d ptTemp = pointsTemp.at(0);
  319.                     if (fabs(ptCurrent.z) > 1.0E-4) // Z 值代表凸度值
  320.                     {
  321.                         // 计算重设 ptCurrent 新的凸度值
  322.                         double dBulge1 = GetBulge(ptCurrent, ptTemp, ptCenter);
  323.                         int nCount = FindPoint(pointsVertexNew, ptCurrent);
  324.                         if (nCount > -1)
  325.                             pointsVertexNew.at(nCount).z = dBulge1;

  326.                         // 计算交点的凸度值
  327.                         double dBulge2 = GetBulge(ptTemp, ptNext, ptCenter);
  328.                         ptTemp.set(ptTemp.x, ptTemp.y, dBulge2);
  329.                         pointsVertexNew.append(ptTemp);
  330.                     }
  331.                     else
  332.                     {
  333.                         pointsVertexNew.append(ptTemp);
  334.                     }
  335.                 }
  336.             }
  337.             pointsVertexNew.append(AcGePoint3d(ptNext.x, ptNext.y, 0.0));
  338.         }
  339.         // 将有与其他曲线相交的曲线点集加入新的集合
  340.         if (pointsVertexNew.length() > 0)
  341.         {
  342.             vecPointsBreak.push_back(pointsVertexNew);
  343.         }
  344.     }
  345.     // 清理
  346.     pointsVertex.removeAll();
  347.     pCurveCopy->close();
  348. }
  349. // 清理
  350. if (curvesCopy.size() > 0)
  351. {
  352.     std::vector<AcDbCurve*>().swap(curvesCopy);
  353. }



本帖子中包含更多资源

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

x

评分

参与人数 2明经币 +2 收起 理由
cable2004 + 1 很给力!
yanshengjiang + 1

查看全部评分

回复

使用道具 举报

发表于 昨天 16:52 | 显示全部楼层
好的 很厉害
回复 支持 反对

使用道具 举报

发表于 昨天 16:56 | 显示全部楼层
感谢gxl大佬的分享
回复 支持 反对

使用道具 举报

发表于 昨天 21:06 | 显示全部楼层
G大 发一下演示效果图
回复 支持 反对

使用道具 举报

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

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2025-9-6 08:37 , Processed in 0.188224 second(s), 25 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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