TRIG Lisp

Capture_10-19-2015

I was looking on the internet for a solution to the problem of graphing the Tangent and Secant functions with the boundless length lines and the undefined point between them when i found some nice clean autolisp functions from Craig Snyder published in Cadalyst magazine 1998 Hot Tip Harry. Tip 1458. They don’t call it Hot Tip Harry anymore, but its still a Hot Tip. AutoLisp is the first macro language in Autocad, wildly popular for 30 years.

I changed the conditional statements that guarded against drawing through the asymptotes, cleaned up some small errors. They were pretty clever though and I appreciate their concise approach.

The cosine and sine show the basic approach, iterate the angle in degrees, convert it to radians for the function, capture and draw individual lines.

(defun C:SINE (/ P1 P2 maxAngl Angl s Y )
   (setq maxAngl (getreal "Enter maximum angle (in degrees): "))
   (setq Angl 0)

   (while (>= maxAngl Angl)
      (setq s (* Angl (/ pi 180)))
      (setq Y (sin s))
      (setq P2 (list s Y))

      (if P1 (command "line" P1 P2 ""))
      (setq P1 P2)
      (setq Angl (+ Angl 1))
   ))


(defun C:COSINE (/ P1 P2 maxAngl Angl s Y )
   (setq maxAngl (getreal "Enter maximum angle (in degrees): "))
   (setq Angl 0)

   (while (>= maxAngl Angl)
      (setq s (* Angl (/ pi 180)))
      (setq Y (cos s))
      (setq P2 (list s Y))

      (if P1 (command "line" P1 P2 ""))
      (setq P1 P2)
      (setq Angl (+ Angl 1))
   ))

The Tangent function is the Sin t divided by the Cos t. The Cos t is zero at pi/2 and multiples. It never seems to error out, probably because the variables are Real or Doubles, because Pi is an irrational number and its never exactly zero. The Cotangent however starts with Sin 0 in the denominator and that is zero. It has to have a test for zero to run.

The lisp routines as downloaded from cadalyst did not have any limit to the length of the lines, which were very large, in the trillions. The asymptote test was to check when a y value went from negative to postive or vice versa. That had a bad side effect of putting a hole anytime the graph crossed the X-axis. A distance test fixes both problems – inconveniently long lines are not drawn, the asymptotes are not crossed, and the line crosses the X-axis like it should. I chose the length 30 arbitrarily. The Secant and Cosecant follow the same pattern. The distance test simplified all the conditionals. It is a built-in function in AutoLisp.

 (defun C:TANGENT (/ P1 P2 maxAngl Angl s Y )
   (setq maxAngl (getreal "Enter maximum angle (in degrees): "))
   (setq Angl 0)

   (while (>= maxAngl Angl)
      (setq s (* Angl (/ pi 180)))
      (setq Y ( / (sin s)(cos s)))
      (setq P2 (list s Y))

      (if P1
          (if (< (distance P1 P2) 30)
               (command "line" P1 P2 "" ) ) )
 
      (setq P1 P2)
      (setq Angl (+ Angl 1))
   ))


(defun C:COTANGENT (/ P1 P2 maxAngl Angl s Y )
   (setq maxAngl (getreal "Enter maximum angle (in degrees): "))
   (setq Angl 0)

   (while (>= maxAngl Angl)
      (setq s (* Angl (/ pi 180)))
       
     (if (/=(sin s) 0)
        (progn
      (setq Y ( / (cos s)(sin s)))
      (setq P2 (list s Y))))

      (if P1
         (if (< (distance P1 P2) 30)
            (command "line" P1 P2 "" ) ) )
 
      (setq P1 P2)
      (setq Angl (+ Angl 1))
   ))
(defun C:SECANT (/ P1 P2 maxAngl s Y )
   (setq maxAngl (getreal "Enter maximum angle (in degrees): "))
   (setq Angl 0)

   (while (>= maxAngl Angl)
      (setq s (* Angl (/ pi 180)))

   (if (/=(cos s) 0)
        (progn
      (setq Y ( / 1 (cos s)))
      (setq P2 (list s Y))))

      (if P1 
          (if (< (distance P1 P2) 30) 
            (command "line" P1 P2 "" )))
 
      (setq P1 P2)
      (setq Angl (+ Angl 1))
   ))


(defun C:COSECANT (/ P1 P2 maxAngl s Y )
   (setq maxAngl (getreal "Enter maximum angle (in degrees): "))
   (setq Angl 0)

   (while (>= maxAngl Angl)
      (setq s (* Angl (/ pi 180)))

     (if (/=(sin s) 0)
          (progn

      (setq Y ( / 1 (sin s)))
      (setq P2 (list s Y))))

      (if P1
          (if (< (distance P1 P2) 30) 
            (command "line" P1 P2 "" )))
 
      (setq P1 P2)
      (setq Angl (+ Angl 1))
   ))

The VBA routine I am using draws a polyline. To feed the polyline an array of points is created. Therefore this method where LINE is embedded in the loop and the “bad” segments are just skipped cannot be used. The ideas can, but we have another problem that we cannot use a single polyline if it is broken. We have good data of points in an array though. We can use the array as is. We just have to process it and make separate arrays from it for each polyline. It’s going to take some work.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s