找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 808|回复: 0

[教学] 【AcBr库应用(六)】给3DSOLID做截面并给截面设置颜色

[复制链接]

已领礼包: 40个

财富等级: 招财进宝

发表于 2018-5-29 21:07:42 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

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

×
问题:


How can I use ObjectARX to color the interstecting area between a solid and an entity? The colored area is the new face that was created for the modified solid.


如何给3DSOLID和实体相交的区域着色? 着色区域是修改后的3DSLID的新截面。

解决方案:
Use the AcBrBrep library to iterate through the faces of the sliced solid. The plane of the slicer, the 2D entity, indicates the plane where the new face of the solid lies. Therefore, a point can be determined that lies on the surface of a face provided by the AcBrBrepFaceTraverser. The point's distance to the slicer's plane is then measured. The face that exhibits a point closest (a distance of 0 is optimal) to the slicer's plane is considered the new face, and AcDb3dSolid::setSubentColor() can be called on it in order to adjust color.
Below is the command from the attached VS 2005 example. The zip file includes a test drawing.
Another approach to consider is to use the SectionPlane object. See this sample in the ObjectARX SDK for more details about this. C:\ObjectARX 2009\samples\graphics\SectionPlane


使用AcBrBrep库遍历切面后的3DSOLID,切面是2D曲线实体,这个切面是3DSOLID切片后的一个面。因此,计算2D切面上的点到3DSOLID所有面的距离,距离=0的面,就是我们要找的。最后通过AcDb3dSolid::setSubentColor()设置这个面的颜色。


下面是ARX实现代码:
[C++] 纯文本查看 复制代码
static void ASDKTS51618_GetSlice_MySlice(void)
{
        if (!acrxClassDictionary->at(_T("AcBrEntity")))
                bool found = acrxDynamicLinker->loadModule(_T("acbr17.dbx"), 0);
        Acad::ErrorStatus es;
        AcDb3dSolid *pSol;
        ads_name en1, en2;
        ads_point pt;
        AcDbObjectId eId;
        acedEntSel(_T("\nSelect a solid: "), en1, pt);
        if (Acad::eOk != acdbGetObjectId(eId, en1))
                return;
        acdbOpenObject(pSol, eId, AcDb::kForWrite);
        if (pSol == NULL) {
                acutPrintf(_T("Can't access solid - aborting"));
                return;
        }
        AcDbEntity *pEnt;
        acedEntSel(_T("\nPick the 2-D slicing entity: "), en2, pt);
        if (Acad::eOk != acdbGetObjectId(eId, en2))
                return;
        acdbOpenObject(pEnt, eId, AcDb::kForRead);
        if (pEnt == NULL) {
                acutPrintf(_T("Can't access slicing entity - aborting"));
                return;
        }
        AcGePlane plane;
        AcDb::Planarity flag;
        pEnt->getPlane(plane, flag);

        if (flag != AcDb::kPlanar) {
                acutPrintf(_T("Not a 2d curve - aborting"));
                return;
        }
        pEnt->close();
        AcDb3dSolid* pJunkSolid;
        es = pSol->getSlice(plane, Adesk::kTrue, pJunkSolid);
        if (!pJunkSolid) return; //no slice made
        AcBrBrep *pBrepSol = new AcBrBrep;

        AcBr::ErrorStatus brErr = pBrepSol->setSubentPath(AcDbFullSubentPath(pSol->objectId(), kNullSubentId));
        AcCmColor Col;
        Col.setColorIndex(1);
        AcBrBrepFaceTraverser brepFaceTrav;
    AcBrFace currentFace;
        AcGeSurface* surface;

        brepFaceTrav.setBrep(*pBrepSol);
        double bestDist = 1000;
        AcDbSubentId closestSubId;
        bool faceFound = false;
        while (!brepFaceTrav.done()) {
                brepFaceTrav.getFace(currentFace);
                brErr = currentFace.getSurface(surface);
                AcGePointOnSurface *repPntSurf = new AcGePointOnSurface(*surface);
                AcGePoint3d repPnt = repPntSurf->point3d();
                double dist = abs(plane.signedDistanceTo(repPnt));
                //does this surface point lie on the plane that contains the 2d slicer?

                if (dist < bestDist) {
                        bestDist = dist;
                        AcDbFullSubentPath subPath(kNullSubent);
                        currentFace.getSubentPath(subPath);
                        closestSubId = subPath.subentId();
                        if (bestDist == 0.000)
                                break;  //can't do better than zero distance
                }
                delete surface;
                delete repPntSurf;
                brepFaceTrav.next();
        }
        delete pBrepSol;
        pSol->setSubentColor(closestSubId, Col);
        pSol->close();

}



3DSOLID-截面.gif

下面是XDRX API的ACBR库函数的LISP解决代码:

  1. (defun c:tt ()
  2.   (defun _traversface (e ln)
  3.     (setq plane  (xdrx_curve_getplane ln)
  4.           ori    (cadr plane)
  5.           vx     (nth 2 plane)
  6.           vy     (nth 3 plane)
  7.           vz     (xdrx_vector_crossproduct vx vy)
  8.           mPlane (xdge::constructor "kPlane" ori vz)
  9.     )
  10.     (setq e1 (xdrx_getpropertyvalue e "slice" mplane t));;3dsolid getSlice截面
  11.     (xdrx_entity_delete e);;删除上部分、留下下半部分
  12.     (setq br (xdbr::constructor e1))
  13.     ;;从BODY创建AcBrBrep
  14.     (setq tr (xdbr::constructor "brepfacetraverser" br))
  15.     ;;构建Brep->Face遍历器
  16.     ;;FACE遍历
  17.     (setq i 0
  18.           ints nil
  19.           bestDist 1e100
  20.           tf t
  21.     )
  22.     (while (and tf (not (xdbr::traverser:done tr)))
  23.       (if (setq face (xdbr::getpropertyvalue tr "face"))
  24.         ;;当前遍历位置获得AcBrFace
  25.         (progn (setq gface (xdbr::getpropertyvalue face "surface"));;AcBrFace->AcGeSurface
  26.                (setq ptOnSurf (xdge::constructor "kPointOnSurface" gface));;构建AcGePointOnCurve对象
  27.                (setq pnt        (xdge::getpropertyvalue ptOnSurf "point");;得到AcGePointOnCurve上一点
  28.                      dist       (xdge::getpropertyvalue mPlane "signeddistanceto" pnt);;求该点到截面的有符号距离
  29.                      subEntPath (xdbr::getpropertyvalue face "subentpath");;获得AcBrFace的子实体路径
  30.                      subEntId   (xdrx_getpropertyvalue subEntPath "subentid");;获得子实体路径的子实体ID
  31.                )
  32.                (if (< dist bestDist);;如果距离小于预设,预设存储当前距离
  33.                  (setq bestDist dist)
  34.                )
  35.                (if (equal bestDist 0.0 1e-5);;如果距离=0,找到截面对应的3DSOLID上的AcBrFace,结束循环
  36.                  (setq tf nil)
  37.                )
  38.                (xdrx_object_release face gface ptonsurf subentpath);;释放中间对象
  39.         )
  40.       )
  41.       (xdbr::traverser:next tr);;遍历下一个面
  42.     )
  43.     (xdrx_setpropertyvalue e1 "SubEntColor" (list subentid 1));;设置3DSOLID子实体(面)的颜色
  44.     (xdrx_object_release tr br subentid);;释放中间对象
  45.     (xdrx_entity_delete ln);;删除多段线
  46.   )
  47.   (if (and (setq e (car (xdrx_entsel "\n选取3DSOLID<退出>:" '((0 . "3DSOLID")))
  48.                    )
  49.            )
  50.            (setq ln (car
  51.                       (xdrx_entsel "\n选择截面线<退出>:" '((0 . "LWPOLYLINE")))
  52.                     )
  53.            )
  54.       )
  55.     (progn (xdrx_begin) (_traversface e ln) (xdrx_end))
  56.   )
  57.   (princ)
  58. )




3DSOLID-截面.gif
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2024-3-29 14:05 , Processed in 0.368412 second(s), 31 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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