Author Topic: Associations, cdr, cadr, and my ignorance  (Read 5565 times)

0 Members and 1 Guest are viewing this topic.

Hangman

  • Guest
Associations, cdr, cadr, and my ignorance
« on: February 17, 2005, 03:49:17 PM »
Howdy all, been a while ...  I was on the unemployment list.  But I'm back with an employer who encourages the learning of LISP (Finally!!!)  :)

So, I have a couple questions for you.

First of all, I'm writing a simple lisp that will give me a couple labels to an entity in the dwg.  But I've run into a problem.  Does anyone know the error:  bad argument type: lentityp nil

here's the code:
Code: [Select]

  (command ".line" pt-02 pt-03 "")
  (setq tmpln (ssget "l"))
  (princ "\nSelect angle")
  (command ".rotate" tmpln "" pt-01 pause)
  (setq start (cdr (assoc 10 (entget (ssname tmpln 1)))))
  (setq end (cdr (assoc 11 (entget (ssname tmpln 1)))))
  (setq angl (angle start end))
  (setq angd (cvunit angl "radian" "degree"))
  (setq d1 (car start))
  (setq d2 (car end))

It is crashing at the (setq start (cdr (assoc 10...  line.
Maybe I'm going about this the wrong way, but I don't know all the details to LISP yet.
I want to create an attribute block that I can edit, text on top of a line, text below.  I have to be able to rotate this entity around the insertion point.  I also need to select a point where the text begins, or do a return to accept a default length from the insertion point.  And have the line in between the text stop at the end of the text.

My other question is, can I create this type of entity, as a block, yet have the line in between the top and bottom texts to be independently stretchable ???  And still be part of the block ???

Thanks guys.[/quote]

Jeff_M

  • King Gator
  • Posts: 4094
  • C3D user & customizer
Re: Associations, cdr, cadr, and my ignorance
« Reply #1 on: February 17, 2005, 04:27:03 PM »
See my comments in-line in RED
Quote from: Hangman
Howdy all, been a while ...  I was on the unemployment list.  But I'm back with an employer who encourages the learning of LISP (Finally!!!)  :) Congratulations!

So, I have a couple questions for you.

First of all, I'm writing a simple lisp that will give me a couple labels to an entity in the dwg.  But I've run into a problem.  Does anyone know the error:  bad argument type: lentityp nil This means you are using (entget) on a nil item, ssets are 0 based lists so your (ssname tmpln 1) needs to be changed to (ssname tmpln 0) in 2 places

here's the code:
<snip>

It is crashing at the (setq start (cdr (assoc 10...  line.
Maybe I'm going about this the wrong way, but I don't know all the details to LISP yet.
I want to ...<snip> It looks like you are getting there.... :)

My other question is, can I create this type of entity, as a block, yet have the line in between the top and bottom texts to be independently stretchable ???  And still be part of the block ??? NO, sorry

Thanks guys.
You're welcome

sinc

  • Guest
Re: Associations, cdr, cadr, and my ignorance
« Reply #2 on: February 17, 2005, 04:53:35 PM »
Quote from: Hangman

My other question is, can I create this type of entity, as a block, yet have the line in between the top and bottom texts to be independently stretchable ???  And still be part of the block ???

You can try using a group instead of a block, and see if it works for your purposes.  Groups are a lot like blocks in most respects.  But one key difference is you can independently move items inside a group and still retain the "groupiness".  I don't really know what you're trying to do, though, so I don't know if groups will work for this task or not.

Hangman

  • Guest
Associations, cdr, cadr, and my ignorance
« Reply #3 on: February 17, 2005, 05:26:23 PM »
This means you are using (entget) on a nil item, ssets are 0 based lists so your (ssname tmpln 1) needs to be changed to (ssname tmpln 0) in 2 places
Thanks again Jeff, I thought that's what it meant but I've got other lisps that are written differently that start with 1 and I was a bit confused.

Sinc,  grouping might possibly work, thanks for the idea.

So, these helps create other questions;  the question being, will the GETSTRING give me the length of a text line ???

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Associations, cdr, cadr, and my ignorance
« Reply #4 on: February 17, 2005, 06:13:21 PM »
Quote from: Hangman
< .. >
So, these helps create other questions;  the question being, will the GETSTRING give me the length of a text line ???



Perhaps something like ;

(setq sTestVal "123456789")
(setq nStrCount (STRLEN sTestVal))
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Adesu

  • Guest
Re: Associations, cdr, cadr, and my ignorance
« Reply #5 on: February 18, 2005, 01:31:44 AM »
here's the code:
Code: [Select]

  (command ".line" pt-02 pt-03 "")
  (setq tmpln (ssget "l"))
  (princ "\nSelect angle")
  (command ".rotate" tmpln "" pt-01 pause)
  (setq start (cdr (assoc 10 (entget (ssname tmpln 1)))))
  (setq end (cdr (assoc 11 (entget (ssname tmpln 1)))))
  (setq angl (angle start end))
  (setq angd (cvunit angl "radian" "degree"))
  (setq d1 (car start))
  (setq d2 (car end))



or here your script after corrected

(setq pt-02 (getpoint "\nCLICK LOCATION FOR OBJECT: "))
(setq pt-03 (getpoint pt-02 "\nCLICK LOCATION FOR OBJECT: "))
(command "_line" pt-02 pt-03 "")
(setq tmpln (ssget "l"))
(setq cnt (1- (sslength tmpln)))
(princ "\nSelect angle")
(setq pt-01 (getpoint "\nCLICK LOCATION FOR OBJECT: "))
(command "_rotate" tmpln "" pt-01 pause)
(setq start (cdr (assoc 10 (entget (ssname tmpln cnt)))))
(setq end (cdr (assoc 11 (entget (ssname tmpln cnt)))))
(setq angl (angle start end))
(setq angd (cvunit angl "radian" "degree"))
(setq d1 (car start))
(setq d2 (car end))

Jeff_M

  • King Gator
  • Posts: 4094
  • C3D user & customizer
Associations, cdr, cadr, and my ignorance
« Reply #6 on: February 18, 2005, 11:57:52 AM »
Quote from: Hangman

Thanks again Jeff,
So, these helps create other questions;  the question being, will the GETSTRING give me the length of a text line ???

Although Kerry gave you one answer, I think that you may be looking for the physical length that the text object occupies in the drawing for the sake of drawing a line below it. If that is the case, then one way to accomplish this is by using ActiveX methods & properties.

Here is a function you can use in your code to obtain the length of a text object. Note, only works for text, not Mtext.
Code: [Select]

;; function to return the physical length of a text object;
;; accepts ename or vla-object as argument
(defun get_txtlength (txt / rot ll ur)
  (vl-load-com)
  (if (= (type txt) 'ENAME);convert to vla-object if needed
    (setq txt (vlax-ename->vla-object txt))
    )
  (setq rot (vla-get-rotation txt));save the rotation angle
  (vla-put-rotation txt 0.0);set rotation to 0
  (vla-getboundingbox txt 'll 'ur);get the bounding box
  (setq ll (vlax-safearray->list ll));convert lower left to list
  (setq ur (vlax-safearray->list ur));convert upper right to list
  (vla-put-rotation txt rot);put the text back to original rotation angle
  (- (car ur) (car ll));subtract lower left x from upper right x for length
  )

Hangman

  • Guest
Associations, cdr, cadr, and my ignorance
« Reply #7 on: February 21, 2005, 01:11:46 PM »
Thanks everyone for your input, it gets the mind racing.  I really appreciate it.  I think Kerry's idea will work better for my application, but let me explain more what I'm trying to accomplish.

I am creating a callout that is...  multipurpose if you will.  This is for calling out the size of a column, for calling out a dead load/snow load and for calling out deck elevations.  It has three purposes so I need to keep it general but specific.  Following me so far ???  :)

So, the callout must have a line below it, roughly an eighth of an inch from the corner of the column, point of intersection on trusses for loads or corner of deck for elevations.  The line must stretch to the end of the callout.
For the column callout, the line has to stretch to the end of; TS 4 x 4 x 1/4"
For the dead load/snow load; #DL750
For the deck elevation; DBE = 23'-4"
So, I need to setq the string length of whatever text is entered, then insert it into an .attdef block.
I then want to create the .attdef block and insert it at the insertion point (i.e. the corner of the column, intersection at trusses or corner of deck)
And then, insert a line from the insertion point to end of the text, keeping the line separate from the .attdef block so as to stretch it if needed.  (redesigns, updating, etc.)
I think Sinc has the right idea of creating the .attdef block and grouping the line with the block.
My question then is, can I insert a getstring like the following;
Code: [Select]

  (setq contt (getstring "\nEnter top line callout:"))
  (setq contb (getstring "\nEnter bottom line callout or return for none:"))
    (if (= contb nil)
        (setq contb "")
    );end if


into a .attdef command like;

Code: [Select]

    (progn
      (command ".attdef" "" "TS---x---x-1/4" "Column" "TS 4 x 4 x 1/4" (polar pt-04 (+ ang2 (* pi 0.5)) lng-4) angd)
      (setq sset-1 (ssadd (entlast) sset-1))
      (command ".attdef" "" "---" "Bottom-Note" "" "j" "tl" (polar pt-04 (+ ang2 (* pi 1.5)) lng-4) angd)  
      (setq sset-1 (ssadd (entlast) sset-1))
    );;;end progn


Then, add a line the length of pt-01 (insert point) to contt (text string) ???
And then group them together ???
Is any of this making sense ???  I hope so, don't know how else to explain this.  :)
And if so, how ???

Jeff_M

  • King Gator
  • Posts: 4094
  • C3D user & customizer
Associations, cdr, cadr, and my ignorance
« Reply #8 on: February 21, 2005, 03:44:36 PM »
Hangman, you don't want to insert your getstring data into an attdef......attdefs are used to create a block with attributes. You then can place the values obtained with getstring into the inserted attributes.

Here's an example for you to play with, losely based on the criteria you set forth:
Code: [Select]

(defun c:snow (/ atts blk blkdef blks contb contt dwg grp l1 ll mspace pt1 pt2 ur)
  (vl-load-com)
  (setq dwg (vla-get-activedocument (vlax-get-acad-object));get our drawing
blks (vla-get-blocks dwg);get the blocks collection
mspace (vla-get-modelspace dwg);get modelspace
)
  (if (not (tblsearch "block" "load_label"));see if the label block exists
    (progn ;create the block with attributes if it doesn't exist
      (setq blkdef (vlax-invoke blks 'add '(0.0 0.0 0.0) "load_label"))
      (vlax-invoke blkdef 'addattribute 0.125 0 "Snow Load?" '(0.0 0.25 0.0) "SNOWLOAD" "0.0")
      (vlax-invoke blkdef 'addattribute 0.125 0 "Elevation?" '(0.0 0.0625 0.0) "ELEV" "")
      )
    )
  (setq contt (getstring "\nEnter top line callout:"));get user input
  (setq contb (getstring "\nEnter bottom line callout or return for none:")) ;get user input
  (setq blk (vlax-invoke mspace 'insertblock
     (getpoint "\nPick Insertion point: ")
     "load_label" 1.0 1.0 1.0 0.0));insert the block
  (setq atts (vlax-invoke blk 'getattributes));get the attributes
  (foreach att atts ;cycle through the attributes and place the user data into them
    (cond ((= "SNOWLOAD" (vla-get-tagstring att))(vla-put-textstring att contt))
 ((and (not (= contb ""))
(= "ELEV" (vla-get-tagstring att)))(vla-put-textstring att contb))
 )
    )
  (vla-getboundingbox blk 'll 'ur);get the block's physical limits
  (setq ll (vlax-safearray->list ll ));convert lower left corner to a list
  (setq ur (vlax-safearray->list ur ));convert upper right corner to a list
  ;create a point list a little lower & longer than the actual text position
  (setq pt1 (list (- (car ll) 0.0625) (- (cadr ll) 0.0625) (caddr ll)))
  (setq pt2 (list (+ (car ur) 0.0625) (- (cadr ll) 0.0625) (caddr ur)))
  (setq l1(vlax-invoke mspace 'addline pt1 pt2)); add the line
  (setq grp (vla-add (vla-get-groups dwg) "*"));create an anonymous group
  (vlax-invoke grp 'appenditems (list blk l1));place the block & line into the group
  )


try this out in a new drawing and see what you think. Then start making adjustments as desired......such as the attribute definition layers, colors, textstyle size, etc.

Hangman

  • Guest
Associations, cdr, cadr, and my ignorance
« Reply #9 on: February 21, 2005, 05:16:58 PM »
Jeff,
I'm impressed !   :genie:
As you can tell from my code I've posted, I'm still a newby.  And the more I learn, the more I realize I know just enough to cause a lot of problems and aggravation.
Which brings me to my next comment, I'm not understanding a thing in there,  :oops:   but it works.
what is all the vla- and vlax- stuff going on ???
At any rate, thanks, I can play with this.

I hope you don't mind my asking, Jeff ... (not to belittle what you have done, I do appreciate it)

Does anyone else have other ideas that would also work ???
-EDITED-
Better yet Jeff, do you have a way of doing what you just did with the ol' generic lisp ???  I don't have a book or any resource to help me at the moment with the vla stuff you have there.  I don't know where to go to find some answers.   :(

Jeff_M

  • King Gator
  • Posts: 4094
  • C3D user & customizer
Associations, cdr, cadr, and my ignorance
« Reply #10 on: February 21, 2005, 08:25:45 PM »
Sorry about overwhelming you with the ActiveX way of doing things. It's just that, IMHO, it is far easier to see what I am trying to accomplish using the ActiveX methods and properties.

Which leads me to your concern of  "I don't have a book or any resource to help me at the moment with the vla stuff you have there. I don't know where to go to find some answers." The answer is your Autocad online help's "Developer Documention: ActiveX and VBA Reference and the Developer's Guide" The vlax- & vla- stuff is just implementing what can be found in those documents. Other great sources of information on those is this forum, the forums at cadvault.com, and the autodesk customization newsgroup.

One other big reason why I went with the ActiveX solutuon is that AFAIK there is no way of obtaining the boundingbox of an entity using plain lisp, and that is one thing that makes this routine work......I commented the heck out of the code in the hopes that you WOULD be able to follow along, and, Yes,  most everyting else can be done using plain lisp........ I just don't use it much anymore since the ActiveX stuff is far more intuitive.

Tomorrow I may try to show how the routine could be written using the command and/or entmake functions, but I sure don't relish the idea.......I'd rather spend the time helping you learn the new stuff :)

Hangman

  • Guest
Active X VLA
« Reply #11 on: February 24, 2005, 10:07:40 AM »
Jeff,

I have been playing with the code you posted earlier, but I'm missing something.  It seems every time I try to edit even the littlest piece, it crashes.  Let me see if I can understand this; (my comments in red)
Quote

(defun c:snow (/ atts blk blkdef blks contb contt dwg grp l1 ll mspace pt1 pt2 ur)
  (vl-load-com); Is this required to load visual lisp active x ???
  (setq dwg (vla-get-activedocument (vlax-get-acad-object));get our drawing Why are we getting our dwg ??? What does this do for us ???
   blks (vla-get-blocks dwg);get the blocks collection I understand we are getting the blocks within our dwg, I have code similar to this as follows;
 
Code: [Select]
 (setq fname (getvar "dwgname"))
 (setq fnamel (strlen fname))
 (setq fname (substr fname 1 (- fnamel 4)))
;;;
;;;;;Create & insert block
;;;
 (command ".-purge" "b" "" "n")
 (while (/= (tblsearch "block" (strcat "call" fname (itoa fn))) nil)
   (setq fn (+ fn 1))
 )
 (setq callout (strcat "call" fname (itoa fn)))
 (command ".-block" callout pt-01 sset-1 "")
 (setvar "attdia" 0)
 (command ".-insert" callout pt-01 "" "" "")

   mspace (vla-get-modelspace dwg);get modelspace
   )
  (if (not (tblsearch "block" "load_label"));see if the label block exists Now this block 'label' can be renamed to something else, correct?, as long as the 'load_' is in front of the name ???
    (progn ;create the block with attributes if it doesn't exist
      (setq blkdef (vlax-invoke blks 'add '(0.0 0.0 0.0) "load_label"));So does this mean you are creating the block at point 0,0 ???
      (vlax-invoke blkdef 'addattribute 0.125 0 "Snow Load?" '(0.0 0.25 0.0) "SNOWLOAD" "0.0");The 0.125 is text size, why can't I put it something like ...blkdef 'addattribute (stht) ... having defined 'stht' as (* dimscale 9) for example
      (vlax-invoke blkdef 'addattribute 0.125 0 "Elevation?" '(0.0 0.0625 0.0) "ELEV" "");Now the (0.0 0.25... from the line of txt above is the elevation from the line, correct ?., and the (0.0 0.0625... is the elevation of the second line of txt ???
      )
    )


I have found a textbox variable that supposedly gets the bot left corner and uppr right corner of the text.  I haven't figured out exactly how to work it yet but, couldn't one take the uppr right corner and place a point south of that corner the height of the txt plus the offset distance of the txt from the line ???  Doesn't the textmask work off of this variable ???

I have a LLLLLLOOOOOOTTTTTT to learn    :x

Thanks for your help.

Jeff_M

  • King Gator
  • Posts: 4094
  • C3D user & customizer
Associations, cdr, cadr, and my ignorance
« Reply #12 on: February 24, 2005, 02:10:48 PM »
I'll try to answer these in the same order you asked them, without quoting the entire post....
(vl-load-com) from the help file:
Quote

This function loads the extended AutoLISP functions provided with Visual LISP. The Visual LISP extensions implement ActiveX and AutoCAD reactor support through AutoLISP, and also provide ActiveX utility and data conversion functions, dictionary handling functions, and curve measurement functions.

If the extensions are already loaded, vl-load-com does nothing.
So you basically had that correct.

We save the ActiveDrawing so we can use it in other portions of our code. Since ActiveX can work on more than just the current drawing, we must explicitly call out the document we are working with......for example from your example:
to get a block in the block table in the current drawing with basic lisp you just call (setq blk (tblsearch "block" "whateverblockyouwant")). To do the same thing in ActiveX requires you to specify which drawing to get the block table in (note there are other ways of doing this, I am just using one for this example):
(setq blks (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object))))
(vlax-for blkdef blks
  (if (eq (vla-get-name blkdef) "whateverblockyouwant")
     (setq blk blkdef)
    )
)

The name need not be "load_label"...it can be whatever you like, provided  it is unique.

We are creating the block with an insertion point at 0,0, yes.

You can create the attribute with any text size you want. But by creating this block with attributes at exactly 1:1 scale you can then use a lisp or menu macro to insert it sclaed by Dimscale (or any other factor) and it will always look the same regardless of scale.

The next two you refer to 'elevation'...if are are referring to the location of the attribute text in relation to the block's insertion point, then yes...otherwise I'm not sure what you want to know.  IOW, what I did was duplicate the following commands with ActiveX:
Code: [Select]

Command:
-ATTDEF
Current attribute modes: Invisible=N  Constant=N  Verify=N  Preset=N
Enter an option to change [Invisible/Constant/Verify/Preset] <done>:

Enter attribute tag name: SNOWLOAD

Enter attribute prompt: Snow Load?

Enter default attribute value: 0.0

Current text style:  "Standard"  Text height:  0.2000
Specify start point of text or [Justify/Style]: 0.0,0.25,0.0

Specify height <0.2000>: 0.125

Specify rotation angle of text <0>:

Command:
-ATTDEF
Current attribute modes: Invisible=N  Constant=N  Verify=N  Preset=N
Enter an option to change [Invisible/Constant/Verify/Preset] <done>:

Enter attribute tag name: ELEV

Enter attribute prompt: Elev?

Enter default attribute value:

Current text style:  "Standard"  Text height:  0.1250
Specify start point of text or [Justify/Style]: 0.0,0.0625,0.0

Specify height <0.1250>:

Specify rotation angle of text <0>:

Command: -block

Enter block name or [?]: load_label
Specify insertion base point: 0.0,0.0

Select objects: Specify opposite corner: 2 found <selected the 2 attributes>

Select objects:

Heh, ya got me on the (textbox)...I'd forgotten about that. :oops: However,  after thinking about it some more, (textbox) only works with, uh, text objects. So our block and/or attributes don't qualify, which brings me back to the ActiveX getboundingbox.....which works for ALL entities.