Jump to content

divide a line equally but with a few restrictions


samifox

Recommended Posts

Hi

using acad 2010

 

I want to draw a line and have a lisp to divide it equally but with a few restrictions

 

1. Each segment wont be less than 6 and/or more than 8

2. If the total length of theline cannot result 6-8, prompt and cancel

Thanks

Shay

Link to comment
Share on other sites

(defun c:lindiv6-8 ( / ptst pten d n6 n8 n1 n2 n k stpt enpt )
 (setq ptst (getpoint "\nStart point of line : "))
 (setq pten (getpoint ptst "\nEnd point of line : "))
 (setq ptst (trans ptst 1 0) pten (trans pten 1 0))
 (setq d (distance ptst pten))
 (setq n6 (/ d 6.0))
 (setq n8 (/ d 8.0))
 (cond 
       ( (equal n6 (float (fix n6)) 1e-15)
         (setq n n6)
       )
       ( (and (null n) (> n6 1.0))
         (setq n1 (fix n8) n2 (+ (fix n6) 1))
         (repeat (+ (- n2 n1) 1)
           (if (<= 6.0 (if (/= n1 0) (/ d (float n1)) 0.0) 8.0)
             (setq n n1)
             (if (null n) (setq n nil))
           )
           (setq n1 (1+ n1))
         )
       )
       ( (< n6 1.0)
         (setq n nil)
       )
 )
 (if n
   (progn
     (setq k -1.0)
     (repeat (fix n)
       (setq stpt (mapcar '+ ptst (mapcar '* (mapcar '/ (mapcar '- pten ptst) (list n n n)) (list (setq k (1+ k)) k k))))
       (setq enpt (mapcar '+ stpt (mapcar '/ (mapcar '- pten ptst) (list n n n))))
       (entmake (list '(0 . "LINE") '(62 . 1) (cons 10 stpt) (cons 11 enpt) (list 210 0.0 0.0 1.0)))
     )
   )
   (prompt "\nOriginal line couldn't be divided into lines with 6-8 units lengths criteria")
 )
 (princ)
)

Edited by marko_ribar
code changed - first condition in (cond...)
Link to comment
Share on other sites

:DAWSOME:D

 

i actually cant use it without completly understanding it. i got lost in your last paragraph

;******************linediv68****************************************
;variables
;ptst - start point of the line
;pten - end point of the line
;d - total length of the line
;n6 - devition by 6
;n8 - devition by 8

(defun c:lindiv6-8 ( / ptst pten d n6 n8 n1 n2 n k stpt enpt )
 ;getting the total length of the line
 (setq ptst (getpoint "\nStart point of line : "))
 (setq pten (getpoint ptst "\nEnd point of line : "))
 (setq ptst (trans ptst 1 0) pten (trans pten 1 0))
 (setq d (distance ptst pten))

;getiing unrestricted devition
 (setq n6 (/ d 6.0))
 (setq n8 (/ d 8.0))

 ;i got lost here 
 (cond 
       ( (equal n6 1.0 1e-15);what is 1e-15???
         (setq n 1.0)
       )
       ( (and (null n) (> n6 1.0))
         (setq n1 (fix n8) n2 (+ (fix n6) 1))
         (repeat (+ (- n2 n1) 1)
           (if (<= 6.0 (if (/= n1 0) (/ d (float n1)) 0.0) 8.0)
             (setq n n1)
             (if (null n) (setq n nil))
           )
           (setq n1 (1+ n1))
         )
       )
       ( (< n6 1.0)
         (setq n nil)
       )
 )
 (if n
   (progn
     (setq k -1.0)
     (repeat (fix n)
       (setq stpt (mapcar '+ ptst (mapcar '* (mapcar '/ (mapcar '- pten ptst) (list n n n)) (list (setq k (1+ k)) k k))))
       (setq enpt (mapcar '+ stpt (mapcar '/ (mapcar '- pten ptst) (list n n n))))
       (entmake (list '(0 . "LINE") '(62 . 1) (cons 10 stpt) (cons 11 enpt) (list 210 0.0 0.0 1.0)))
     )
   )
   (prompt "\nOriginal line couldn't be divided into lines with 6-8 units lengths criteria")
 )
 (princ)
)

 

Thanks

Shay

Edited by samifox
Link to comment
Share on other sites

I've changed exactly that condition that was confusing you - like you smell for an error... The mistake was in condition that n6 variable should be checked for any complete number (1,2,3,...) in first condition so if your original line had exactly length 18.0, it should divide it into 3 segments of 6.0 length as n6 would be exactly n6=3.0...

 

1e-15 is number (to be exact - very small number 0.000000000000001) that represents tolerance fuzz factor supplied to (equal) function for comparison of equality of 2 main argument numbers (equal number1 number2 fuzz)... If number1 is the same as number2 and difference between them is in range from 0.0 to 1e-15 (fuzz), then (equal number1 number2 fuzz) should return T...

 

Note that when (equal) function is used with supplied 3rd fuzz argument - then fuzz argument must be in range from 0.0 to 1.0 for function (equal) to operate correctly... So, because fuzz argument is from 0.0 to 1.0 it is common that this small number is supplied in 1e-decimals behind 0.0 form... If you want to express very big number, than you should use 1e+decimal places in front of 0.0...

 

M.R.

Link to comment
Share on other sites

:oops:

hi marko

just for you to know, i couldnt sleep tonight so i tryed to analyze the code line by line, after 2 hours i realize that (with my minor knowladge in lisp) i just cant. i wish i could ask more simple and less nasted or havy commanted version of the code...

 

Thanks

S

Link to comment
Share on other sites

Could the test be :

(if (or (zerop (rem distance 8.))
       (>= (rem distance 8.) 6.))
   then do the math
   else alert)

 

-David

Link to comment
Share on other sites

This also works. Take a look.

 

(defun c:dx (/ a as b bs c d dv dvs u)
 ;(while
   (setq a (getpoint "\n Start point: "))
   (setq b   (getpoint a "\n Endpoint: ")
  d   (distance a b)
  dv  (fix (/ d )
  dvs (/ d dv)
   )
   (if	(> dvs 
     (setq dv	(fix (/ d 7))
    dvs	(/ d dv)
     )
   )
   (if	(> dvs 
     (setq dv	(fix (/ d 6))
    dvs	(/ d dv)
     )
   )

   (setq u  (angle a b)
  as a
  bs (polar a u dvs)
  c  1
   )
   (cond ((< d 12.0) (alert "Line is smaller than 12 units"))
  ((> 18 d 16) (alert "Line can't be divided as required"))
  (t
   (repeat dv
     (entmake (list (cons 0 "line")
		    (cons 10 as)
		    (cons 11 bs)
		    ;(cons 62 c)
	      )
     )
     (setq c  (+ 1 c)
	   as bs
	   bs (polar a u (* dvs c))
     )
   )
  )
   )
 
 (princ)
)

Link to comment
Share on other sites

Well, this is very low-tech solution. I thought the code is so primitive, it wouldn't need any explanation. What specific part of the code you need help with?

Link to comment
Share on other sites

Here is the code explanation:

 

(defun c:dx (/ a as b bs c d dv dvs u)
 ;(while [color="red"]; uncomment if needed, repeats dx function until pressing enter on "Start point" prompt[/color]
   (setq a (getpoint "\n Start point: "))
   (setq b   (getpoint a "\n Endpoint: ")
  d   (distance a b)[color="red"]; line length[/color]
  dv  (fix (/ d )[color="red"]; division integer = number of line segments to be drawn[/color]
  dvs (/ d dv)[color="red"]; line segment length[/color]
   )
   (if	(> dvs [color="red"]; if line segment>8 get shorter one[/color]
     (setq dv	(fix (/ d 7))[color="red"]; division integer = number of line segments to[/color] [color="red"]be drawn[/color]
    dvs	(/ d dv)[color="red"]; segment length[/color]
     )
   )
   (if	(> dvs [color="red"]; if line segment>8 get shorter one[/color]
     (setq dv	(fix (/ d 6))[color="red"]; division integer = number of line segments to be drawn[/color]
    dvs	(/ d dv)[color="red"]; segment length[/color]
     )
   )

   (setq u  (angle a b)[color="red"]; line segments angle[/color]
  as a [color="red"]; start point of first line segment[/color]
  bs (polar a u dvs)[color="red"]; end point of first line segment[/color]
  c  1 [color="red"]; counter, starting at 1[/color]
   )
[color="red"];;; first 2 conditions bellow are testing if line length is disqualified for required division, triggers alert, if it is[/color]
   (cond ((< d 12.0) (alert "Line is shorter than 12 units"))[color="red"]; line shorter than 12 can't be used[/color]
  ((> 18 d 16) (alert "Line can't be divided as required"))[color="red"]; line greater than 16 and shorter than 18 can't be used[/color]
  (t [color="red"]; true condition[/color]
   (repeat dv [color="red"]; repeat by above calculated number of segments[/color]
     (entmake (list (cons 0 "line")[color="red"]; entmake = drawing a line segment[/color]
		    (cons 10 as)[color="red"]; entmake[/color]
		    (cons 11 bs)[color="red"]; entmake[/color]
	      )[color="red"]; entmake[/color]
     )[color="red"]; entmake > line segment has been drawn[/color]
     (setq c  (+ 1 c)[color="red"]; counter increased by 1[/color]
	   as bs [color="red"]; setting start point for the next line segment[/color]
	   bs (polar a u (* dvs c))[color="red"]; setting end point for the next line segment[/color]
     )
   )[color="red"]; end of repeat loop[/color]
  )[color="red"]; end of true condition[/color]
   ) [color="red"]; end of cond function[/color]
 [color="red"]; uncomment if needed, repeats dx function until pressing enter on "Start point" prompt[/color]
 (princ)
)

Link to comment
Share on other sites

  • 2 weeks later...

hi

 

im reediting the code to suite my program need (based on marko_ribar code).

 

the first thing i thinking is how to reuse the code in other programs so i avoiding specific function.

 

few question/problems

 

 

  1. since its gonna be 100's of centimeters ive change from decimal numbers to real. since than it yell an error. why?
  2. i need all variables to be global so i can access their value any time i need in the program life. i find myself defining local and global twice, what practice i should use in order to have those variables global but still have in mind that one day ill need those function in other program?

 

(setq TotaLng 0)
(setq minLng 600)
(setq maxLng 800)


(defun c:main ()
 (setq totLng (getTotalLength))
 (setq segLng (getSegmentLength))
 
 (princ)
 )
(defun getTotalLength ( / ptst pten TotaLng minLng maxLng n1 n2 n k stpt enpt )
 (princ "getting the total length of the line")
 (setq ptst (getpoint "\nStart point of line : "))
 (setq pten (getpoint ptst "\nEnd point of line : "))
 (setq ptst (trans ptst 1 0) pten (trans pten 1 0))
 (setq TotaLng (distance ptst pten))
 )
(defun getSegmentLength (/ totLng minLng maxLng )
 ;getiing unrestricted devition
 (setq minLng (/ totLng minLng))
 (setq maxLng (/ totLng maxLng))
 (princ)
 )

Thanks

Shay

Link to comment
Share on other sites

  • 4 weeks later...
(defun c:lindiv6-8 ( / ptst pten d n6 n8 n1 n2 n k stpt enpt )
 (setq ptst (getpoint "\nStart point of line : "))
 (setq pten (getpoint ptst "\nEnd point of line : "))
 (setq ptst (trans ptst 1 0) pten (trans pten 1 0))
 (setq d (distance ptst pten))
 (setq n6 (/ d 6.0))
 (setq n8 (/ d 8.0))
 (cond 
       ( (equal n6 (float (fix n6)) 1e-15)
         (setq n n6)
       )
       ( (and (null n) (> n6 1.0))
         (setq n1 (fix n8) n2 (+ (fix n6) 1))
         (repeat (+ (- n2 n1) 1)
           (if (<= 6.0 (if (/= n1 0) (/ d (float n1)) 0.0) 8.0)
             (setq n n1)
             (if (null n) (setq n nil))
           )
           (setq n1 (1+ n1))
         )
       )
       ( (< n6 1.0)
         (setq n nil)
       )
 )
 (if n
   (progn
     (setq k -1.0)
     (repeat (fix n)
       (setq stpt (mapcar '+ ptst (mapcar '* (mapcar '/ (mapcar '- pten ptst) (list n n n)) (list (setq k (1+ k)) k k))))
       (setq enpt (mapcar '+ stpt (mapcar '/ (mapcar '- pten ptst) (list n n n))))
       (entmake (list '(0 . "LINE") '(62 . 1) (cons 10 stpt) (cons 11 enpt) (list 210 0.0 0.0 1.0)))
     )
   )
   (prompt "\nOriginal line couldn't be divided into lines with 6-8 units lengths criteria")
 )
 (princ)
)

 

Hi

 

can please explain the code

 

ill tell what i understand

 

 

  1. get start,end and calculate the distance
  2. devide the total distance by 6 and by 8
  3. and than im lost

hope you can make my day again!

Shay

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