ARX直线打断(可打断直线、弧线、多线段)
本帖最后由 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, 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
不错。居然没人顶。 AcDbCurve下面,有个叫getSplitCurves,专门对付这些,
楼主的思路是从lsp中来的 luowy 发表于 2011-10-28 09:40 static/image/common/back.gif
AcDbCurve下面,有个叫getSplitCurves,专门对付这些,
楼主的思路是从lsp中来的
啊,lsp我不懂啊,没接触那个东西O(∩_∩)O~;AcDbCurve::getSplitCurves Function 比较长,回头慢慢看了,呵呵,其实我之前想单独处理,后来主管帮我的,才改写成这样。不过会留意这个函数,当时看网上提到这个函数很多次。具体怎么用还没整过。 确实,还是感觉用getSplitCurves函数来写比较好,尤其是拉框之类裁切大数据量的时候。
不错,很好的东西,可以借鉴…… 好程序,一定要顶啊! 楼主犀利!!! 这个必须顶! 很好的东西不错,顶楼主
页:
[1]
2