### 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.

• Bull Frog
• Posts: 424
##### [AcBr Library(2)] Make a section for 3DSOLID and set the color for the section
« on: November 14, 2023, 09:46:28 PM »
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")))
6.         AcDb3dSolid *pSol;
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;
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)
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. )