Jump to content

Lisp routine to scale an object down equally


BrianTFC

Recommended Posts

Hi All,

 

I was wondering if there was a lisp routine that would scale an object (like a rectangle) down to a certain scale factor like offset works to where it gets scaled down equally? or maybe I'm missing something with the scale command. if I could get some help on this I would appreciate it. and if its not possible just let me know.

 

Thanks,

Brian

Link to comment
Share on other sites

  • Replies 27
  • Created
  • Last Reply

Top Posters In This Topic

  • BrianTFC

    8

  • BIGAL

    6

  • Lee Mac

    4

  • ReMark

    3

Top Posters In This Topic

Posted Images

You could use the SCALE command with a base point located at the center of the rectangle - snap to this center using the M2P snap with two corners of a diagonal.

Link to comment
Share on other sites

Or, as a convenient LISP program:

([color=BLUE]defun[/color] c:cscale ( [color=BLUE]/[/color] l s )
   ([color=BLUE]if[/color] ([color=BLUE]setq[/color] s ([color=BLUE]ssget[/color] [color=MAROON]"_:L"[/color]))
       ([color=BLUE]if[/color] ([color=BLUE]setq[/color] l (LM:ssboundingbox s))
           ([color=BLUE]command[/color] [color=MAROON]"_.scale"[/color] s [color=MAROON]""[/color] [color=MAROON]"_non"[/color] ([color=BLUE]apply[/color] '[color=BLUE]mapcar[/color] ([color=BLUE]cons[/color] '([color=BLUE]lambda[/color] ( a b ) ([color=BLUE]/[/color] ([color=BLUE]+[/color] a b) 2.0)) l)) [color=MAROON]"\\"[/color])
           ([color=BLUE]princ[/color] [color=MAROON]"\nUnable to calculate center."[/color])
       )
   )
   ([color=BLUE]princ[/color])
)        

[color=GREEN];; Selection Set Bounding Box  -  Lee Mac[/color]
[color=GREEN];; Returns a list of the lower-left and upper-right WCS coordinates of a[/color]
[color=GREEN];; rectangular frame bounding all objects in a supplied selection set.[/color]
[color=GREEN];; s - [sel] Selection set for which to return bounding box[/color]

([color=BLUE]defun[/color] LM:ssboundingbox ( s [color=BLUE]/[/color] a b i m n o )
   ([color=BLUE]repeat[/color] ([color=BLUE]setq[/color] i ([color=BLUE]sslength[/color] s))
       ([color=BLUE]if[/color]
           ([color=BLUE]and[/color]
               ([color=BLUE]setq[/color] o ([color=BLUE]vlax-ename->vla-object[/color] ([color=BLUE]ssname[/color] s ([color=BLUE]setq[/color] i ([color=BLUE]1-[/color] i)))))
               ([color=BLUE]vlax-method-applicable-p[/color] o 'getboundingbox)
               ([color=BLUE]not[/color] ([color=BLUE]vl-catch-all-error-p[/color] ([color=BLUE]vl-catch-all-apply[/color] '[color=BLUE]vla-getboundingbox[/color] ([color=BLUE]list[/color] o 'a 'b))))
           )
           ([color=BLUE]setq[/color] m ([color=BLUE]cons[/color] ([color=BLUE]vlax-safearray->list[/color] a) m)
                 n ([color=BLUE]cons[/color] ([color=BLUE]vlax-safearray->list[/color] b) n)
           )
       )
   )
   ([color=BLUE]if[/color] ([color=BLUE]and[/color] m n)
       ([color=BLUE]mapcar[/color] '([color=BLUE]lambda[/color] ( a b ) ([color=BLUE]apply[/color] '[color=BLUE]mapcar[/color] ([color=BLUE]cons[/color] a b))) '([color=BLUE]min[/color] [color=BLUE]max[/color]) ([color=BLUE]list[/color] m n))
   )
)

([color=BLUE]vl-load-com[/color]) ([color=BLUE]princ[/color])

Selection Set Bounding Box function from here.

Link to comment
Share on other sites

Lee,

 

Like usual your always there to help out...this is going to be a little bit trickier, say you scale down a rectangle at 1/16 or .9994 it only reduces the length of the rectangle and not the width or height. So to make this happen wouldn't you have to take the scale factor and change it somehow for the width? I need it to scale down a 1/16 both ways...well I did some test panels and found out that I was right about having to have separate scale factors because the length and the height are two different dimension's i.e. 36" =.9982638889 and 120" = .999479167. So in conclusion the scale factors would change with the dimension. I think if there was a routine that if you selected the object and put in how much you wanted to scale it down by that would be a start.

Edited by BrianTFC
Link to comment
Share on other sites

If its a rectang which is a pline then get the existing co-ords work out the centroid then ERASE IT, draw a brand new one as you say scales length and width as a scale factor. Verion 2 to do scales in X & Y you could block it rescale X Y then explode and purge temporary block. See if I can find time to do something got a couple to answer now.

Link to comment
Share on other sites

here is ver 2 only problem is it will make new answer as lines. So maybe ver1 is the way to go

(defun plcords (/ pt x y ent obj plobs )
(vl-load-com)


(defun getcoords (ent)
 (vlax-safearray->list
   (vlax-variant-value
     (vlax-get-property
   (vlax-ename->vla-object ent)
   "Coordinates"
     )
   )
 )
) ; defun


(setq plobjs (car (entsel "Pick rectang polyline")))
(setq co-ords (getcoords plobjs))

(setq x1 (nth  0 co-ords))
(setq y1 (nth  1 co-ords))
(setq x2 (nth  0 co-ords))
(setq y2 (nth  1 co-ords))
(setq x (/ (+ x1 x2) 2.0))
(setq y (/ (+ y1 y2) 2.0))
(setq pt (list x y))

(command "-block" "BIGAL" pt plobjs "")
(setq xsc (Getreal "\nEnter x scale"))
(setq ysc (getreal "\nEnter y scale"))
(command "-Insert" "BIGAL" pt xsc ysc 0)

(command "explode" "Last" "")
(command "-purge" "Block" "BIGAL" "N")
) ; master defun  
(plcords)

Link to comment
Share on other sites

...say you scale down a rectangle at 1/16 or .9994 it only reduces the length of the rectangle and not the width or height.

 

Scaling any shape will scale all dimensions by the given scale factor - scaling a rectangle will scale both the width and height by the same scale factor.

 

Could you post an image to explain the result you are looking for?

Link to comment
Share on other sites

Why not offset the rectangle 1/32nd of an inch inward thus reducing the overall length and width by 1/16th of an inch?

Link to comment
Share on other sites

Lee & Bigal

 

 

Here's what I'm trying to do. when I do my drawings the client wants all of the panels to be the actual size drawing but when I run it through the CNC program we have to scale down the panel by 1/16th (length & height) but the tabs that are .7188 are scaled down by 1/32nd. Right now I have to use stretch to accomplish this. it would be nice to be able to select a bunch of panels all at once to accomplish the task..it would really save a crap ton of time...

 

 

Thanks,

Brian

PANEL.dwg

PANEL.jpg

Link to comment
Share on other sites

Lee & Bigal

 

 

Here's what I'm trying to do. when I do my drawings the client wants all of the panels to be the actual size drawing but when I run it through the CNC program we have to scale down the panel by 1/16th (length & height) but the tabs that are .7188 are scaled down by 1/32nd. Right now I have to use stretch to accomplish this. it would be nice to be able to select a bunch of panels all at once to accomplish the task..it would really save a crap ton of time...

 

 

Thanks,

Brian

 

Usually when folding material is involved after cutting dim should be based on neutral fiber minus 1x the thickness of the material for 2 folds.

and all inner corners should have a small radius added of half or equal the material thickness to prevents cracking

Link to comment
Share on other sites

Forget about scaling just redraw it all from 1st principles pick Length from dim1 pick Height from dim 2, this gives you the base dimensions and just work out the new sizes accordingly to your rules. Yes its a lot of polars but an easy shape you can make the size defaults a preset and use to accept or input new values. Not sure but you may be able to use constraints draw the two rectangs and have the constraints linked so as you enter values for top rectang bottom one appears. You can edit the constraints in terms of the small offset value if required. Watch this space two rectangs.

Link to comment
Share on other sites

It sounds like the OP could use a custom lisp routine that could offset multiple rectangles inward towards their centers. Obviously each rectangle would have to be offset based upon their specific center as one point cannot be used as the basepoint for the offset. Is there an offset multiple objects (based upon their individual centerpoints) lisp that anyone knows of?

Link to comment
Share on other sites

Haven't read all the topic, but I wrote what ReMark was looking for... Maybe something like this :

 

(defun c:offsrectsbycent ( / *error* *adoc* rectangle-p nobulge-p osm cmde sss ss i ent offch d p1 p2 p3 p4 cp d1 d2 in )

 (vl-load-com)
 (setq *adoc* (vla-get-activedocument (vlax-get-acad-object)))

 (defun *error* ( msg )
   (if osm (setvar 'osmode osm))
   (if cmde (setvar 'cmdecho cmde))
   (vla-endundomark *adoc*)
   (if msg (prompt msg))
   (princ)
 )

 (defun rectangle-p ( e f / dpar stp enp ptn k parpts index ptlst )
    (setq dpar (/ (+ (abs (setq enp (vlax-curve-getendparam e))) (abs (setq stp (vlax-curve-getstartparam e)))) (setq ptn (cdr (assoc 90 (entget e))))))
    (setq k -1.0)
    (repeat ptn
       (setq parpts (append parpts (setq parpts (list (+ stp (* (setq k (1+ k)) dpar))))))
    )
    (setq k -1)
    (repeat ptn
       (setq index (append index (setq index (list (setq k (1+ k))))))
    )
    (setq ptlst (mapcar '(lambda (x) (vlax-curve-getpointatparam e x)) parpts))
    (and
       (eq ptn 4)
       (nobulge-p (if (eq (type e) 'ENAME) (vlax-ename->vla-object e) e) index f)
       (equal (distance (nth 0 ptlst) (nth 1 ptlst)) (distance (nth 2 ptlst) (nth 3 ptlst)) f)
       (equal (distance (nth 1 ptlst) (nth 2 ptlst)) (distance (nth 3 ptlst) (nth 0 ptlst)) f)
       (equal (distance (nth 0 ptlst) (nth 2 ptlst)) (distance (nth 1 ptlst) (nth 3 ptlst)) f)
    )
 )

 (defun nobulge-p ( e i f )
    (apply 'and (mapcar '(lambda (x) (equal (vla-getbulge e x) 0.0 f)) i))
 )

 (vla-startundomark *adoc*)
 (setq osm (getvar 'osmode))
 (setvar 'osmode 0)
 (setq cmde (getvar 'cmdecho))
 (setvar 'cmdecho 0)
 (setq sss (ssadd))
 (while (= (sslength sss) 0)
   (prompt "\nSelect rectangles...")
   (setq ss (ssget "_:L" '((0 . "*POLYLINE"))))
   (while (not ss)
     (prompt "\nEmpty sel.set... Select rectangles again...")
     (setq ss (ssget "_:L" '((0 . "*POLYLINE"))))
   )
   (setq sss (ssadd))
   (repeat (setq i (sslength ss))
     (setq ent (ssname ss (setq i (1- i))))
     (if (rectangle-p ent 1e-
       (ssadd ent sss)
     )
   )
   (if (= (sslength sss) 0)
     (prompt "\nNo rectangles in sel.set...")
   )
 )
 (initget 1 "In Out")
 (setq offch (getkword "\nSpecify side to perform multiple rectangles offset in relation of their center point [in/Out] : "))
 (initget 7)
 (setq d (getdist "\nPick or specify offset distance : "))
 (setq in 0)
 (repeat (setq i (sslength sss))
   (setq ent (ssname sss (setq i (1- i))))
   (command "_.UCS" "_E" ent)
   (setq p1 (vlax-curve-getpointatparam ent 0.0))
   (setq p2 (vlax-curve-getpointatparam ent 1.0))
   (setq p3 (vlax-curve-getpointatparam ent 2.0))
   (setq p4 (vlax-curve-getpointatparam ent 3.0))
   (setq cp (mapcar '/ (mapcar '+ p1 p2 p3 p4) '(4.0 4.0 4.0)))
   (setq d1 (distance cp (mapcar '/ (mapcar '+ p1 p2) '(2.0 2.0 2.0))))
   (setq d2 (distance cp (mapcar '/ (mapcar '+ p2 p3) '(2.0 2.0 2.0))))
   (if (eq offch "In")
     (if (or (< d1 d) (< d2 d))
       (setq in (1+ in))
       (command "_.OFFSET" d ent (mapcar '+ '(0.0 0.0) (trans cp 0 1)) "")
     )
     (command "_.OFFSET" d ent (mapcar '+ '(0.0 0.0) (trans (mapcar '+ p1 (mapcar '- p1 cp)) 0 1)) "")
   )
   (command "_.UCS" "_P")
 )
 (if (/= in 0)
   (alert (strcat "There were : " (princ (itoa in)) " \"not possible\" offset operations due to the fact that offset distance was bigger than minimal distance of rectangles toward their center points and requested side of offset was toward center point - \"In\""))
 )
 (*error* nil)
)

Regards, M.R.

Edited by marko_ribar
Link to comment
Share on other sites

Marko_Ribar

 

 

Thanks for your input, I don't think it's possible to do what I'm trying to do...if the lisp genius on this site can't figure it out then it's not possible.

Link to comment
Share on other sites

Maybe you should restate the nature of the problem you are trying to solve as obviously we don't seem to understand what it is you are trying to do.

Link to comment
Share on other sites

Like Remark I am confused what you want can be done, did you have a look at using constraints ? They take a little bit of time to learn but are extremely powerful. Else go down the lisp path and just write all the rules I would start with a complete blank screen Enter width, length, side fold, top fold, draw two completely seperate rectangs not real hard.

Link to comment
Share on other sites

Let me explain a little bit about what I do, I draw aluminum wall panels for building i.e. car dealerships, hospital, schools and so fourth. The first part of doing the drawings is to draw the panels off of the elevations which have to be to scale, and given thanks to a few people on this website they have helped me write or have written lisp routines to accomplish this part fairly quickly, now when it comes to running the material through the CNC machine the size of the panel needs to be smaller than what was first drawn due to the fact that when you bend the tabs the panel will grow a 1/16". Ok so here's what I would like to do, I would like to be able to make a copy of what was drawn to scale and shrink it down by 1/16" so I can import it into my program. Here is what I think the program has to figure out the following steps:

 

1. since the panels are all different sizes it needs to figure out the scale factor for the length and the height.

2. once it does that it needs to be able to scale down the panel by those factors.

3. here where it gets tricky, when you scale down the length and the width of the panel by 1/16" you also have to shrink the tabs a 1/16" also, if all you do is scale the panel down by a 1/16" the tabs will only be scaled by 1 /32".

 

the only rectangle that is used is the first one to get the size of the panel that rectangle is then explode and offset the tab length which is done by a lisp routine. Here is what the panel looks like in STEP 1 and STEP 2 is what I need to have done so I can import it into the CNC program. I hope this helps. Thanks everyone

 

PANEL.jpg

PANEL.dwg

Link to comment
Share on other sites

Brian,

 

To clarify, when you say 'scale by 1/16"', this is not in fact a scale factor, but instead you are subtracting 1/16" from both dimensions - correct?

 

Also, you state:

"when you scale down the length and the width of the panel by 1/16" you also have to shrink the tabs a 1/16" also, if all you do is scale the panel down by a 1/16" the tabs will only be scaled by 1/32"."

 

However your image seems to show that each of the tabs have been shortened by 1/32".

 

Therefore, which is required?

Should the tabs be shortened by 1/16" or 1/32"?

Link to comment
Share on other sites

Lee,

 

You are correct in saying "subtract 1/16" from both dimensions" and you are also correct about the tabs they would need to be "shorten by 1/32"". sorry about the misinformation..

Link to comment
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
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  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...