Author Topic: (cadr (nentsel))  (Read 4595 times)

0 Members and 1 Guest are viewing this topic.

velasquez

  • Newt
  • Posts: 195
(cadr (nentsel))
« on: December 14, 2016, 03:14:46 PM »
I get a point on a line using (setq xpto (cadr (nentsel))) with (getvar "viewdir") = (-1.0 -1.0 1.0)
I need to calculate whether xpto is closest to DXF 10 or DXF 11 of this line.
Anyone already had to do this and can you help me?

Thanks

Grrr1337

  • Swamp Rat
  • Posts: 812
Re: (cadr (nentsel))
« Reply #1 on: December 14, 2016, 03:33:17 PM »
Simple example:
Code: [Select]
(and
  (setq pick (nentsel "\nPick a line: "))
  (= "LINE" (cdr (assoc 0 (setq enx (entget (car pick))))))
  (if (apply '< (mapcar '(lambda (x) (distance (cadr pick) (cdr (assoc x enx)))) (list 10 11)))
    (entmakex (list (cons 0 "POINT") (cons 62 1) (assoc 10 enx)))
    (entmakex (list (cons 0 "POINT") (cons 62 1) (cons 10 (cdr (assoc 11 enx)))))
  )
)

Well the worst scenario would be to pick a segment from a nested block.. maybe anyone else?
(apply ''((a b c)(a b c))
  '(
    (( f L ) (apply 'strcat (f L)))
    (( L ) (if L (cons (chr (car L)) (f (cdr L)))))
    (72 101 108 108 111 32 87 111 114 108 100)
  )
)
vevo.bg

velasquez

  • Newt
  • Posts: 195
Re: (cadr (nentsel))
« Reply #2 on: December 14, 2016, 04:07:15 PM »
Simple example:
Code: [Select]
(and
  (setq pick (nentsel "\nPick a line: "))
  (= "LINE" (cdr (assoc 0 (setq enx (entget (car pick))))))
  (if (apply '< (mapcar '(lambda (x) (distance (cadr pick) (cdr (assoc x enx)))) (list 10 11)))
    (entmakex (list (cons 0 "POINT") (cons 62 1) (assoc 10 enx)))
    (entmakex (list (cons 0 "POINT") (cons 62 1) (cons 10 (cdr (assoc 11 enx)))))
  )
)

Well the worst scenario would be to pick a segment from a nested block.. maybe anyone else?

Its function always returns the same point.
I believe the problem is in transporting the point to the current plane but I could not.

Thanks

Grrr1337

  • Swamp Rat
  • Posts: 812
Re: (cadr (nentsel))
« Reply #3 on: December 14, 2016, 04:58:57 PM »
Should've included trans function, maybe attach sample drawing?
(apply ''((a b c)(a b c))
  '(
    (( f L ) (apply 'strcat (f L)))
    (( L ) (if L (cons (chr (car L)) (f (cdr L)))))
    (72 101 108 108 111 32 87 111 114 108 100)
  )
)
vevo.bg

velasquez

  • Newt
  • Posts: 195
Re: (cadr (nentsel))
« Reply #4 on: December 14, 2016, 05:09:42 PM »
Should've included trans function, maybe attach sample drawing?

Follow the drawing.
Thanks for your help.

Grrr1337

  • Swamp Rat
  • Posts: 812
Re: (cadr (nentsel))
« Reply #5 on: December 14, 2016, 06:23:41 PM »
Ok, try:
Code: [Select]
(and
  (setq pick (nentsel "\nPick a line: "))
  (= "LINE" (cdr (assoc 0 (setq enx (entget (car pick))))))
  (if (apply '< (mapcar '(lambda (x) (distance (osnap (cadr pick) "_NEA") (cdr (assoc x enx)))) (list 10 11)))
    (entmakex (list (cons 0 "POINT") (cons 62 1) (assoc 10 enx)))
    (entmakex (list (cons 0 "POINT") (cons 62 1) (cons 10 (cdr (assoc 11 enx)))))
  )
)
And a recently created, related thread:-D
(apply ''((a b c)(a b c))
  '(
    (( f L ) (apply 'strcat (f L)))
    (( L ) (if L (cons (chr (car L)) (f (cdr L)))))
    (72 101 108 108 111 32 87 111 114 108 100)
  )
)
vevo.bg

velasquez

  • Newt
  • Posts: 195
Re: (cadr (nentsel))
« Reply #6 on: December 15, 2016, 06:46:28 AM »
Ok, try:
Code: [Select]
(and
  (setq pick (nentsel "\nPick a line: "))
  (= "LINE" (cdr (assoc 0 (setq enx (entget (car pick))))))
  (if (apply '< (mapcar '(lambda (x) (distance (osnap (cadr pick) "_NEA") (cdr (assoc x enx)))) (list 10 11)))
    (entmakex (list (cons 0 "POINT") (cons 62 1) (assoc 10 enx)))
    (entmakex (list (cons 0 "POINT") (cons 62 1) (cons 10 (cdr (assoc 11 enx)))))
  )
)
And a recently created, related thread:-D

This worked well with the line.
I am now trying the same result with the selection on the block, without working with the line.
The reference points are the top and bottom center.
Thank you very much for your help.

Grrr1337

  • Swamp Rat
  • Posts: 812
Re: (cadr (nentsel))
« Reply #7 on: December 15, 2016, 08:10:02 AM »
I am now trying the same result with the selection on the block, without working with the line.
The reference points are the top and bottom center.
Thank you very much for your help.
The problem is that your block doesn't contain any lines, just the 3D Solid.
However it is possible to obtain these points, but the routine will work specifically for this particular block, Example:

Code: [Select]
(defun C:test ( / blk blkobj explosion TheSolid Lst pts)
  (and
    (setq blk (car (entsel "\nSelect the block: ")))
    (setq blkobj (vlax-ename->vla-object blk))
    (setq explosion (vlax-invoke blkobj 'Explode))
    (vl-some (function (lambda (o) (and (eq (vla-get-ObjectName o) "AcDb3dSolid") (setq TheSolid o)))) explosion)
    (not (command "_.EXPLODE" (setq TheSolid (vlax-vla-object->ename TheSolid))))
    (setq Lst (GetEnamesFrom TheSolid))
    (setq pts
      (mapcar
        (function
          (lambda (o / ll ur)
            (vla-GetBoundingBox o 'll 'ur)
            (apply 'mapcar (cons '(lambda (a b) (/ (+ a b) 2.)) (mapcar 'vlax-safearray->list (list ll ur))))
          )
        )
        (mapcar 'vlax-ename->vla-object (vl-remove-if-not (function (lambda (x) (= "REGION" (cdr (assoc 0 (entget x)))))) Lst))
      )
    )
    (mapcar 'entdel Lst)
  ); and
  (and pts (= 2 (length pts)) (apply 'grdraw (append pts (list 1 7))))
)

(defun GetEnamesFrom ( e / next Lst )
  (if (setq next (entnext e))
    (while next
      (setq Lst (cons next Lst))
      (setq next (entnext next)) 
    )
  )
  Lst
)
In other words the above checks for the first occurence of a 3D Solid object, after exploding the block, then it explodes that same solid and looks for REGION objects.
After exploding the solid, both region objects are occuring at the top and bottom of the block, and just extract their boundingbox centroids, that are the desired points.
And at the end just erase all the created entities after exploding that block.
(apply ''((a b c)(a b c))
  '(
    (( f L ) (apply 'strcat (f L)))
    (( L ) (if L (cons (chr (car L)) (f (cdr L)))))
    (72 101 108 108 111 32 87 111 114 108 100)
  )
)
vevo.bg

velasquez

  • Newt
  • Posts: 195
Re: (cadr (nentsel))
« Reply #8 on: December 15, 2016, 12:05:12 PM »
I am now trying the same result with the selection on the block, without working with the line.
The reference points are the top and bottom center.
Thank you very much for your help.
The problem is that your block doesn't contain any lines, just the 3D Solid.
However it is possible to obtain these points, but the routine will work specifically for this particular block, Example:

Code: [Select]
(defun C:test ( / blk blkobj explosion TheSolid Lst pts)
  (and
    (setq blk (car (entsel "\nSelect the block: ")))
    (setq blkobj (vlax-ename->vla-object blk))
    (setq explosion (vlax-invoke blkobj 'Explode))
    (vl-some (function (lambda (o) (and (eq (vla-get-ObjectName o) "AcDb3dSolid") (setq TheSolid o)))) explosion)
    (not (command "_.EXPLODE" (setq TheSolid (vlax-vla-object->ename TheSolid))))
    (setq Lst (GetEnamesFrom TheSolid))
    (setq pts
      (mapcar
        (function
          (lambda (o / ll ur)
            (vla-GetBoundingBox o 'll 'ur)
            (apply 'mapcar (cons '(lambda (a b) (/ (+ a b) 2.)) (mapcar 'vlax-safearray->list (list ll ur))))
          )
        )
        (mapcar 'vlax-ename->vla-object (vl-remove-if-not (function (lambda (x) (= "REGION" (cdr (assoc 0 (entget x)))))) Lst))
      )
    )
    (mapcar 'entdel Lst)
  ); and
  (and pts (= 2 (length pts)) (apply 'grdraw (append pts (list 1 7))))
)

(defun GetEnamesFrom ( e / next Lst )
  (if (setq next (entnext e))
    (while next
      (setq Lst (cons next Lst))
      (setq next (entnext next)) 
    )
  )
  Lst
)
In other words the above checks for the first occurence of a 3D Solid object, after exploding the block, then it explodes that same solid and looks for REGION objects.
After exploding the solid, both region objects are occuring at the top and bottom of the block, and just extract their boundingbox centroids, that are the desired points.
And at the end just erase all the created entities after exploding that block.

Hello Grrr1337,
Excellent job.

I was able to solve the problem with the list of points.
I include the values with xdata in block creation.
But the problem is still carrying the selection point exactly up the entity and then checking the distance with the points in the list.
I tried with the trans function and excellent Lee Mac code to work with the matrix, but I did not get it.

ronjonp

  • Needs a day job
  • Posts: 7529
Re: (cadr (nentsel))
« Reply #9 on: December 15, 2016, 12:56:45 PM »
If you're now getting the correct point, maybe you could use vlax-curve-getparamatpoint & check which one you're closest to ?

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

Grrr1337

  • Swamp Rat
  • Posts: 812
Re: (cadr (nentsel))
« Reply #10 on: December 15, 2016, 01:18:38 PM »
But the problem is still carrying the selection point exactly up the entity and then checking the distance with the points in the list.
I tried with the trans function and excellent Lee Mac code to work with the matrix, but I did not get it.
I thought you want to obtain the nearest picked to. The issue is that (cadr pick) always get Z=0, so (trans (cadr pick) (car pick) 0) seems to slove that problem (still has high failure chance):

Code: [Select]
(defun C:test ( / pick blk blkobj explosion TheSolid Lst pts ClosestPoint )
  (and
    (setq pick (entsel "\nSelect the block: "))
    (setq blk (car pick))
    (setq blkobj (vlax-ename->vla-object blk))
    (setq explosion (vlax-invoke blkobj 'Explode))
    (vl-some (function (lambda (o) (and (eq (vla-get-ObjectName o) "AcDb3dSolid") (setq TheSolid o)))) explosion)
    (not (command "_.EXPLODE" (setq TheSolid (vlax-vla-object->ename TheSolid))))
    (setq Lst (GetEnamesFrom TheSolid))
    (setq pts
      (mapcar
        (function
          (lambda (o / ll ur)
            (vla-GetBoundingBox o 'll 'ur)
            (apply 'mapcar (cons (function (lambda (a b) (/ (+ a b) 2.))) (mapcar 'vlax-safearray->list (list ll ur))))
          )
        )
        (mapcar 'vlax-ename->vla-object (vl-remove-if-not (function (lambda (x) (= "REGION" (cdr (assoc 0 (entget x)))))) Lst))
      )
    )
    (mapcar 'entdel Lst)
  ); and
  (and pts (= 2 (length pts))
    (not (apply 'grdraw (append pts (list 1 7))))
    (setq ClosestPoint
      (cadar
        (vl-sort
          (mapcar 'list
            (mapcar 'distance (mapcar (function (lambda (x) (trans (cadr x) (car x) 0))) (list pick pick)) (mapcar (function (lambda (x) (trans x 1 0))) pts))
            pts
          )
          (function (lambda (a b) (< (car a) (car b))))
        )
      )
    )
    (entmakex (list (cons 0 "POINT") (cons 62 1) (cons 10 ClosestPoint)))
  ); and
)

(defun GetEnamesFrom ( e / next Lst )
  (if (setq next (entnext e))
    (while next
      (setq Lst (cons next Lst))
      (setq next (entnext next)) 
    )
  )
  Lst
)
If you always want to obtain the top point, which is the block's basepoint, just use (cdr (assoc 10 (entget blk))). Not sure whats your end goal.
Maybe someone else could help.

If you're now getting the correct point, maybe you could use vlax-curve-getparamatpoint & check which one you're closest to ?
Problem is that there are no curves involved, only "REGION", "SURFACE", "3DSOLID" and "INSERT" entities.
(apply ''((a b c)(a b c))
  '(
    (( f L ) (apply 'strcat (f L)))
    (( L ) (if L (cons (chr (car L)) (f (cdr L)))))
    (72 101 108 108 111 32 87 111 114 108 100)
  )
)
vevo.bg

ronjonp

  • Needs a day job
  • Posts: 7529
Re: (cadr (nentsel))
« Reply #11 on: December 15, 2016, 01:27:06 PM »
From the first post in this thread I assumed it was a LINE  :)

I get a point on a line using (setq xpto (cadr (nentsel))) with (getvar "viewdir") = (-1.0 -1.0 1.0)
..

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

velasquez

  • Newt
  • Posts: 195
Re: (cadr (nentsel))
« Reply #12 on: December 15, 2016, 02:40:32 PM »
From the first post in this thread I assumed it was a LINE  :)

I get a point on a line using (setq xpto (cadr (nentsel))) with (getvar "viewdir") = (-1.0 -1.0 1.0)
..

My English is not good.
I used the line to demonstrate what I need.
Thanks

velasquez

  • Newt
  • Posts: 195
Re: (cadr (nentsel))
« Reply #13 on: December 15, 2016, 02:49:16 PM »
But the problem is still carrying the selection point exactly up the entity and then checking the distance with the points in the list.
I tried with the trans function and excellent Lee Mac code to work with the matrix, but I did not get it.
I thought you want to obtain the nearest picked to. The issue is that (cadr pick) always get Z=0, so (trans (cadr pick) (car pick) 0) seems to slove that problem (still has high failure chance):

Code: [Select]
(defun C:test ( / pick blk blkobj explosion TheSolid Lst pts ClosestPoint )
  (and
    (setq pick (entsel "\nSelect the block: "))
    (setq blk (car pick))
    (setq blkobj (vlax-ename->vla-object blk))
    (setq explosion (vlax-invoke blkobj 'Explode))
    (vl-some (function (lambda (o) (and (eq (vla-get-ObjectName o) "AcDb3dSolid") (setq TheSolid o)))) explosion)
    (not (command "_.EXPLODE" (setq TheSolid (vlax-vla-object->ename TheSolid))))
    (setq Lst (GetEnamesFrom TheSolid))
    (setq pts
      (mapcar
        (function
          (lambda (o / ll ur)
            (vla-GetBoundingBox o 'll 'ur)
            (apply 'mapcar (cons (function (lambda (a b) (/ (+ a b) 2.))) (mapcar 'vlax-safearray->list (list ll ur))))
          )
        )
        (mapcar 'vlax-ename->vla-object (vl-remove-if-not (function (lambda (x) (= "REGION" (cdr (assoc 0 (entget x)))))) Lst))
      )
    )
    (mapcar 'entdel Lst)
  ); and
  (and pts (= 2 (length pts))
    (not (apply 'grdraw (append pts (list 1 7))))
    (setq ClosestPoint
      (cadar
        (vl-sort
          (mapcar 'list
            (mapcar 'distance (mapcar (function (lambda (x) (trans (cadr x) (car x) 0))) (list pick pick)) (mapcar (function (lambda (x) (trans x 1 0))) pts))
            pts
          )
          (function (lambda (a b) (< (car a) (car b))))
        )
      )
    )
    (entmakex (list (cons 0 "POINT") (cons 62 1) (cons 10 ClosestPoint)))
  ); and
)

(defun GetEnamesFrom ( e / next Lst )
  (if (setq next (entnext e))
    (while next
      (setq Lst (cons next Lst))
      (setq next (entnext next)) 
    )
  )
  Lst
)
If you always want to obtain the top point, which is the block's basepoint, just use (cdr (assoc 10 (entget blk))). Not sure whats your end goal.
Maybe someone else could help.

If you're now getting the correct point, maybe you could use vlax-curve-getparamatpoint & check which one you're closest to ?
Problem is that there are no curves involved, only "REGION", "SURFACE", "3DSOLID" and "INSERT" entities.

Your picture shows the work.
My final goal is to work with the selection point to calculate the distance between it and the ends of the block.

velasquez

  • Newt
  • Posts: 195
Re: (cadr (nentsel))
« Reply #14 on: December 15, 2016, 03:16:19 PM »
But the problem is still carrying the selection point exactly up the entity and then checking the distance with the points in the list.
I tried with the trans function and excellent Lee Mac code to work with the matrix, but I did not get it.
I thought you want to obtain the nearest picked to. The issue is that (cadr pick) always get Z=0, so (trans (cadr pick) (car pick) 0) seems to slove that problem (still has high failure chance):

In my drawing if the block is moved the code always returns the lower point of the block.


Grrr1337

  • Swamp Rat
  • Posts: 812
Re: (cadr (nentsel))
« Reply #15 on: December 15, 2016, 03:20:41 PM »
Your picture shows the work.
My final goal is to work with the selection point to calculate the distance between it and the ends of the block.
IMO alot more efficient would be if you include that axis line into the block's definition, so we could skip all the nasty explode stuff.
And this one should give you everything you need, both distances and the coordinates of the closest point:
Code: [Select]
(defun C:test ( / p pick e enx BothDistances ClosestPoint)
  (while
    (not
      (and
        (setq p (getpoint "\nSelect the line: "))
        (setq pick (nentselp p))
        (setq e (car pick))
        (= "LINE" (cdr (assoc 0 (setq enx (entget e)))))
        (if (apply '< (setq BothDistances (mapcar '(lambda (x) (distance p (cdr (assoc x enx)))) (list 10 11))))
          (setq ClosestPoint (cdr (assoc 10 enx)))
          (setq ClosestPoint (cdr (assoc 11 enx)))
        )     
      )
    )
    p
  )
  (alert
    (strcat
      "\nFirst distance: " (rtos (car BothDistances) 2) " units."
      "\nSecond Distance: " (rtos (cadr BothDistances) 2) " units."
      "\nClosest Point is located at: " (vl-princ-to-string ClosestPoint) " coordinates."
    )
  )
  (princ)
)
Although it was an interesting practice! :-D
(apply ''((a b c)(a b c))
  '(
    (( f L ) (apply 'strcat (f L)))
    (( L ) (if L (cons (chr (car L)) (f (cdr L)))))
    (72 101 108 108 111 32 87 111 114 108 100)
  )
)
vevo.bg

velasquez

  • Newt
  • Posts: 195
Re: (cadr (nentsel))
« Reply #16 on: December 15, 2016, 05:23:05 PM »
Your picture shows the work.
My final goal is to work with the selection point to calculate the distance between it and the ends of the block.
IMO alot more efficient would be if you include that axis line into the block's definition, so we could skip all the nasty explode stuff.
And this one should give you everything you need, both distances and the coordinates of the closest point:
Although it was an interesting practice! :-D

The image shows how my work is.
The selection point obtained with (cadr (nentsel) is used in the left block without problem.
Note that in the right block the calculation fails, always returning the same coordinate.

Grrr1337

  • Swamp Rat
  • Posts: 812
Re: (cadr (nentsel))
« Reply #17 on: December 15, 2016, 05:47:03 PM »
I don't think you'll have this problem with the last code I posted, the only requirement is to include that line into the block's definition.
(apply ''((a b c)(a b c))
  '(
    (( f L ) (apply 'strcat (f L)))
    (( L ) (if L (cons (chr (car L)) (f (cdr L)))))
    (72 101 108 108 111 32 87 111 114 108 100)
  )
)
vevo.bg

ribarm

  • Gator
  • Posts: 3279
  • Marko Ribar, architect
Re: (cadr (nentsel))
« Reply #18 on: December 15, 2016, 10:08:35 PM »
Here is my snippet, but I haven't read whole topic deeply, so this is only applicable for picking curves such as LINE among others...

Code - Auto/Visual Lisp: [Select]
  1. (defun c:test ( / s l p )
  2.  
  3.  
  4.   (while (setq s (nentsel))
  5.     (setq l (car s))
  6.     (setq p (cadr s))
  7.     (setq p (vlax-curve-getclosestpointtoprojection l (trans p 1 0) (getvar 'viewdir)))
  8.       (prompt "\nPicked point is closer to end point of curve...")
  9.       (prompt "\nPicked point is closer to start point of curve...")
  10.     )
  11.   )
  12.   (princ)
  13. )
  14.  

Regards...
« Last Edit: December 16, 2016, 06:55:50 AM by ribarm »
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Re: (cadr (nentsel))
« Reply #19 on: December 16, 2016, 10:17:05 AM »
@Marko:
I think the viewdir is expressed in the current UCS.
So you should use:
Code: [Select]
(trans (getvar 'viewdir) 1 0 T)

ribarm

  • Gator
  • Posts: 3279
  • Marko Ribar, architect
Re: (cadr (nentsel))
« Reply #20 on: December 16, 2016, 11:27:14 AM »
@Marko:
I think the viewdir is expressed in the current UCS.
So you should use:
Code: [Select]
(trans (getvar 'viewdir) 1 0 T)

Yes, Roy, you're right... Thanks for heads up... I've corrected my library in all occurs of this mistake... I simply haven't checked it in random UCS...
Many thanks... M.R.
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

velasquez

  • Newt
  • Posts: 195
Re: (cadr (nentsel))
« Reply #21 on: December 16, 2016, 11:30:20 AM »
I appreciate the help I'm getting.