Author Topic: Select objects inside 3D solid - SOLVED -  (Read 2974 times)

0 Members and 1 Guest are viewing this topic.

nekonihonjin

  • Newt
  • Posts: 103
Select objects inside 3D solid - SOLVED -
« on: August 14, 2022, 07:41:27 PM »
 hey guys, I have already googled and searched in some forums, but I can't find any information about it,
with the help of a lisp, is it possible to select the objects that are contained within the volume of a 3D solid?

In a drawing with lots of blocks, I would like to be able to select only those within a 3d solid to perform other actions only with them.


« Last Edit: August 22, 2022, 07:22:07 PM by nekonihonjin »

ScottMC

  • Newt
  • Posts: 191
Re: Select objects inside 3D solid
« Reply #1 on: August 14, 2022, 08:44:04 PM »
A worthwhile consideration and easily re-moveable is "imprint". Easy to remove too. Consider..

nekonihonjin

  • Newt
  • Posts: 103
Re: Select objects inside 3D solid
« Reply #2 on: August 14, 2022, 09:41:03 PM »
It seems to me that what you mention does not relate to what I am asking.
I want to know if something like this is possible:

https://www.youtube.com/watch?v=hjd5XvRWJA0&ab_channel=Se%C3%B1orChong

but not inside a polyline, but inside a solid, to filter a selection with only what can fit in the space occupied by the 3D solid.

ScottMC

  • Newt
  • Posts: 191
Re: Select objects inside 3D solid
« Reply #3 on: August 14, 2022, 10:09:10 PM »
Must be you are working with the objects to detect within "Z" space as well ore the option would be to make a boundary from the solid, then use it to be the Select within tool: https://www.cadtutor.net/forum/topic/29523-how-to-select-all-objects-enclosed-in-a-poly-line/?do=findComment&comment=237006
It appears objects within [from the top] would be what you need. Might also consider group using 'WP'

nekonihonjin

  • Newt
  • Posts: 103
Re: Select objects inside 3D solid
« Reply #4 on: August 14, 2022, 10:47:10 PM »
it will be used in irregular solids, that can enlarge or shrink as the Z coordinate changes, so something that works with only a flat region would not work.

I'm attaching an example file.

ScottMC

  • Newt
  • Posts: 191
Re: Select objects inside 3D solid
« Reply #5 on: August 15, 2022, 08:30:22 AM »
Copy both Solid and blocks, using the blocks coords, make a solid sphere [size?] to insert at each, use interfere to get solids[coords].  Copy/keep only the results, group and bring back to original. Resize the new spheres so u can id which blocks you want. My guess is you need a coords/list of the interfering.

nekonihonjin

  • Newt
  • Posts: 103
Re: Select objects inside 3D solid
« Reply #6 on: August 15, 2022, 11:14:22 AM »
Thanks for the answers Scott, that's a good starting point, I'm going to approach it that way.

The coordinates are not necessary for the ultimate goal, I have a lisp that generates a table where it lists the attributes of the selected objects and calculates the weighted average of each of the elements.
To be able to say, this zone that represents the solid is, for example, 857m3 with an average value of x x x x x x. It is only necessary to have the elements in selection, filtered of those that remain outside the solid, to apply to that selection the lisp that generates the table.

ribarm

  • Gator
  • Posts: 3225
  • Marko Ribar, architect
Re: Select objects inside 3D solid
« Reply #7 on: August 19, 2022, 07:37:45 AM »
Just as an alternative, though not so elegant and proficient... Instead of spheres - bounding, simply bounding box 3D SOLID could be as same good as reference spheres... Or perhaps, find Bounding Box around objects, calculate it's mid point (centroid) and then use small 3D SPHERES, or recreate small BBOXES - simply SCALE over centroids... Finally perform checkinterfere method over all BBOXES...
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

nekonihonjin

  • Newt
  • Posts: 103
Re: Select objects inside 3D solid
« Reply #8 on: August 19, 2022, 02:49:19 PM »
Marko, this code of yours does exactly what I need:

https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/checking-for-interference-between-3dsolids/td-p/6539474

after using it, just Shift-click in the big solid to de-select it, and I have all intersecting solids selected.

I made a copy of the block, with a little sphere on it, but the lisp only accepts 3d solids on the ssget, so the blocks are ignored even if they contain a sphere...

The interfere command does allow to use this block and detects interferences.


I tried just to remove the line  '((0 . "3DSOLID"))  so that it would allow me to select any object, but it didn't work.



So I wonder if it would be an easy task for you to modify your code so it can use blocks to work with.

thanks in advance.
« Last Edit: August 19, 2022, 02:58:22 PM by nekonihonjin »

ribarm

  • Gator
  • Posts: 3225
  • Marko Ribar, architect
Re: Select objects inside 3D solid
« Reply #9 on: August 19, 2022, 03:24:52 PM »
Look, if you try to use DXF 10 Group Code for INSERT entities as some kind of center of small spheres, you could avoid previously maybe better approach through center of Bounding Box... I'd use (vla-getboundingbox (vlax-ename->vla-object INSERT-ENAME) 'minpt 'maxpt) and then (setq midpt (mapcar (function /) (mapcar (function +) (mapcar 'safearray-value (list minpt maxpt))) (list 2.0 2.0 2.0)) )... When you get midpt, you either use exact BBOX : (vl-cmdf "_.BOX" "_non" minpt "_non" (list (car maxpt) (cadr maxpt) (caddr minpt)) (- (caddr maxpt) (caddr minpt))), or small sphere : (vl-cmdf "_.SPHERE" "_non" midpt 1.0) [radius=1.0]... Then when you create those solids, you should think how could you link blocks to solids... There are several ways, but for me the simple one is to group them with GROUP command... Then just use my code, and after highlighting, press ctrl+shift+A combo to switch to auto group mode off/on... If solids are still selected with blocks, go to qselect, filter for just non solids and there you are - use SELECT command, press ENTER, then do with qselect filtering of solids and hit del... Finally, you should have (ssget "_P") which should have all your desired blocks in bounding perimeter of reference 3DSOLID... For visualization, use (sssetfirst nil (ssget "_P"))...
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

nekonihonjin

  • Newt
  • Posts: 103
Re: Select objects inside 3D solid
« Reply #10 on: August 19, 2022, 04:50:27 PM »
I grouped every pair of sphere-block, after using your lisp only spheres are selected not the entire group.
another way to link them?

tried Gccoincident but only works with 2d objects
« Last Edit: August 19, 2022, 06:30:27 PM by nekonihonjin »

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8659
  • AKA Daniel
Re: Select objects inside 3D solid
« Reply #11 on: August 19, 2022, 11:32:01 PM »
I have no idea how you would approach this in lisp, but maybe you can use ray tracing, i.e
iterate the faces find the closest point on the closest face, now you have a vector from the block position to the face.
now you can try to find if the opposite vector intersects another face.

something like

 

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8659
  • AKA Daniel
Re: Select objects inside 3D solid
« Reply #12 on: August 20, 2022, 12:10:27 AM »
here's an ARX acad 2021-23 to show the concept, the command is doit

Code - C: [Select]
  1.   static void ArxBrxTest_doit()
  2.     {
  3.         if (const auto [bes, bid, bpnt] = entSel(_T("\nSelect Block"));
  4.             bes == eOk && bid.objectClass()->isDerivedFrom(AcDbBlockReference::desc()))
  5.         {
  6.             std::vector<std::unique_ptr<AcGeSurface>> acGeSurfaces;
  7.             AcDbObjectPointer<AcDbBlockReference> pBlock(bid);
  8.  
  9.             if (const auto [ses, sid, spnt] = entSel(_T("\nSelect Solid"));
  10.                 ses == eOk && sid.objectClass()->isDerivedFrom(AcDb3dSolid::desc()))
  11.             {
  12.                 AcBrBrep pBrep;
  13.                 AcDbObjectPointer<AcDb3dSolid> pSolid(sid);
  14.                 AcDbFullSubentPath SubEntPh(sid, kNullSubentId);
  15.                 if (pBrep.setSubentPath(SubEntPh) != AcBr::ErrorStatus::eOk)
  16.                     return;
  17.                 AcBrBrepFaceTraverser biter;
  18.                 if (biter.setBrep(pBrep) != AcBr::ErrorStatus::eOk)
  19.                     return;
  20.                 for (auto bEok = AcBr::ErrorStatus::eOk; !biter.done(); bEok = biter.next())
  21.                 {
  22.                     if (bEok != AcBr::ErrorStatus::eOk)
  23.                         continue;
  24.                     AcBrFace brFace;
  25.                     if (biter.getFace(brFace) != AcBr::ErrorStatus::eOk)
  26.                         continue;
  27.                     AcGeSurface* psurf = nullptr;
  28.                     if (brFace.getSurface(psurf) != eOk)
  29.                         continue;
  30.                     if (psurf != nullptr)
  31.                         acGeSurfaces.push_back(std::unique_ptr<AcGeSurface>(psurf));
  32.                 }
  33.             }
  34.             AcGePoint3d closest;
  35.             AcGeSurface* pLast = nullptr;
  36.             double dist = DBL_MAX;
  37.             for (auto& item : acGeSurfaces)
  38.             {
  39.                 auto pnt = item->closestPointTo(pBlock->position());
  40.                 double _dist = pnt.distanceTo(pBlock->position());
  41.                 if (_dist < dist)
  42.                 {
  43.                     dist = _dist;
  44.                     closest = pnt;
  45.                     pLast = item.get();
  46.                 }
  47.             }
  48.             AcGeLineSeg3d seg(pBlock->position(), pBlock->position() - closest);
  49.             seg.scaleBy(1000, pBlock->position());//hackola wtf
  50.             bool found = false;
  51.             for (const auto& item : acGeSurfaces)
  52.             {
  53.                 if (item.get() == pLast)
  54.                     continue;
  55.                 AcGeCurveSurfInt sint(seg, *item);
  56.                 AcGeIntersectError  err_1 = AcGe::kXXOk;
  57.                 const int cnt = sint.numIntPoints(err_1);
  58.                 for (int idx = 0; idx < cnt; idx++)
  59.                 {
  60.                     const auto on = sint.intPoint(idx, err_1);
  61.                     if (item->isOn(on))
  62.                     {
  63.                         found = true;
  64.                         break;
  65.                     }
  66.                 }
  67.                 if(found)
  68.                     break;
  69.             }
  70.             acutPrintf(_T("\nBlock is inside = %ls"), found ? _T("TRUE") : _T("FALSE"));
  71.         }
  72.     }
  73.  

edit AcGeCurveSurfInt index it inconsistent with the docs,
Quote
This function returns a particular intersection point between the curve and surface. intNum must be greater than zero and less than the total number of intersection points.
the index is zero based
« Last Edit: August 20, 2022, 12:28:13 AM by It's Alive! »

nekonihonjin

  • Newt
  • Posts: 103
Re: Select objects inside 3D solid
« Reply #13 on: August 20, 2022, 01:09:04 AM »
Thanks for answering Daniel, I have autocad 2018, I get error message: ARX load failed.

I don't know how to calculate in lisp to find the nearest point of the nearest face, but I can think of a ray in each direction of the axes and check if they are all intersected, what would happen if it is inside.

I will look for a code to check if a line intersects a face.


It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8659
  • AKA Daniel
Re: Select objects inside 3D solid
« Reply #14 on: August 20, 2022, 03:51:48 AM »
Bummer, yeah you can probably get the solid and decode it (http://www.theswamp.org/index.php?topic=25097.0)
You should be able to build a list of planes from the face vertexs, then do the ray trace thing. 
I noticed some plane functions here (http://www.theswamp.org/index.php?topic=40494.msg457913#msg457913)

here's the list of objects I found.. though it seems the ID is not unique

Quote
ID = BJ1-106
ID = BJ1-106
ID = BJ1-106
ID = BJ1-140
ID = BJ1-108
ID = BJ1-102
ID = BJ1-140
ID = BJ1-125
ID = BJ1-102
ID = BJ1-143
ID = BJ1-132
ID = BJ1-132
ID = BJ1-119
ID = BJ1-115
ID = BJ1-145
ID = BJ1-141
ID = BJ1-131
ID = BJ1-129
ID = BJ1-127
ID = BJ1-122
ID = BJ1-12
ID = BJ1-117
ID = BJ1-107
ID = BJ1-106
ID = BJ1-10