Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

The smallest rectangle enclosing selected set of objects

22 REPLIES 22
SOLVED
Reply
Message 1 of 23
aqdam1978
9120 Views, 22 Replies

The smallest rectangle enclosing selected set of objects

Hi,

 

How can I draw a The smallest rectangle enclosing for a selected set of objects in current drawing?

 

Does anybody has a solution?

 

Thanks.

 

 

 

22 REPLIES 22
Message 2 of 23
Kent1Cooper
in reply to: aqdam1978

Try a Search.  I put "smallest rectangle" into the Search window and not too far down the resulting list found this, which seems to do something like what you're asking [plus dimensioning the rectangle], at Message 19 where it gets to multiple objects [it's about single objects earlier on].  But there are many more threads to check, and there may be something exactly on your topic.

 

But a question:  Do you want the smallest orthogonally-oriented rectangle, or the smallest rectangle at any angle?  That question is discussed on some other threads returned by the Search.

Kent Cooper, AIA
Message 3 of 23
Kent1Cooper
in reply to: aqdam1978


@aqdam1978 wrote:

.... 

How can I draw a The smallest rectangle enclosing for a selected set of objects in current drawing?

.... 


But in simplest terms, if you want the smallest orthogonally-oriented rectangle [lightly tested]:

 

;;  SmallestRectangle.lsp [command name: SR]
;;  To draw the Smallest orthogonal Rectangle around a User-
;;    selected group of objects.  Draws on the current Layer.
;;  Kent Cooper, 27 February 2013
(defun C:SR (/ obb oLL oUR ss LL UR); = Smallest Rectangle
  (defun obb (ent); = Object's Bounding Box corners
    (vla-getboundingbox (vlax-ename->vla-object ent) 'minpt 'maxpt)
    (setq
      oLL (vlax-safearray->list minpt); Object's Lower Left
      oUR (vlax-safearray->list maxpt); Object's Upper Right
    ); setq
  ); defun -- obb
  (vl-load-com)
  (prompt "\nTo draw the Smallest Rectangle around them,")
  (setq ss (ssget))
  (obb (ssname ss 0))
  (setq LL oLL UR oUR); initial overall LL & UR [of first object]
  (ssdel (ssname ss 0) ss)
  (repeat (sslength ss)
    (obb (ssname ss 0))
    (setq
      LL (mapcar 'min oLL LL); least of each component
      UR (mapcar 'max oUR UR); greatest of each component
    ); setq
    (ssdel (ssname ss 0) ss)
  ); repeat
  (command "_.rectangle" "_none" LL "_none" UR)
  (princ)
); defun -- C:SR

 

Kent Cooper, AIA
Message 4 of 23
aqdam1978
in reply to: Kent1Cooper

Hi Kent,

 

This is an amazing lisp program, great code!

 

Thank you so much,

 

Abbas

 

Message 5 of 23
Kent1Cooper
in reply to: aqdam1978


@aqdam1978 wrote:

....

This is an amazing lisp program, great code!

Thank you so much,

....


You're welcome [I'm not sure about amazing, but....].  It doesn't account for several things that might be of concern to some people [things drawn in different coordinate systems and their potential effect on the 3rd dimension and the resulting elevation of the Rectangle, etc.], but for many, I assume it will do.

 

 One thing to be aware of is that if, by any chance, any of the objects selected are Mtext, the bounding box for that goes to its defined "window" width, which can be [and, more often than not, is] wider than the actual textual content is -- it doesn't go to the extent of the characters themselves [unless they happen to exactly fill that defined width].  If that should be an issue, there are threads on the Discussion Group about paring down Mtext's defined width to match its actual content.

Kent Cooper, AIA
Message 6 of 23
marko_ribar
in reply to: Kent1Cooper

The problem are also bounding boxes of SPLINE objects...

Don't know if Autodesk solved this issue with A2013... It only remains to us to wait and see...

 

M.R.

Marko Ribar, d.i.a. (graduated engineer of architecture)
Message 7 of 23
Kent1Cooper
in reply to: marko_ribar


@marko_ribar wrote:

The problem are also bounding boxes of SPLINE objects...

....


True -- I so rarely use Splines that I don't always have them in mind when trying things out, but sometimes their bounding boxes are bigger than their visible selves.  They seem to be influenced by their control points, which don't show as grips when a Spline as originally drawn is selected [i.e. that hasn't been broken, or that isn't the result of something like Offsetting an Ellipse].  The fit points are what show, but you can see where the control points are by stepping through them in the Properties box.  But the bounding box doesn't always extend all the way out to encompass all the control points on more irregularly shaped Splines.  Yet it seems to work as you would expect on simpler ones [e.g. again, one that's from Offsetting an Ellipse].  It's all a mystery....

Kent Cooper, AIA
Message 8 of 23
Kent1Cooper
in reply to: Kent1Cooper


@Kent1Cooper wrote:

....Do you want the smallest orthogonally-oriented rectangle, or the smallest rectangle at any angle? ....


I played around with that -- check out the attached SmallestRectangle.lsp and its SR command.  It finds the smallest rectangle at any angle [in 1-degree increments, though you can set that differently].  I thought maybe one could rotate the UCS and test bounding-box extents, but that didn't work because they still come back in WCS terms.  So the routine pastes the selection in at each rotation increment, and checks whether the resulting bounding box is smaller than before, and if so, replaces the former rectangle and orients the new one relative to the original selection.  [It's actually kind of fun to watch it do its thing!]

Kent Cooper, AIA
Message 9 of 23
Rikkes
in reply to: Kent1Cooper

Hi! I use your lsp for a while now and I tried to add a feature but it doesn't work.

 

Would it be possible to draw the rectangle with an offset of 2.5mm on each side? That would be very usefull for me. Or perhaps with a prompt that asks for the amount of offset (normal 2.5)?

 

Thx!

 

Eric

 

Message 10 of 23
Lee_Mac
in reply to: Rikkes

Try the following Eric:

 

(defun c:test ( / box off sel )
    (if (null bbox:offset)
        (setq bbox:offset 2.5)
    )
    (if (null (setq off (getdist (strcat "\nSpecify offset <" (rtos bbox:offset) ">: "))))
        (setq off bbox:offset)
        (setq bbox:offset off)
    )    
    (if (and (setq sel (ssget))
             (setq box (LM:ssboundingbox sel))
        )
        (entmake
            (list
               '(000 . "LWPOLYLINE")
               '(100 . "AcDbEntity")
               '(100 . "AcDbPolyline")
               '(090 . 4)
               '(070 . 1)
                (list 10 (- (caar  box) off) (- (cadar  box) off))
                (list 10 (+ (caadr box) off) (- (cadar  box) off))
                (list 10 (+ (caadr box) off) (+ (cadadr box) off))
                (list 10 (- (caar  box) off) (+ (cadadr box) off))
            )
        )
    )
    (princ)
)

;; Selection Set Bounding Box  -  Lee Mac
;; Returns the lower-left and upper-right WCS points of a rectangle
;; bounding all objects in a supplied selection set

(defun LM:ssboundingbox ( ss / i l1 l2 ll ur )
    (repeat (setq i (sslength ss))
        (vla-getboundingbox (vlax-ename->vla-object (ssname ss (setq i (1- i)))) 'll 'ur)
        (setq l1 (cons (vlax-safearray->list ll) l1)
              l2 (cons (vlax-safearray->list ur) l2)
        )
    )
    (mapcar '(lambda ( a b ) (apply 'mapcar (cons a b))) '(min max) (list l1 l2))
)
(vl-load-com) (princ)
Message 11 of 23
Rikkes
in reply to: Lee_Mac

I don't quit get it... Do I have to add some lines of your program to the existing lsp file? 

Message 12 of 23
Rikkes
in reply to: Lee_Mac

Sorry for the delay but is it also possible to roundup the size of the rectangle? For example: if the enclosinbg rectangle turns out to be 211.35 x 500.1236 , it should be nice that it becomes 212 x 1237mm. Capice?

 

 

Message 13 of 23
Lee_Mac
in reply to: Rikkes


@Rikkes wrote:

I don't quit get it... Do I have to add some lines of your program to the existing lsp file? 


No, my program is independent of any previously posted code, simply save the code to a LISP file and run the program as you would any other LISP program.

Message 14 of 23
Kent1Cooper
in reply to: Rikkes


@Rikkes wrote:

.... 

Would it be possible to draw the rectangle with an offset of 2.5mm on each side? That would be very usefull for me. Or perhaps with a prompt that asks for the amount of offset (normal 2.5)?

.... 


For the fixed-value version, and assuming a millimeter is a drawing unit, add this after the end of the (repeat) function, before the closing-out things:

 

(vla-offset (vlax-ename->vla-object rect) 2.5)

(entdel rect); optional

 

You can prompt for an offset distance earlier on [lots of examples in this Forum -- Search for (getdist) functions], save it in a variable, and use the variable name in place of the 2.5.

Kent Cooper, AIA
Message 15 of 23
Kent1Cooper
in reply to: Kent1Cooper


@Kent1Cooper wrote:

@Rikkes wrote:

.... 

Would it be possible to draw the rectangle with an offset of 2.5mm on each side? .... 


.... 

(vla-offset (vlax-ename->vla-object rect) 2.5)

(entdel rect); optional

....


[That was assuming you were talking about the smallest-at-any-angle rectangle routine, not the smallest orthogonal rectangle routine, which doesn't have its result in the rect variable.  For the orthogonal one, substitute (entlast) in place of rect in the above.]

Kent Cooper, AIA
Message 16 of 23
Kent1Cooper
in reply to: Kent1Cooper


@Kent1Cooper wrote:

@Kent1Cooper wrote:

@Rikkes wrote:

.... 

Would it be possible to draw the rectangle with an offset of 2.5mm on each side? .... 


.... 

(vla-offset (vlax-ename->vla-object rect) 2.5)

(entdel rect); optional

....


[....  For the orthogonal one, substitute (entlast) in place of rect in the above.]


No, actually, don't do that if you're deleting the original [it will delete the newer outboard rectangle instead of the older inner one].  In that case substitute (entlast) for rect only in the (vla-offset) function.  If you want to get rid of the initial rectangle, you would need to save it to a variable before offsetting, and delete that rather than (entlast), essentially duplicating what the at-any-angle routine does:

....

(setq rect (entlast))

(vla-offset (vlax-ename->vla-object rect) 2.5); or (entlast) instead

(entdel rect); optional

....

Kent Cooper, AIA
Message 17 of 23
Kent1Cooper
in reply to: Rikkes


@Rikkes wrote:

...is it also possible to roundup the size of the rectangle? For example: if the enclosinbg rectangle turns out to be 211.35 x 500.1236 , it should be nice that it becomes 212 x 1237mm. Capice?


[I assume you mean 212 x 501.  And (beside the point, but...) that you mean Capisce (as here).]

 

That's certainly possible.  Would you want the rounded-up rectangle centered around the objects, or could two of the edges touch them?  Would you want rounding up combined with the offsetting in your other question?  Would you want it for the at-any-angle smallest rectangle or just the orthogonal one?

Kent Cooper, AIA
Message 18 of 23
Lee_Mac
in reply to: Rikkes


@Rikkes wrote:

Sorry for the delay but is it also possible to roundup the size of the rectangle? For example: if the enclosinbg rectangle turns out to be 211.35 x 500.1236 , it should be nice that it becomes 212 x 1237mm. Capice?


Try the following code:

 

(defun c:test ( / box hgt off ofh ofv sel wid )
    (if (null bbox:offset)
        (setq bbox:offset 2.5)
    )
    (if (null (setq off (getdist (strcat "\nSpecify offset <" (rtos bbox:offset) ">: "))))
        (setq off bbox:offset)
        (setq bbox:offset off)
    )    
    (if (and (setq sel (ssget))
             (setq box (LM:ssboundingbox sel))
        )
        (progn
            (setq wid (- (caadr  box) (caar  box))
                  hgt (- (cadadr box) (cadar box))
                  ofh (+ off (/ (- (LM:roundup wid 1.0) wid) 2.0))
                  ofv (+ off (/ (- (LM:roundup hgt 1.0) hgt) 2.0))
            )
            (entmake
                (list
                   '(000 . "LWPOLYLINE")
                   '(100 . "AcDbEntity")
                   '(100 . "AcDbPolyline")
                   '(090 . 4)
                   '(070 . 1)
                    (list 10 (- (caar  box) ofh) (- (cadar  box) ofv))
                    (list 10 (+ (caadr box) ofh) (- (cadar  box) ofv))
                    (list 10 (+ (caadr box) ofh) (+ (cadadr box) ofv))
                    (list 10 (- (caar  box) ofh) (+ (cadadr box) ofv))
                )
            )
        )
    )
    (princ)
)

;; Selection Set Bounding Box  -  Lee Mac
;; Returns the lower-left and upper-right WCS points of a rectangle
;; bounding all objects in a supplied selection set

(defun LM:ssboundingbox ( ss / i l1 l2 ll ur )
    (repeat (setq i (sslength ss))
        (vla-getboundingbox (vlax-ename->vla-object (ssname ss (setq i (1- i)))) 'll 'ur)
        (setq l1 (cons (vlax-safearray->list ll) l1)
              l2 (cons (vlax-safearray->list ur) l2)
        )
    )
    (mapcar '(lambda ( a b ) (apply 'mapcar (cons a b))) '(min max) (list l1 l2))
)

;; Round Up  -  Lee Mac
;; Rounds 'n' up to the nearest 'm'

(defun LM:roundup ( n m )
    (cond
        ((equal 0.0 (rem n m) 1e-8) n)
        ((< n 0) (- n (rem n m)))
        ((+ n (- m (rem n m))))
    )
)

(vl-load-com) (princ)

 

If you were instead looking for the smallest rectangle bounding the set of objects, consider my Minimum Bounding Box function.

 

Lee

Message 19 of 23
Rikkes
in reply to: Lee_Mac

THAT'S IT !!!

 

Thx Pal!!!

Message 20 of 23
Lee_Mac
in reply to: Rikkes

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost