How to get bounding box

How to get bounding box

J-Rocks
Collaborator Collaborator
4,068 Views
22 Replies
Message 1 of 23

How to get bounding box

J-Rocks
Collaborator
Collaborator

Hello,

How can I get bounding box of such rotated polyline in below posted snapshot to get the red polyline ?

Thanks.

BB.PNG

0 Likes
Accepted solutions (1)
4,069 Views
22 Replies
Replies (22)
Message 2 of 23

Moshe-A
Mentor
Mentor

@J-Rocks  hi,

 

if you can define some roles to rotate this figure to align with wcs then you can use (vla-getboundingbox)

I would try to find the dominant vertex (who's angle appears the most).

 

moshe

 

0 Likes
Message 3 of 23

ВeekeeCZ
Consultant
Consultant

Maybe try THIS 

 

But agree with @Moshe-A that it might be advantageous to follow the angle of the longest segment or sum of lengths.

0 Likes
Message 4 of 23

Kent1Cooper
Consultant
Consultant

You can at least get very close with SmallestRectangle.lsp, >here<.  It goes in 1° increments of rotation, but you can reduce that.  But it won't give you precisely the outline you want unless the original's angles fall on one of the rotational increments.

EDIT:  Never mind that -- see Message 5.

Kent Cooper, AIA
0 Likes
Message 5 of 23

Kent1Cooper
Consultant
Consultant

Kent1Cooper_0-1677673852928.png

With OFFSETGAPTYPE set to zero, Offset the original [white] outboard by a large distance relative to the size of the undulations.  [In this case, the Offset distance is the shorter dimension of the enclosing rectangle.]  That outward Offset gives the red result, which kills all the undulations.  Offset that back inward by the same distance to get the yellow result.

Kent Cooper, AIA
Message 6 of 23

J-Rocks
Collaborator
Collaborator

Thank you all for your kind and quick replies.

I was thinking the same to rotate the polyline from the longest segment and this will take more codes from me to get that working but this deserves a try.

 

Kent, your offset idea seems good but I got the curves offset as well even with system variable set to zero and not like your example in snapshot.

0 Likes
Message 7 of 23

Kent1Cooper
Consultant
Consultant

@J-Rocks wrote:

.... your offset idea seems good but I got the curves offset as well even with system variable set to zero ....


That must mean, I think, that your original has slightly rounded corners.  Does it work if you do Fillet, Radius zero, Polyline option on it first?  If the corners are rounded with a single arc segment at each, that would square them off.

 

An actual drawing file with some real-life examples may be helpful.

 

I was thinking of setting the UCS to align with the Polyline under the Object option, then getting its bounding box, but I find the bounding box is returned in WCS values, even when in a different UCS.

Kent Cooper, AIA
0 Likes
Message 8 of 23

Moshe-A
Mentor
Mentor

@J-Rocks  hi,

 

Check this command PBND - works? 😀

thank you Lee Mac for this (LM:ListDupes) function.

 

Moshe

 

 

;; List Duplicates  -  Lee Mac
;; Returns a list of items appearing more than once in a supplied list

(defun LM:ListDupes ( l )
    (if l
        (if (member (car l) (cdr l))
            (cons (car l) (LM:ListDupes (vl-remove (car l) (cdr l))))
            (LM:ListDupes (vl-remove (car l) (cdr l)))
        )
    )
)


(vl-load-com)

;; draw the boundary of zigzag pline based on angles
(defun c:pbnd (/ vertices angle_list _dtr _wcs2ucs
	         ss points^ angles^ AcDbPline p0 p1)

  
 ; return pline points 
 (defun vertices (ent)
  (vl-remove-if
   'not
   (mapcar
    '(lambda (itm)
      (if (= (car itm) 10) 
       (cdr itm)
      )
     ); lambda
    (entget ent)	    
   ); mapcar
  ); vl-remove-if
 ); vertices 


 (defun angle_list (lst / qang)

  (defun qang (a)
   (angtos 
    (if (and (>= a (* pi 0.5)) (< a (* pi 1.5)))
     a 
     (+ a pi)
    )
   0 4) 
  ); qang
   
  (mapcar
   (function
     (lambda (t0 t1)
      (atof (qang (angle t0 t1)))
     )
   )
   lst (append (cdr lst) (list (car lst)))
  )
 ); angle_list

 ; anonymous functions
 (setq _dtr (lambda (a) (* (/ a 360.0) 2 pi)))
 (setq _wcs2ucs (lambda (p) (trans p 0 1)))

  
 ; here start c:pbnd 
 (setvar "cmdecho" 0)
 (command "._undo" "_begin")
  
 (if (setq ss (ssget '((0 . "lwpolyline,polyline") (70 . 129))))
  (progn
   (foreach ename (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss)))
    (setq points^ (vertices ename))
    (setq angles^ (vl-sort (LM:ListDupes (angle_list points^)) '>))

    (setq AcDbPline (vla-copy (vlax-ename->vla-object ename)))
    (vla-rotate AcDbPline (vlax-3d-point '(0.0 0.0 0.0)) (- (* pi 2) (+ (_dtr (car angles^)) pi)))
    (vla-getBoundingBox AcDbPline 'p0 'p1)
    (vla-delete AcDbPline)
    (vlax-release-object AcDbPline)
     
    (command "._rectangle" (_wcs2ucs (vlax-safearray->list p0)) (_wcs2ucs (vlax-safearray->list p1)))
    (vla-rotate (vlax-ename->vla-object (entlast)) (vlax-3d-point '(0.0 0.0 0.0)) (+ (_dtr (car angles^)) pi))
   ); foreach
  ); progn
 ); if


 (command "._undo" "_end") 
 (setvar "cmdecho" 1) 
  
 (princ)
); c:pbnd

 

0 Likes
Message 9 of 23

J-Rocks
Collaborator
Collaborator

Sorry, I did not mean by curves rounded but sharp angles, the fillet did not solve / fix the polyline to work around it with offset as suggested earlier by you.

 

I did also thought about changing the UCS but that is what I have not worked with before.

Please find an example drawing in this post below.

Thank you.

0 Likes
Message 10 of 23

J-Rocks
Collaborator
Collaborator

Thank you, that did not work at all and just drawn square box.

JRocks_0-1677746182440.png

 

0 Likes
Message 11 of 23

Moshe-A
Mentor
Mentor

@J-Rocks ,

 

post a sample dwg

 

 

0 Likes
Message 12 of 23

Moshe-A
Mentor
Mentor

yes i see the issue working on it

 

 

0 Likes
Message 13 of 23

Kent1Cooper
Consultant
Consultant

Offsetting outward and then back inward, by the distance across the end of the overall shape, worked for me in your sample drawing.  Even though in this particular configuration the outward Offset included a bump in the left end [green]:

Kent1Cooper_0-1677760660988.png

still, Offsetting back inward removed that, and gave the red result.

Kent Cooper, AIA
0 Likes
Message 14 of 23

Moshe-A
Mentor
Mentor
Accepted solution

@J-Rocks 

 

ok fixed

 

;; Count Items  -  Lee Mac
;; Returns a list of dotted pairs detailing the number of
;; occurrences of each item in a supplied list.

(defun LM:CountItems ( l / c x )
    (if (setq x (car l))
        (progn
            (setq c (length l)
                  l (vl-remove x (cdr l))
            )
            (cons (cons x (- c (length l))) (LM:CountItems l))
        )
    )
)


(vl-load-com)

;; draw the boundary of zigzag pline based on angles
(defun c:pbnd (/ vertices angle_list _dtr _wcs2ucs
	         ss points^ angles^ AcDbPline p0 p1)

  
 ; return pline points 
 (defun vertices (ent)
  (vl-remove-if
   'not
   (mapcar
    '(lambda (itm)
      (if (= (car itm) 10) 
       (cdr itm)
      )
     ); lambda
    (entget ent)	    
   ); mapcar
  ); vl-remove-if
 ); vertices 


 (defun angle_list (lst / qang)

  (defun qang (a)
   (angtos 
    (if (and (>= a (* pi 0.5)) (< a (* pi 1.5)))
     a 
     (+ a pi)
    )
   0 4) 
  ); qang
   
  (mapcar
   (function
     (lambda (t0 t1)
      (atof (qang (angle t0 t1)))
     )
   )
   lst (append (cdr lst) (list (car lst)))
  )
 ); angle_list

 ; anonymous functions
 (setq _dtr (lambda (a) (* (/ a 360.0) 2 pi)))
 (setq _wcs2ucs (lambda (p) (trans p 0 1)))

  
 ; here start c:pbnd 
 (setvar "cmdecho" 0)
 (command "._undo" "_begin")
  
 (if (setq ss (ssget '((0 . "lwpolyline,polyline"))))
  (progn
   (foreach ename (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss)))
    (setq points^ (vertices ename))
    (setq angles^ (vl-sort (LM:CountItems (angle_list points^)) '(lambda (e0 e1) (> (cdr e0) (cdr e1)))))
     
    (setq AcDbPline (vla-copy (vlax-ename->vla-object ename)))
    (vla-rotate AcDbPline (vlax-3d-point '(0.0 0.0 0.0)) (- (* pi 2) (+ (_dtr (caar angles^)) pi)))
    (vla-getBoundingBox AcDbPline 'p0 'p1)
    (vla-delete AcDbPline)
    (vlax-release-object AcDbPline)
     
    (command "._rectangle" (_wcs2ucs (vlax-safearray->list p0)) (_wcs2ucs (vlax-safearray->list p1)))
    (vla-rotate (vlax-ename->vla-object (entlast)) (vlax-3d-point '(0.0 0.0 0.0)) (+ (_dtr (caar angles^)) pi))
   ); foreach
  ); progn
 ); if


 (command "._undo" "_end") 
 (setvar "cmdecho" 1) 
  
 (princ)
); c:pbnd
Message 15 of 23

Kent1Cooper
Consultant
Consultant

@Kent1Cooper wrote:

Offsetting outward and then back inward, by the distance across the end of the overall shape, worked for me in your sample drawing.  ....


Which can be automated in a fairly short routine:

 

(vl-load-com)
(defun C:CURE (/ sel rec UR start temp) ; = Clean Up Rectangle Edges
  (if
    (and
      (setq sel (entsel "\nRectangle to Clean Up: "))
      (wcmatch (cdr (assoc 0 (entget (setq rec (car sel))))) "*POLY*")
    ); and
    (progn ; then
      (vla-getboundingbox (vlax-ename->vla-object rec) 'minpt 'maxpt)
      (command "_.offset"
        (apply 'min (cdr (reverse (mapcar '- (setq UR (vlax-safearray->list maxpt)) (vlax-safearray->list minpt)))))
          ;; lesser XY dimension of bounding box for Offset distance
        (setq start (vlax-curve-getStartPoint rec))
        (polar UR 0 1); guaranteed outboard
        ""
      ); command
      (setq temp (entlast))
      (command
        "_.zoom" "_object" temp "" ; [pick point must be visible on-screen]
        "_.offset" "" (vlax-curve-getStartPoint temp) start ""
        "_.zoom" "_previous"
      ); command
      (entdel temp)
      (entdel rec) ;;;;; OR NOT, if you want it to remain
    ); progn
  ); if
  (prin1)
); defun

 

[It doesn't actually use the dimension across the end of the shape after all, but an easier-to-determine dimension that has the same effect.]

 

It could use some of the usual enhancements.  It doesn't check that the Polyline is of the right kind of configuration, or closed, or on an unlocked Layer, etc. -- it's up to you to choose appropriate objects.  [Some of those things can be checked easily enough, but the configuration type would be a real challenge, if even possible.]

Kent Cooper, AIA
0 Likes
Message 16 of 23

komondormrex
Mentor
Mentor

hey,

if that routine has to deal with singular convex pline only as shown at first picture, then that code may be of help.

 

 

 

(defun c:pline_bounding_box (/ pline_ename vertex_list leftmost_vertex topmost_vertex rightmost_vertex bottommost_vertex bounding_box_pline)
	(setq pline_ename (car (entsel))
		  vertex_list (mapcar 'cdr (vl-remove-if-not '(lambda (group) (= 10 (car group))) (entget pline_ename)))
		  leftmost_vertex (car (vl-sort vertex_list '(lambda (vertex_1 vertex_2) (< (car vertex_1) (car vertex_2)))))
		  topmost_vertex (car (vl-sort vertex_list '(lambda (vertex_1 vertex_2) (> (cadr vertex_1) (cadr vertex_2)))))
		  rightmost_vertex (car (vl-sort vertex_list '(lambda (vertex_1 vertex_2) (> (car vertex_1) (car vertex_2)))))
		  bottommost_vertex (car (vl-sort vertex_list '(lambda (vertex_1 vertex_2) (< (cadr vertex_1) (cadr vertex_2)))))
	)
	(vla-put-color
		(setq bounding_box_pline (vla-addlightweightpolyline (vla-get-block (vla-get-activelayout (vla-get-activedocument (vlax-get-acad-object))))
															 (vlax-safearray-fill 
															 	(vlax-make-safearray vlax-vbdouble '(0 . 7)) 
																(apply 'append (list leftmost_vertex topmost_vertex rightmost_vertex bottommost_vertex))
															 )
								 )
		)
		1
	)
	(vla-put-closed bounding_box_pline :vlax-true)
	(vlax-release-object bounding_box_pline) 
)

 

 

0 Likes
Message 17 of 23

greg_battin
Advocate
Advocate

Just thought that I'd try this routine for fun.
Thanks for your efforts.
See below for what I got from using c:pline_bounding_box.

~thanks

0 Likes
Message 18 of 23

ronjonp
Mentor
Mentor

@J-Rocks There is also THIS.

0 Likes
Message 19 of 23

komondormrex
Mentor
Mentor

))) well it wasn't obviously pretended to replace 'getboundingbox))) for orthogonally placed bitten rectangles

0 Likes
Message 20 of 23

Moshe-A
Mentor
Mentor

@J-Rocks 

 

did you test it?

 

 

0 Likes