Author Topic: [AcBr LIB(3)]Find the closest point from a spatial point to each face of 3DSOLID  (Read 1348 times)

0 Members and 1 Guest are viewing this topic.

xdcad

  • Swamp Rat
  • Posts: 527
question:

I have a point in 3D space and I would like to get the closest point on a 3D solid from this input point. Is there any API to achieve this?


Which API can solve the problem of the closest input point to 3DSOLID?

solution:


It is possible to realize that using the BRep API (located in the <ObjectARX 2009 Path>\utils\brep directory): you need to traverse all the faces that are contained in your 3D solid and for each face use the AcBrFace::getFace method. It returns an AcGeSurface object from where you can use AcGeSurface::closestPointTo, passing in your input point.


Using the BRep API, you need to iterate through all the faces contained in the 3D entity and use the AcBrFace::getFace method for each face to get the AcGeSurface object, and use AcGeSurface::closestPointTo to get the closest point between the input point and the AcGeSurface object.



Here is the ARX code:
Code - C++: [Select]
  1. static AcBr::ErrorStatus TraverseFaces(const AcBrBrep& brepEntity, const AcGePoint3d& pointToTest)
  2. {
  3.         AcBr::ErrorStatus returnValue = AcBr::eOk;
  4.         // make a global face traverser
  5.         AcBrBrepFaceTraverser brepFaceTrav;
  6.         returnValue = brepFaceTrav.setBrep(brepEntity);
  7.         if (returnValue != AcBr::eOk)
  8.         {
  9.                 acutPrintf(ACRX_T("\n Error in AcBrBrepFaceTraverser::setBrep:"));
  10.                 errorReport(returnValue);
  11.                 return returnValue;
  12.         }
  13.         int faceCount = 0;
  14.        while (!brepFaceTrav.done() && (returnValue == AcBr::eOk))
  15.         {
  16.                 ++faceCount;
  17.                 AcBrFace face;
  18.                 if (brepFaceTrav.getFace(face) == AcBr::ErrorStatus::eOk)
  19.                 {
  20.                         AcGeSurface* pSurface;
  21.                         if (face.getSurface(pSurface) == AcBr::ErrorStatus::eOk)
  22.                         {
  23.                                 AcGePoint3d closestPoint = pSurface->closestPointTo(pointToTest);
  24.  
  25.                                 double dist = AcGeVector3d(closestPoint.asVector() - pointToTest.asVector()).length();
  26.  
  27.                                 acutPrintf(L"\n - Face[%d]: closest point [%f, %f, %f]   Distance: %f", faceCount, closestPoint.x, closestPoint.y, closestPoint.z, dist);
  28.  
  29.                                 delete pSurface;
  30.                         }
  31.                 }
  32.                 returnValue = brepFaceTrav.next();
  33.                 if (returnValue != AcBr::eOk) {
  34.                         acutPrintf(ACRX_T("\n Error in AcBrBrepFaceTraverser::next:"));
  35.                         errorReport(returnValue);
  36.                         return returnValue;
  37.                 }
  38.         }
  39.         return returnValue;
  40. }
  41. void TestClosestPoint(void)
  42. {
  43.         AcBr::ErrorStatus returnValue = AcBr::eOk;
  44.         Acad::ErrorStatus acadReturnValue = eOk;
  45.         AcGePoint3d pointToTest;
  46.         // pick a point
  47.         acedGetPoint(NULL, L"\nPick a point: ", asDblArray(pointToTest));
  48.         // Get the subentity path for a brep
  49.         AcDbFullSubentPath subPath(kNullSubent);
  50.         acadReturnValue = selectEntity(AcDb::kNullSubentType, subPath);
  51.         if (acadReturnValue != eOk)
  52.         {
  53.                 acutPrintf(ACRX_T("\n Error in getPath: %d"), acadReturnValue);
  54.                 return;
  55.         }
  56.         // Make a brep entity to access the solid
  57.         AcBrBrep brepEntity;
  58.         returnValue = ((AcBrEntity*)&brepEntity)->set(subPath);
  59.         if (returnValue != AcBr::eOk)
  60.         {
  61.                 acutPrintf(ACRX_T("\n Error in AcBrBrep::set:"));
  62.                 errorReport(returnValue);
  63.                 return;
  64.         }
  65.         returnValue = TraverseFaces(brepEntity, pointToTest);
  66.         if (returnValue != AcBr::eOk)
  67.         {
  68.                 acutPrintf(ACRX_T("\n Error in TraverseFaces:"));
  69.                 errorReport(returnValue);
  70.                 return;
  71.         }
  72. }
  73.  

Next, use the ACBR library function of the XDRX API to complete the same work as ARX above.





Code - Auto/Visual Lisp: [Select]
  1. (defun c:tt ()
  2.    (defun _traversface (e pnt)
  3.      (setq br (xdbr::constructor e))
  4.      (setq tr (xdbr::constructor "brepfacetraverser" br))
  5.      ;;FACE traversal
  6.      (setq face-count 0)
  7.      (xdrx_entity_delete co-ss)
  8.      (xdrx_setmark)
  9.      (while (not (xdbr::traverser:done tr)); loop traversal
  10.        (if (setq face (xdbr::getpropertyvalue tr "face"));;AcBrFace object
  11.          (progn (setq face-count (1+ face-count)
  12.                       gface (xdbr::getpropertyvalue face "surface") ;;Get AcGeSurface object
  13.                       closest-pnt (xdge::getpropertyvalue gface "closestpointto" pnt);;closest point
  14.                       dist (distance pnt closest-pnt)
  15.                 )
  16.            (xdrx_object_release gface face);;Release AcBrFace, AcGeSurface
  17.            (xdrx_point_make closest-pnt)
  18.            (xdrx_entity_setcolor (entlast) 2)
  19.            (xdrx_line_make pnt closest-pnt)
  20.            (xdrx_entity_setcolor (entlast) 1)
  21.                 (xdrx_prompt
  22.                   (xdrx_string_format "\n - Surface [%d]: nearest point [%f, %f, %f] distance %f"
  23.                                       face-count
  24.                                       (car closest-pnt)
  25.                                       (cadr closest-pnt)
  26.                                       (caddr closest-pnt)
  27.                                       dist
  28.                   )
  29.                 )
  30.          )
  31.        )
  32.        (setq co-ss (xdrx_getss))
  33.        (xdbr::traverser:next tr)
  34.      )
  35.      (xdrx_object_release tr br)
  36.    )
  37.    (if (setq e (car (xdrx_entsel "\nSelect 3DSOLID<Exit>:" '((0 . "3DSOLID")))))
  38.      (progn
  39.        (xdrx_begin)
  40.        (xdrx_sysvar_push '("osmode" 512))
  41.        (xdrx_setvar "pdmode" 35)
  42.        (while (setq pt (getpoint "\nClick to get the test point <exit>:"))
  43.        (_traversface e (setq pt (trans pt 1 0))))
  44.        (xdrx_end)
  45.      )
  46.    )
  47.    (princ)
  48. )
  49.  

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 20, 2023, 10:08:14 PM by xdcad »
The code I wrote uses XDRX-API,which can be downloaded from github.com and is updated at any time.
===================================
https://github.com/xdcad
https://sourceforge.net/projects/xdrx-api-zip/
http://bbs.xdcad.net