马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
问题:
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();
}
下面是XDRX API的ACBR库函数的LISP解决代码:
- (defun c:tt ()
- (defun _traversface (e ln)
- (setq plane (xdrx_curve_getplane ln)
- ori (cadr plane)
- vx (nth 2 plane)
- vy (nth 3 plane)
- vz (xdrx_vector_crossproduct vx vy)
- mPlane (xdge::constructor "kPlane" ori vz)
- )
- (setq e1 (xdrx_getpropertyvalue e "slice" mplane t));;3dsolid getSlice截面
- (xdrx_entity_delete e);;删除上部分、留下下半部分
- (setq br (xdbr::constructor e1))
- ;;从BODY创建AcBrBrep
- (setq tr (xdbr::constructor "brepfacetraverser" br))
- ;;构建Brep->Face遍历器
- ;;FACE遍历
- (setq i 0
- ints nil
- bestDist 1e100
- tf t
- )
- (while (and tf (not (xdbr::traverser:done tr)))
- (if (setq face (xdbr::getpropertyvalue tr "face"))
- ;;当前遍历位置获得AcBrFace
- (progn (setq gface (xdbr::getpropertyvalue face "surface"));;AcBrFace->AcGeSurface
- (setq ptOnSurf (xdge::constructor "kPointOnSurface" gface));;构建AcGePointOnCurve对象
- (setq pnt (xdge::getpropertyvalue ptOnSurf "point");;得到AcGePointOnCurve上一点
- dist (xdge::getpropertyvalue mPlane "signeddistanceto" pnt);;求该点到截面的有符号距离
- subEntPath (xdbr::getpropertyvalue face "subentpath");;获得AcBrFace的子实体路径
- subEntId (xdrx_getpropertyvalue subEntPath "subentid");;获得子实体路径的子实体ID
- )
- (if (< dist bestDist);;如果距离小于预设,预设存储当前距离
- (setq bestDist dist)
- )
- (if (equal bestDist 0.0 1e-5);;如果距离=0,找到截面对应的3DSOLID上的AcBrFace,结束循环
- (setq tf nil)
- )
- (xdrx_object_release face gface ptonsurf subentpath);;释放中间对象
- )
- )
- (xdbr::traverser:next tr);;遍历下一个面
- )
- (xdrx_setpropertyvalue e1 "SubEntColor" (list subentid 1));;设置3DSOLID子实体(面)的颜色
- (xdrx_object_release tr br subentid);;释放中间对象
- (xdrx_entity_delete ln);;删除多段线
- )
- (if (and (setq e (car (xdrx_entsel "\n选取3DSOLID<退出>:" '((0 . "3DSOLID")))
- )
- )
- (setq ln (car
- (xdrx_entsel "\n选择截面线<退出>:" '((0 . "LWPOLYLINE")))
- )
- )
- )
- (progn (xdrx_begin) (_traversface e ln) (xdrx_end))
- )
- (princ)
- )
|