Jump to content

Why would entlast not be getting the unioned entity in this code?


sambar37

Recommended Posts

when using this code on a file with a large set of regions in it entlast seems to be picking a random region. How do i fix this? i want to ent3name to be the entity name of the newly unioned object.

 

Quote
(defun c:ac1  ()
(setq ss1 nil)
(setq ss1 (ssadd))
(setq ent1name (car (entsel "\nSelect region 1: ")))
(setq obj1 (vlax-ename->vla-object ent1name))
(setq ent1area (rtos (vla-get-area obj1) 2 3))
(ssadd ent1name ss1)
(setq ent2name (car (entsel "\nSelect region 2: ")))
(setq obj2 (vlax-ename->vla-object ent2name))
(setq ent2area (rtos (vla-get-area obj2) 2 3))
(ssadd ent2name ss1)
(command "union" ss2 "")
(setq ent3name (entlast))
(setq obj3 (vlax-ename->vla-object ent3name))
(setq ent3area (rtos (vla-get-area obj3) 2 3))
);end defun

(defun c:testcalc  ()
(setq num1 (atof ent1area))
(setq num2 (atof ent2area))
(setq num3 (atof ent3area))
(- (+ num1 num2) num3)
);end defun

 

 

Link to comment
Share on other sites

As far as I can see, you should change this line :

(command "union" ss2 "")

To this :

(command "union" ss1 "")

Link to comment
Share on other sites

sorry, i have done that in my version. Its (entlast) not getting the newly unioned object that's creating the issue. 

 

13 hours ago, marko_ribar said:

As far as I can see, you should change this line :

(command "union" ss2 "")

To this :

(command "union" ss1 "")

 

Link to comment
Share on other sites

Might be wrong but entlast will find the last entity created, (I don't use regions). So if you create regions 1, 2, 3, and 4 in that order and then in the LIS P union together regions 1 and 2 entlast will still select region 4 because that was the last entity created. The modified region 2 was existing but not the last created.

Link to comment
Share on other sites

entlast should pick up the last thing modified or created in the drawing.

please upload a sample drawing

  • Like 1
Link to comment
Share on other sites

Isn't it just the last thing created? You're making me think now!

  • Like 1
Link to comment
Share on other sites

10 minutes ago, Steven P said:

Isn't it just the last thing created? You're making me think now!

 

its kinda a backwards way of thinking but when we modify an entity we are essentially "deleting" the old one and "creating" a new one.

 

Quote

The AutoLISP function entlast retrieves the most recently created entity, regardless of whether it's a new entity or a modified one. It essentially returns the last entity that was created or modified in the drawing database since the last time entlast was called. So, it doesn't specifically differentiate between created and modified entities; it simply returns the last one accessed.

 

  • Like 2
Link to comment
Share on other sites

Posted (edited)

See if this code can help you, OP...

 

(defun c:arcalc ( / ftoa ss es pt ent1name obj1 num1 ent2name obj2 num2 ent3name obj3 num3 )

  (or (not (vl-catch-all-error-p (vl-catch-all-apply (function vlax-get-acad-object) nil))) (vl-load-com))

  (defun ftoa ( n / m a s b )
    (if (numberp n)
      (progn
        (setq m (fix ((if (< n 0) - +) n 1e-8)))
        (setq a (abs (- n m)))
        (setq m (itoa m))
        (setq s "")
        (while (and (not (equal a 0.0 1e-6)) (setq b (fix (* a 10.0))))
          (setq s (strcat s (itoa b)))
          (setq a (- (* a 10.0) b))
        )
        (if (= (type n) 'int)
          m
          (if (= s "")
            m
            (if (and (= m "0") (< n 0))
              (strcat "-" m "." s)
              (strcat m "." s)
            )
          )
        )
      )
    )
  )

  (setq ss (ssadd))
  (setq es (entsel "\nSelect region 1: "))
  (setq ent1name (car es))
  (setq pt (cadr es))
  (setq obj1 (vlax-ename->vla-object ent1name))
  (setq num1 (vla-get-area obj1))
  (ssadd ent1name ss)
  (setq ent2name (car (entsel "\nSelect region 2: ")))
  (setq obj2 (vlax-ename->vla-object ent2name))
  (setq num2 (vla-get-area obj2))
  (ssadd ent2name ss)
  (if command-s
    (command-s "union" ss "")
    (vl-cmdf "union" ss "")
  )
  (if (and ss (= (sslength ss) 1))
    (setq ent3name (ssname ss 0))
    (setq ent3name (car (nentselp pt)))
  )
  (setq obj3 (vlax-ename->vla-object ent3name))
  (setq num3 (vla-get-area obj3))
  (setq *rtn* (- (+ num1 num2) num3))
  (prompt "\nResulting area (sum and subtraction) is stored in global variable *rtn*... You can call it with : !*rtn*")
  (prompt "\n")
  (princ (ftoa *rtn*))
  (princ)
)

 

Edited by marko_ribar
  • Like 1
Link to comment
Share on other sites

Posted (edited)

Sample drawing attached as requested and my final lisp to give you a bit of an idea what the end intent was for those playing along at home.

 

I ended up changing the layers to find the entity as a workaround because I couldn't get entlast to work properly. 

 

The sample file is a bunch of stage boundaries for a subdivision, their usually polygons not regions but I turned them to regions for this lisp as its just an error finding lisp and this way seemed like the best way to find the overlaps. 

 

22 hours ago, Steven P said:

Might be wrong but entlast will find the last entity created, (I don't use regions). So if you create regions 1, 2, 3, and 4 in that order and then in the LIS P union together regions 1 and 2 entlast will still select region 4 because that was the last entity created. The modified region 2 was existing but not the last created.

 

Entlast was actually picking up a random region for some reason. 

Sample Drawing.dwg Ac1 Automatic Version.lsp

Edited by sambar37
Link to comment
Share on other sites

It works for me, even the code from first post, with changed ss2 to ss1 of course. I didn't quite understand what error are you getting and where?
Is this what you want as result? Image attached, red are the difference areas.
Also I edited main defun a bit, its better to use real number for area comparison, you can adjust the tolerance
 

(defun c:ac1  ()
(setq ss1 nil)
(setq ss1 (ssadd))
(setq sstemp nil)
(setq layer-name "Temp")



(setq ssmain (ssget "_X" '((0 . "REGION"))))
(setq ssmainlength (sslength ssmain))
(setq counter 1)

(while (< counter ssmainlength)

(if (= sstemp nil)
(setq ent1name (ssname ssmain 0))
(setq ent1name (ssname sstemp 0))
);endif
(setq obj1 (vlax-ename->vla-object ent1name))
(setq ent1area (vla-get-area obj1))
(ssadd ent1name ss1)
(setq ent-data (entget ent1name))
(setq new-ent-data (subst (cons 8 layer-name) (assoc 8 ent-data) ent-data))
(entmod new-ent-data)

(setq ent2name (ssname ssmain counter))
(setq obj2 (vlax-ename->vla-object ent2name))
(setq ent2area (vla-get-area obj2))
(ssadd ent2name ss1)
(setq ent-data (entget ent2name))
(setq new-ent-data (subst (cons 8 layer-name) (assoc 8 ent-data) ent-data))
(entmod new-ent-data)

(command "_.union" ss1 "")

(setq ss2 (ssget "_X" '((0 . "REGION") (8 . "Temp"))))
(setq ent3name (ssname ss2 0))
(setq obj3 (vlax-ename->vla-object ent3name))
(setq ent3area (vla-get-area obj3))


(setq difference (- (+ ent1area ent2area) ent3area))

(if (not (equal difference 0 0.0001)); tolerance
(progn
(command "_.UNDO" 1)
(CopyToNewLayer)
(Subtractfunction)
(setq ss1 (ssget "_X" '((0 . "REGION") (8 . "Temp"))))
(command "_.union" ss1 "")
(alert (strcat "A difference of " (rtos difference 2 4) " has been found"))
);end progn
):endif

(setq sstemp (ssadd))
(setq sstemp (ssget "_X" '((0 . "REGION") (8 . "Temp"))))

(setq counter (+ counter 1))

);end while

);end defun

 

test1.png

  • Like 1
Link to comment
Share on other sites

Try this one as well, taking out the 'entlast' parts.

I've added comments what I changed on your original 

 

 

(defun c:ac1 ( / ss1 entname1 obj1 ent1area ss2 ent2name obj2 ent2area ent3name obj3 ent3area)
;;  (setq ss1 nil)              ;;Union can work on entities, not necessary to make selection set
;;  (setq ss1 (ssadd))          ;;As above
  (setq ent1name (car (entsel "\nSelect region 1: ")))
  (setq obj1 (vlax-ename->vla-object ent1name))
  (setq ent1area (rtos (vla-get-area obj1) 2 3))
;;  (ssadd ent1name ss1)       ;;As above
  (setq ent2name (car (entsel "\nSelect region 2: ")))
  (setq obj2 (vlax-ename->vla-object ent2name))
  (setq ent2area (rtos (vla-get-area obj2) 2 3))
;;  (ssadd ent2name ss1)       ;;As above
;;  (command "union" ss2 "")   ;;Union works on Entities
;;  (setq ent3name (entlast))  ;;Union modifies ent1 so use that
;;  (setq obj3 (vlax-ename->vla-object ent3name))
;;  (setq ent3area (rtos (vla-get-area obj3) 2 3))

(command "union" ent1name ent2name "") ; modified 'union' line
(setq ent3area (rtos (vla-get-area obj1) 2 3)) ; Use 'Ent1', and 'Obj1'

);end defun

 

  • Like 1
Link to comment
Share on other sites

Above code tidied up and a slight change

 

(defun c:ac1 ( / entname1 ent2name obj1 ent3name )
  (setq ent1name (car (entsel "\nSelect region 1: ")))  ;;Select region 1. Maybe use ss get with single selection & region filters
  (setq ent2name (car (entsel "\nSelect region 2: ")))  ;;Select region 2. Maybe use ss get with single selection & region filters

  (setq ent3name (entmakex (entget ent1name)))          ;;Copy region 1
  (setq ent4name (entmakex (entget ent2name)))          ;;copy region 2
  (command "union" ent3name ent4name "")                ;;Union Regions

  (setq obj3 (vlax-ename->vla-object ent3name))         ;;VLA- object name for region 1 copy
  (setq ent3area (rtos (vla-get-area obj3) 2 3))        ;;Area of 2 regions

  (redraw ent3name 3)                                   ;;Highlight selected areas

  (getstring (strcat "\nArea: " ent3area ". Press Enter") )
  (redraw ent3name 4)                                   ;;Remove highlights
  (entdel ent3name)                                     ;;Delete unioned area
  (princ)                                               ;;Exit quietly
)

 

  • Like 2
Link to comment
Share on other sites

Posted (edited)
17 hours ago, lastknownuser said:

It works for me, even the code from first post, with changed ss2 to ss1 of course. I didn't quite understand what error are you getting and where?
Is this what you want as result? Image attached, red are the difference areas.
Also I edited main defun a bit, its better to use real number for area comparison, you can adjust the tolerance
 

 

Yeah the .lsp i attached is working, i removed entlast from that lisp to get it to work though.

 

For me with the original code i attached, if i select the two polys in the red area below, after this (command "union" ss1 ""), (setq ent3name (entlast)) will get the region in green not the newly unioned region in red, even though the green poly has not been touched at all.  

 

image.png.e540c7248e8c59d266a0fbd226dc1478.png

 

and yes, the red areas highlighted in your image above are the sections that the regions overlap. 

Edited by sambar37
Link to comment
Share on other sites

15 hours ago, Steven P said:

Try this one as well, taking out the 'entlast' parts.

I've added comments what I changed on your original 

 

 

15 hours ago, Steven P said:

Above code tidied up and a slight change

 

(defun c:ac1 ( / entname1 ent2name obj1 ent3name )
  (setq ent1name (car (entsel "\nSelect region 1: ")))  ;;Select region 1. Maybe use ss get with single selection & region filters
  (setq ent2name (car (entsel "\nSelect region 2: ")))  ;;Select region 2. Maybe use ss get with single selection & region filters

  (setq ent3name (entmakex (entget ent1name)))          ;;Copy region 1
  (setq ent4name (entmakex (entget ent2name)))          ;;copy region 2
  (command "union" ent3name ent4name "")                ;;Union Regions

  (setq obj3 (vlax-ename->vla-object ent3name))         ;;VLA- object name for region 1 copy
  (setq ent3area (rtos (vla-get-area obj3) 2 3))        ;;Area of 2 regions

  (redraw ent3name 3)                                   ;;Highlight selected areas

  (getstring (strcat "\nArea: " ent3area ". Press Enter") )
  (redraw ent3name 4)                                   ;;Remove highlights
  (entdel ent3name)                                     ;;Delete unioned area
  (princ)                                               ;;Exit quietly
)

 

 

 

 

OHHHH, so when i (command "union" ent3name ent4name ""), the first entity name listed after "union"  (in this case ent3name) remains the entity name for the newly unioned region?

If that's correct this is exactly what i was getting messed up on. Thankyou so much. 

  • Like 1
Link to comment
Share on other sites

Yes, that's right.

 

I try to avoid entlast if I can unless it is in the line straight after I have created an entity.

 

 

  • Like 1
  • Agree 1
Link to comment
Share on other sites

Posted (edited)

only real time is use entlast is in instances like @Steven P said or when i have to build a selection set after modifying/creating a bunch of stuff inside a lisp and don't want to prompt the user to select them again.

 

 

(setq SS (ssadd)) ;how to create a blank selection set

(setq LastEnt (entlast))                ;set right before you create objects. you want to either add to a selection set or track while in a lisp

(while (setq LastEnt (entnext LastEnt)) ;after entities are created this will add them to a selection set.
  (ssadd EntLst SS)  ;a blank selection set or existing selection set is needed.
)


 

Edited by mhupp
  • Like 2
Link to comment
Share on other sites

Posted (edited)
13 hours ago, marko_ribar said:

OP, have you tested the code I provided here : https://www.cadtutor.net/forum/topic/85374-why-would-entlast-not-be-getting-the-unioned-entity-in-this-code/?do=findComment&comment=640320

It seems that you avoid my inputs... It should do what should, as I also avoided (entlast)...

 

sorry i did see this. my end goal was to actually highlight the overlapping areas so the user can go in and fix them up. When I looked at this It looks like it just stores the overlapping area as a value and didn't help me identify its location, so Stephens was just more useful for this specific goal. Thank you so much though, that would have been much better for me if i was just looking for the overlap value itself. 

 

When i wrote this post too i already basically had a work around in terms of code, i was just trying to figure out why entlast wasn't working for my own knowledge more then anything.  This was why i was asking for the below, so i could work backwards and figure out why entlast didn't work. 

 

On 5/13/2024 at 5:44 PM, sambar37 said:

 i want to ent3name to be the entity name of the newly unioned object.

 

Thankyou so much everyone for the help :)

Edited by sambar37
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...