明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 10233|回复: 15

ARX直线打断(可打断直线、弧线、多线段)

  [复制链接]
发表于 2011-9-20 21:42:42 | 显示全部楼层 |阅读模式
本帖最后由 zltangent 于 2011-9-20 21:42 编辑

前阵子发的贴子只可以打断单个直线,且打断方式是重新绘制直线,实现打断效果。这样理解比较容易,但是带来的问题也比较多,首先内存的开辟,一根没事,多根线打断就是问题了;再者打断前如果线在某个涂层,而且有多种属性,则靠重新绘制的方法要考虑很多东西,而且容易出错。

鉴于以上问题,可以用打断命令来处理。打断命令函数如下:
ads_command(
RTSTR, _T("BREAK"),
RTLB,
RTENAME,
(LONG_PTR*)entSel,
RT3DPOINT, pt1,
RTLE,
RTSTR, _T("F"),
RT3DPOINT, pt1,
RT3DPOINT, pt2,
RTNONE)
注:ads_point pt1, pt2;(或者用AcGePoint3d ptS, ptE; 但是要取地址才行。)

现在的代码,可以打断直线、弧线、多线段。可以单独处理它们,也可以综合处理他们。综合处理的根据是AcDbLine\AcDbArc\AcDbPolyline的基类均是AcDbCurve,所以可以用处理曲线的方式来统一处理直线、弧线和多线段。
现把BreakLine命令函数内主要代码分享如下:

// 添加实体进G-DB
AcDbObjectId PostToModelSpace(AcDbEntity* pEnt);   
// This is command 'BREAKLINE'
// AcDbLine\AcDbArc\AcDbPolyline->AcDbCurve,用曲线处理直线段、弧线、多线段
void T4BreakLine()
{
  // 关闭对象捕捉
struct resbuf os1, os2;
ads_getvar(_T("osmode"), &os1);          // acedGetVar("osmode", &os1);
os2.restype = RTSHORT;            // 设置系统变量数据类型
os2.resval.rint = 0;            // 设置系统变量新值
ads_setvar(_T("osmode"), &os2);

CAcModuleResourceOverride resOverride;        // 防止资源冲突

if(NULL == pDlg)
{
  pDlg = new CBreakLineLenDlg(acedGetAcadFrame());
  pDlg->Create(IDD_LINELENGTH);
  pDlg->ShowWindow(SW_SHOW);  
}
else
{
  // 防止用户按下Esc隐藏对话框,在此若隐藏则显示出来
  pDlg->ShowWindow(SW_SHOW);
}

ads_point ptPick1,ptPick2;           // 给一个起点,终点
AcGePoint3d ptS, ptE;            // 线段始末点
  
AcDbLine* pLine = NULL;            // 实体对象      
AcDbObjectId IdCur;             // 当前线段ID

double breakLen = 0;

ads_name ssname;             // 选择集
  
// 主循环
while(1)
{
  // 第一个点
  if(RTNORM != acedGetPoint(NULL, _T("\n输入第一个点:"), ptPick1))
  {
   break;
  }  
  ptS = asPnt3d(ptPick1);
  
  // 第二个点
  if(RTNORM != acedGetPoint(ptPick1, _T("\n输入第二个点:"), ptPick2))
  {
   break;
  }  
  ptE = asPnt3d(ptPick2);
  
  // 生成线段
  pLine = new AcDbLine;
  pLine->setStartPoint(ptS);
  pLine->setEndPoint(ptE);
  IdCur = PostToModelSpace(pLine);        // 添加实体进G-DB
  pLine = NULL;             // 使用后先赋值NULL
  ads_name CurName;            // 当前线name
  acdbGetAdsName(CurName, IdCur);           
   
  if (!pDlg->IsBreak())
  {
   continue;
  }
  // 接收长度
  breakLen = atof(pDlg->GetBreakLen());        
  
  ads_name entName;
  long ssLen = 0;             // 记录选择集长度
  
  AcDbEntity* pEnt = NULL;          // 目标实体
  AcDbCurve* pLinePre = NULL;          // 目标line(AcDbLine\AcDbArc\AcDbPolyline)
  AcDbObjectId linePreId;           // 目标实体ID
   
  AcGePoint3dArray ArsNodPt;          // 交点数组
   
  // 选择0图层上的与当前线始末点坐标连成的区域相交的线
  resbuf* ptLst = ads_buildlist(RTPOINT, ptPick1, RTPOINT, ptPick2, NULL);
  ads_ssget(_T("F"), ptLst, NULL, NULL, ssname);
  
  // 获取选择集长度
  ads_sslength(ssname, &ssLen);
  
  // 过滤、求交点、打断处理
  for(; ssLen > 0; )
  {
   // 获取当前线
   acdbOpenObject(pLine, IdCur, AcDb::kForRead);
   
   // 判断当前线是否有效
   if(pLine)
   {
    // 遍历选择集提取当前的前一个实体ID,并由此ID获取其实体
    // 多线段的话总是提取处理后的剩余部分
    ads_ssname(ssname, 0, entName);           
    acdbGetObjectId(linePreId, entName);
    acdbOpenObject(pEnt, linePreId, AcDb::kForWrite);
    if(pEnt)
    {
     // 直线、曲线、多线段均属于曲线,直接转换
     pLinePre = AcDbCurve::cast(pEnt);
     if(pLinePre)
     {
      // 获取交点
      ArsNodPt.setLogicalLength(0);
      pLine->intersectWith(pLinePre, AcDb::kOnBothOperands, ArsNodPt);
      pEnt->close();
      
      // 有交点处理
      int iNum = ArsNodPt.length();
      if(iNum > 0)
      {
       // 获取打断点
       AcGePoint3d AptS, AptE;         // 弧线打断始末点
       double Alen;           // 一段线长        
       pLinePre->getDistAtPoint(ArsNodPt[0], Alen);   // 获取线起点到交点距离
       pLinePre->getPointAtDist(Alen - breakLen / 2, AptS); // 获取线打断点
       pLinePre->getPointAtDist(Alen + breakLen / 2, AptE); // 获取线远打断点
      
       // 从选择集中除去即将处理的实体
       ads_ssdel(entName,ssname);
      
       // 打断处理
       ads_command(RTSTR, _T("BREAK"),
        RTLB, RTENAME, (LONG*)entName, RT3DPOINT, &AptS,
        RTLE, RTSTR, _T("F"), RT3DPOINT, &AptS, RT3DPOINT, &AptE, RTNONE);      
      
       // 多点处理,重建选择集
       if(iNum > 1)
       {
        // 首先释放先前选择集
        ads_ssfree(ssname);
        
        // 重建选择集
        ads_ssget(_T("F"), ptLst, NULL, NULL, ssname);
        
        // 除去当前线
        ads_ssdel(CurName, ssname);
       }
      
       // 重新计算选择集内元素个数
       ads_sslength(ssname, &ssLen);
      }
      else
      {
       break;
      }
      
      // 还原对象捕捉
      ads_setvar(_T("osmode"), &os1);      
     }
     else
     {
      // 转换失败处理
      pEnt->close();
      continue;
     }
    } // end of if(pEnt)
   
    pLine->close();
   } // end of if(pLine)
   
  } // end of for(过滤、求交点、打断)
  acutRelRb(ptLst);
} // end of while(主循环)
// 命令结束,资源释放
ads_ssfree(ssname);

// 打断结束关闭对话框
pDlg->CloseDialog();
}
// 添加实体进G-DB
AcDbObjectId PostToModelSpace(AcDbEntity* pEnt)
{
// 获取当前活动G-DB的块表指针
AcDbBlockTable *pBlockTable;
acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlockTable,
  AcDb::kForRead);
// 获取块表记录指针
AcDbBlockTableRecord *pBlockTableRecord;
pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockTableRecord, AcDb::kForWrite);
// 添加实体进G-DB
AcDbObjectId entId;
pBlockTableRecord->appendAcDbEntity(entId, pEnt);
// last-close
pBlockTable->close();
pBlockTableRecord->close();
pEnt->close();
return entId;
}

打断效果贴图如下:

刚接触不久,不清楚的地方还很多,请大家多批评指正,O(∩_∩)O~。
有问题随时交流,zltangent@163.com

本帖子中包含更多资源

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

x
发表于 2011-10-25 20:30:57 | 显示全部楼层
不错。居然没人顶。
发表于 2011-10-28 09:40:30 | 显示全部楼层
AcDbCurve下面,有个叫getSplitCurves,专门对付这些,
楼主的思路是从lsp中来的
 楼主| 发表于 2011-11-3 22:47:40 | 显示全部楼层
luowy 发表于 2011-10-28 09:40
AcDbCurve下面,有个叫getSplitCurves,专门对付这些,
楼主的思路是从lsp中来的

啊,lsp我不懂啊,没接触那个东西O(∩_∩)O~;AcDbCurve::getSplitCurves Function 比较长,回头慢慢看了,呵呵,其实我之前想单独处理,后来主管帮我的,才改写成这样。不过会留意这个函数,当时看网上提到这个函数很多次。具体怎么用还没整过。
发表于 2011-11-10 10:00:58 | 显示全部楼层
确实,还是感觉用getSplitCurves函数来写比较好,尤其是拉框之类裁切大数据量的时候。
发表于 2011-11-16 21:42:45 | 显示全部楼层
不错,很好的东西,可以借鉴……
发表于 2011-11-28 21:13:48 | 显示全部楼层
好程序,一定要顶啊!
发表于 2011-12-17 22:25:06 | 显示全部楼层
楼主犀利!!!
发表于 2012-1-4 21:06:46 | 显示全部楼层
这个必须顶!
发表于 2012-4-16 09:53:14 | 显示全部楼层
很好的东西不错,顶楼主
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-11-25 06:59 , Processed in 0.167516 second(s), 26 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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