Author Topic: [AcBr Library(2)] Make a section for 3DSOLID and set the color for the section  (Read 1068 times)

0 Members and 1 Guest are viewing this topic.

xdcad

  • Bull Frog
  • Posts: 424
question:


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.


How to color the area where 3DSOLID and entity intersect? The shaded area is the new section of the modified 3DSLID.

solution:
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


Use the AcBrBrep library to traverse the 3DSOLID after the slice. The slice is a 2D curve entity. This slice is a surface after slicing the 3DSOLID. Therefore, calculate the distance from the point on the 2D slice to all faces of 3DSOLID. The face with distance = 0 is what we are looking for. Finally, set the color of this surface through AcDb3dSolid::setSubentColor().


The following is the ARX implementation code:
Code - C++: [Select]
  1. static void ASDKTS51618_GetSlice_MySlice(void)
  2. {
  3.         if (!acrxClassDictionary->at(_T("AcBrEntity")))
  4.                 bool found = acrxDynamicLinker->loadModule(_T("acbr17.dbx"), 0);
  5.         Acad::ErrorStatus es;
  6.         AcDb3dSolid *pSol;
  7.         ads_name en1, en2;
  8.         ads_point pt;
  9.         AcDbObjectId eId;
  10.         acedEntSel(_T("\nSelect a solid: "), en1, pt);
  11.         if (Acad::eOk != acdbGetObjectId(eId, en1))
  12.                 return;
  13.         acdbOpenObject(pSol, eId, AcDb::kForWrite);
  14.         if (pSol == NULL) {
  15.                 acutPrintf(_T("Can't access solid - aborting"));
  16.                 return;
  17.         }
  18.         AcDbEntity *pEnt;
  19.         acedEntSel(_T("\nPick the 2-D slicing entity: "), en2, pt);
  20.         if (Acad::eOk != acdbGetObjectId(eId, en2))
  21.                 return;
  22.         acdbOpenObject(pEnt, eId, AcDb::kForRead);
  23.         if (pEnt == NULL) {
  24.                 acutPrintf(_T("Can't access slicing entity - aborting"));
  25.                 return;
  26.         }
  27.         AcGePlane plane;
  28.         AcDb::Planarity flag;
  29.         pEnt->getPlane(plane, flag);
  30.  
  31.         if (flag != AcDb::kPlanar) {
  32.                 acutPrintf(_T("Not a 2d curve - aborting"));
  33.                 return;
  34.         }
  35.         pEnt->close();
  36.         AcDb3dSolid* pJunkSolid;
  37.         es = pSol->getSlice(plane, Adesk::kTrue, pJunkSolid);
  38.         if (!pJunkSolid) return; //no slice made
  39.         AcBrBrep *pBrepSol = new AcBrBrep;
  40.  
  41.         AcBr::ErrorStatus brErr = pBrepSol->setSubentPath(AcDbFullSubentPath(pSol->objectId(), kNullSubentId));
  42.         AcCmColor Col;
  43.         Col.setColorIndex(1);
  44.         AcBrBrepFaceTraverser brepFaceTrav;
  45.     AcBrFace currentFace;
  46.         AcGeSurface* surface;
  47.  
  48.         brepFaceTrav.setBrep(*pBrepSol);
  49.         double bestDist = 1000;
  50.         AcDbSubentId closestSubId;
  51.         bool faceFound = false;
  52.         while (!brepFaceTrav.done()) {
  53.                 brepFaceTrav.getFace(currentFace);
  54.                 brErr = currentFace.getSurface(surface);
  55.                 AcGePointOnSurface *repPntSurf = new AcGePointOnSurface(*surface);
  56.                 AcGePoint3d repPnt = repPntSurf->point3d();
  57.                 double dist = abs(plane.signedDistanceTo(repPnt));
  58.                 //does this surface point lie on the plane that contains the 2d slicer?
  59.  
  60.                 if (dist < bestDist) {
  61.                         bestDist = dist;
  62.                         AcDbFullSubentPath subPath(kNullSubent);
  63.                         currentFace.getSubentPath(subPath);
  64.                         closestSubId = subPath.subentId();
  65.                         if (bestDist == 0.000)
  66.                                 break;  //can't do better than zero distance
  67.                 }
  68.                 delete surface;
  69.                 delete repPntSurf;
  70.                 brepFaceTrav.next();
  71.         }
  72.         delete pBrepSol;
  73.         pSol->setSubentColor(closestSubId, Col);
  74.         pSol->close();
  75.  
  76. }
  77.  



The following is the LISP solution code for the ACBR library function of the XDRX API:

Code - Auto/Visual Lisp: [Select]
  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 section
  11.      (xdrx_entity_delete e);;Delete the upper part and leave the lower part
  12.      (setq br (xdbr::constructor e1))
  13.      ;;Create AcBrBrep from BODY
  14.      (setq tr (xdbr::constructor "brepfacetraverser" br))
  15.      ;;Build Brep->Face traverser
  16.      ;;FACE traversal
  17.      (setq i 0
  18.            ints nil
  19.            bestDist 1e100
  20.            tf
  21.      )
  22.      (while (and tf (not (xdbr::traverser:done tr)))
  23.        (if (setq face (xdbr::getpropertyvalue tr "face"))
  24.          ;;Get AcBrFace at the current traversal position
  25.          (progn (setq gface (xdbr::getpropertyvalue face "surface"));;AcBrFace->AcGeSurface
  26.                 (setq ptOnSurf (xdge::constructor "kPointOnSurface" gface));;Construct AcGePointOnCurve object
  27.                 (setq pnt (xdge::getpropertyvalue ptOnSurf "point");;Get the previous point of AcGePointOnCurve
  28.                       dist (xdge::getpropertyvalue mPlane "signeddistanceto" pnt);; Find the signed distance from the point to the section
  29.                       subEntPath (xdbr::getpropertyvalue face "subentpath");; Get the subentity path of AcBrFace
  30.                       subEntId (xdrx_getpropertyvalue subEntPath "subentid");; Get the subentity ID of the subentity path
  31.                 )
  32.                 (if (< dist bestDist);;If the distance is less than the preset, the current distance is stored by default
  33.                   (setq bestDist dist)
  34.                 )
  35.                 (if (equal bestDist 0.0 1e-5);; If distance = 0, find the AcBrFace on the 3DSOLID corresponding to the cross section, and end the loop
  36.                   (setq tf nil)
  37.                 )
  38.                 (xdrx_object_release face gface ptonsurf subentpath);;Release the intermediate object
  39.          )
  40.        )
  41.        (xdbr::traverser:next tr);;Traverse the next face
  42.      )
  43.      (xdrx_setpropertyvalue e1 "SubEntColor" (list subentid 1));;Set the color of 3DSOLID subentity (face)
  44.      (xdrx_object_release tr br subentid);;Release intermediate object
  45.      (xdrx_entity_delete ln);;Delete polyline
  46.    )
  47.    (if (and (setq e (car (xdrx_entsel "\nSelect 3DSOLID<Exit>:" '((0 . "3DSOLID"))))
  48.                     )
  49.             )
  50.             (setq ln (car
  51.                        (xdrx_entsel "\nSelect section line<Exit>:" '((0 . "LWPOLYLINE")))
  52.                      )
  53.             )
  54.        )
  55.      (progn (xdrx_begin) (_traversface e ln) (xdrx_end))
  56.    )
  57.    (princ)
  58. )

The above LISP code uses the XDRX-API, which can be downloaded from https://github.com/xdcad/XDrx-API

The XDRX API encapsulates AcDb, AcEd, AcGe, AcBr... C++ library, using C++ methods to develop LISP programs.Thousands of Lisp functions are available.
« Last Edit: November 14, 2023, 09:49:58 PM by xdcad »
The code I wrote uses XDRX-API,which can be downloaded from github.com and is updated at any time.
===================================
[XDrx-Sub Forum]
https://www.theswamp.org/index.php?board=78.0
https://github.com/xdcad/XDrx-API
http://bbs.xdcad.net