sambar37 Posted May 13 Posted May 13 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 Quote
marko_ribar Posted May 13 Posted May 13 As far as I can see, you should change this line : (command "union" ss2 "") To this : (command "union" ss1 "") Quote
sambar37 Posted May 14 Author Posted May 14 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 "") Quote
Steven P Posted May 14 Posted May 14 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. Quote
mhupp Posted May 14 Posted May 14 entlast should pick up the last thing modified or created in the drawing. please upload a sample drawing 1 Quote
Steven P Posted May 14 Posted May 14 Isn't it just the last thing created? You're making me think now! 1 Quote
mhupp Posted May 14 Posted May 14 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. 2 Quote
marko_ribar Posted May 14 Posted May 14 (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 May 14 by marko_ribar 1 Quote
sambar37 Posted May 15 Author Posted May 15 (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 May 15 by sambar37 Quote
lastknownuser Posted May 15 Posted May 15 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 1 Quote
Steven P Posted May 15 Posted May 15 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 1 Quote
Steven P Posted May 15 Posted May 15 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 ) 2 Quote
sambar37 Posted May 16 Author Posted May 16 (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. and yes, the red areas highlighted in your image above are the sections that the regions overlap. Edited May 16 by sambar37 Quote
sambar37 Posted May 16 Author Posted May 16 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. 1 Quote
Steven P Posted May 16 Posted May 16 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. 1 1 Quote
marko_ribar Posted May 16 Posted May 16 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)... 2 Quote
mhupp Posted May 16 Posted May 16 (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 May 16 by mhupp 2 Quote
sambar37 Posted May 17 Author Posted May 17 (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 May 17 by sambar37 Quote
Recommended Posts
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.