Jump to content
mdbdesign

Enclose objects with rectangle

Recommended Posts

mdbdesign

Hi!

Recently find nice codes written by VVA and posted by ASMI:

http://www.cadtutor.net/forum/showthread.php?t=14493&highlight=draw+boundary+box+around+selected+object

Question is: I need similar routine that will draw rectangular box around selected object with option to offset it at user specify distance from most outer edges of selected objects as shown on dwg with phantom yellow line, can you help me?:)

enclose object with rectngle.dwg

Share this post


Link to post
Share on other sites
VovKa

it will draw a rectangle (with offset) around selected objects.

it DOES NOT work correctly with splines :(

(vl-load-com)
(defun vk_GetEntBoundingBox (Ent / LL UR)
 (vla-GetBoundingBox (vlax-ename->vla-object Ent) 'LL 'UR)
 (list (vlax-safearray->list LL) (vlax-safearray->list UR))
)
(defun vk_GetSSBoundingBox (SS /)
 (if SS
   ((lambda (Coords)
      (apply (function
	(lambda (mn mx) (mapcar (function (lambda (n x) (list n x))) mn mx))
      )
      (mapcar (function (lambda (c) (list (apply 'min c) (apply 'max c))))
	      (list (mapcar 'car Coords) (mapcar 'cadr Coords))
      )
      )
    )
     (apply 'append
     (mapcar (function vk_GetEntBoundingBox)
	     (vl-remove-if 'listp (mapcar 'cadr (ssnamex SS)))
     )
     )
   )
 )
)
(defun test (/ SS Offset Bounds)
 (setq Offset 5.0)
 (if (setq SS (ssget))
   (progn (setq Bounds	(mapcar	(function (lambda (Coords Off)
				    (mapcar (function (lambda (c) (- c Off))) Coords)
				  )
			)
			(vk_GetSSBoundingBox SS)
			(list Offset (- Offset))
		)
   )
   (entmake (list (cons 0 "LWPOLYLINE")
		  (cons 100 "AcDbEntity")
		  (cons 100 "AcDbPolyline")
		  (cons 90 4)
		  (cons 70 1)
		  (cons 10 (car Bounds))
		  (list 10 (caar Bounds) (cadadr Bounds))
		  (cons 10 (cadr Bounds))
		  (list 10 (caadr Bounds) (cadar Bounds))
	    )
   )
   )
 )
 (princ)
)

Share this post


Link to post
Share on other sites
mdbdesign

Tested tried, work very good. I know I will never use it for spline.

Thank you VovKa

Share this post


Link to post
Share on other sites
vladthedog

I was searching the forums for a lisp that does what this sounds like it does. However I've never dealt with this sort of list. what is the command for this?

Share this post


Link to post
Share on other sites
vladthedog

nevermind. Figured it out :)

Share this post


Link to post
Share on other sites
taner

Maybe this one is easier to understand.

(defun vk_GetSSBoundingBox (SS / ptlst llur)
 (if SS
   (progn
     (setq ptlst (apply
                   'append
                   (mapcar
                     (function vk_GetEntBoundingBox)
                     (vl-remove-if 'listp (mapcar
                                            'cadr
                                            (ssnamex SS)
                                          )
                     )
                   )
                 )
     )
     (setq llur (list (apply
                        'mapcar
                        (cons 'min ptlst)
                      ) (apply
                          'mapcar
                          (cons 'max ptlst)
                        )
                )
     )
   )
 )
)

Share this post


Link to post
Share on other sites
Hunter

Hi all:

I'm new to lisp, would u please tell me how to run this code? type "vk_GetEntBoundingBox" seems don't work~

 

thanks~

Share this post


Link to post
Share on other sites
Lee Mac

For help on running LISPs in general, refer to the FAQ section on this site.

 

As for this LISP - I assume you are referring to the LISP posted by VVA - all functions in the LISP are left local and so cannot be run through the command line.

 

When I say "local" I mean, they use:

 

(defun ... ()

 

instead of

 

(defun [b]c[/b]: ... ()

 

To run the posted LISP, just make the "test" function into a "defun c:..." function and it can be run through the command line as normal.

 

Hope this helps

 

Lee

Share this post


Link to post
Share on other sites
vladthedog

Ok, I've been playing around with this lisp, and have actually found quite a few uses for my process which cuts minutes off processing time. However, It seemingly randomly doesn't work. But when it doesn't work it's consistent to the objects i'm trying to surround. attached is a dwg with a top (I work in countertops) WITH the outcome of running this lisp. As you can see it draws a square but it's huge. When I say it's consistent, I can copy/paste that top onto a completely new (and empty) template, and run the lisp and it will produce the exact same outcome. Any help/pointers would be greatly appreciated. Thanks.

boxsurroundtest.dwg

Share this post


Link to post
Share on other sites
VovKa

vladthedog, it seems that vla-GetBoundingBox does not like your "arced" wall-polyline. try using "._pedit _decurve" on it.

Share this post


Link to post
Share on other sites
vladthedog

Looks like you are right. Played around with it a bit, and that's exactly it. Unfortunately, and this is where I become difficult; I do apologize.... I can't decurve my polyedited lines (in this example it would be ok, but there are times it wouldn't) and I need the lines to be polyedited.............

Share this post


Link to post
Share on other sites
VovKa

you can also use ._convertpoly _light command to convert your heavyweight polylines into light ones. this will solve your problem.

you may also want to set system variable plinetype to 2.

Share this post


Link to post
Share on other sites
sadhu
it will draw a rectangle (with offset) around selected objects.

it DOES NOT work correctly with splines :(

(vl-load-com)
(defun vk_GetEntBoundingBox (Ent / LL UR)
 (vla-GetBoundingBox (vlax-ename->vla-object Ent) 'LL 'UR)
 (list (vlax-safearray->list LL) (vlax-safearray->list UR))
)
(defun vk_GetSSBoundingBox (SS /)
 (if SS
   ((lambda (Coords)
      (apply (function
       (lambda (mn mx) (mapcar (function (lambda (n x) (list n x))) mn mx))
         )
         (mapcar (function (lambda (c) (list (apply 'min c) (apply 'max c))))
             (list (mapcar 'car Coords) (mapcar 'cadr Coords))
         )
      )
    )
     (apply 'append
        (mapcar (function vk_GetEntBoundingBox)
            (vl-remove-if 'listp (mapcar 'cadr (ssnamex SS)))
        )
     )
   )
 )
)
(defun test (/ SS Offset Bounds)
 (setq Offset 5.0)
 (if (setq SS (ssget))
   (progn (setq Bounds    (mapcar    (function (lambda (Coords Off)
                       (mapcar (function (lambda (c) (- c Off))) Coords)
                     )
               )
               (vk_GetSSBoundingBox SS)
               (list Offset (- Offset))
           )
      )
      (entmake (list (cons 0 "LWPOLYLINE")
             (cons 100 "AcDbEntity")
             (cons 100 "AcDbPolyline")
             (cons 90 4)
             (cons 70 1)
             (cons 10 (car Bounds))
             (list 10 (caar Bounds) (cadadr Bounds))
             (cons 10 (cadr Bounds))
             (list 10 (caadr Bounds) (cadar Bounds))
           )
      )
   )
 )
 (princ)
)

 

Can you help me modify / integrate the above code.

I need to add a number to the box (rectangle) so that all the boxes on the drawing are progressively numbered .

 

The number should be placed bottom-center or bottom-right. the numbers should not repeat.

 

thankx

Share this post


Link to post
Share on other sites
JohnM

give this a try it works with splines, arcs, polylines, blocks

 

 
(vl-load-com)
(defun c:mkbbx ( / a axss lpx lpy upx upy rtpts maxp minp points ss ofdst pt1 pt3)
  (setq ss (ssget))
  (if ss
    (progn
(setq axss (vla-get-activeselectionset(vla-get-activedocument(vlax-get-acad-object)))
       )
  (vlax-for a  axss
    (if(not (vl-catch-all-error-p
        (vl-catch-all-apply
 (function (lambda ()
 (vla-getboundingbox a 'minp 'maxp))))))
      (setq points (append (list (vlax-safearray->list minp)
    (vlax-safearray->list maxp))
     points)
)
      )
    )
  (setq lpx (car(car(vl-sort points
   (function (lambda (a b)        
          (> (car a) (car b))           
        )))))
);_setq
  (setq lpy (cadr(car(vl-sort points
   (function (lambda (a b)        
          (< (cadr a) (cadr b))           
        )))))
);_setq
  (setq upx (car(car(vl-sort points
   (function (lambda (a b)        
          (< (car a) (car b))           
        )))))
);_setq
  (setq upy (cadr(car(vl-sort points
   (function (lambda (a b)        
          (> (cadr a) (cadr b))           
        )))))
);_setq
  (setq rtpts (list(list upx upy)(list lpx lpy)))        
(setq ofdst (getreal "\nEnter Offset"))
       (if ofdst
       (progn
(setq pt1 (nth 0 rtpts))
(setq pt3 (nth 1 rtpts))
(setq pt1 (polar (polar pt1 (angtof "90" 0) ofdst) (angtof "180" 0) ofdst))
(setq pt3 (polar (polar pt3 (angtof "0" 0) ofdst) (angtof "270" 0) ofdst))
(command "rectangle" pt1 pt3)
       );_progn
         );_if
     );_progn
   );_if
 );_defun

Share this post


Link to post
Share on other sites
sadhu

Thankx John. Mkbbx works fine for me . I use it for blocks.

 

I still need to have them numbered univocally. A hint on how I should proceed or look for will be helpful.

Share this post


Link to post
Share on other sites
JohnM

You need to make a few decisions on the text first and the code will be easer to do

 

You can approach it 2 different ways

  • Make your rectangles then come back and make one text to the scale and layer you want then copy the text and use express tools automatic text number command. This is a manual method
  • If you want the code to do it you would need to create a specific layer for the text so you can use SSGET to determine the number to be used.

What happens if you delete a rectangle in the middle of a number sequence?

Will the number text be scaled?

Share this post


Link to post
Share on other sites
sadhu

Do you think its possible to add an attribute - ( auto incremental ) to the rectangle ?

Share this post


Link to post
Share on other sites
JohnM

Almost anything is possible if you try

I would use a block with a attribute just for easy access if you want to change it.

I think a quick way is to:

Create a wblock or a block that you save to your template with one attribute

In your code find the insert point for your block on the rectangle

Insert the block

Use ssget with a filter for the block name so you can determine the attribute number

Use sslength for the number

Write the number to the attribute.

Now it’s your turn to write the code

If you get stuck just post for help

Share this post


Link to post
Share on other sites
Lee Mac

Another way to box it:

 

(defun c:BoxObj (/ ss obj ss doc Mi Ma pts)
 (vl-load-com) ;; Lee Mac  ~  11.02.10
 
 (if (setq ss (ssget))
   (progn
     (vlax-for obj (setq ss (vla-get-ActiveSelectionSet
                              (setq doc (vla-get-ActiveDocument
                                          (vlax-get-acad-object)))))
       (vla-getBoundingbox obj 'Mi 'Ma)
       (setq pts (cons (vlax-safearray->list Mi)
                       (cons (vlax-safearray->list Ma) pts))))
     (vla-delete ss)
     (setq Mi (apply (function mapcar) (cons 'min pts))
           Ma (apply (function mapcar) (cons 'max pts)))

     (vla-put-closed
       (vla-addLightWeightPolyline
         
         (if (zerop (vla-get-ActiveSpace doc))
           (if (eq :vlax-true (vla-get-mspace doc))
             (vla-get-ModelSpace doc)
             (vla-get-PaperSpace doc))
           (vla-get-ModelSpace doc))
         
         (variant (vlax-safearray-fill (safearray vlax-vbDouble '(0 . 7))
                    (list (car Mi) (cadr Mi) (car Mi) (cadr Ma)
                          (car Ma) (cadr Ma) (car Ma) (cadr Mi))))) :vlax-true)))
 (princ))

 

Edit: Updated to include working through a viewport.

Share this post


Link to post
Share on other sites
sadhu
Another way to box it:

 

(defun c:BoxObj (/ ss obj ss doc Mi Ma pts)
 (vl-load-com) ;; Lee Mac  ~  11.02.10
 
 (if (setq ss (ssget))
   (progn
     (vlax-for obj (setq ss (vla-get-ActiveSelectionSet
                              (setq doc (vla-get-ActiveDocument
                                          (vlax-get-acad-object)))))
       (vla-getBoundingbox obj 'Mi 'Ma)
       (setq pts (cons (vlax-safearray->list Mi)
                       (cons (vlax-safearray->list Ma) pts))))
     (vla-delete ss)
     (setq Mi (apply (function mapcar) (cons 'min pts))
           Ma (apply (function mapcar) (cons 'max pts)))

     (vla-put-closed
       (vla-addLightWeightPolyline
         (if (zerop (vla-get-ActiveSpace doc))
           (vla-get-PaperSpace doc) (vla-get-ModelSpace doc))
         (variant (vlax-safearray-fill (safearray vlax-vbDouble '(0 . 7))
                    (list (car Mi) (cadr Mi) (car Mi) (cadr Ma)
                          (car Ma) (cadr Ma) (car Ma) (cadr Mi))))) :vlax-true)))
 (princ))

 

for Lee Mac :

BoxObj does not draw around selected objects - unless you intended some other use for it that I didn't understand.

 

 

Any way what I am looking for is to draw a box around selected objects and number it. The numbering should be progressive / incremental and I should be able to continue numbering even after I close the drawing and reopen it later.

 

I thought I could follow JohnM advice but I'm light years form coding ssget, vla- and stuff.

 

So all help is appreciated.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...