Here are 2 lisp I had in mind... :
First one for WCS bounding box(es) :
(defun c:bboxpolygon ( / pl p1 p2 p3 p4 r1 r2 r3 r4 )
(setq pl (mapcar 'cdr (mapcar (function (lambda ( x ) (append x (list 0.0)))) (vl-remove-if (function (lambda ( x ) (/= (car x) 10))) (entget (car (entsel "\nPick closed POLYGON...")))))))
(setq p1 (car (vl-sort pl (function (lambda ( a b ) (< (cadr a) (cadr b)))))))
(setq p2 (car (vl-sort pl (function (lambda ( a b ) (< (car a) (car b)))))))
(setq p3 (car (vl-sort pl (function (lambda ( a b ) (> (car a) (car b)))))))
(setq p4 (car (vl-sort pl (function (lambda ( a b ) (> (cadr a) (cadr b)))))))
(setq r1 (inters p1 (polar p1 0.0 1.0) p2 (polar p2 (* 0.5 pi) 1.0) nil))
(setq r2 (inters p1 (polar p1 0.0 1.0) p3 (polar p3 (* 0.5 pi) 1.0) nil))
(setq r3 (inters r1 (polar r1 (* 0.5 pi) 1.0) p4 (polar p4 0.0 1.0) nil))
(setq r4 (inters r2 (polar r2 (* 0.5 pi) 1.0) p4 (polar p4 0.0 1.0) nil))
(entmake
(list
'(0 . "LWPOLYLINE")
'(100 . "AcDbEntity")
'(100 . "AcDbPolyline")
'(90 . 4)
(cons 70 (1+ (* 128 (getvar 'plinegen))))
'(38 . 0.0)
(cons 10 r1)
(cons 10 r2)
(cons 10 r4)
(cons 10 r3)
'(210 0.0 0.0 1.0)
'(62 . 3)
)
)
(prompt "\nArea : ") (princ (rtos (* (distance r1 r2) (distance r1 r3)) 2 20))
(princ)
)
(defun c:bboxpolygons ( / ss i pl p1 p2 p3 p4 r1 r2 r3 r4 )
(prompt "\nSelect closed POLYGONS...")
(setq ss (ssget (list '(0 . "LWPOLYLINE") '(-4 . "&=") '(70 . 1) '(-4 . "<not") '(-4 . "<>") '(42 . 0.0) '(-4 . "not>"))))
(if ss
(repeat (setq i (sslength ss))
(setq pl (mapcar 'cdr (mapcar (function (lambda ( x ) (append x (list 0.0)))) (vl-remove-if (function (lambda ( x ) (/= (car x) 10))) (entget (ssname ss (setq i (1- i))))))))
(setq p1 (car (vl-sort pl (function (lambda ( a b ) (< (cadr a) (cadr b)))))))
(setq p2 (car (vl-sort pl (function (lambda ( a b ) (< (car a) (car b)))))))
(setq p3 (car (vl-sort pl (function (lambda ( a b ) (> (car a) (car b)))))))
(setq p4 (car (vl-sort pl (function (lambda ( a b ) (> (cadr a) (cadr b)))))))
(setq r1 (inters p1 (polar p1 0.0 1.0) p2 (polar p2 (* 0.5 pi) 1.0) nil))
(setq r2 (inters p1 (polar p1 0.0 1.0) p3 (polar p3 (* 0.5 pi) 1.0) nil))
(setq r3 (inters r1 (polar r1 (* 0.5 pi) 1.0) p4 (polar p4 0.0 1.0) nil))
(setq r4 (inters r2 (polar r2 (* 0.5 pi) 1.0) p4 (polar p4 0.0 1.0) nil))
(entmake
(list
'(0 . "LWPOLYLINE")
'(100 . "AcDbEntity")
'(100 . "AcDbPolyline")
'(90 . 4)
(cons 70 (1+ (* 128 (getvar 'plinegen))))
'(38 . 0.0)
(cons 10 r1)
(cons 10 r2)
(cons 10 r4)
(cons 10 r3)
'(210 0.0 0.0 1.0)
'(62 . 3)
)
)
)
)
(princ)
)
(defun c:bboxpolygons-global ( / ss i pl pll p1 p2 p3 p4 r1 r2 r3 r4 )
(prompt "\nSelect closed POLYGONS...")
(setq ss (ssget (list '(0 . "LWPOLYLINE") '(-4 . "&=") '(70 . 1) '(-4 . "<not") '(-4 . "<>") '(42 . 0.0) '(-4 . "not>"))))
(if ss
(repeat (setq i (sslength ss))
(setq pl (mapcar 'cdr (mapcar (function (lambda ( x ) (append x (list 0.0)))) (vl-remove-if (function (lambda ( x ) (/= (car x) 10))) (entget (ssname ss (setq i (1- i))))))))
(setq pll (append pl pll))
)
)
(if pll
(progn
(setq p1 (car (vl-sort pll (function (lambda ( a b ) (< (cadr a) (cadr b)))))))
(setq p2 (car (vl-sort pll (function (lambda ( a b ) (< (car a) (car b)))))))
(setq p3 (car (vl-sort pll (function (lambda ( a b ) (> (car a) (car b)))))))
(setq p4 (car (vl-sort pll (function (lambda ( a b ) (> (cadr a) (cadr b)))))))
(setq r1 (inters p1 (polar p1 0.0 1.0) p2 (polar p2 (* 0.5 pi) 1.0) nil))
(setq r2 (inters p1 (polar p1 0.0 1.0) p3 (polar p3 (* 0.5 pi) 1.0) nil))
(setq r3 (inters r1 (polar r1 (* 0.5 pi) 1.0) p4 (polar p4 0.0 1.0) nil))
(setq r4 (inters r2 (polar r2 (* 0.5 pi) 1.0) p4 (polar p4 0.0 1.0) nil))
(entmake
(list
'(0 . "LWPOLYLINE")
'(100 . "AcDbEntity")
'(100 . "AcDbPolyline")
'(90 . 4)
(cons 70 (1+ (* 128 (getvar 'plinegen))))
'(38 . 0.0)
(cons 10 r1)
(cons 10 r2)
(cons 10 r4)
(cons 10 r3)
'(210 0.0 0.0 1.0)
'(62 . 3)
)
)
(prompt "\nArea global : ") (princ (rtos (* (distance r1 r2) (distance r1 r3)) 2 20))
)
)
(princ)
)
(prompt "\nInvoke with : (c:bboxpolygon) for single closed POLYGON input, or with : (C:bboxpolygons) for multiple closed POLYGONS input, or with : (C:bboxpolygons-global) for multiple closed POLYGONS input and single bbox output...")
(princ)
The second one is for calculation of minimal bounding box(es) :
; transptucs & transptwcs by M.R. (Marko Ribar, d.i.a.)
; arguments :
; pt - point to be transformed from WCS to imaginary UCS with transptucs and from imaginary UCS to WCS with transptwcs
; pt1 - origin of imaginary UCS
; pt2 - point to define X axis of imaginary UCS (vector pt1-pt2 represents X axis)
; pt3 - point to define Y axis of imaginary UCS (vector pt1-pt3 represents Y axis)
; important note : angle between X and Y axises of imaginary UCS must always be 90 degree for correct transformation calculation
;; Unit Vector - M.R.
;; Args: v - vector in R^n
(defun unit ( v / d )
(mapcar '(lambda ( x y ) (/ x y)) v (list (setq d (distance '(0.0 0.0 0.0) v)) d d))
)
;; Matrix x Vector - Vladimir Nesterovsky
;; Args: m - nxn matrix, v - vector in R^n
(defun mxv ( m v )
(mapcar '(lambda ( r ) (apply '+ (mapcar '* r v))) m)
)
;; Vector Cross Product - Lee Mac
;; Args: u,v - vectors in R^3
(defun v^v ( u v )
(list
(- (* (cadr u) (caddr v)) (* (caddr u) (cadr v)))
(- (* (caddr u) (car v)) (* (car u) (caddr v)))
(- (* (car u) (cadr v)) (* (cadr u) (car v)))
)
)
(defun transptucs ( pt p1 p2 p3 / ux uy uz )
(setq uz (unit (v^v (mapcar '- p2 p1) (mapcar '- p3 p1))))
(setq ux (unit (mapcar '- p2 p1)))
(setq uy (unit (mapcar '- p3 p1)))
(mxv (list ux uy uz) (mapcar '- pt p1))
)
(defun transptwcs ( pt pt1 pt2 pt3 / pt1n pt2n pt3n )
(setq pt1n (transptucs '(0.0 0.0 0.0) pt1 pt2 pt3))
(setq pt2n (transptucs '(1.0 0.0 0.0) pt1 pt2 pt3))
(setq pt3n (transptucs '(0.0 1.0 0.0) pt1 pt2 pt3))
(transptucs pt pt1n pt2n pt3n)
)
;; Convex Hull - Lee Mac
;; Implements the Graham Scan Algorithm to return the Convex Hull of a list of points.
(defun LM:ConvexHull ( lst / ch p0 )
(cond
( (< (length lst) 4) lst)
( (setq p0 (car lst))
(foreach p1 (cdr lst)
(if (or (< (cadr p1) (cadr p0))
(and (equal (cadr p1) (cadr p0) 1e-8) (< (car p1) (car p0)))
)
(setq p0 p1)
)
)
(setq lst (vl-remove p0 lst))
(setq lst (append (list p0) lst))
(setq lst
(vl-sort lst
(function
(lambda ( a b / c d )
(if (equal (setq c (angle p0 a)) (setq d (angle p0 b)) 1e-8)
(< (distance p0 a) (distance p0 b))
(< (if (equal c (* 2.0 pi) 1e-8) 0.0 c) (if (equal d (* 2.0 pi) 1e-8) 0.0 d))
)
)
)
)
)
(setq ch (list (caddr lst) (cadr lst) (car lst)))
(foreach pt (cdddr lst)
(setq ch (cons pt ch))
(while (and (caddr ch) (LM:Clockwise-p (caddr ch) (cadr ch) pt))
(setq ch (cons pt (cddr ch)))
)
)
(reverse ch)
)
)
)
;; Clockwise-p - Lee Mac
;; Returns T if p1,p2,p3 are clockwise oriented or collinear
(defun LM:Clockwise-p ( p1 p2 p3 )
(< (- (* (- (car p2) (car p1)) (- (cadr p3) (cadr p1)))
(* (- (cadr p2) (cadr p1)) (- (car p3) (car p1)))
)
1e-8
)
)
(defun minarearec ( ccwchullpts / edges p1 p2 pts r1 r2 pp r3 r4 ar arlst rtn )
(setq edges (mapcar (function (lambda ( a b ) (list a b))) ccwchullpts (cdr (reverse (cons (car ccwchullpts) (reverse ccwchullpts))))))
(foreach edge edges
(setq p1 (car edge) p2 (cadr edge))
(setq pts (mapcar (function (lambda ( x ) (transptucs x p1 p2 (polar p1 (+ (angle p1 p2) (* 0.5 pi)) 1.0)))) ccwchullpts))
(setq r1 (transptwcs (list (car (car (vl-sort pts (function (lambda ( a b ) (< (car a) (car b))))))) 0.0 0.0) p1 p2 (polar p1 (+ (angle p1 p2) (* 0.5 pi)) 1.0)))
(setq r2 (transptwcs (list (car (car (vl-sort pts (function (lambda ( a b ) (> (car a) (car b))))))) 0.0 0.0) p1 p2 (polar p1 (+ (angle p1 p2) (* 0.5 pi)) 1.0)))
(setq pp (transptwcs (car (vl-sort pts (function (lambda ( a b ) (> (abs (cadr a)) (abs (cadr b))))))) p1 p2 (polar p1 (+ (angle p1 p2) (* 0.5 pi)) 1.0)))
(setq r3 (inters r1 (polar r1 (+ (angle r1 r2) (* 0.5 pi)) 1.0) pp (polar pp (angle r1 r2) 1.0) nil))
(setq r4 (inters r2 (polar r2 (+ (angle r1 r2) (* 0.5 pi)) 1.0) pp (polar pp (angle r1 r2) 1.0) nil))
(setq ar (* (distance r1 r2) (distance r1 r3)))
(setq arlst (cons (cons (list r1 r2 r4 r3) ar) arlst))
)
(setq rtn (car (vl-sort arlst (function (lambda ( a b ) (< (cdr a) (cdr b)))))))
rtn
)
(defun c:minbboxpolygon ( / pl rtn )
(setq pl (mapcar 'cdr (mapcar (function (lambda ( x ) (append x (list 0.0)))) (vl-remove-if (function (lambda ( x ) (/= (car x) 10))) (entget (car (entsel "\nPick closed POLYGON...")))))))
(setq rtn (minarearec (LM:ConvexHull pl)))
(entmake
(list
'(0 . "LWPOLYLINE")
'(100 . "AcDbEntity")
'(100 . "AcDbPolyline")
'(90 . 4)
(cons 70 (1+ (* 128 (getvar 'plinegen))))
'(38 . 0.0)
(cons 10 (car (car rtn)))
(cons 10 (cadr (car rtn)))
(cons 10 (caddr (car rtn)))
(cons 10 (cadddr (car rtn)))
'(210 0.0 0.0 1.0)
'(62 . 3)
)
)
(prompt "\nMinimal area : ") (princ (rtos (cdr rtn) 2 20))
(princ)
)
(defun c:minbboxpolygons ( / ss i pl rtn )
(prompt "\nSlect closed POLYGONS...")
(setq ss (ssget (list '(0 . "LWPOLYLINE") '(-4 . "&=") '(70 . 1) '(-4 . "<not") '(-4 . "<>") '(42 . 0.0) '(-4 . "not>"))))
(if ss
(repeat (setq i (sslength ss))
(setq pl (mapcar 'cdr (mapcar (function (lambda ( x ) (append x (list 0.0)))) (vl-remove-if (function (lambda ( x ) (/= (car x) 10))) (entget (ssname ss (setq i (1- i))))))))
(setq rtn (minarearec (LM:ConvexHull pl)))
(entmake
(list
'(0 . "LWPOLYLINE")
'(100 . "AcDbEntity")
'(100 . "AcDbPolyline")
'(90 . 4)
(cons 70 (1+ (* 128 (getvar 'plinegen))))
'(38 . 0.0)
(cons 10 (car (car rtn)))
(cons 10 (cadr (car rtn)))
(cons 10 (caddr (car rtn)))
(cons 10 (cadddr (car rtn)))
'(210 0.0 0.0 1.0)
'(62 . 3)
)
)
)
)
(princ)
)
(defun c:minbboxpolygons-global ( / ss i pl pll rtn )
(prompt "\nSlect closed POLYGONS...")
(setq ss (ssget (list '(0 . "LWPOLYLINE") '(-4 . "&=") '(70 . 1) '(-4 . "<not") '(-4 . "<>") '(42 . 0.0) '(-4 . "not>"))))
(if ss
(repeat (setq i (sslength ss))
(setq pl (mapcar 'cdr (mapcar (function (lambda ( x ) (append x (list 0.0)))) (vl-remove-if (function (lambda ( x ) (/= (car x) 10))) (entget (ssname ss (setq i (1- i))))))))
(setq pll (append pl pll))
)
)
(if pll
(progn
(setq rtn (minarearec (LM:ConvexHull pll)))
(entmake
(list
'(0 . "LWPOLYLINE")
'(100 . "AcDbEntity")
'(100 . "AcDbPolyline")
'(90 . 4)
(cons 70 (1+ (* 128 (getvar 'plinegen))))
'(38 . 0.0)
(cons 10 (car (car rtn)))
(cons 10 (cadr (car rtn)))
(cons 10 (caddr (car rtn)))
(cons 10 (cadddr (car rtn)))
'(210 0.0 0.0 1.0)
'(62 . 3)
)
)
(prompt "\nMinimal global area : ") (princ (rtos (cdr rtn) 2 20))
)
)
(princ)
)
(prompt "\nInvoke with : (c:minbboxpolygon) for single closed POLYGON input, or with : (C:minbboxpolygons) for multiple closed POLYGONS input, or with : (C:minbboxpolygons-global) for multiple closed POLYGONS input and single bbox output...")
(princ)
HTH., M.R.
If answer satisfies your requirements, mark the answer as solution to your question...
Regards...
Marko Ribar, d.i.a. (graduated engineer of architecture)