Author Topic: LISP similar to "BLOCK" command  (Read 4266 times)

0 Members and 1 Guest are viewing this topic.

like_citrus

  • Newt
  • Posts: 114
LISP similar to "BLOCK" command
« on: August 11, 2020, 12:09:05 AM »
I wanted to achieve the following in LISP, relating to creating a block:
- Select elements.
- Choose a point (usually Endpoint for one of the lines).
- Once the point is selected, two things happen. (1) Elements are deleted (2) A block is inserted with anchor or base at previous chosen point. This is done all on one step, triggered by the chosen point.

The above is similar to the BLOCK command which converts elements into a block. But I prefer not to enter a name, just to use randomly generated name.

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16899
  • Superior Stupidity at its best
Re: LISP similar to "BLOCK" command
« Reply #1 on: August 11, 2020, 12:28:35 PM »
Something I wrote maybe 20 years ago to turn a selection set into an anonymous block

Code - Auto/Visual Lisp: [Select]
  1. (defun C:ANON()
  2.  (SETQ SSST (SSGET))
  3.  (SETQ ST (GETPOINT "\nInsertion point: "))
  4.    (LIST
  5.      (CONS 0 "BLOCK")
  6.      (CONS 2 "*U")
  7.      (CONS 10 ST)
  8.      (CONS 70 67)
  9.    )
  10.  )
  11.  (SETQ NDX 0)
  12.  (REPEAT (SSLENGTH SSST)
  13.   (ENTMAKE
  14.     (CDR (ENTGET (SSNAME SSST NDX)))
  15.   )
  16.   (SETQ NDX (+ 1 NDX))
  17.  )
  18.  (SETQ BKN(entmake (list (cons 0 "ENDBLK"))))
  19.  (SETQ EEE
  20.    (LIST
  21.      (CONS 0 "INSERT")
  22.      (CONS 2 BKN)
  23.      (CONS 6 (GETVAR "CELTYPE"))
  24.      (CONS 8 (GETVAR "CLAYER"))
  25.      (CONS 66 0)
  26.      (CONS 10 ST)
  27.      (CONS 41 1)
  28.      (CONS 42 1)
  29.      (CONS 43 1)
  30.      (CONS 50 (GETANGLE ST "\nRotation angle: "))
  31.      (CONS 71 0)
  32.      (CONS 44 0)
  33.      (CONS 45 0)
  34.    )
  35.   )
  36.  (ENTMAKE EEE
  37.  )
  38.  (COMMAND "_.ERASE" SSST "")
  39. )
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Find me on https://parler.com @kblackie

like_citrus

  • Newt
  • Posts: 114
Re: LISP similar to "BLOCK" command
« Reply #2 on: August 12, 2020, 12:54:58 AM »
Keith, this is what I was looking for. Thanks for sending.
If I want to remove the rotation angle input, can I just delete the line shown below? Or remove other portions as well?

Code: [Select]
(CONS 50 (GETANGLE ST "\nRotation angle: "))

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16899
  • Superior Stupidity at its best
Re: LISP similar to "BLOCK" command
« Reply #3 on: August 12, 2020, 01:02:41 AM »
I am not 100% sure you have to specify a rotation angle, but specifying 0 will not change the orientation of anything and it certainly won't hurt anything.

Change this:
Code - Auto/Visual Lisp: [Select]
  1. (CONS 50 (GETANGLE ST "\nRotation angle: "))
to this:
Code - Auto/Visual Lisp: [Select]
  1. (CONS 50 0.0)
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Find me on https://parler.com @kblackie

like_citrus

  • Newt
  • Posts: 114
Re: LISP similar to "BLOCK" command
« Reply #4 on: August 12, 2020, 05:34:01 AM »
This works as intended now. Thank you for the revised code.
I also wanted to know: Whilst looking at the block name "*U", a search suggests this is an anonymous block. How does this differ to blocks with names such as A$C0E547C8C? Do you know of a reference which could explain this?

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16899
  • Superior Stupidity at its best
Re: LISP similar to "BLOCK" command
« Reply #5 on: August 12, 2020, 08:34:12 AM »
I do not know of any particular reference that will explain it, but I will explain what I understand:

An anonymous block is not named, at least not in the classical sense. It is numbered in the block table and that is pretty much it. So for what that gets you, you cannot insert a block reference using the insert command. You can however, entmake one. Whenever you create an anonymous block, it is guaranteed to have a unique name (they are incremented numerically in the block table *U1, *U2, *U3 etc.)

When you have a block that is named with a random name as you have shown in your example, a block reference may be inserted using the insert command, I suppose you could also entmake the reference is you wanted.

The name as you have shown is a name just like any other named block. There is nothing materially different except the name is probably meaningless. It can be inserted and manipulated just like any block reference because it IS just a regular block reference, only with a weird name.

The added benefit of anonymous blocks is that if you create a single anonymous block in two drawings, both indexed at 1 (i.e. *U1) and you insert both base drawings into a third drawing, the anonymous blocks remain unique. On the other hand, if you create a block in one drawing named A$C0E547C8C and you create a block in another drawing named A$C0E547C8C with different geometry, then try to insert both of those base drawings into a new third drawing, the block named A$C0E547C8C will be redefined such that both instances in the third drawing will have identical geometry.

In essence so far as AutoCAD is concerned, *U1 does not equal *U1 if they come from different drawings, but A$C0E547C8C does equal A$C0E547C8C when from different drawings IF you try to put them both in the same drawing.

I hope this makes sense.
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Find me on https://parler.com @kblackie

ronjonp

  • Needs a day job
  • Posts: 7527
Re: LISP similar to "BLOCK" command
« Reply #6 on: August 12, 2020, 02:34:42 PM »
A$* blocks are generated using the paste as block option from the clipboard: CNTRL+SHIFT+V or PASTEBLOCK command.

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

like_citrus

  • Newt
  • Posts: 114
Re: LISP similar to "BLOCK" command
« Reply #7 on: August 12, 2020, 09:11:20 PM »
@Keith, thanks for the detailed explanation, it certainly helps.
Unfortunately it seems that the anonymous block can't be edited using the "Edit Block In-place" function.
Is there a way to turn the elements into a block of "A$*" type. I tried replacing "*U" with "A$*" in the code but noting happened.

Text in bottom window: Invalid block name.; error: bad DXF group: (2)
« Last Edit: August 12, 2020, 09:18:53 PM by like_citrus »

BIGAL

  • Swamp Rat
  • Posts: 1407
  • 40 + years of using Autocad
Re: LISP similar to "BLOCK" command
« Reply #8 on: August 12, 2020, 10:52:16 PM »
Why not give it  a proper name like random1 random2 etc can pretty easy check if exists already and x=x+1
A man who never made a mistake never made anything

like_citrus

  • Newt
  • Posts: 114
Re: LISP similar to "BLOCK" command
« Reply #9 on: August 13, 2020, 02:28:25 AM »
Quote
Why not give it  a proper name like random1 random2 etc
How could this be done?

ronjonp

  • Needs a day job
  • Posts: 7527
Re: LISP similar to "BLOCK" command
« Reply #10 on: August 13, 2020, 03:21:19 PM »
Quote
Why not give it  a proper name like random1 random2 etc
How could this be done?
Try this quick mod:
Code - Auto/Visual Lisp: [Select]
  1. (defun c:anon (/ bkn eee i ndx nm ssst st)
  2.   (if (and (setq ssst (ssget)) (setq st (getpoint "\nInsertion point: ")))
  3.     ;; RJP modified to generate a "Block-#" name
  4.     (progn (setq i -1)
  5.            (setq ndx 0)
  6.            (while (tblobjname "block" (setq nm (strcat "Block-" (itoa (setq i (1+ i)))))))
  7.            (entmake (list '(0 . "BLOCK")
  8.                           '(100 . "AcDbEntity")
  9.                           '(67 . 0)
  10.                           '(8 . "0")
  11.                           '(100 . "AcDbBlockReference")
  12.                           (cons 2 nm)
  13.                           (cons 10 st)
  14.                           '(70 . 0)
  15.                     )
  16.            )
  17.            (repeat (sslength ssst)
  18.              (entmake (cdr (entget (ssname ssst ndx))))
  19.              (entdel (ssname ssst ndx))
  20.              (setq ndx (+ 1 ndx))
  21.            )
  22.            (entmake '((0 . "ENDBLK") (100 . "AcDbBlockEnd") (8 . "0")))
  23.            (entmake (list (cons 0 "INSERT")
  24.                           (cons 2 nm)
  25.                           (cons 6 (getvar "CELTYPE"))
  26.                           (cons 8 (getvar "CLAYER"))
  27.                           (cons 66 0)
  28.                           (cons 10 st)
  29.                           (cons 41 1)
  30.                           (cons 42 1)
  31.                           (cons 43 1)
  32.                           (cons 50 0)
  33.                           (cons 71 0)
  34.                           (cons 44 0)
  35.                           (cons 45 0)
  36.                     )
  37.            )
  38.     )
  39.   )
  40.   (princ)
  41. )
« Last Edit: August 13, 2020, 11:47:28 PM by ronjonp »

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Re: LISP similar to "BLOCK" command
« Reply #11 on: August 13, 2020, 03:57:09 PM »
Note that with the proposed method, entget-entmake cloning, all associative relations between the selected objects will be lost.

like_citrus

  • Newt
  • Posts: 114
Re: LISP similar to "BLOCK" command
« Reply #12 on: August 13, 2020, 10:44:31 PM »
@ronjop, thanks very much this works very well. It could not delete the original elements for me, so replaced one of your lines with @Keith code, see below. Now it's all good.
@roy_043, what do you mean by "all associative relations between the selected objects will be lost"? Is it any different than if I was to Copy and Paste as Block as done normally, giving an $A* block?

This is more complicated than I originally thought.



Code: [Select]
; (mapcar 'entdel ssst)
; replaced with

(ENTMAKE EEE
)
(COMMAND "_.ERASE" SSST "")
)

ronjonp

  • Needs a day job
  • Posts: 7527
Re: LISP similar to "BLOCK" command
« Reply #13 on: August 13, 2020, 11:48:14 PM »
@ronjop, thanks very much this works very well. It could not delete the original elements for me, so replaced one of your lines with @Keith code, see below. Now it's all good.
@roy_043, what do you mean by "all associative relations between the selected objects will be lost"? Is it any different than if I was to Copy and Paste as Block as done normally, giving an $A* block?

This is more complicated than I originally thought.



Code: [Select]
; (mapcar 'entdel ssst)
; replaced with

(ENTMAKE EEE
)
(COMMAND "_.ERASE" SSST "")
)
Updated the code above to remove the items selected.

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

like_citrus

  • Newt
  • Posts: 114
Re: LISP similar to "BLOCK" command
« Reply #14 on: August 14, 2020, 12:05:16 AM »
Thank you again.