Jump to content

LISP to divide to certain length


Recommended Posts

Posted

I am wanting to see if the LISP I have attached could be made to do a few more things.

 

Currently what it does is divides a line and places perpendicular lines through it at 1/4" distance. I work for a stone company and when drawing a stone window surround, it has to be divided in sections (if it is over 36") and spaced @ 1/4" to allow for mortar to be applied.

 

What I would like it to be able to do is divide the line automatically (while still being able to give the length of the lines output) instead of requiring user input.

 

Also, kind of a side note, is it possible to make a dynamic version of it? End goal would be able to insert a window as a dynamic block and as you stretch it to dimensions provided, the joints automatically adjust to never be longer than 36"?

Stone Segments.LSP

Posted

I can't manage the dynamic bit, but regarding your first request, like this? (red I've commented out, blue is what I've added) You can adjust the formula in blue if it's not what you're after (if you don't know how just ask).

 

;;  StoneSegments for Stone by www.CADTutor.com with help from Eric Monceaux
;;  pick 2 points & it draws mortar joints
;;  suitable for vertical sides only
;;  For North American Stone Company
(defun c:ss (/ dxf tmp del ent elst #len startpt endpt ang #seglen pt p1 p2 clayer a90 slst
            )
 ;;  Set current or Create
 (defun layersetcurrent (layername layercolor)
   ;;  expects var LayerColor
   (or layercolor (setq layercolor 7))
   (if (tblsearch "Layer" layername)
     (command "._layer" "_thaw" layername "_on" layername "_unlock" layername "_set" layername ""
             ) ;_ closes command
     (command "._layer" "_make" layername "_color" layercolor layername ""
             ) ;_ closes command
   )
 )

 (defun dxf (code lst)
   (cdr (assoc code lst))
 )
 ;;Make 2D point from 3D point
 (defun 3dp->2dp (3dpt) (list (car 3dpt) (cadr 3dpt)))

 (or #seg (setq #seg 4))
 (setq #gap 0.25)
 (or #mlen (setq #mlen 6))

[color=Red];;;  (initget 6) ; No null, negative, zero
;;;  (setq tmp (getint (strcat "\nEnter the number of segments.<" (itoa #seg) ">")))
;;;  (setq #seg (if tmp tmp #seg))[/color]
 (initget 6) ; No null, negative, zero
 (setq tmp (getdist (strcat "\nEnter width of surround.<" (rtos #mlen) ">")))
 (setq #mlen (if tmp tmp #mlen))
 (setq p1 (getpoint "\nPick bottom of longest side."))
 (setq p2 (getpoint p1 "\nPick top of longest side."))
 (if (and p1 p2)
   (progn
[color=Blue]     (if (> (setq #len (distance p1 p2)) 36.) ; 36" ~ 0.9144
   (if (= (fix (setq #seg (/ #len 36.))) #seg)
     (setq #seg (fix #seg))
     (setq #seg (fix (1+ #seg)))
     )
   )[/color]
     (setq #seglen (/ (- #len (- (* #seg #gap) #gap)) #seg))
     (if (minusp #seglen)
       (alert "Line is too short.")
       (progn
         (setq clayer (getvar "clayer")
               ang    (angle p1 p2)
               pt     (polar p1 ang #seglen)
               a90    (+ ang (/ pi 2))
         )
         (layersetcurrent "Mortar" 2)
         (setq slst (ssadd))
         (repeat (- #seg 1)
           (command "._Line" "_non" pt "_non" (polar pt a90 #mlen) "")
           (setq slst (ssadd (entlast) slst))
           (command "._Line" "_non" (setq pt (polar pt ang #gap)) "_non" (polar pt a90 #mlen) "" )
           (setq slst (ssadd (entlast) slst))
           (setq pt (polar pt ang #seglen))
         )
         (setvar "clayer" clayer)
         (initget "Yes No")
         (setq ans (getkword "Flip Lines? <No> "))
         (if (= ans "Yes")
           (command ".mirror" slst "" "non" p1 "non" p2 "Y")
         )

       )
     )


   )
 )
 (princ)
)
(prompt "\nStone Segments Loaded, enter ss to run. For North American Stone Company")
(princ)

Posted

That is definately the right direction. However, when I performed the command, I applied it to a line 10'-0" long, and it divided it into 30 pieces @ 3-3/4". I need that to change to be no greater than 36" for each piece. Kind of like if distance of point x to y>36" then divide.

 

I hope this helps.

Posted

I've edited my previous post to include an if distance > 36 statement. How's that?

Posted

Sorry I'm taking a while to get it & I'm not used to imperial measurements. I've updated the code again anyway.

Posted

I applied the changes, and invoked the command again on the 3.048m line, and it divided into over 100 sections @ 20.6375mm. From what little I know about LISP, what you added seems right.

 

I really appreciate your help, by the way.

Posted

Ok glad it seems to be working.

 

If it's not quite right I think best thing would be to just ignore lisp and try work out a formula for how it would calculate the sections, then once done you can have a go or I can plug it into the lisp for you. Cause I might still be struggling with the mathematics of it...

Posted

I completely understand....here is how the process goes on calculator.

 

(AUTOCAD) DIST, Pick A then B

We'll use 120 as an example (A to B=120)

[C] = Then divide (120/36 = 3.3333333)

[D] = Now take that REAL number (3*0.25=0.75)

[E] = Subtract that value from A,B (120-0.75=119.25)

 

Then divide E by CEILING C

 

That gets your final division output seperated by the two lines spaced 0.25 apart.

 

Hope this helps!

Posted
I completely understand....here is how the process goes on calculator.

 

(AUTOCAD) DIST, Pick A then B

We'll use 120 as an example (A to B=120)

[C] = Then divide (120/36 = 3.3333333)

[D] = Now take that REAL number (3*0.25=0.75)

[E] = Subtract that value from A,B (120-0.75=119.25)

 

Then divide E by CEILING C

 

That gets your final division output seperated by the two lines spaced 0.25 apart.

 

Hope this helps!

That does help (at least to get us on the right track :))

 

Just so you know what I'm doing this is the combined formula I get in lisp format:

[C],[D],[E]

(/ [color=DarkOrange](- #len
     [color=Green](* (atoi (rtos [color=Red](/ #len 36.)[/color] 2 0))
         0.25)[/color])[/color]
  (/ #len 36.)))

The thing I want to check though is, when you calculate this do you input it in when the program asks you to "enter the number of segments"? In which case it's a real number and you want it as an integer? So I've rounded it down to an integer in the lisp (updated post).

Posted

Yes you are right. "enter the number of segments" is the output of [C]. Really what I am wanting to accomplish is to automate that integer. To give you a little bit further background behind the use of this program, let me explain what it is for.

 

I work at a architectural cast stone company, and we manufacturer a masonry type product for residential and commercial buildings. This program helps in a process that I used to do manually, or with QBASIC...yes QBASIC :). When I draw window surrounds, for example (included in the DWG uploaded) the legs and header pieces cannot be longer than 36" due to the lengths in which we make the plaster molds, or the negative. So, I would draw the window surround, get the distance of the leg or header in decimal units, input that amount into QBASIC, which would know to divide the integer by 36, and then display the division output, and I would enter the displayed number into the next section of the program, and it would give me my offset distance. I would still have to offset the joints (the portion of the LISP that is 0.25) manually between the output integer.

 

Whats important to remember is that if [C] is greater than a whole integer it needs to always round up, never down. So, in EXCEL for instance, it would look like:

Cell A1 [3.333333]

Cell B1 [=CEILING(A1,1)] with A1 being the number, and 1 being the significance.

 

On to the changes you made. I have uploaded a dwg showing what has happened, and what needs to happen.

 

Also, once again, I want to thank you for all of your help. Hopefully I can be the one answering questions one day.:D

Output.dwg

Posted

Ah, so all that formula wasn't for just the number of segments - I notice now there is a segment length formula in there which looks similar to what you put:

(setq #seglen (/ (- #len (- (* #seg #gap) #gap)) #seg))

where: #seg = [C] and #gap = 0.25

Can you make sense of that?

 

Anyways, so I just put in the value of [C] (updated post #2) and it returned the right segments in your example drawing. Let me know,

 

steve

Posted

And for an explanation of the code I added:

[color=DarkGreen](if (> (setq #len (distance p1 p2)) 36.)[/color] ; 36" ~ 0.9144
   [color=Sienna](if (/= (fix (setq #seg (/ #len 36.))) #seg)[/color]
     [color=Sienna](setq #seg (fix #seg))[/color]
     [color=Navy](setq #seg (fix (1+ #seg)))[/color]
     )
   )

If the length of the line is less than 36 then don't change the number of segments (the value is originally 4 I think), otherwise if the value of the rounded down length is equal to the length (ie, whole number) then return the number of segments as length / 36, otherwise return the number of segments as the value of length / 36 rounded up to the next whole number.

 

Just double check that the output of metric ~ imperial is correct. I believe the distance function works always in metric yet the output is what you want :?

Posted

Absolutely perfect! Great job! I love how CADtutor can bridge the gap between all of the CAD users around the world. Otherwise this GREAT lisp would not be what it is today. Thanks again Steve1...you are a life saver.

Posted

Lol, yeah, except our locations around the world sometimes make things take a week that you could do in a day. Glad it all worked!

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