Author Topic: (entprev)  (Read 56512 times)

0 Members and 1 Guest are viewing this topic.

LE3

  • Guest
Re: (entprev)
« Reply #30 on: November 22, 2013, 04:14:09 PM »
Code: [Select]
(defun entprev (e / e1 e2)
  (setq e1 (entnext))
  (while (and e1 (not (eq e (setq e2 (entnext e1)))))
    (setq e1 e2)
  )
  e1
)

be careful with decreasing hex, sometimes handles in custom generated dxfs are total mess
nice... I tried a similar approach but no luck -- I recall seeing a ent prev function on the old CompuServe forums that was also a simple one... again nice stuff.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: (entprev)
« Reply #31 on: November 23, 2013, 06:42:46 AM »
Good call Vovka. I did know there was some weird situations with the handle. Actually noted some issue with deleted entities as well in an old Augi thread: http://forums.augi.com/showthread.php?92053-Help-Rotation-angle-of-text&p=918573&viewfull=1#post918573

But obviously your brute-force method could become extremely slow on large drawings. That's the main reason for using the handle decrement idea. I wonder if something similar could be achieved using ObjectID's instead? Though I think those are random numbers (i.e. the drawing database has a hash-table index and the ID is the hash code), but would have to check.

Another issue with yours is it won't work inside of block definitions. Neither would the selection set versions. E.g. if the given ename is a nested entity inside a block, entnext gives the next entity inside that block - so you'd expect this entprev to give the previous entity also. Same would go for dictionaries & xrecords.

Perhaps that is the idea Owen mentioned about optimizing: If the given entity is inside a block then only search from that block's nested entities, if outside then skip all entities owned by a block record (which is not too difficult as it's just a dxf code of any one of the nesded entities). Though going through all possibilities could become a bit hairy since Model space and Paper Space tabs are also stored as block definitions, but in their case entnext mashes them up.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

ribarm

  • Gator
  • Posts: 3265
  • Marko Ribar, architect
Re: (entprev)
« Reply #32 on: November 23, 2013, 09:24:34 AM »
Just to make it clear...
Where (entnext) won't enter and return result, (entprev) shouldn't too... (entprev) is opposed function to (entnext)... So if handles are somehow altered by Autodesk intervention in future releases, I think IMO that this VovKa's code is the most acceptable no matter for its brute force slowness on large drawings... (I've tested mine witch is similar to VovKa's in method it is used with difference that my is building list along with checking during while loop on 140000 entities and it returned result in approx. 2-5 sec.)... I doubt that this function will be used in that big drawings, but then again VovKa's code doesn't built list and I suppose it's also therefore faster... So my conclusion is that probably the most adequate answer to this task is VovKa's reply with small intervention for checking argument type at the beginning and error message if argument condition isn't satisfied...

Code - Auto/Visual Lisp: [Select]
  1. (defun entprev (e / e1 e2)
  2.   (if (eq (type e) 'ename)
  3.     (progn
  4.       (setq e1 (entnext))
  5.       (while (and e1 (not (eq e (setq e2 (entnext e1)))))
  6.         (setq e1 e2)
  7.       )
  8.       e1
  9.     )
  10.     (progn (prompt "\n; error: bad argument type: lentityp ")(princ e)(princ))
  11.   )
  12. )
  13.  

You may agree with me or you may not, but I was trying to make some reasonable conclusion...
M.R.
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

Marc'Antonio Alessi

  • Swamp Rat
  • Posts: 1451
  • Marco
Re: (entprev)
« Reply #33 on: November 23, 2013, 01:04:05 PM »
I figured why Antonio's code isn't working as it should...

When (entprev (entnext e))
(entnext e) is actually nested entity from entity e, so when supplied this kind of entity, ...
Yes previous version do not works with nested entity (my tests was with entsel not with nentsel).
Try this, MAYBE it is faster if there are many complex entities:

Code: [Select]
; Version 1.10 - 23/11/2013
(defun ALE_NEntPrevious_110 (EntNam / SelSet EntDat Countr SsLngt EntOut EntNxt PrnEnt)
  (if (and (eq (type EntNam) 'ename) (assoc 410 (setq EntDat (entget EntNam))))
    (if (= "BLOCK_RECORD" (DXF 0 (entget (setq PrnEnt (DXF 330 EntDat)))))
      (if (setq SelSet (ssget "_X"))
        (progn
         (setq Countr 0   SsLngt (sslength SelSet))
          (while (> SsLngt Countr)
            (if (eq EntNam (ssname SelSet Countr))
              (setq SsLngt 0)
              (setq Countr (1+ Countr))
            )
          )
          (setq EntOut (ssname SelSet (1+ Countr))  EntNxt EntOut)
          (while (and EntNxt (setq EntNxt (entnext EntNxt)))
            (if (eq EntNxt EntNam) (setq EntNxt nil) (setq EntOut EntNxt))
          )
        )
      )
      (progn
        (setq EntOut PrnEnt)
        (while (and PrnEnt (setq PrnEnt (entnext PrnEnt)))
          (if (eq PrnEnt EntNam) (setq PrnEnt nil) (setq EntOut PrnEnt))
        )
      )
    )
  )
  EntOut
)


Marc'Antonio Alessi

  • Swamp Rat
  • Posts: 1451
  • Marco
Re: (entprev)
« Reply #34 on: November 23, 2013, 01:08:53 PM »
...
You may agree with me or you may not, but I was trying to make some reasonable conclusion...
M.R.

IMHO in VovKa's entprev you can put a condition to avoid false results if the entity is the first in the database (no previous).

VovKa

  • Water Moccasin
  • Posts: 1629
  • Ukraine
Re: (entprev)
« Reply #35 on: November 23, 2013, 01:26:16 PM »
little improvement (i hope)
Code: [Select]
(defun entprev (e / e1 e2)
  (setq e1 (cdr (assoc 360
       (entget (cdr (assoc 330 (entget e))))
)
   )
  )
  (while (and e1 (not (eq e (setq e2 (entnext e1)))))
    (setq e1 e2)
  )
  e1
)
test it with nentsel

Marc'Antonio Alessi

  • Swamp Rat
  • Posts: 1451
  • Marco
Re: (entprev)
« Reply #36 on: November 23, 2013, 03:27:19 PM »
little improvement (i hope)
Code: [Select]
(defun entprev (e / e1 e2)
  (setq   e1 (cdr   (assoc 360
             (entget (cdr (assoc 330 (entget e))))
      )
      )
  )
  (while (and e1 (not (eq e (setq e2 (entnext e1)))))
    (setq e1 e2)
  )
  e1
)
test it with nentsel
I have tested but I had some problems. This is another version with your contribution:
Code: [Select]
; Version 2.00 - 23/11/2013
(defun ALE_NEntPrevious_2 (EntNam / EntNm2 EntDat SsLngt EntOut PrnEnt)
  (if
    (and
      (assoc 410 (setq EntDat (entget EntNam)))
      (= "BLOCK_RECORD" (DXF 0 (entget (setq PrnEnt (DXF 330 EntDat)))))
    )
    (setq EntOut (entnext))
    (setq EntOut PrnEnt)
  )
  (while (and EntOut (not (eq EntNam (setq EntNm2 (entnext EntOut)))))
    (setq EntOut EntNm2)
  )
  EntOut
)

Marc'Antonio Alessi

  • Swamp Rat
  • Posts: 1451
  • Marco
Re: (entprev)
« Reply #37 on: November 24, 2013, 04:54:01 AM »
Last version, less code:
Code: [Select]
; Version 3.00 - 2013/11/24
(defun ALE_EntPrevious (EntNam / SelSet EntDat Countr SsLngt EntOut PrnEnt)
  (if
    (and
      (assoc 410 (setq EntDat (entget EntNam)))
      (= "BLOCK_RECORD" (DXF 0 (entget (setq PrnEnt (DXF 330 EntDat)))))
    )
    (progn
      (setq SelSet (ssget "_X")   Countr 0   SsLngt (sslength SelSet))
      (while (> SsLngt Countr)
        (if (eq EntNam (ssname SelSet Countr)) (setq SsLngt 0) (setq Countr (1+ Countr)))
      )
      (setq EntOut (ssname SelSet (1+ Countr))  PrnEnt EntOut)
    )
    (setq EntOut PrnEnt)
  )
  (while (and EntOut (not (eq EntNam (setq PrnEnt (entnext EntOut)))))
    (setq EntOut PrnEnt)
  )
  EntOut
)

ribarm

  • Gator
  • Posts: 3265
  • Marko Ribar, architect
Re: (entprev)
« Reply #38 on: November 24, 2013, 06:22:23 AM »
I was just going to propse the same, Marc'...

Even more optimized...

Code - Auto/Visual Lisp: [Select]
  1. ; Version 3.00 - 24/11/2013
  2. (defun entprev (EntNam / EntNm2 EntDat SsEnts SsCount EntOut PrnEnt)
  3.   (if
  4.     (and
  5.       (assoc 410 (setq EntDat (entget EntNam)))
  6.       (= "BLOCK_RECORD" (ACET-DXF 0 (entget (setq PrnEnt (ACET-DXF 330 EntDat)))))
  7.     )
  8.     (progn
  9.       (setq SsCount -1)
  10.       (setq SsEnts (ssget "_X" (list (assoc 410 EntDat))))
  11.       (while (not (eq EntNam (setq PrnEnt (ssname SsEnts (setq SsCount (1+ SsCount)))))))
  12.       (setq PrnEnt (ssname SsEnts (1+ SsCount)))
  13.       (setq EntOut PrnEnt)
  14.     )
  15.     (setq EntOut PrnEnt)
  16.   )
  17.   (while (and EntOut (not (eq EntNam (setq EntNm2 (entnext EntOut)))))
  18.     (setq EntOut EntNm2)
  19.   )
  20.   EntOut
  21. )
  22.  

Thanks, Marc'
« Last Edit: November 24, 2013, 09:06:45 AM by ribarm »
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

Stefan

  • Bull Frog
  • Posts: 319
  • The most I miss IRL is the Undo button
Re: (entprev)
« Reply #39 on: November 24, 2013, 06:53:57 AM »
Another one:
Code - Auto/Visual Lisp: [Select]
  1. (defun entprev (e / owner i prev crt)
  2.   (setq owner (vla-objectidtoobject *acdoc* (vla-get-ownerid (setq e (vlax-ename->vla-object e))))
  3.         i     -1
  4.   )
  5.   (while
  6.     (not
  7.       (=
  8.         (vla-get-objectid e)
  9.         (vla-get-objectid (setq crt (vla-item owner (setq i (1+ i)))))
  10.       )
  11.     )
  12.     (setq prev crt)
  13.   )
  14.   (if
  15.     prev
  16.     (vlax-vla-object->ename prev)
  17.     (not (princ "\nNo previous entity.\n"))
  18.   )
  19. )

Code - Auto/Visual Lisp: [Select]
  1. (defun c:test ( / e)
  2.   (if
  3.     (and
  4.       (setq e (car (entsel)))
  5.       (setq e (entprev e))
  6.       )
  7.     (sssetfirst nil (ssadd e (ssadd)))
  8.     )
  9.   (princ)
  10.   )
entprev works with (nentsel) too.

ribarm

  • Gator
  • Posts: 3265
  • Marko Ribar, architect
Re: (entprev)
« Reply #40 on: November 24, 2013, 07:09:33 AM »
Stefan, your version isn't good, although another cunning approach...

Here are results :
Code: [Select]
Command: (entnext (entprev (entlast)))
<Entity name: 7ffff5beb30>
Command: (entlast)
<Entity name: 7ffff5bec40>
Command: (entprev (entnext (entlast)))
; error: ActiveX Server returned the error: unknown name: Item

Tested on 10000 2d Polyline entities... (not LWPOLYLINEs)
M.R.
« Last Edit: November 24, 2013, 07:13:57 AM by ribarm »
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

Lee Mac

  • Seagull
  • Posts: 12913
  • London, England
Re: (entprev)
« Reply #41 on: November 24, 2013, 07:56:51 AM »
Even more optimized...

You sure about that...?  :?

Your code is retrieving a new selection set (and hence iterating over the entire drawing database) for every iteration of the while loop...  :-o
Quote from: ribarm
Code - Auto/Visual Lisp: [Select]
  1.     (not
  2.         (eq EntNam
  3.             (setq PrnEnt
  4.                 (ssname
  5.                     (setq SsEnts
  6.                         (ssget "_X" (list (assoc 410 EntDat)))
  7.                     )
  8.                     (setq SsCount (1+ SsCount))
  9.                 )
  10.             )
  11.         )
  12.     )
  13. )

Stefan

  • Bull Frog
  • Posts: 319
  • The most I miss IRL is the Undo button
Re: (entprev)
« Reply #42 on: November 24, 2013, 08:30:02 AM »
Stefan, your version isn't good, although another cunning approach...

Here are results :
Code: [Select]
Command: (entnext (entprev (entlast)))
<Entity name: 7ffff5beb30>
Command: (entlast)
<Entity name: 7ffff5bec40>
Command: (entprev (entnext (entlast)))
; error: ActiveX Server returned the error: unknown name: Item
You are right Marko. I didn't test my lisp on 2dpolylines. My mistake.
About the last error, (entnext (entlast)) is always nil, so (entprev nil) ends with an error as it should be. But you are right again, I should catch this error and print a message instead.

ribarm

  • Gator
  • Posts: 3265
  • Marko Ribar, architect
Re: (entprev)
« Reply #43 on: November 24, 2013, 08:30:48 AM »
Even more optimized...

You sure about that...?  :?

Your code is retrieving a new selection set (and hence iterating over the entire drawing database) for every iteration of the while loop...  :-o
Quote from: ribarm
Code - Auto/Visual Lisp: [Select]
  1.     (not
  2.         (eq EntNam
  3.             (setq PrnEnt
  4.                 (ssname
  5.                     (setq SsEnts
  6.                         (ssget "_X" (list (assoc 410 EntDat)))
  7.                     )
  8.                     (setq SsCount (1+ SsCount))
  9.                 )
  10.             )
  11.         )
  12.     )
  13. )

It depends where our entity supplied to function is situated... If it's near last entity (ssname ss 0), than this is more optimized - if it's near starting entity (ssname ss (1- (sslength ss)) than this isn't case, but in fact that newer version is searching for parent entity and when it finds it then steps to searching nested it is better structured function than just using (entnext) from starting entity till the previous one... IMO

M.R.
« Last Edit: November 24, 2013, 08:35:22 AM by ribarm »
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

ribarm

  • Gator
  • Posts: 3265
  • Marko Ribar, architect
Re: (entprev)
« Reply #44 on: November 24, 2013, 08:33:13 AM »
Stefan, your version isn't good, although another cunning approach...

Here are results :
Code: [Select]
Command: (entnext (entprev (entlast)))
<Entity name: 7ffff5beb30>
Command: (entlast)
<Entity name: 7ffff5bec40>
Command: (entprev (entnext (entlast)))
; error: ActiveX Server returned the error: unknown name: Item
You are right Marko. I didn't test my lisp on 2dpolylines. My mistake.
About the last error, (entnext (entlast)) is always nil, so (entprev nil) ends with an error as it should be. But you are right again, I should catch this error and print a message instead.

No, Stefan (entnext (entlast)) if (entlast) is polyline entity is very next nested entity to parent (entlast)... In my case where (entlast) is polyline (entnext (entlast)) = VERTEX entity...
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube