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.
Solved! Go to Solution.
Solved by Kent1Cooper. Go to Solution.
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.
@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
Hi Kent,
This is an amazing lisp program, great code!
Thank you so much,
Abbas
@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.
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 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....
@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!]
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
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)
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?
@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.
@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.
@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.]
@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
....
@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?
@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
Can't find what you're looking for? Ask the community or share your knowledge.