fit block in certain area

fit block in certain area

J-Rocks
Collaborator Collaborator
991 Views
15 Replies
Message 1 of 16

fit block in certain area

J-Rocks
Collaborator
Collaborator

Hello guys,

I am trying to fit a block in certain area based on the bounding Box ( width & Length ) of block into a certain area, I think I need to know how to get the XYZ scales of area which is the hardest part to me so far.

 

NOTE: I need to do the same process on other blocks and not necessarily the attached block.

Drawing attached.

Thank you.

0 Likes
Accepted solutions (1)
992 Views
15 Replies
Replies (15)
Message 2 of 16

jeltododre
Explorer
Explorer

This should get you started:

 

(defun c:foo ( / p1 p2 ob )
  
  (defun bboxcen ( o / mi ma )
    (vla-getboundingbox o 'mi 'ma)
    (mapcar '(lambda (x y) (/ (+ x y) 2)) (vlax-safearray->list mi) 
    (vlax-safearray->list ma))
  )
  
  (setq p1 (bboxcen (setq ob (vlax-ename->vla-object (car (entsel))))))
  (setq p2 (bboxcen (vlax-ename->vla-object (car (entsel)))))
  (vla-move ob p1 p2)
)
0 Likes
Message 3 of 16

J-Rocks
Collaborator
Collaborator

Why the program asks to select two objects ?

You may need to review the attached drawing.

0 Likes
Message 4 of 16

haper74945
Explorer
Explorer

First the block, then the green polyline ?

0 Likes
Message 5 of 16

Kent1Cooper
Consultant
Consultant

@J-Rocks wrote:

.... I need to know how to get the XYZ scales of area ....


This will give you the dimensions of the bounding box in all three axis directions:

 

(vla-getboundingbox (vlax-ename->vla-object TheEntityName) 'minpt 'maxpt)
(mapcar '- (vlax-safearray->list maxpt) (vlax-safearray->list minpt))

 

I was thinking in terms of the Block you want to put somewhere, but if you're talking about the size of the available area to put it in [the rectangle built from the two green edges with added red parts], in an orthogonal situation like that and with the green edges being one object, the same procedure will give you the dimensions of the area of that.  But will they always fit those conditions?

Kent Cooper, AIA
0 Likes
Message 6 of 16

J-Rocks
Collaborator
Collaborator

That is not the goal although the codes will not work because the coordinates have to be variant.

0 Likes
Message 7 of 16

J-Rocks
Collaborator
Collaborator

That is a very important point, the rotation is not all the time orthogonal but in general all cases currently are orthogonal.

Maybe select the area ( closed polyline ) then get the bounding box then set the scale factor of a block XYZ which is the hardest part for me which is how to do the calculation.

I have seen one routine by @ronjonp somewhere while searching but it did error due to divide on zero or so.

 

Thank you.  

0 Likes
Message 8 of 16

Kent1Cooper
Consultant
Consultant

If the idea is that the column Block is sized to fit the rectangular area, I think I can imagine a way to do this, BUT it would be essential that you redefine the Block so that  1)  at scale factors of 1 in all directions it is one drawing unit square, meaning that the available area's dimensions can be used directly as scale factors in its insertion, and  2)  its insertion point has some meaningful relation to its content [preferably either at the middle or at the lower left corner].

Kent Cooper, AIA
0 Likes
Message 9 of 16

J-Rocks
Collaborator
Collaborator

I don't think I can play with the blocks and if its up to me then I will convert the block to dynamic and add parameters for Length x Height and this should work perfectly.

0 Likes
Message 10 of 16

jeltododre
Explorer
Explorer

You want something like this?

Select a rectangular polyline for scale first, then the block to fit inside.

Keep in mind that something in the block from your sample drawing sticks out over the edges so the x scale will be a little off. There are also too many variables to make this work correctly for all cases (rotation, what is x or y scale, etc..)

 

(defun c:foo ( / o1 o2 ob en x y xn yn xblock yblock anx )
  
  (defun bbox ( o / mi ma )
    (vla-getboundingbox o 'mi 'ma)
    (list (vlax-safearray->list mi) (vlax-safearray->list ma))
  )
  
  (defun bboxcen ( o / mi ma )
    (vla-getboundingbox o 'mi 'ma)
    (mapcar '(lambda (x y) (/ (+ x y) 2)) (vlax-safearray->list mi) (vlax-safearray->list ma))
  )
  
  (setq o1 (mapcar 'cdr (vl-remove-if-not '(lambda (x) (eq (car x) 10)) (entget (setq en (car (entsel "Select Polyline: ")))))))
  (setq x (distance (car o1) (cadr o1)))
  (setq y (distance (cadr o1) (caddr o1)))
  (setq yn (min x y))
  (setq xn (max x y))
  (cond 
    ( (eq x xn)
      (setq anx (angle (car o1) (cadr o1)))
    )
    ( t (setq anx (angle (cadr o1 (caddr o1)))))
  )  
  (setq ob (vlax-ename->vla-object (car (entsel "Select Block: "))))
  (vla-put-rotation ob 0)
  (setq o2 (bbox ob))   
  (setq xblock (abs (- (caar o2) (caadr o2))))
  (setq yblock (abs (- (cadar o2) (cadr (cadr o2)))))
  (vla-put-xeffectivescalefactor ob (* (/ xn xblock) (vla-get-xeffectivescalefactor ob)))
  (vla-put-yeffectivescalefactor ob (* (/ yn yblock) (vla-get-yeffectivescalefactor ob)))
  (vla-rotate ob (bboxcen ob) anx)
  (vla-move ob (bboxcen ob) (bboxcen (vlax-ename->vla-object en)))
)

 

0 Likes
Message 11 of 16

J-Rocks
Collaborator
Collaborator

The code errors :

Command: foo Select Polyline: Select Block: ; error: lisp value has no coercion to VARIANT with this type: (58.8878 12.0748 0.0)

0 Likes
Message 12 of 16

jeltododre
Explorer
Explorer
Accepted solution

Hm.. works for me. Try this modification. move and rotate probably need a variant.

 

 

 

(defun c:foo ( / o1 o2 ob en x y xn yn xblock yblock anx )
  
  (defun bbox ( o / mi ma )
    (vla-getboundingbox o 'mi 'ma)
    (list (vlax-safearray->list mi) (vlax-safearray->list ma))
  )
  
  (defun bboxcen ( o / mi ma )
    (vla-getboundingbox o 'mi 'ma)
    (mapcar '(lambda (x y) (/ (+ x y) 2)) (vlax-safearray->list mi) (vlax-safearray->list ma))
  )
  
  (setq o1 (mapcar 'cdr (vl-remove-if-not '(lambda (x) (eq (car x) 10)) (entget (setq en (car (entsel "Select Polyline: ")))))))
  (setq x (distance (car o1) (cadr o1)))
  (setq y (distance (cadr o1) (caddr o1)))
  (setq yn (min x y))
  (setq xn (max x y))
  (cond 
    ( (eq x xn)
      (setq anx (angle (car o1) (cadr o1)))
    )
    ( t (setq anx (angle (cadr o1) (caddr o1))))
  )  
  (setq ob (vlax-ename->vla-object (car (entsel "Select Block: "))))
  (vla-put-rotation ob 0)
  (setq o2 (bbox ob))   
  (setq xblock (abs (- (caar o2) (caadr o2))))
  (setq yblock (abs (- (cadar o2) (cadr (cadr o2)))))
  (vla-put-xeffectivescalefactor ob (* (/ xn xblock) (vla-get-xeffectivescalefactor ob)))
  (vla-put-yeffectivescalefactor ob (* (/ yn yblock) (vla-get-yeffectivescalefactor ob)))
  (vla-rotate ob (vlax-3d-point (bboxcen ob)) anx)
  (vla-move ob (vlax-3d-point (bboxcen ob)) (vlax-3d-point (bboxcen (vlax-ename->vla-object en))))
)
Message 13 of 16

J-Rocks
Collaborator
Collaborator

Beautiful, thank you.

 

0 Likes
Message 14 of 16

ronjonp
Mentor
Mentor

@J-Rocks 

If you hit this line the code will error out:

 

( t (setq anx (angle (cadr o1 (caddr o1)))))

 

Maybe it's my OCD but you should really fix the insertion point of your block to something that makes more sense.

ronjonp_0-1686607898614.png

 

 

 

Message 15 of 16

marko_ribar
Advisor
Advisor

Here is my attempt and I think it's good one - just needed to redefine block from start...

 

(defun c:foooo ( / bbox bboxcen ss o1 o2 ob en x y xn yn xblock yblock an )

  (vl-load-com)

  (defun bbox ( o / mi ma )
    (vla-getboundingbox o 'mi 'ma)
    (list (vlax-safearray->list mi) (vlax-safearray->list ma))
  )

  (defun bboxcen ( o / mi ma )
    (vla-getboundingbox o 'mi 'ma)
    (mapcar '(lambda ( x y ) (/ (+ x y) 2.0)) (vlax-safearray->list mi) (vlax-safearray->list ma))
  )

  (setvar 'insunits 0)
  (setvar 'clayer "0")
  (setvar 'cecolor "ByLayer")
  (setq ss (ssadd))
  (vl-cmdf "_.rectangle" "_non" (list 0.0 0.0 0.0) "_non" (list 1.0 1.0 0.0))
  (ssadd (entlast) ss)
  (setvar 'cecolor "4")
  (vl-cmdf "_.text" "_j" "_mc" "_non" (list 0.5 0.5 0.0) 0.15 0.0 "Column")
  (setvar 'cecolor "3")
  (ssadd (entlast) ss)
  (vl-cmdf "_.-block" "rect" "_o" "_c" "_non" (list 0.0 0.0 0.0) ss "")
  (setq o1 (mapcar 'cdr (vl-remove-if '(lambda ( x ) (/= (car x) 10)) (entget (setq en (car (entsel "Select LWPolyline: ")))))))
  (setq x (distance (car o1) (cadr o1)))
  (setq y (distance (cadr o1) (caddr o1)))
  (setq yn (min x y))
  (setq xn (max x y))
  (cond 
    ( (and (= x xn) (= y yn))
      (setq an (angle (car o1) (cadr o1)))
    )
    ( t (setq an (angle (cadr o1) (caddr o1)))
    )
  )
  (vl-cmdf "_.zoom" "_c" (list 0.5 0.5 0.0) "2.0xp")
  (vl-cmdf "_.erase" ss "")
  (vl-cmdf "_.insert" "rect" "_non" (list 0.0 0.0 0.0))
  (while (< 0 (getvar 'cmdactive))
    (vl-cmdf "")
  )
  (setq ob (vlax-ename->vla-object (car (entsel "\nSelect Block: "))))
  (vl-cmdf "_.zoom" "_p")
  (vla-put-rotation ob 0.0)
  (vla-put-xeffectivescalefactor ob 1.0)
  (vla-put-yeffectivescalefactor ob 1.0)
  (vla-put-zeffectivescalefactor ob 1.0)
  (setq o2 (bbox ob))
  (if (and (= x xn) (= y yn))
    (progn
      (setq xblock (max (abs (- (caar o2) (caadr o2))) (abs (- (cadar o2) (cadr (cadr o2))))))
      (setq yblock (min (abs (- (caar o2) (caadr o2))) (abs (- (cadar o2) (cadr (cadr o2))))))
    )
    (progn
      (setq xblock (min (abs (- (caar o2) (caadr o2))) (abs (- (cadar o2) (cadr (cadr o2))))))
      (setq yblock (max (abs (- (caar o2) (caadr o2))) (abs (- (cadar o2) (cadr (cadr o2))))))
    )
  )
  (vla-put-xscalefactor ob (* (/ xn xblock) (vla-get-xscalefactor ob)))
  (vla-put-yscalefactor ob (* (/ yn yblock) (vla-get-yscalefactor ob)))
  (vla-put-zscalefactor ob 1.0)
  (vla-rotate ob (vlax-3d-point (bboxcen ob)) an)
  (vla-move ob (vlax-3d-point (bboxcen ob)) (vlax-3d-point (bboxcen (vlax-ename->vla-object en))))
  (princ)
)

 

Marko Ribar, d.i.a. (graduated engineer of architecture)
Message 16 of 16

jeltododre
Explorer
Explorer

Oops, thanks for pointing it out Ron. It's fixed now.

Not great coding, but I guess it does do the needful.

 

@marko_ribar

It gets stuck in a loop for me, trying to redefine a block..

 

edit: Just realized you copy pasted most of my shitty code. Hilarious

0 Likes