Jump to content

How t add WCMATCH to program


StevJ

Recommended Posts

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

Link to comment
Share on other sites

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)
)

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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)
)

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

(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:

 

letteredrectangle.png

 

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)

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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 :thumbsup:

 

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.

Link to comment
Share on other sites

You're welcome; no pardon necessary :thumbsup:

 

 

 

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

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...