StevJ Posted February 9, 2016 Share Posted February 9, 2016 This little guy will outline every stinkin' named view in your drawing's model space. Quite helpful and it works great, and though I'm sure it could be written better, this is its original form as written by the unknown author in 1993, and part of a much larger program. ;* DRAW BOX AROUND ALL VIEWS ;; unceremoniously ripped from the bowels of some ancient LISP ;; program (circa 1993) by SteveJ on 11 JUN 2009 to quickly show ;; the outlines of all exisiting named views on yer drawing as a ;; stand-alone program. (defun DXF (code elist) (cdr (assoc code elist)) ) (defun C:SHOWVIEWS ( / frst tbdata elist edata llist) (if (setq tbdata (tblnext "VIEW" T)) (while (/= tbdata nil) (setq port (getvar "CVPORT") vname (dxf 2 tbdata) ;extract view name Y (* (dxf 40 tbdata) 0.5) ;view height X (* (dxf 41 tbdata) 0.5) ;view width );setq (setq CP (dxf 10 tbdata) P1 (list (- (car CP) X) (- (cadr CP) Y)) ;lower left corner P2 (list (- (car CP) X) (+ (cadr CP) Y)) ;upper left corner P3 (list (+ (car CP) X) (+ (cadr CP) Y)) ;upper right corner P4 (list (+ (car CP) X) (- (cadr CP) Y)) ;lower right corner );setq (grdraw P1 P2 7 1) ; draws vector (grdraw P2 P3 7 1) (grdraw P3 P4 7 1) (grdraw P4 P1 7 1) (setq tbdata (tblnext "VIEW")) ;* get next view ) ;* while end ) ;* endif (prompt " Done") (princ) ) My wish is to incorporate a wcmatch statement so it only shows the view that ends with H1, but I have never been able to grasp wcmatch, so I must ask for help with this one. There will only ever be one named view in a drawing to end that way, but it's in all the drawings, and it sure would make drawing checking easier and much faster if I could quickly check the position of that one view, of the many named views that will be there. Thinking ahead: by simply incorporating an appropriate wcmatch statement, the program could also easily be adapted to display other specially-named views in the future, should that need arise. Problem is I don't know where to put it or exactly how it should be configured. Does it "and" with the while statement? Give it it's own "if" line? If so, where? What about "vname" ? Can that be the key? Thanks in advance for any assistance. Steve Quote Link to comment Share on other sites More sharing options...
satishrajdev Posted February 9, 2016 Share Posted February 9, 2016 Usage of WCMATCH :- _1$ (wcmatch "test-h1" "*h1") T _1$ (wcmatch "test-h12" "*h1") nil _1$ (wcmatch "test-h12" "*h1*") T Try this :- (defun c:test (/ tbdata vname Y X CP P1 P2 P3 P4) (if (setq tbdata (tblnext "VIEW" T)) (while tbdata (setq vname (strcase (dxf 2 tbdata))) ;extract view name (if [b](wcmatch vname "*H1")[/b] (progn (setq Y (* (dxf 40 tbdata) 0.5) ;view height X (* (dxf 41 tbdata) 0.5) ;view width CP (dxf 10 tbdata) P1 (list (- (car CP) X) (- (cadr CP) Y)) ;lower left corner P2 (list (- (car CP) X) (+ (cadr CP) Y)) ;upper left corner P3 (list (+ (car CP) X) (+ (cadr CP) Y)) ;upper right corner P4 (list (+ (car CP) X) (- (cadr CP) Y)) ;lower right corner ) ;setq (grdraw P1 P2 7 1) ; draws vector (grdraw P2 P3 7 1) (grdraw P3 P4 7 1) (grdraw P4 P1 7 1) ) ;* end PROGN ) ;* end if (setq tbdata (tblnext "VIEW")) ;* get next view ) ;* while end ) ;* endif (prompt " Done") (princ) ) Quote Link to comment Share on other sites More sharing options...
StevJ Posted February 9, 2016 Author Share Posted February 9, 2016 Satish Rajdev, Your modification is exactly what I was asking for. Works perfectly. You make it look so easy. OK. I must study this. Thank you. Steve Quote Link to comment Share on other sites More sharing options...
satishrajdev Posted February 9, 2016 Share Posted February 9, 2016 You're welcome Quote Link to comment Share on other sites More sharing options...
Lee Mac Posted February 9, 2016 Share Posted February 9, 2016 FWIW, the code could be shortened slightly: (defun c:test ( / c l v x y ) (while (setq v (tblnext "view" (not v))) (if (wcmatch (strcase (cdr (assoc 2 v))) "*H1") (progn (setq x (* 0.5 (cdr (assoc 40 v))) y (* 0.5 (cdr (assoc 41 v))) c (cdr (assoc 10 v)) l (list (mapcar '- c (list x y)) (mapcar '+ c (list x (- y))) (mapcar '+ c (list x y)) (mapcar '+ c (list (- x) y)) ) ) (mapcar '(lambda ( a b ) (grdraw a b 7 1)) (cons (last l) l) l) ) ) ) (princ) ) Quote Link to comment Share on other sites More sharing options...
StevJ Posted February 9, 2016 Author Share Posted February 9, 2016 FWIW, the code could be shortened slightly: (defun c:test ( / c l v x y ) (while (setq v (tblnext "view" (not v))) (if (wcmatch (strcase (cdr (assoc 2 v))) "*H1") (progn (setq x (* 0.5 (cdr (assoc 40 v))) y (* 0.5 (cdr (assoc 41 v))) c (cdr (assoc 10 v)) l (list (mapcar '- c (list x y)) (mapcar '+ c (list x (- y))) (mapcar '+ c (list x y)) (mapcar '+ c (list (- x) y)) ) ) (mapcar '(lambda ( a b ) (grdraw a b 7 1)) (cons (last l) l) l) ) ) ) (princ) ) Hey now. That's excellent. I'll be studying the differences. Thanks for the program upgrade, Lee. Steve Quote Link to comment Share on other sites More sharing options...
Lee Mac Posted February 9, 2016 Share Posted February 9, 2016 You're welcome Steve, feel free to question the code. Quote Link to comment Share on other sites More sharing options...
StevJ Posted February 11, 2016 Author Share Posted February 11, 2016 You're welcome Steve, feel free to question the code. Lee, After spending a some time on your web site and Afralisp in attempts to decipher your code, there are questions. (mapcar '(lambda ( a b ) (grdraw a b 7 1)) (cons (last l) l) l) I understand what the grdraw portion does, but how is the 'a b' of it (and the lambda) pointed, if that's the right term, to the x and y coordinates in the list above? Also, in the cons portion, why 'last' and not 'list'? Is the box is being drawn by working the list from bottom to top? If the 'l' list represents line lengths or vertices, why only 3 and not 4? Steve Quote Link to comment Share on other sites More sharing options...
Lee Mac Posted February 11, 2016 Share Posted February 11, 2016 (mapcar '(lambda ( a b ) (grdraw a b 7 1)) (cons (last l) l) l) I understand what the grdraw portion does, but how is the 'a b' of it (and the lambda) pointed, if that's the right term, to the x and y coordinates in the list above? Also, in the cons portion, why 'last' and not 'list'? Is the box is being drawn by working the list from bottom to top? If the 'l' list represents line lengths or vertices, why only 3 and not 4? Hi Steve, To help to explain how the mapcar expression is evaluated, consider the following console tutorial: Assume that the variable 'l' is assigned the following list of four coordinates (vertices of the rectangle): _$ (setq l '((1 2) (3 4) (5 6) (7 )) ((1 2) (3 4) (5 6) (7 ) The expression (cons (last l) l) will push the last item in the list onto the front of the list: _$ (cons (last l) l) ((7 (1 2) (3 4) (5 6) (7 ) Now, consider that mapcar will cease evaluation when any of the supplied list arguments is fully processed, e.g.: _$ (mapcar '+ '(1 2 3) '(4 5 6 7 8 9)) (5 7 9) _$ (mapcar 'strcat '("A" "B" "C" "D" "E" "F") '("1" "2" "3")) ("A1" "B2" "C3") Therefore, evaluating the following mapcar expression with our two lists will yield the following result: _$ (mapcar '[color=blue](lambda ( [color=purple]a[/color] [color=plum]b[/color] ) [color=purple](print a)[/color] [color=plum](princ b)[/color])[/color] [color=green](cons (last l) l)[/color] [color=red]l[/color]) [color=purple](7 [/color] [color=plum](1 2)[/color] [color=purple](1 2)[/color] [color=plum](3 4)[/color] [color=purple](3 4)[/color] [color=plum](5 6)[/color] [color=purple](5 6)[/color] [color=plum](7 [/color] To visualise this, consider a rectangle with the vertices lettered A to D, starting from the bottom-left and going counter-clockwise around the rectangle: Now, the list 'l' contains vertices: (setq l (list A B C D)) And the expression (cons (last l) l) contains the vertices: (cons (last l) l) = (D A B C D) Therefore, the mapcar expression takes the following form: (mapcar '(lambda ( a b ) (grdraw a b 7 1)) (D A B C D) (A B C D) ) And so the grdraw function is evaluated with the following arguments: (grdraw D A 7 1) (grdraw A B 7 1) (grdraw B C 7 1) (grdraw C D 7 1) Quote Link to comment Share on other sites More sharing options...
satishrajdev Posted February 12, 2016 Share Posted February 12, 2016 Nice Explanination Quote Link to comment Share on other sites More sharing options...
Lee Mac Posted February 12, 2016 Share Posted February 12, 2016 Nice Explanination Thank you Satish Quote Link to comment Share on other sites More sharing options...
StevJ Posted February 13, 2016 Author Share Posted February 13, 2016 Lee, Thanks for that most excellent step-by-step explanation. Please pardon the delayed response, I've been studying it. If I can paraphrase what I understand from your tutorial above; we create two identical lists, and shift one to the right because its last item is duplicated and set into the first position (cons), then pair the lists one for one until the short list is all used up (mapcar), with the resultant list passed to grdraw to display as joined vertices. Yes? Curiosity question: would grvecs need similar list manipulation? Steve Quote Link to comment Share on other sites More sharing options...
Lee Mac Posted February 13, 2016 Share Posted February 13, 2016 Thanks for that most excellent step-by-step explanation. Please pardon the delayed response, I've been studying it. You're welcome; no pardon necessary we create two identical lists, and shift one to the right because its last item is duplicated and set into the first position (cons), then pair the lists one for one until the short list is all used up (mapcar), with the resultant list passed to grdraw to display as joined vertices. Yes? Only one list is assigned to a variable 'l': the list of four ordered vertices of the rectangle - this list does not contain any duplicate items. This list of four vertices is passed as the second list argument for the mapcar expression. The last function will retrieve the last item in this list, and the cons function will 'push' the value returned by the last function onto the front of the list, returning a list with five items (with the first item equal to the last item). This list of five items is then passed as the first list argument for the mapcar expression. Each item in each list argument is then passed as an argument to the lambda function - the lists are not 'merged' in any way, and no new list is created before the items are supplied to the function argument of the mapcar expression. mapcar will then return a list containing the result of each evaluation of its function argument (the lambda function in this particular case). Curiosity question: would grvecs need similar list manipulation? Firstly, I would note that the list manipulation demonstrated by my example is not at all necessary for successful operation of the program (as you will know, since your original code would also perform equally well); the use of mapcar merely makes the code more concise, with fewer repeated expressions. There are many ways to write AutoLISP expressions whilst still achieving the same end result: some algorithms might be more elegant or concise, others may be more efficient. Depending on the application, the most elegant route may introduce inefficiency (especially with some recursive solutions), whilst for other applications, the most efficient route may render the code unmanageable. The use of grvecs could be substituted for grdraw in the existing code and be written in exactly the same way, or this could be written as multiple grvecs expressions, or as a single grvecs expression with many arguments - there isn't necessarily a single 'correct' answer. Quote Link to comment Share on other sites More sharing options...
StevJ Posted February 13, 2016 Author Share Posted February 13, 2016 You're welcome; no pardon necessary Only one list is assigned to a variable 'l': the list of four ordered vertices of the rectangle - this list does not contain any duplicate items. This list of four vertices is passed as the second list argument for the mapcar expression. The last function will retrieve the last item in this list, and the cons function will 'push' the value returned by the last function onto the front of the list, returning a list with five items (with the first item equal to the last item). This list of five items is then passed as the first list argument for the mapcar expression. Each item in each list argument is then passed as an argument to the lambda function - the lists are not 'merged' in any way, and no new list is created before the items are supplied to the function argument of the mapcar expression. mapcar will then return a list containing the result of each evaluation of its function argument (the lambda function in this particular case). Firstly, I would note that the list manipulation demonstrated by my example is not at all necessary for successful operation of the program (as you will know, since your original code would also perform equally well); the use of mapcar merely makes the code more concise, with fewer repeated expressions. There are many ways to write AutoLISP expressions whilst still achieving the same end result: some algorithms might be more elegant or concise, others may be more efficient. Depending on the application, the most elegant route may introduce inefficiency (especially with some recursive solutions), whilst for other applications, the most efficient route may render the code unmanageable. The use of grvecs could be substituted for grdraw in the existing code and be written in exactly the same way, or this could be written as multiple grvecs expressions, or as a single grvecs expression with many arguments - there isn't necessarily a single 'correct' answer. Seems I oversimplified. Thank you for the kind correction and further clarification. Much clearer now. Cheers, Steve Quote Link to comment Share on other sites More sharing options...
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.