ojacomarket Posted April 16, 2020 Posted April 16, 2020 (edited) Dear friends, The issue is: I want to get selection set with ssget (specified by cons) Then I want function FOREACH to check every entity from the list is there any entities that MATCH "*lp*" with command WCMATCH and if there are so draw a object on drawing (which is specified with entmake). This one runs perfectly, BUT how to MATCH not only for "*lp*" but for (list "*lp*" "*kk*" "bet*"), so that EVERY entity from entget_data_from_selection_1 was checked by EVERY entity of another list of wcmatch. I tried for mapcar, but mapcar require same sized list.. (defun c:qwerty () (setq list_of_selections_1 (ssget "x" (list (cons 0 "TEXT") (cons 8 "Mootkood") (cons 7 "Standard")))) (setq l_o_s_1_length (sslength list_of_selections_1)) (setq number_1 (- 0 1)) (setq new_lili (list)) (repeat l_o_s_1_length (setq number_1 (1+ number_1)) (setq entget_data_from_selection_1 (entget (ssname list_of_selections_1 number_1))) (foreach x entget_data_from_selection_1 (setq p1 (car x)) (setq p2 (cdr x)) (if (and (= p1 1) (wcmatch p2 "*lp*")) (entmake (list (cons 0 "INSERT") (cons 8 "PUU") (cons 10 (cdr (assoc 11 entget_data_from_selection_1))))))) u have ideas? Edited April 16, 2020 by ojacomarket Quote
Jonathan Handojo Posted April 16, 2020 Posted April 16, 2020 Replace the last line of your code (your foreach loop) with: (if (wcmatch (cdr (assoc 1 entget_data_from_selection_1)) "*lp*") (entmake (list '(0 . "INSERT") '(2 . <block_name_in_string>) '(8 . "PUU") (cons 10 (cdr (assoc 11 entget_data_from_selection_1))) '(41 . 1.0) '(42 . 1.0) '(43 . 1.0) '(50 . 0.0))) ) When drawing a block, you need to define the block name (2), scale (X,Y,Z : 41,42,43), and rotation (50) of the block... just like how you need the text height and text content for text. If you don't give it a block name, how can AutoCAD possibly insert the block? 1 Quote
ojacomarket Posted April 16, 2020 Author Posted April 16, 2020 1 minute ago, Jonathan Handojo said: Replace the last line of your code (your foreach loop) with: (if (wcmatch (cdr (assoc 1 entget_data_from_selection_1)) "*lp*") (entmake (list '(0 . "INSERT") '(2 . <block_name_in_string>) '(8 . "PUU") (cons 10 (cdr (assoc 11 entget_data_from_selection_1))) '(41 . 1.0) '(42 . 1.0) '(43 . 1.0) '(50 . 0.0))) ) When drawing a block, you need to define the block name (2), scale (X,Y,Z : 41,42,43), and rotation (50) of the block... just like how you need the text height and text content for text. If you don't give it a block name, how can AutoCAD possibly insert the block? Thank you Jonathan, as always your code works amazing, and actually I fixed that stuff, and edited this topic, for now I have issue to try match every entity from entget with another list (list "*lp*" "bet*" "*kk*") Quote
Jonathan Handojo Posted April 16, 2020 Posted April 16, 2020 (edited) (wcmatch (cdr (assoc 1 entget_data_from_selection_1)) "*lp*,*kk*,bet*") Edited April 16, 2020 by Jonathan Handojo 1 Quote
ojacomarket Posted April 16, 2020 Author Posted April 16, 2020 1 minute ago, Jonathan Handojo said: (wcmatch (cdr (assoc 1 entget_data_from_selection_1)) "*lp*,*kk*,bet*) Sorry, forgot to say, I need it to match every entity from entget to wcmatch and if it is "*lp*" it draws one object if "*kk*" another object and so on.. I have very long code for that, is that possible to deal with foreach in that case? Quote
Jonathan Handojo Posted April 16, 2020 Posted April 16, 2020 (edited) 49 minutes ago, ojacomarket said: Sorry, forgot to say, I need it to match every entity from entget to wcmatch and if it is "*lp*" it draws one object if "*kk*" another object and so on.. I have very long code for that, is that possible to deal with foreach in that case? Foreach is not the solution to everything. There are other ways to do it. For example: Include this in the start of the code: (setq pairs '( ("lp" . block_name1) ("bet" . block_name2) ("kk" . block_name3) ) ) And rather than replacing the original foreach in the forum with my previous code, replace the foreach with this instead: (vl-some '(lambda (x) (if (wcmatch (cdr (assoc 1 entget_data_from_selection_1)) (strcat "*" (car x) "*")) (entmake (list '(0 . "INSERT") (cons 2 (cdr x)) '(8 . "PUU") (cons 10 (cdr (assoc 11 entget_data_from_selection_1))) '(41 . 1.0) '(42 . 1.0) '(43 . 1.0) '(50 . 0.0))) ) ) pairs ) vl-some processes every element in the list with a function accepting one argument representing each element in the list (like x in foreach) (in the above case, it's "lambda"), and returns what the function will return resulting from the first element in the list that evaluates to anything other than nil to the function. Once that happens, vl-some will stop processing the remainder of the list. Edited April 16, 2020 by Jonathan Handojo 1 Quote
ojacomarket Posted April 16, 2020 Author Posted April 16, 2020 26 minutes ago, Jonathan Handojo said: Foreach is not the solution to everything. There are other ways to do it. For example: Include this in the start of the code: (setq pairs '( ("lp" . block_name1) ("bet" . block_name2) ("kk" . block_name3) ) ) And rather than replacing the original foreach in the forum with my previous code, replace the foreach with this instead: (vl-some '(lambda (x) (if (wcmatch (cdr (assoc 1 entget_data_from_selection_1)) (strcat "*" (car x) "*")) (entmake (list '(0 . "INSERT") (cons 2 (cdr x)) '(8 . "PUU") (cons 10 (cdr (assoc 11 entget_data_from_selection_1))) '(41 . 1.0) '(42 . 1.0) '(43 . 1.0) '(50 . 0.0))) ) ) pairs ) vl-some processes every element in the list with a function accepting one argument representing each element in the list (like x in foreach) (in the above case, it's "lambda"), and returns the expression resulting from the first element in the list that evaluates to anything other than nil. Very clear explanation! Thank you for your amazing job! Look, I got here also code made before but as again it doesn't show error but still doesn't ENTMAKE me, what I asked that code to do.. (defun c:qwerty () (setq list_of_selections_1 (ssget "x" (list (cons 0 "TEXT") (cons 8 "Mootkood") (cons 7 "Standard")))) (setq l_o_s_1_length (sslength list_of_selections_1)) (setq number_1 (- 0 1)) (setq list_wcm '(("*vp*" "INSERT" "VILJA1" "PUU") ("*lp*" "INSERT" "LEHTP1" "PUU") ("*mand*" "INSERT" "MAND1" "PUU") )) (repeat l_o_s_1_length (setq number_1 (1+ number_1)) (setq entget_data_from_selection_1 (entget (ssname list_of_selections_1 number_1))) (foreach xx list_wcm (setq pp1 (car xx)) (if (wcmatch pp1 (cdr (assoc 1 entget_data_from_selection_1))) (entmake (list (cons 0 (nth 1 xx)) (cons 2 (nth 2 xx)) (cons 8 (nth 3 xx)) (cons 10 (cdr (assoc 11 (entget_data_from_selection_1)))) (cons 41 0.5) (cons 42 0.5) (cons 43 0.5) (cons 50 0.00))))) )) Quote
Jonathan Handojo Posted April 16, 2020 Posted April 16, 2020 16 minutes ago, ojacomarket said: Very clear explanation! Thank you for your amazing job! Look, I got here also code made before but as again it doesn't show error but still doesn't ENTMAKE me, what I asked that code to do.. (defun c:qwerty () (setq list_of_selections_1 (ssget "x" (list (cons 0 "TEXT") (cons 8 "Mootkood") (cons 7 "Standard")))) (setq l_o_s_1_length (sslength list_of_selections_1)) (setq number_1 (- 0 1)) (setq list_wcm '(("*vp*" "INSERT" "VILJA1" "PUU") ("*lp*" "INSERT" "LEHTP1" "PUU") ("*mand*" "INSERT" "MAND1" "PUU") )) (repeat l_o_s_1_length (setq number_1 (1+ number_1)) (setq entget_data_from_selection_1 (entget (ssname list_of_selections_1 number_1))) (foreach xx list_wcm (setq pp1 (car xx)) (if (wcmatch pp1 (cdr (assoc 1 entget_data_from_selection_1))) (entmake (list (cons 0 (nth 1 xx)) (cons 2 (nth 2 xx)) (cons 8 (nth 3 xx)) (cons 10 (cdr (assoc 11 (entget_data_from_selection_1)))) (cons 41 0.5) (cons 42 0.5) (cons 43 0.5) (cons 50 0.00))))) )) Turn your wcmatch around 1 Quote
ojacomarket Posted April 16, 2020 Author Posted April 16, 2020 (edited) 3 minutes ago, Jonathan Handojo said: Turn your wcmatch around If you meant to change places of "pp1" "cdr (assoc...." so CAD gives syntax error...:( Edited April 16, 2020 by ojacomarket Quote
Jonathan Handojo Posted April 16, 2020 Posted April 16, 2020 (edited) 4 minutes ago, ojacomarket said: If you meant to change places of "pp1" "cdr (assoc...." so CAD gives syntax error...:( like this... (wcmatch (cdr (assoc 1 entget_data_from_selection_1)) pp1) Well, all the steps I posted here are not tested, mainly seen from pure eye, but it should work (from my eyes at least) Edited April 16, 2020 by Jonathan Handojo 1 Quote
ojacomarket Posted April 16, 2020 Author Posted April 16, 2020 2 minutes ago, Jonathan Handojo said: like this... (wcmatch (cdr (assoc 1 entget_data_from_selection_1)) pp1) Yeah, this string of code retrieves > syntax error Cannot invoke (command) from *error* without prior call to (*push-error-using-command*). Converting (command) calls to (command-s) is recommended. Quote
ojacomarket Posted April 16, 2020 Author Posted April 16, 2020 13 minutes ago, ojacomarket said: Yeah, this string of code retrieves > syntax error Cannot invoke (command) from *error* without prior call to (*push-error-using-command*). Converting (command) calls to (command-s) is recommended. I thought maybe there was problem with list of strings, but i changed it to form like that: But nothing changed, codes loads without errors but no object (which are specified with entmake) are drawn... (setq list_wcm (list (list "*vp*" "INSERT" "VILJA1" "PUU") (list "*lp*" "INSERT" "LEHTP1" "PUU") (list "*mand*" "INSERT" "MAND1" "PUU") Quote
Jonathan Handojo Posted April 16, 2020 Posted April 16, 2020 (edited) Let that be a lesson for you then... That's why it's best to include error-handling functions in the beginning of the code: (defun *error* (msg) (princ (strcat "\nError: " msg))) When a function fails from an error, the *error* function is executed. You can of course define your own *error* function to execute what to do if the function fails. Next lesson, set all your variables local to the function. That way it won't mess up other functions containing the same variables. You know how, right? (defun c:functionname ( / *error* list_wcm l_o_s_1_length ...) ; <--- Set local to the function (defun *error* (msg) (princ (strcat "\nError: " msg))) ;; Rest of code ) It's crucial that you set the *error* local to the function, because if you don't, then other functions that doesn't have the *error* function will call that very same function on fail. As an added function, run the (*push-error-using-command*) command and proceed. Not that I know much about error-handling, so I'm in no position to be teaching you. Edited April 16, 2020 by Jonathan Handojo 1 Quote
ojacomarket Posted April 16, 2020 Author Posted April 16, 2020 55 minutes ago, Jonathan Handojo said: Let that be a lesson for you then... That's why it's best to include error-handling functions in the beginning of the code: (defun *error* (msg) (princ (strcat "\nError: " msg))) When a function fails from an error, the *error* function is executed. You can of course define your own *error* function to execute what to do if the function fails. Next lesson, set all your variables local to the function. That way it won't mess up other functions containing the same variables. You know how, right? (defun c:functionname ( / *error* list_wcm l_o_s_1_length ...) ; <--- Set local to the function (defun *error* (msg) (princ (strcat "\nError: " msg))) ;; Rest of code ) It's crucial that you set the *error* local to the function, because if you don't, then other functions that doesn't have the *error* function will call that very same function on fail. As an added function, run the (*push-error-using-command*) command and proceed. Not that I know much about error-handling, so I'm in no position to be teaching you. Thank you for this lesson, it is so nice, that you could explain those thing so perfectly, so even me understood, but it still doesn't execute, it writes "syntax error", but when i exclude those ...defun *error* stuff.. it writes as before " syntax error Cannot invoke (command) from *error* without prior call to (*push-error-using-command*). Converting (command) calls to (command-s) is recommended. Quote
ojacomarket Posted April 16, 2020 Author Posted April 16, 2020 1 hour ago, Jonathan Handojo said: Let that be a lesson for you then... That's why it's best to include error-handling functions in the beginning of the code: (defun *error* (msg) (princ (strcat "\nError: " msg))) When a function fails from an error, the *error* function is executed. You can of course define your own *error* function to execute what to do if the function fails. Next lesson, set all your variables local to the function. That way it won't mess up other functions containing the same variables. You know how, right? (defun c:functionname ( / *error* list_wcm l_o_s_1_length ...) ; <--- Set local to the function (defun *error* (msg) (princ (strcat "\nError: " msg))) ;; Rest of code ) It's crucial that you set the *error* local to the function, because if you don't, then other functions that doesn't have the *error* function will call that very same function on fail. As an added function, run the (*push-error-using-command*) command and proceed. Not that I know much about error-handling, so I'm in no position to be teaching you. As I understood it wrote "syntax error" it is now message for me, that code doesn;t apply beacause of syntax error, and the only possible error in my code is "(wcmatch (cdr (assoc.... pp1", when it is written like that it gives syntax error (if i have defun *error* at the beginning, if not it gives "cannot invoke..." as I wrote above). When (wcmatch pp1 (cdr (assoc......) it executes, BUT nothing appear on screen in CAD, but it should write object at specified places...:( (defun c:qwerty ( / *error* list_of_selections_1 l_o_s_1_length list_wcm number_1 entget_data_from_selection_1 pp1 pp2 pp3 pp4 xx) (defun *error* (msg) (princ (strcat "\nError: " msg))) (setq list_of_selections_1 (ssget "x" (list (cons 0 "TEXT") (cons 8 "Mootkood") (cons 7 "Standard")))) (setq l_o_s_1_length (sslength list_of_selections_1)) (setq number_1 (- 0 1)) (setq list_wcm (list (list "*vp*" "INSERT" "VILJA1" "PUU") (list "*lp*" "INSERT" "LEHTP1" "PUU") (list "*mand*" "INSERT" "MAND1" "PUU") )) (repeat l_o_s_1_length (setq number_1 (1+ number_1)) (setq entget_data_from_selection_1 (entget (ssname list_of_selections_1 number_1))) (foreach xx list_wcm (setq pp1 (car xx)) (setq pp2 (cadr xx)) (setq pp3 (caddr xx)) (setq pp4 (caddr (cdr xx))) (if (wcmatch pp1 (cdr (assoc 1 entget_data_from_selection_1))) (entmake (list (cons 0 pp2) (cons 2 pp3) (cons 8 pp4) (cons 10 (cdr (assoc 11 (entget_data_from_selection_1)))) (cons 41 0.5) (cons 42 0.5) (cons 43 0.5) (cons 50 0.00))))) (princ) ) ) 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.