Lisp to Fix Block scale

Lisp to Fix Block scale

arpansark0544TCX
Advocate Advocate
866 Views
13 Replies
Message 1 of 14

Lisp to Fix Block scale

arpansark0544TCX
Advocate
Advocate

Dear All,

 

I am working on a code which can remove the scale factor from the block and make it 1,1,1. 

For this, I have taken the following method 

Used the scale factor of the block and then scaled the content of the block taking base point of the block as reference.(As to avoid shifting of the blocks)

 

Then reset the block scale factor to 1,1,1 for x , y , z.

 

The problem I am facing :

 

The code is correctly scaling the block, But the code is unable to correctly detect the base point of the block. And the block gets shifted from its location.

 

Help Need:

 Kindly help to fix the  code such that the block does not move from its location.

 

 

 

 

 

(defun c:FixBlocksScale_v2 (/ ss ent scX scY scZ insertionPoint scaleFactor)
  ;; Prompt the user to select block references
  (setq ss (ssget '((0 . "INSERT"))))  ;; Filter only block references (INSERT entities)

  ;; If selection is not empty, proceed
  (if ss
    (progn
      ;; Loop through all selected blocks
      (setq i 0)
      (while (< i (sslength ss))
        ;; Get the current block reference
        (setq ent (ssname ss i))

        ;; Get the current X, Y, Z scale factors
        (setq scX (cdr (assoc 41 (entget ent))))
        (setq scY (cdr (assoc 42 (entget ent))))
        (setq scZ (cdr (assoc 43 (entget ent))))

        ;; Get the insertion point of the block
        (setq insertionPoint (cdr (assoc 10 (entget ent))))

        ;; Apply scaling to the block's contents using the current scale factor
        (progn
          ;; Store the current uniform scale factor (use X scale factor)
          (setq scaleFactor scX)

          ;; Scale the contents of the block
          (command "BEDIT" (cdr (assoc 2 (entget ent)))) ;; Open block editor
          (command "ZOOM" "E") ;; Zoom to extents in block editor
          (command "SCALE" "ALL" "" insertionPoint scaleFactor) ;; Scale all objects
          (command "BCLOSE" "SAVE") ;; Close and save block editor changes

          ;; Reset the block scale factor to 1,1,1 for X, Y, Z
          (entmod (subst (cons 41 1.0) (assoc 41 (entget ent)) (entget ent))) ;; X scale to 1
          (entmod (subst (cons 42 1.0) (assoc 42 (entget ent)) (entget ent))) ;; Y scale to 1
          (entmod (subst (cons 43 1.0) (assoc 43 (entget ent)) (entget ent))) ;; Z scale to 1

          ;; Update the block entity in the drawing
          (entupd ent)
        )

        ;; Move to the next block in the selection set
        (setq i (1+ i))
      )
      (prompt "\nAll selected blocks processed.")
    )
    (prompt "\nNo blocks were selected.")
  )
  (princ)
)

 

;; Open the block definition to get the base point
        (setq blockName (cdr (assoc 2 (entget ent))))
        (setq blockDef (tblsearch "BLOCK" blockName))

        ;; Retrieve the base point from the block definition
        (setq basePoint (cdr (assoc 10 blockDef))) ;; Assuming the base point is stored as 10

        ;; Open the block editor and scale the contents using the base point
        (command "BEDIT" blockName) ;; Open block editor
        (command "ZOOM" "E") ;; Zoom to extents in block editor

        ;; Select all objects in the block
        (command "SELECTALL")

        ;; Scale using base point and the current scale factors
        (command "SCALE" "P" "" basePoint scX) ;; Scale using the X scale factor

        (command "BCLOSE" "SAVE") ;; Close and save block editor changes

 

I used this part of this code to detect the basepoint of the block in the block.

But there was no luck.

 

0 Likes
867 Views
13 Replies
Replies (13)
Message 2 of 14

Moshe-A
Mentor
Mentor

@arpansark0544TCX  hi,

 

Do not enter the block definition to scale it's content, cause this drags the update of all the block references (inserts)

only modify the block references scale.

 

Scaling the content of block definition changes the relation (distance) between the base point and the content, that's why you are thinking the insertion base point is changing (it is not)

 

Moshe

 

0 Likes
Message 3 of 14

arpansark0544TCX
Advocate
Advocate
You are correct. But as a standard, we all put the base points at the corner or centre. In the drawing attached, for simplicity, I have used a circle and a base point at the circle's centre. So, the code should detect that base point and scale the content of the Block.
0 Likes
Message 4 of 14

Moshe-A
Mentor
Mentor

@arpansark0544TCX ,

 

inside the block definition the base point is at 0,0,0

 

0 Likes
Message 5 of 14

Kent1Cooper
Consultant
Consultant

I would not use a SCALE command, but rather change the insertion's entity data to make all its scale factors 1 [or -1].  That will eliminate any need to find the insertion base point, which will stay where it is.  It can also be done with

(setpropertyvalue theEntityName "ScaleFactors" '(1 1 1))

except that it [or the entity data approach] should get more sophisticated and check for negative current scale factors for Mirrored Blocks.

Kent Cooper, AIA
Message 6 of 14

ronjonp
Mentor
Mentor

Maybe this?

(defun c:foo (/ s)
  (if (setq s (ssget ":L" '((0 . "INSERT"))))
    (foreach e (vl-remove-if 'listp (mapcar 'cadr (ssnamex s)))
      (entmod (append (entget e) '((41 . 1) (42 . 1) (43 . 1))))
    )
  )
  (princ)
)
0 Likes
Message 7 of 14

arpansark0544TCX
Advocate
Advocate
Dear Sir,
I checked you code. It simpli remove the scale from all the blocks making them return to there original size.
Let say for an example. I have a block with circle in it. Originally the dia of the circle is 10. Now this block is scale to make the dia 100. So we get the scale factor of 10.
What is the code suppose to do is to retain the block current size (dia 100) . By making the inside of the block scale up to 10 times. And then rescaling the block to 1,1,1.

I have made a video and attached he same in above message.

If any further input is need do let me know.
0 Likes
Message 8 of 14

arpansark0544TCX
Advocate
Advocate

In This version i tried to used Referedit. to avoid going into block editor. but no luck yet. But in the process I added some basic checks to perform before moving onto  the main code.

 

(defun c:FixBlocksScale_v2v17 (/ ss ent scX scY scZ blockName)
  ;; Prompt the user to select block references
  (setq ss (ssget '((0 . "INSERT"))))  ;; Filter only block references (INSERT entities)

  ;; If selection is not empty, proceed
  (if ss
    (progn
      ;; Loop through all selected blocks
      (setq i 0)
      (while (< i (sslength ss))
        ;; Get the current block reference
        (setq ent (ssname ss i))

        ;; Get the current X, Y, Z scale factors
        (setq scX (cdr (assoc 41 (entget ent))))
        (setq scY (cdr (assoc 42 (entget ent))))
        (setq scZ (cdr (assoc 43 (entget ent))))

        ;; Check if the scale factor is different from 1.0
        (if (or (/= scX 1.0) (/= scY 1.0) (/= scZ 1.0))
          (progn
            ;; Store the current block name
            (setq blockName (cdr (assoc 2 (entget ent))))

            ;; Reset the block's scale factors to 1,1,1 in model space
            (entmod (subst (cons 41 1.0) (assoc 41 (entget ent)) (entget ent))) ;; Reset X scale
            (entmod (subst (cons 42 1.0) (assoc 42 (entget ent)) (entget ent))) ;; Reset Y scale
            (entmod (subst (cons 43 1.0) (assoc 43 (entget ent)) (entget ent))) ;; Reset Z scale

            ;; Update the block entity in model space
            (entupd ent)

            ;; Use REFEDIT to edit the block reference
            (command "_.REFEDIT" ent) ;; Start REFEDIT on the current block reference
            (command "ZOOM" "E") ;; Zoom to extents within the block

            ;; Scale the block contents using the original scale factors
            (command "SCALE" "ALL" "" '(0 0 0) scX scY scZ)

            ;; End the REFEDIT session and save the changes
            (command "REFCLOSE" "Y") ;; Save changes made in REFEDIT

            ;; Notify the user of successful processing
            (prompt (strcat "\nBlock '" blockName "' scaled and reset to (1,1,1)."))
          )
          (prompt (strcat "\nBlock '" blockName "' skipped: Scale is already 1,1,1."))
        )

        ;; Clear the variables to avoid lingering values
        (setq scX nil scY nil scZ nil blockName nil)

        ;; Move to the next block in the selection set
        (setq i (1+ i))
      )
      (prompt "\nAll selected blocks processed.")
    )
    (prompt "\nNo blocks were selected.")
  )
  (princ)
)

 

 

0 Likes
Message 9 of 14

-didier-
Advisor
Advisor

Bonjour @arpansark0544TCX 

 

In the first post (10-10-2024 02:26 PM)

The line highlighted in red is wrong, replace it with the green line

Snag_8bcdc3b.png

 

Because, in the block editor the insertion point is (0 0 0)

I think it will fix your problem.

 

Amicalement

Éternel débutant.. my site for learning : Programmer dans AutoCAD

DA

EESignature

0 Likes
Message 10 of 14

Kent1Cooper
Consultant
Consultant

@arpansark0544TCX wrote:
.... I have a block with circle in it. Originally the dia of the circle is 10. Now this block is scale to make the dia 100. So we get the scale factor of 10.
What is the code suppose to do is to retain the block current size (dia 100) . By making the inside of the block scale up to 10 times. And then rescaling the block to 1,1,1......

I misunderstood what you wanted before.  But from this description, a big question arises:  Do you ever have more than one of the same Block inserted ?  If you do what you describe, every Block of that name will get ten times as big as it was before, including those that were scaled just like the one you operate on, -- those will all keep their scale factor of 10 and so become 10 times as big as that one.  Is that the intent?  Or should the new Block definition be given a new Block name to prevent that?

 

I think the easier way to do this would be not to scale elements in the Block definition, but simply to Explode the Block and then redefine it [whether or not you use the same name] using the pieces resulting, which will turn their scale-factor-of-one size into what it was in the other-than-one-scaled source Block.  But then there's the question of unequal scale factors, and also the question of non-zero rotation.

Kent Cooper, AIA
0 Likes
Message 11 of 14

ronjonp
Mentor
Mentor

@arpansark0544TCX 

You should post a drawing with all your elements. The purpose of a block is to have one definition with the same elements within it. Your sample drawing has 3 block definitions (01 02 03) with the same elements within which defeats the purpose of having a block.

 

This seems to work with your sample drawing. Be aware that the 'X' scale used is only grabbed from the first instance of the block found. If it's like your example drawing then it should be ok .. but then you might as well explode everything and not mess with this scaling. : )

 

 

(defun c:foo (/ blks bn el s scl)
  (setq blks (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object))))
  (if (setq s (ssget ":L" '((0 . "INSERT"))))
    (foreach e (vl-remove-if 'listp (mapcar 'cadr (ssnamex s)))
      (setq scl (cdr (assoc 41 (setq el (entget e)))))
      (setq bn (cons (cdr (assoc 2 el)) bn))
      (or (member (car bn) (cdr bn))
	  (vlax-for i (vla-item blks (car bn)) (vlax-invoke i 'scaleentity '(0. 0. 0.) scl))
      )
      (entmod (append el '((41 . 1) (42 . 1) (43 . 1))))
    )
  )
  (princ)
)

 

 

2024-10-11_14-43-01.gif

0 Likes
Message 12 of 14

arpansark0544TCX
Advocate
Advocate
Sorry for the delayed response. As it was a holiday here in India.
Sure, let me try it out. I will let you know.
0 Likes
Message 13 of 14

arpansark0544TCX
Advocate
Advocate
Do you ever have more than one of the same Block inserted - Yes there are multiple blocks of same name and all have same scale factor.
If you do what you describe, every Block of that name will get ten times as big as it was before, including those that were scaled just like the one you operate on, -- those will all keep their scale factor of 10 and so become 10 times as big as that one. Is that the intent? - Yes
0 Likes
Message 14 of 14

arpansark0544TCX
Advocate
Advocate
Sorry for the confusion. But there will be multiple blocks of multiple scale factors in the whole drawing. I just put these three to make the requirements.
0 Likes