Jump to content

making layer in lisp routine


Einsener12

Recommended Posts

Hi!

Beginner right.

But i would like to great a layer during lisp routine.

I tried this one

(if (not(tblsearch "layer" "Kmark"))
 (command "-layer" "m" "Kmark" "c" "255" "")
 (setvar "clayer" "Kmark")
 )

But it seems not to work.

Any help?

Link to comment
Share on other sites

Glad you got it working!

 

As a tip: When sending options to the command, try to use the full name. Like in rather than "m" send "Make". We've recently run into situations where AutoDesk decided to change the shortcuts in some commands - thus making old lisp routines break down. If you send the whole word it won't matter if they do that in the future.

 

Also, to have your lisp work even on acad's localized to other languages, you can prefix an underscore to the command and its options so it forces the English onto it. E.g.

(command "[color=red]_[/color]-layer" "[color=red]_make[/color]" "Kmark" "[color=red]_color[/color]" "255" "Kmark" "")

Some even use the dot prefix which enables a command even if it's undefined. E.g. if some code previously did this:

(command "_undefine" "-layer")

Then the above would fail with an "Unknown command "-LAYER"." error. To get around even this you could use:

(command "[color=red].[/color]_-layer" "_make" "Kmark" "_color" "255" "Kmark" "")

Link to comment
Share on other sites

A handy hint make the new layer a defun then you can call it from any routine if you add it to your autoload, maybe also look at entmake.

 

Ps not tested no cad.

 

(defun C:laymake (lay col Ltype)
(if (= col nil) (setq col 3))
(if (= ltype nil)(setq ltype "continuous"))
(if (not(tblsearch "layer" lay))
(progn
(command "._layer" "_make" lay "_color" col lay "_ltype" lay ltype "")
(setvar "clayer" lay)
) ;end progn  
) ;end if
) ;end defun
;
;
; 
(setq lay "kmark"
col 255
ltype "continuous")
(laymake lay col ltype) 

Link to comment
Share on other sites

A handy hint make the new layer a defun then you can call it from any routine if you add it to your autoload,...

 

(defun C:laymake (lay col Ltype)  snipped code here...)

 

Simple typo here (very easy to catch if you have AutoCAD handy;)). Remove the C: prefix thus:

 

(defun laymake (lay col Ltype)  snipped code here...)

 

Note that the C: prefix would try to define 'laymake' to work as an AutoCAD command, that is, so that you would be able to type LAYMAKE on the command line to run this routine. It won't work here (because of the parameter list), and you don't need it here anyway. Also, you cannot call such a prefixed routine within another plain AutoLISP routine.

Edited by neophoible
one last point
Link to comment
Share on other sites

I also agree that the c: function prefix should be removed, as functions requiring parameters cannot be used directly at the command-line, however, when you say:

 

Also, you cannot call such a prefixed routine within another plain AutoLISP routine.

 

Since the function name is simply a symbol pointing to the function definition, this symbol can still be called from another function, e.g.:

 

(defun c:add3 ( x )
   (+ x 3)
)
(defun c:test ( / n )
   (if (setq n (getint "\nChoose a Number: "))
       (print (c:add3 n))
   )
   (princ)
)

Command: TEST
Choose a Number: 3
6

Link to comment
Share on other sites

Well, I'm not likely to argue about AutoLISP with you, Lee. :oops: I think I was thinking about using AutoLISP within AutoLISP at the command line, but I suppose that is really a separate issue.

 

I noticed that in your example you even used a C: prefixed routine with a parameter call. That one, "C:add3", would not be intended for use on the AutoCAD command line, right? That would go along with your first statement. From your example, evidently you can use parameter calls thus, but is it a common or recommended practice to use the C: prefix that way?

Link to comment
Share on other sites

Yep, you have to see the lisp defun name and the command name as 2 separate things. There's a list of lisp symbols - you can see these using the atoms-family function - this includes all global variables and defuns (even those with c: prefixes). When AutoCad notices a defun being declared with a c: prefix it "also" adds the rest of the name to a list of commands. So the c: prefix simply adds the name to another list as well - it doesn't remove it from the normal lisp functions.

 

Also notice this "feature" is sometimes used to have callable lisp functions from other types of addons (from ARX / DotNet). An addon which uses this exclusively is OpenDCL - all the call-back defuns would be written with a C: prefix (even though they have arguments) so the ARX can directly call them instead of cluttering the command-line with sendkeys / command-calls. They could've required use of vl-acad-defun instead but this was chosen as a more "elegant" solution.

Link to comment
Share on other sites

Well, I'm not likely to argue about AutoLISP with you, Lee. :oops:

 

Oh please do - I've been known to be wrong on many things, we are all still learning after all.

 

I noticed that in your example you even used a C: prefixed routine with a parameter call. That one, "C:add3", would not be intended for use on the AutoCAD command line, right?

 

Correct, the example was purely to demonstrate that it was indeed possible to call LISP 'command' functions from within other LISP functions since the function name is just a symbol, whether prefixed by c: or not. At least, that was my intention, hopefully I haven't added further confusion with the example.

 

...but is it a common or recommended practice to use the C: prefix that way?

 

No, the c: prefix is purely to allow a LISP function to be called at the command-line and hence would not be used for functions requiring parameters; my example was purely to dispell any idea that it was 'impossible' to call such functions from within other functions.

 

Of course, there are cases in which you would call a c: prefixed function from within another LISP function, where you want both functions to be available at the command-line, but for these cases, the c: prefixed function would not require arguments.

Link to comment
Share on other sites

Just to get back to the OP's idea ... also to give a further option of doing this I'm showing a non-command way of going about it:

(defun MakeLayer  (name col ltype plot lweight)
 (cond ((tblobjname "layer" name)) ;Check if layer exists
       ;; Else
       ((entmakex (list '(0 . "LAYER") ;Entity type = Layer
                        '(100 . "AcDbSymbolTableRecord") ;Table Record
                        '(100 . "AcDbLayerTableRecord") ;Layer Table Record
                        (cons 2 name) ;Layer name
                        '(70 . 0) ;Is thawed, thawed by default in VP's, unlocked, etc.
                        (cons 62 ;Layer colour
                              (cond (col) ;If col argument /= nil, then use the argument
                                    (7))) ;Else default colour White(7)
                        (cons 6 ;Layer linetype
                              (cond (ltype) ;If ltype argument /= nil, then use the argument
                                    ("CONTINUOUS"))) ;Else default line type Continuous
                        (cons 290 ;Plot / Not plot
                              (cond (plot 1) ;If plot argument /= nil, set to 1
                                    (0))) ;Else set to 0
                        (cons 370 ;Line weight
                              (cond ((>= lweight 0) lweight) ;If lweight is a usable value, then use it
                                    (-3)))))))) ;Else default to the "default" lineweight

Let's break that down to see what's happening:

 

  1. It's a new function which takes 5 arguments and returns the ename of a layer (either if already existing or after creating it), or nil if it cannot create the layer. So you can call this as if it's a normal built-in lisp function: (MakeLayer ...)
  2. The 1st argument is the name and has to be a valid layername string. The rest of the arguments can be nil or their relevant values.
  3. The cond is like a multiple if statement. It runs through each option's first item until that returns non-nil and then continues with that items rest. Though here I use it without any rest portions for each item.

    1. The 1st item checks if the layer already exists using the tblobjname function. If such is found the cond returns and thus returns the entire defun with the value obtained from tblobjname.
    2. "Else" entmakex is called with a newly built-up DXF data list. For the DXF codes in a layer see here: http://docs.autodesk.com/ACD/2011/ENU/filesDXF/WS1a9193826455f5ff18cb41610ec0a2e719-7a51.htm
      1. Some of the codes never change, like the entity type (code 0) will be a "LAYER", thus these are simply quoted.
      2. Those that do change (depending on the values of the arguments) are generated using the cons function. E.g. the layer name (code 2) is generated from the name argument.
      3. Some of those generated codes can have a default value. In which case I again use the cond idea to either send the argument's value (if not nil) or the default value into the cons.
      4. In one case (lweight) the default line weight is a value of -3. While -2=ByBlock and -1=ByLayer which makes no sense for a layer itself. Thus I check for a lweight argument greater-than or equal to 0, otherwise I send a -3 as default.
      5. This then returns the ename of the newly created layer - unless some error has occurred like an argument with a wrong type of value (e.g. the colour has to be an integer from 1 to 255).
      6. So the OP's example would then become

        (MakeLayer "Kmark" 255 nil T nil)


Link to comment
Share on other sites

I would like to thanks to everyone who would willing to share the experiences in every problems we encountered. As a matter of fact, for example, the question in this thread is not difficult at all (even I, as a not experienced lisp writer can provide the solution), but what impressed me is that there are so many experts would suggest more information ,options or possibilities about the question. To me, this is a forum where we can not just kill the problem, but also to learn how to do better. This is one the reasons why I love this forum very much.

 

Thanks again to everyone.

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