Jump to content

Changing lines into a block


brianhiroshi

Recommended Posts

Hi there!

I'm new at AutoCAD and AutoLisp and I was trying to transform a set of lines that I've created in Autolisp into a single block. Is it possible? If someone knows how to do it, please give me a hand.

Thanks

Link to comment
Share on other sites

Here is my old one

I don't remeber how it's working

Give this a try

 

(defun C:AXB (/	      acsp    adoc    block_coll      block_def
      bname   bpt     cnt     hgt     i	      obj_list
      ob_list opt     promp   pt      ss      tag     val
     )

 (vl-load-com)
 (setq	adoc (vla-get-activedocument
       (vlax-get-acad-object)
     )
 )
 (if (and
(= (getvar "tilemode") 0)
(= (getvar "cvport") 1)
     )
   (setq acsp (vla-get-paperspace adoc))
   (setq acsp (vla-get-modelspace adoc))
 )
 (setq block_coll (vla-get-blocks adoc))
 (vla-endundomark
   adoc
 )
 (vla-startundomark
   adoc
 )
 (prompt "\nSelect entities to add into block\n")
 (setq ss (ssget))
 (setq i -1)
 (repeat (sslength ss)
   (setq obj_list
   (cons
     (vlax-ename->vla-object
       (ssname ss (setq i (1+ i)))
     )
     obj_list
   )
   )
 )
 (setq ob_list (reverse obj_list))
 (initget 1)
 (setq	bpt   (getpoint "\nBase point Point >> ")
bname (getstring T "\nEnter block label (block name) : \n")
 )
 (setq block_def (vla-add block_coll (vlax-3D-Point bpt) bname))
 (initget "Yes No")
 (setq opt (getkword "\nDo you want to add attribute(s) in this block? (Yes/No) <Y>\n"))
 (if (not opt)
   (setq opt "Yes")
 )
 (if (eq opt "Yes")
   (progn
     (setq hgt (getreal "\nEnter text height <0.05>: \n"))
     (if (not hgt)
(setq hgt 0.05)
     )
     (setq cnt 1)
     (while (setq
       pt (getpoint
	    (strcat "\nPick "
		    (itoa cnt)
		    " attribute insertion point (Enter to stop) \n"
	    )
	  )
     )
(setq promp (strcase (getstring	(strcat	"\nEnter "
					(itoa cnt)
					" attribute prompt : \n"
				)
		     )
	    )
      tag   (strcase
	      (getstring
		(strcat "\nEnter " (itoa cnt) " attribute tag : \n")
	      )
	    )
      val   (getstring
	      T
	      (strcat "\nEnter " (itoa cnt) " attribute value : \n")
	    )
      pt    (mapcar '- pt bpt)
)
(vlax-invoke
  block_def	 'Addattribute	hgt
  acAttributeModeVerify		promp	       pt
  tag		 val
 )
(setq cnt (1+ cnt))
     )
     (vla-copyobjects
adoc
(vlax-safearray-fill
  (vlax-make-safearray
    vlax-vbobject
    (cons 0 (1- (length obj_list)))
  )
  obj_list
)
block_def
     )
     (vlax-release-object block_def)
   )
 )
 (vla-endundomark
   adoc
 )
 (princ)
)
(prompt "\n===========================\n")
(prompt "\n   	Type AXB to run ...	")
(prompt "\n===========================\n")
(princ)

 

~'J'~

Link to comment
Share on other sites

I've seen that with this lisp it is necessary for the user to select the lines. What I meant is that I've created an Autolip program do draws a hole (I've used many "._line" commands) and at the enn of the program I wanted that those lines were joined into a single block without having to select them. Do you think that's possible? Thanks!!!

Link to comment
Share on other sites

Forgot to say - welcome on board :)

Try edited version instead

 

(defun C:XB (/	      acsp    adoc    block_coll      block_def
      bname   bpt     cnt     hgt     i	      obj_list
      ob_list opt     p1      p2      promp   pt
       ss     tag     val
     )

 (vl-load-com)
 (setq	adoc (vla-get-activedocument
       (vlax-get-acad-object)
     )
 )
 (if (and
(= (getvar "tilemode") 0)
(= (getvar "cvport") 1)
     )
   (setq acsp (vla-get-paperspace adoc))
   (setq acsp (vla-get-modelspace adoc))
 )
 (setq block_coll (vla-get-blocks adoc))
 (vla-endundomark
   adoc
 )
 (vla-startundomark
   adoc
 )

 (prompt "\nDraw the lines to add into block\n")
 (setq ss (ssadd))
 (while (setq p1 (getpoint "\nSpecify starting point (or press Enter to Exit):"))
   (setq p2 (getpoint p1 "\nSpecify ending point: "))
   (command "._line" "_non" p1 "_non" p2 "")
   (ssadd (entlast) ss))
 (setq i -1)
 (repeat (sslength ss)
   (setq obj_list
   (cons
     (vlax-ename->vla-object
       (ssname ss (setq i (1+ i)))
     )
     obj_list
   )
   )
 )
 (setq ob_list (reverse obj_list))
 (initget 1)
 (setq	bpt   (getpoint "\nBase point Point >> "))
 (while (not (and (setq bname (getstring T "\nEnter block label (block name) : "))
        (not (tblsearch "block" bname)))
      )
   (princ "\nBlock already exist. Use another name")
   )
 (setq block_def (vla-add block_coll (vlax-3D-Point bpt) bname))
 (initget "Yes No")
 (setq opt (getkword "\nDo you want to add attribute(s) in this block? (Yes/No) <Y> : "))
 (if (not opt)
   (setq opt "Yes")
 )
 (if (eq opt "Yes")
   (progn
     (setq hgt (getreal "\nEnter text height <0.05>: "))
     (if (not hgt)
(setq hgt 0.05)
     )
     (setq cnt 1)
     (while (setq
       pt (getpoint
	    (strcat "\nPick "
		    (itoa cnt)
		    " attribute insertion point (Enter to stop) "
	    )
	  )
     )
(setq promp (strcase (getstring	(strcat	"\nEnter "
					(itoa cnt)
					" attribute prompt : "
				)
		     )
	    )
      tag   (strcase
	      (getstring
		(strcat "\nEnter " (itoa cnt) " attribute tag : ")
	      )
	    )
      val   (getstring
	      T
	      (strcat "\nEnter " (itoa cnt) " attribute value : ")
	    )
      pt    (mapcar '- pt bpt)
)
(vlax-invoke
  block_def	 'Addattribute	hgt
  acAttributeModeVerify		promp	       pt
  tag		 val
 )
(setq cnt (1+ cnt))
     )
     )
   )
     (vla-copyobjects
adoc
(vlax-safearray-fill
  (vlax-make-safearray
    vlax-vbobject
    (cons 0 (1- (length obj_list)))
  )
  obj_list
)
block_def
     )
     (vlax-release-object block_def)
 (initget "Yes No")
 (setq opt (getkword "\nDo you want to delete parent lines? (Yes/No) <Y> : "))
   (if (not opt)
   (setq opt "Yes")
 )
 (if (eq opt "Yes")
   (command "._erase" ss "")
   )
 (vla-endundomark
   adoc
 )
 (princ)
)
(prompt "\n===========================\n")
(prompt "\n   	Type XB to run ...	")
(prompt "\n===========================\n")
(princ)

 

~'J'~

Link to comment
Share on other sites

Creating a block in lisp can be difficult but you can take a short cut.

If I understand correctly you could try this:

At the beginning of your code make a blank selection set

(setq ss1 (ssadd)) ;_makes a blank selection set

Now right after your program creates 1 new object put this code

(ssadd (entlast ss1)));_adds the last entity made to the selection set

 

Example:

(Command “_line” pt1 pt2 “”)

(ssadd (entlast ss1))

(command “_Rectangle” pt1 pt2 )

(ssadd (entlast ss1))

 

If everything is done correctly you end up with a selection set with all the objects your program made.

 

At the end of the program use this code.

(command "-block" "block name" Ipt "p" "" "");_makes a block , the P = previous selection set made

(command "-insert" "block name" Ipt "" "" "");_inserts the block

 

Ipt = a point. Either use a point from your program or use the getpoint function to get a point.

 

The reason there is a insert command is when you use the command line version of the block command there is no option to keep the block visible when made so it disappears.

So we use the insert command to put it back and make it visible again.

 

The problem will be the block name. You have to give it a name. If you are only going to use this once in a drawing then you can hard code the name. But if you want to use it more than once you have to give it a different name.

There are 2 ways to do this.

1- If your picky about the block name then you will have to use the getstring function prior to the making of the block and pass the variable to it where it says, “block name”.

2- If you don’t care then you can use the date function to create a unique name every time the program is used and the pass it to the block command.

Example:

(setq blkname (strcat "BLK_"(itoa(fix(* 86400.0 (- (getvar "date") (fix (getvar "date"))))))));-unique name for block

(command "-block" blkname Ipt "p" "" "");_makes a block

(command "-insert" blkname Ipt "" "" "");_inserts the block

 

Hope this helps. Making a block the other way is way more difficult and you still have the name issue.

Link to comment
Share on other sites

A program I worked on with David Bethel ~ may be of some use here:

 

(defun c:obj2blk1 (/ ss bn pt i ent elist)

 ; Get Entities

   (while (not ss)
   (princ "\nSelect Objects to Convert to Blocks:")
   (setq ss (ssget '((-4 . "<NOT") (0 . "INSERT,POLYLINE,VIEWPORT") (-4 . "NOT>"))))
   ) ;_  end while

 ; Get Block Name and Base Point

   (while (or (not bn)
          (not (snvalid bn))
      ) ;_  end or
   (setq bn (getstring "Specify Block Name: "))
   ) ;_  end while

   (initget 1)
   (setq pt (getpoint "Specify Base Point for Block: "))

;;; Create BLOCK Header
   (entmake (list (cons 0 "BLOCK") (cons 10 pt) (cons 2 bn) (cons 70 0)))

;;;STEP THRU THE SET
   (setq i (sslength ss))
   (while (>= i (setq i (1- i)) 0)
   (setq ent   (ssname ss i)
         elist (entget ent)
   ) ;_  end setq
   (entmake elist)
   ) ;_  end while

;;;FINISH THE BLOCK DEFINITION
   (entmake (list (cons 0 "ENDBLK") (cons 8 "0")))

;;;Insert the Block & Delete Originals
   (entmake (list (cons 0 "INSERT") (cons 2 bn) (cons 8 "0") (cons 10 pt)))
   (command "_.ERASE" ss "")
   (redraw)
   (prin1)
) ;_  end defun

Link to comment
Share on other sites

Thanks for the welcoming. I'm sorry to ask, but what does the "vla" do? There are some lisps that use it, but when I was reading about AutoLisp and VisualLisp on the Internet a didn't learn anything about it.

Thanks again!

Link to comment
Share on other sites

Hi JohnM, I've tried your advice, but the AutoCAD returns an "error: too many arguments" message at the line "(ssadd (entlast ss1))". Would you know what could be the problem? Thanks again and sorry for bothering you guys.

Link to comment
Share on other sites

Another thing John, I may have fixed the "too many arguments problem" by doing this:

 

At the beginning of the function,

 

(setq ss1 (ssadd))

(setq el1 (entlast))

 

Then, after every line I've created,

 

(ssadd el1 ss1)

 

Then at the end, the lines...

 

(command "._block" tipo pt1 "p" "" "") ;"tipo" is the name of the block the user entered

(command "._insert" tipo pt1 "" "" "")

 

But now there is a messge "No previous selection set"... Do you think what I did may be worng?

 

Thanks again

Link to comment
Share on other sites

The difference between autolisp and visual lisp is that autolisp is designed with it’s own list of functions like getstring , entget, vl-string-search and so on. Visual lisp is a way to utilize visual basic functions in autolisp. Open the lisp environment and than click on view then select apropos window. This will display a dialog box; in the text box you can enter a term to search for to see if there are any VLA functions available for it. Try typing the word line then click ok and you will see a list of stuff in the results box that has to do with the term line. Scroll down the list and anything with a vla in front of it is a visual basic function. Then you can highlight the item and click the? (Question mark) and the help file will open on that function. The help file is for visual basic users and is helpful but the actual vla function might be stated different in your code. So just copy the vla- function into google and typically you will find examples on how to implement it into your code.

 

As far as the issues you’re having with the code I really need to see your code in order to trouble shoot it.

My first posts where just thoughts and not tested so I’m not to surprised it has errors.

If you could post or email me your code and we can fix it.

Link to comment
Share on other sites

Thank you very much for explaining. I think I'll have to learn more about programming before being able to use VLA functions :)

 

About the code, it doesn´t belongs to me, I'm really sorry but I'm not aloud to post it anywhere even if it is were simple one.

 

I've managed to do it selecting the lines by using a window drom a point to another with the block command, but I'm afraid that this may not be a good solution if I use the program into a more complex drawing. It may select entities that were not suposed to be part of the block. I'm sorry if I explain anything you didn't understand, my English is not that good.

 

Do you think the "pedit" function could help?

 

Thanks again and I'm really sorry I can't post the code.

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