Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

problems with if statement for an autoLisp newbie!

6 REPLIES 6
Reply
Message 1 of 7
130900
751 Views, 6 Replies

problems with if statement for an autoLisp newbie!

Hello!

 

I know the file is complicated, but if you could give me some hints, then I could explain me further about them.

I have a problem with if statements, and I would like to know if the following is formulated as it should be, because I have problem running the command, even if it is loaded through appload without problems:

(defun C:JCPerpendicul( / pt1 pt1x pt1y pt2 pt2x pt2y temppt tempptx temppty ix iy jcpDistance di nm)
    ;get the start point of the leader line
    (setq pt1(getpoint "\n Klik på start linie: "))
    (setq pt1x (car pt1))
    (setq pt1y (cadr pt1))
    ;get the end point of the leader line
    (setq pt2(getpoint "\n Klik på **** linie: "))
    (setq pt2x (car pt2))
    (setq pt2y (cadr pt2))
    ;Choose the point you want to have perpendiculary measured (and drawn) to the reference line
    (setq temppt(getpoint "\n Målt punkt "))
    (setq tempptx (car temppt))
    (setq temppty (cadr temppt))

    (if (< (+(*(- pt2x pt1x)(- pt2x pt1x))(*(- pt2y pt1y)(- pt2y pt1y))) (* 0.000001 0.000001))
        (progn
            ( )  ; If true chosse new temppt but I don't know how to write it!
            (if (or (< (/(+(*(- tempptx pt1x)(- pt2x pt1x))(*(- temppty pt1y)(- pt2y pt1y))) (+(*(- pt2x pt1x)(- pt2x pt1x))(*(- pt2y pt1y)(- pt2y pt1y)))) 0.000001)
                    (> (+(*(- tempptx pt1x)(- pt2x pt1x))(*(- temppty pt1y)(- pt2y pt1y))) 1)
                )    
                (progn
                    (
                        (setq ix (+(*(- tempptx pt1x)(- tempptx pt1x))(*(- temppty pt1y)(- temppty pt1y))))
                        (setq iy (+(*(- tempptx pt2x)(- tempptx pt2x))(*(- temppty pt2y)(- temppty pt2y))))
                        ( cond
                            (
                                (< ix iy)
                                (setq jcpDistance (ix))
                            )
                            (
                                (< iy ix)
                                (setq jcpDistance (iy))
                            )
                        )
                        (setq jcpDistance (sqrt jcpDistance))
                    )    
                    (
                        (setq ix (+ pt1x (* (+(*(- tempptx pt1x)(- pt2x pt1x))(*(- temppty pt1y)(- pt2y pt1y))) (- ptx2 ptx1))))
                        (setq iy (+ pt1y (* (+(*(- tempptx pt1x)(- pt2x pt1x))(*(- temppty pt1y)(- pt2y pt1y))) (- pty2 pty1))))
                        (setq jcpDistance (+(*(- tempptx ix)(- tempptx ix))(*(- temppty iy)(- temppty iy))))
                        (setq jcpDistance (sqrt jcpDistance))
                    )    
                )
            )
        )
    )

;(setq (car ix) pti) Here I would like to pass the x coordinate in a new point but I don't know how to write it!
;(setq (cadr iy) pti) Here I would like to pass the y coordinate in a new point but I don't know how to write it!

; FROM HERE I KNOW THE CODE IS WORKING    
; Horizontal distance
(setq jcpDistance (* jcpDistance 1000))
; Convert Float to int
 (setq jcpDistance (fix jcpDistance))
; Convert int to str
    (setq jcpDistance (itoa jcpDistance))
; Add mm. to string
    (setq jcpDistance (strcat jcpDistance "mm."))
; Write distance in mm.   
    (command "TEXT" "j" "br" temppt "" jcpDistance)
;    Draw arrow
    (setq di (/ jcpDistance 3.0) nm (trans '(0. 0. 1.) 1 0 t) )
    (entmake
        (list
            '(0 . "LWPOLYLINE")
            '(100 . "AcDbEntity")
            '(100 . "AcDbPolyline")
            '(90 . 3)
            '(70 . 0)
            (cons 10 (trans temppt 1 nm))
            '(40 . 0.0)
            (cons 41 (/ di 2.0))
            (cons 10 (trans (polar pt1 (angle temppt pt1) di) 1 nm))
            (cons 10 (trans temppt 1 nm))
            (cons 210 nm)
        )
    )
    (princ)
)

 

6 REPLIES 6
Message 2 of 7
martti.halminen
in reply to: 130900

Before going to the real problems, you should work a little on the readability.

Your test clauses in the IF statements are pretty unreadable, you should separate them to their own functions, named clearly and the variable parts as parameters. Some comments might be useful, too.

 

Also, how about (defun sqr (a) (* a a))

- using this would make the stuff  more readable:

(setq iy (+ (sqr (- tempptx pt2x))
                (sqr (- temppty pt2y))))

instead of

(setq iy (+(*(- tempptx pt2x)(- tempptx pt2x))(*(- temppty pt2y)(- temppty pt2y))))

etc.

 

Your major problem seems to be misunderstanding the role of parentheses in Lisp. Unlike many other languages, you can not freely add parentheses to group separate parts in Lisp. Whenever you have a list as part of program text (not data), the first item must evaluate to a function definition.

 

So instead of using ( ... ), use (progn ... ) to group stuff.

 

Similarly,  if you pop parens around the name of a variable, the system tries to call it as a function

. Only works if the value is something like #<SUBR @0000000038f32bd8 PLUS>

 

You have stuff like

(cond  ((< ix iy)
            (setq jcpDistance (ix))) )

Here the first ix is a number (or creates an error), so (ix) tries to call a number as a function.

 

That works just like this:

$ (55)
; error: bad function: 55

 

--

 

Message 3 of 7
Kent1Cooper
in reply to: 130900

I think you can reduce the amount of code considerably by using some functions that you may not be aware of.  For instance, it looks like this:

 

    (if (< (+ (* (- pt2x pt1x) (- pt2x pt1x)) (* (- pt2y pt1y) (- pt2y pt1y))) (* 0.000001 0.000001))

 

is calculating the distance between pt1 and pt2, and whether it's less than 0.000001, using Pythagoras's sum-of-squares approach but without bothering to take the square root of the sum for the actual length of the hypotenuse.  In place of that approach, there's a function to get the distance between two points directly, and you can express the small tolerance distance in scientific notation.  I think this is equivalent to what you have above:

 

    (if (< (distance pt1 pt2) 1e-6)

 

Another even shorter way is to check whether the two points are equal to within that tolerance:

 

    (if (equal pt1 pt2 1e-6)

 

You may be able to eliminate the separate variables for X and Y components of points entirely using those methods, though I haven't analyzed the entire routine enough to know.

 

Also [though you may not need this at all if you use the above methods], look at the (expt) function to raise numbers to powers.  This:

 

    (* (- pt2x pt1x) (- pt2x pt1x))

 

can be done this way:

 

    (expt (- pt2x pt1x) 2)

 

An image or sample drawing would be helpful to understand what you are trying to do, because there may be other functions that can similarly do other parts of it much more directly.

Kent Cooper, AIA
Message 4 of 7
Kent1Cooper
in reply to: 130900

Another little thing:

 

Your jcpdistance text string thing, using (fix), will round the result downward only.  If you want it rounded to the nearest whole number, whether that should be upward or downward, you can replace this:

 

; Horizontal distance
    (setq jcpDistance (* jcpDistance 1000))
; Convert Float to int
    (setq jcpDistance (fix jcpDistance))
; Convert int to str
    (setq jcpDistance (itoa jcpDistance))
; Add mm. to string
    (setq jcpDistance (strcat jcpDistance "mm."))

 

with this:

 

  (setq jcpdistance (strcat (rtos (* jcpdistance 1000) 2 0) "mm."))

Kent Cooper, AIA
Message 5 of 7
130900
in reply to: Kent1Cooper

Sorry for the delay, but I was in the field!

Thank you for your answers Martti & Kent. Smiley Happy

I am going to work on your suggestions.

I am quiet new with AutoLISP and the main problem for me, was to make something works, and it is mostly.

I am aware that I can improve my knowledge a lot, but I can't really use my Pascal experience her.

Anyway thanks again. I am not closing the thread yet, because I already know, that I will have more questions soon.

In the meantime I wish you a nice day, whereever you are.

 

Best Regards

Jean-Christophe

Message 6 of 7
doni49
in reply to: 130900

I tried to look through your code.  It looks really complicated -- especially for a self-described "newbie".

 

My best advice would be to work on getting a firm understanding of the basics and THEN dig in to your complicated routine.  It'll make your final result so much better (easier for you to troubleshoot later if need-be AND probably give better performance).

 

And when I say "the basics", I mean every aspect of what the script uses -- make sure you understand how to build points, how to best use if statements how entmake works etc.  Don't be afraid to ask questions if you're unable to figure out what some function does.

 

We've all been new at some point so we've all been there.



Don Ireland
Engineering Design Technician




If a reply solves your issue, please remember to click on "Accept as Solution". This will help other users looking to solve a similar issue. Thank you.


Please do not send a PM asking for assistance. That's what the forums are for. This allows everyone to benefit from the question asked and the answers given.

Message 7 of 7
doni49
in reply to: doni49

I just read through some of your code.

 

Instead of

(cond
  (
    (< ix iy)
    (setq jcpDistance (ix))
  )
  (
    (< iy ix)
    (setq jcpDistance (iy))
  )
)

 

 

Try

;your test condition can only be true or false -- perfect for IF statement.
(if
  (< ix iy)  ;Test Condition
  (setq jcpDistance (ix)) ;If the test condition is true
  (setq jcpDistance (iy)) ;If the test condition is false
)

 And save this one for after you've gotten to the point where you have a firm grasp of this stuff.

 

The above can be boiled down even further to this:

 

(setq jcpDistance (if (< ix iy) ix iy))

 



Don Ireland
Engineering Design Technician




If a reply solves your issue, please remember to click on "Accept as Solution". This will help other users looking to solve a similar issue. Thank you.


Please do not send a PM asking for assistance. That's what the forums are for. This allows everyone to benefit from the question asked and the answers given.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

”Boost