stlo Posted February 10, 2022 Posted February 10, 2022 Hi everyone! I wonder if this is possible? I have a dwg file that I would like to simplify. I have already created 2 macros that are freezing all the unwanted layers (one is for the french layers and the other one is for the english layers). Take note that in the test drawing, the macro has already been perform. After that, I would like to explode all the elements and delete all the new text created by the explode command. Finally, since there will be overlapping lines, I would like to keep only the longer one. For visual information, please have a look a the Test dwg with all the explaination in it and also I'm sending the 2 macros that I've recorded. Probably they can be added to the potentiel routine. Both would have to be played because some drawings are in french and some other are in english! Would this kind of routine be possible? Thank you very much! Have a good day! Gelerlayeranglais.actm Gelerlayerfrancais.actm Test.dwg Quote
stlo Posted February 10, 2022 Author Posted February 10, 2022 Hi again! I forgot to mention that every lines would have to stay on its original layer! Sorry! Thanks Quote
BIGAL Posted February 11, 2022 Posted February 11, 2022 (edited) Have you tried OVERKILL after exploding ? You can type this on command line or do in lisp. ERASE (ssget '((0 . "TEXT"))) Edited February 11, 2022 by BIGAL Quote
marko_ribar Posted February 11, 2022 Posted February 11, 2022 (edited) I tried to be as much as comprehensive as possible... It is very important that you understand the code... First part with layer manipulation, I left to you to implement if you want... It is not neccessity, as that procedure is totally independent of routines main purpose, so it could be omitted with justification... ;;; https://www.cadtutor.net/forum/topic/74477-looking-for-a-lisp-to-simplify-a-20-20-converted-dwg/ ;;; By M.R. 11.02.2022. (defun c:doit ( / _xrefs _unit _getlength _overkill _ssget _copyss fuzz ss xr ex sp ) (vl-load-com) ;;; load ActivX extensions (VLA functions) (defun _xrefs ( / b x n l ) (setq b (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object)))) (while (setq x (tblnext "BLOCK" (not x))) (if (= (vla-get-isxref (vla-item b (setq n (cdr (assoc 2 x))))) :vlax-true) (setq l (cons n l)) ) ) l ) (defun _unit ( v / d ) (if (and v (not (equal (setq d (distance '(0.0 0.0 0.0) v)) 0.0 1e-8))) (mapcar (function (lambda ( x ) (/ x d))) v) ) ) (defun _getlength ( e ) (- (vlax-curve-getdistatparam e (vlax-curve-getendparam e)) (vlax-curve-getdistatparam e (vlax-curve-getstartparam e))) ) (defun _overkill ( e l fuzz / p q u1 u2 d dd ) ;;; e - reference entity ; l - list of entity names with which reference entity is to be checked ; fuzz - small tolerance distance between point that belong reference entity and the same point (or very close one - vlax-curve-getclosestpointto) belonging checking entity or between distance of unit vector of first derivative at some point from reference entity and unit vector of first derivative at the same point from checking entity (foreach x (vl-remove e l) (if (and x (not (vlax-erased-p x)) e (not (vlax-erased-p e)) (< (distance (setq p (vlax-curve-getstartpoint e)) (setq q (vlax-curve-getclosestpointto x p))) fuzz) (if (and (setq u1 (_unit (vlax-curve-getfirstderiv e (vlax-curve-getparamatpoint e p)))) (setq u2 (_unit (vlax-curve-getfirstderiv x (vlax-curve-getparamatpoint x q))))) (or (< (setq d (distance u1 u2)) fuzz) (< (abs (- d 2.0)) fuzz)) ;;; (abs (- d 2.0)) if unit vectors align, but are opposite oriented, meaning (lenght of 1st vector = 1.0 + length of 2nd vector = 1.0 == 2.0), so (abs (- d 2.0)) should be near 0.0 and always positive (thats why (abs))... t ;;; if any of firstderiv vectors couldn't be founded - nil, assume that that check is not important for overkill process, so "t" is processed in (and) condition of main (if)... ) (< (distance (setq p (vlax-curve-getpointatdist e (/ (setq dd (_getlength e)) 2))) (setq q (vlax-curve-getclosestpointto x p))) fuzz) (if (and (setq u1 (_unit (vlax-curve-getfirstderiv e (vlax-curve-getparamatpoint e p)))) (setq u2 (_unit (vlax-curve-getfirstderiv x (vlax-curve-getparamatpoint x q))))) (or (< (setq d (distance u1 u2)) fuzz) (< (abs (- d 2.0)) fuzz)) ;;; (abs (- d 2.0)) if unit vectors align, but are opposite oriented, meaning (lenght of 1st vector = 1.0 + length of 2nd vector = 1.0 == 2.0), so (abs (- d 2.0)) should be near 0.0 and always positive (thats why (abs))... t ;;; if any of firstderiv vectors couldn't be founded - nil, assume that that check is not important for overkill process, so "t" is processed in (and) condition of main (if)... ) (< (distance (setq p (vlax-curve-getendpoint e)) (setq q (vlax-curve-getclosestpointto x p))) fuzz) (if (and (setq u1 (_unit (vlax-curve-getfirstderiv e (vlax-curve-getparamatpoint e p)))) (setq u2 (_unit (vlax-curve-getfirstderiv x (vlax-curve-getparamatpoint x q))))) (or (< (setq d (distance u1 u2)) fuzz) (< (abs (- d 2.0)) fuzz)) ;;; (abs (- d 2.0)) if unit vectors align, but are opposite oriented, meaning (lenght of 1st vector = 1.0 + length of 2nd vector = 1.0 == 2.0), so (abs (- d 2.0)) should be near 0.0 and always positive (thats why (abs))... t ;;; if any of firstderiv vectors couldn't be founded - nil, assume that that check is not important for overkill process, so "t" is processed in (and) condition of main (if)... ) (< dd (_getlength x)) ;;; length of reference entity is smaller than checking entity... ) (entdel e) ) ) ) (defun _ssget ( ss filter fuzz / _match ) ;;; ss - selection set to which filter is to be applied ; filter - list similar to filter of ordinary (ssget) function ; fuzz - small tolerance number for matching entity data with filter specification data (defun _match ( filter edata fuzz ) (vl-every (function (lambda ( x ) (vl-some (function (lambda ( y ) (cond ( (and (car x) (car y) (cdr x) (cdr y) (= (type (cdr x)) 'int) (= (type (cdr y)) 'int)) (and (= (car x) (car y)) (= (cdr y) (cdr x))) ) ( (and (car x) (car y) (cdr x) (cdr y) (= (type (cdr x)) 'real) (= (type (cdr y)) 'real)) (and (= (car x) (car y)) (equal (cdr y) (cdr x) fuzz)) ) ( (and (car x) (car y) (cdr x) (cdr y) (= (type (cdr x)) 'str) (= (type (cdr y)) 'str)) (and (= (car x) (car y)) (wcmatch (cdr y) (cdr x))) ) ( (and (car x) (car y) (cdr x) (cdr y) (= (type (cdr x)) 'list) (= (type (cdr y)) 'list)) (and (= (car x) (car y)) (_match (cdr x) (cdr y) fuzz)) ) ( t (if (not (vl-catch-all-error-p (vl-catch-all-apply (function cadr) (list x y)))) (cond ( (and (car x) (car y) (cadr x) (cadr y) (= (type (cadr x)) 'int) (= (type (cadr y)) 'int)) (and (= (car x) (car y)) (= (cadr y) (cadr x))) ) ( (and (car x) (car y) (cadr x) (cadr y) (= (type (cadr x)) 'real) (= (type (cadr y)) 'real)) (and (= (car x) (car y)) (equal (cadr y) (cadr x) fuzz)) ) ( (and (car x) (car y) (cadr x) (cadr y) (= (type (cadr x)) 'str) (= (type (cadr y)) 'str)) (and (= (car x) (car y)) (wcmatch (cadr y) (cadr x))) ) ( (and (car x) (car y) (cadr x) (cadr y) (= (type (cadr x)) 'list) (= (type (cadr y)) 'list)) (and (= (car x) (car y)) (_match (cadr x) (cadr y) fuzz)) ) ) ) ) ) ) ) edata ) ) ) filter ) ) (foreach e (vl-remove-if (function listp) (mapcar (function cadr) (ssnamex ss))) (if (not (_match filter (entget e (list "*")) fuzz)) (ssdel e ss) ) ) ss ) (defun _copyss ( ss / sn ) (setq sn (ssadd)) (foreach e (vl-remove-if (function listp) (mapcar (function cadr) (ssnamex ss))) (ssadd e sn) ) sn ) (initget 6) (setq fuzz (getdist "\nSpecify fuzz factor for processing <1e-4> : ")) (if (not fuzz) (setq fuzz 1e-4) ) (prompt "\nENTER FOR ALL, OR SELECT ORDINARY...") (if (not (setq ss (ssget "_I"))) (if (not (setq ss (ssget "_:L"))) (setq ss (ssget "_A" (list (cons 0 "~VIEWPORT") (cons 60 0) (cons 410 (if (= 1 (getvar 'cvport)) (getvar 'ctab) "Model"))))) ;;; if pressed ENTER at beginning - selecting all visible (if in isolation mode - you previously used command ISOLATEOBJECTS, so thats why (60 . 0)), excluding all VIEWPORT entities and assuming all that is possible to be selected within current active layout tab (getvar 'ctab)... ) ) (if (setq xr (_xrefs)) ;;; if some xrefs are present in DWG... (foreach e (vl-remove-if (function listp) (mapcar (function cadr) (ssnamex ss))) ;;; iterating main selection set... (if (and (= (cdr (assoc 0 (setq ex (entget e)))) "INSERT") (vl-position (cdr (assoc 2 ex)) xr)) ;;; if some of entity from main selection set belongs to xrefs... (ssdel e ss) ;;; don't account for that INSERT xref entity and remove it from main selestion set... ) ) ) (vl-cmdf "_.EXPLODE" ss) ;;; exploding pre selection, or selection, or if just pressed ENTER all visible... (setq sp (ssget "_P")) ;;; getting selection set with entities gained after exploding... (mapcar (function entdel) (vl-remove-if (function listp) (mapcar (function cadr) (ssnamex (_ssget (_copyss sp) (list (cons 0 "*TEXT")) fuzz))))) ;;; removing all "*TEXT" entities that were generated through process of exploding... ;;; at this point, according to your provided DWG, you also have turned visible attribute definitions that were invisible before blocks were exploded... ;;; so consider using this line, if you want to remove them too, like dummy "*TEXT" entities... (mapcar (function entdel) (vl-remove-if (function listp) (mapcar (function cadr) (ssnamex (_ssget (_copyss sp) (list (cons 0 "ATTDEF")) fuzz))))) ;;; removing all "ATTDEF" entities that were generated through process of exploding... (foreach e (vl-remove-if (function listp) (mapcar (function cadr) (ssnamex (_copyss sp)))) ;;; iterating through selection set obtained after exploding... (if (and (not (vl-catch-all-error-p (vl-catch-all-apply (function vlax-curve-getstartpoint) (list e)))) (not (vl-position (cdr (assoc 0 (entget e))) '("XLINE" "RAY")))) ;;; if entity belongs to curve entity types and also not XLINE or RAY (XLINES and RAYS are not acceptable for processing custom overkill)... (setq el (cons e el)) ;;; constructing list of entity names of only curve entity types... ) ) (foreach e el (_overkill e el fuzz) ) ;;; performing custom overkill (princ) ) Regards, M.R. HTH. Edited February 11, 2022 by marko_ribar Quote
stlo Posted February 11, 2022 Author Posted February 11, 2022 Thanks everyone! BigAL: The overkill command is very good! I knew this one but the problem is that I wasn't using it properly! When I check all the boxes in the upper section of the overkill menu, it does what I was hoping for! I have used Selectsimilar to erase all the text boxes following the explode command! Marko: When I try your routine, it seems that a lot of blocks are not able to be exploded! Maybe I'm doing something wrong? I'm not familiar with the fuzz factor so I've tried some different numbers but the result is the same. Here is a screen capture of my command line! Thanks again have a good day! Quote
marko_ribar Posted February 11, 2022 Posted February 11, 2022 FYI., When specifying fuzz factor, be sure you know what are you doing... Ordinary fuzz values go from 0.1 to 0.00000001... (all are decimal digits and represent small values; for easier writing of numbers that are far too small - like 0.00000001, you can simply write 1e-8...). That sign : - between 1e and 8 is very important... If you wrie it like 1e+8, it means you wanted this : 100000000... You used number 4, meaning 4.0 DWG units, meaning that your drawn entities are in very big scale and that is fairly unusual... IMHO, my defaults I provided in the code should work well in every usual situation, even you are working in some specific measurements, DWG units are DWG units... So 1e-4 : 0.0001 was well proposed... If you don't like it, change it, right at beginning of the code... All should work well, you simply have to tap ENTER 2 times when executing... As for exploding process : I don't know your all blocks have explodable parameter set to be enabled, or if you are facing some entities not usual and standard (some 3rd party software you are importing...)... Any way, make sure your LAYERS where entites reside are unlocked - I assume you have been checking this with your first setting and those recording macros... If you want, you can go selecting manually to avoid locked LAYERS scenario : you only have to select it with mouse, and not like I prompted : pressing ENTER when asked for selection... I predicted that you want to do things standardly : (setq ss (ssget "_:L")) was the line that manages just this and it's already coded... Quote
stlo Posted February 15, 2022 Author Posted February 15, 2022 Hi Marko! Thanks for the explaination! I understand the fuzz factor part! For the exploding process, all layers are unlocked. I just pasted two rectangles as blocks to make further tests and it seems that even if I select all, it will only explode one of the two blocks! As for If it is explodable or not, I went to my test drawing that I've sent and if I use the explode command, it would explode all 31 blocks in the drawing making 144 lines but when I use your command it explodes 1 block leaving 30 blocks intact and creating 12 lines. Is there something I'm doing wrong? Thanks! Quote
marko_ribar Posted February 15, 2022 Posted February 15, 2022 (edited) I see... I've neglected the fact that EXPLODE inside LISP don't work with selection sets... To ovecome this issue, there are 2 ways : 1. insert this line before (vl-cmdf "_.EXPLODE" ss) : (initcommandversion) 2. experiment with undocumented system varibale : QAFLAGS... Place inside error handler : (if qaf (setvar 'qaflags qaf) ) At beggining of main part of routine, get value of QAFLAGS : (setq qaf (getvar 'qaflags)) Then place this before (vl-cmdf "_.EXPLODE" ss) : (setvar 'qaflags 1) *** It's strongly recommended that you place after (vl-cmdf "_.EXPLODE" ss) : (setvar 'qaflags qaf) *** Messing with QAFLAGS may lead to some unusual behaving of AutoCAD, so if you can, alwasy avoid it... [ Don't forget to localize "qaf" variable in main (c:doit) definition : (defun c:doit ( / *error* ... qaf ... ) ... rest of routine ... (*error* nil)) ] So, my recomendation is - use first fix... HTH. Edited February 15, 2022 by marko_ribar 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.