# Curve Catalog

AutoLisp DCL Curve Graphing with curve “recipes” – equation, x value ranges, x value increment – saved and retrieved in an excel CSV file. Curve parameters in an excel list can be edited, sorted and re-organized. A sub-form Curve Catalog is popped up, data filled from the CSV file. User selects curve. Parameters are input to the Graph screen.

The code to Read the Excel.CSV file was written by Lee Mac and downloaded from his premier lisp site.

Graphing mathematical equations with autolisp –
as an example,
(setq strfunc “(* a x x )”)
(setq a 2) returns 2
(setq x 2.1) returns 2.1
Strfunc returns “(* a x x )”
(read strfunc) returns (* A X X)

With this we can set up a function to return a result for any legal lisp statement and values x a b c d.
The function is passed as a string, strfunc. X is passed in as a Real. X will vary with each call from xmin to xmax by increment xinc,
The global vars for a_dim b_dim c_dim and d_dim do not vary.

(defun func_eval (x strfunc / a b c d)
(setq a a_dim b b_dim c c_dim d d_dim )
(setq result (eval (read strfunc))) )

The equations must be input in lisp form, prefix notation with the operator first in a list, expressions nested. As long as it is legal lisp, the above code will interpret it. The loop to draw the curve is basic lisp using the command function for either line or pline.

```;; location of
;; graph.lsp and dcl
;; catalog.lsp and dcl
;; curve_catalog.csv

(setq graph_progdir "c:\\lisp\\graph\\")

(defun c:graph ()
;catalog sub form program

(setq dcl_id (load_dialog (strcat graph_progdir "graph.dcl")))
(if (< dcl_id 0)
(progn
(exit) ) )

(if (not (new_dialog "graph" dcl_id))
(progn
(alert "DCL file loaded but not definition, internal problem with files" )
(exit) )   )

(set_graph_vars)
(action_tile "catalog" "(catalog) (set_graph_vars)")
(action_tile "graphlines" "(savevars) (done_dialog 2)")
(action_tile "graphpolylines" "(savevars) (done_dialog 3)")
(action_tile "cancel" "(done_dialog 0)")

(setq ddiag (start_dialog))
(if (= ddiag 2) (graphlines) )
(if (= ddiag 3) (graphpolylines) )
)

(defun savevars	()
(setq xmin (atof (get_tile "xmin")))
(setq xmax (atof (get_tile "xmax")))
(setq xinc (atof (get_tile "xinc")))
(setq a_dim (atof (get_tile "a_dim")))
(setq b_dim (atof (get_tile "b_dim")))
(setq c_dim (atof (get_tile "c_dim")))
(setq d_dim (atof (get_tile "d_dim")))
(setq strfunc (get_tile "equation"))
)

(defun set_graph_vars ()
(if xmin
(set_tile "xmin" (rtos xmin 2 2))
(set_tile "xmin" "-3.0")  )

(if xmax
(set_tile "xmax" (rtos xmax 2 2))
(set_tile "xmax" "3.0")  )

(if xinc
(set_tile "xinc" (rtos xinc 2 2))
(set_tile "xinc" "0.1")  )

(if a_dim
(set_tile "a_dim" (rtos a_dim 2 2))
(set_tile "a_dim" "2")  )

(if b_dim
(set_tile "b_dim" (rtos b_dim 2 2))
(set_tile "b_dim" "3")  )

(if c_dim
(set_tile "c_dim" (rtos c_dim 2 2))
(set_tile "c_dim" "4")  )

(if d_dim
(set_tile "d_dim" (rtos d_dim 2 2))
(set_tile "d_dim" "5")  )

;initial equation ax^2 + bx + c
(if (null strfunc)
(set_tile "equation" "(+ (* a X X) (* b X) c)")
(set_tile "equation" strfunc)  )
)

(defun func_eval (x strfunc / a b c d)
(setq	a a_dim    b b_dim   c c_dim   d d_dim  )
(setq result (eval (read strfunc))) )

(defun graphlines ()	;working with all global variables from savevars

(setq numlines (/ (- xmax xmin) xinc))
(setq i 1)
(setq x1 xmin)
(setq y1 (func_eval x1 strfunc))

(repeat (fix numlines)

(setq x2 (+ xmin (* i xinc)))
(setq y2 (func_eval x2 strfunc))

(setq pt1 (list x1 y1))
(setq pt2 (list x2 y2))

(command "line" pt1 pt2)
(command)

(setq x1 x2)
(setq y1 y2)

(setq i (1+ i))
)
)

(defun graphpolylines ()    ;working with all global variables from savevars

(setq numlines (/ (- xmax xmin) xinc))
(setq x1 xmin)
(setq y1 (func_eval x1 strfunc))
(setq pt1 (list x1 y1))

(command "pline" pt1)

(setq i 1)
(repeat (fix numlines)

(setq x2 (+ xmin (* i xinc)))
(setq y2 (func_eval x2 strfunc))

(setq pt2 (list x2 y2))

(command pt2)
(setq i (1+ i))
)
(command)
)

```

Graph.DCL is straightforward

Each curve then is defined by its lisp string, xmin, xmax, xinc and the specific values of A B C and D if they are used. Those 8 variables can be saved in an Excel file, a list of curve recipes, and input to the Graph program through a nested dialog called Catalog. A couple extra information columns are added.

The Excel format is called CSV, Comma Separated Values. It is actually a text file. It can be loaded directly into a text editor. Autolisp has tools to read this format. Excel is very handy for displaying and managing it. Lee Mac’s program reads the table and returns a list of rows with each cell a separate item in the sub-list. With Lisp tools we can take that and re-display the CSV file in DCL list boxes.

I only make one list box active to user selection, the box with the legal lisp equation. the other boxes are for user reference. all list boxes are given the same height and handled the same way so the rows line up. When the user selects an equation, its parameters are written to the textboxes, however he has to select OK to dismiss the dialog and use the parameters. Selecting cancel will abandon the values and return the previous screen with the values unchanged.

Here is Catalog LSP, called from the button on Graph. much of its length is just from loading the 10 listboxes and dealing with variables.

```;catalog_lsp called from graph_lsp

(defun catalog_setup ()
(setq file (strcat graph_progdir "curve_catalog.csv"))

;;*********************************************
;;*********************************************

(setq theList1  (mapcar 'car data))

(setq theList4  (mapcar '(lambda (abc) (nth 3 abc)) data))
(setq theList5  (mapcar '(lambda (abc) (nth 4 abc)) data))
(setq theList6  (mapcar '(lambda (abc) (nth 5 abc)) data))
(setq theList7  (mapcar '(lambda (abc) (nth 6 abc)) data))
(setq theList8  (mapcar '(lambda (abc) (nth 7 abc)) data))
(setq theList9  (mapcar '(lambda (abc) (nth 8 abc)) data))
(setq theList10  (mapcar '(lambda (abc) (nth 9 abc)) data))
)

(defun catalog ()
(catalog_setup)

(setq dcl_id (load_dialog (strcat graph_progdir "catalog.dcl")))
(if (< dcl_id 0)
(exit) ) )

(if (not (new_dialog "catalog" dcl_id))
(progn (alert "DCL file loaded but not definition, internal problem with files")
(exit) ) )

(set_catalog_vars)

(start_list "list1" 3)
(end_list)

(start_list "list2" 3)
(end_list)

(start_list "list3" 3)
(end_list)

(start_list "list4" 3)
(end_list)

(start_list "list5" 3)
(end_list)

(start_list "list6" 3)
(end_list)

(start_list "list7" 3)
(end_list)

(start_list "list8" 3)
(end_list)

(start_list "list9" 3)
(end_list)

(start_list "list10" 3)
(end_list)

;only list that is pickable is lisp equation
(action_tile "list3" "(list-pick)")

(action_tile "ok" "(savevars) (done_dialog 2)")
(action_tile "cancel" "(done_dialog 0)")

(setq ddiag (start_dialog))

;(if (= ddiag 2) (nothing) )
;not required - savevars in ok button writes vars
;catalog button in graph lsp reads vars to screen
)

(defun savevars	()
(setq xmin (atof (get_tile "xmin")))
(setq xmax (atof (get_tile "xmax")))
(setq xinc (atof (get_tile "xinc")))

(setq a_dim (atof (get_tile "a_dim")))
(setq b_dim (atof (get_tile "b_dim")))
(setq c_dim (atof (get_tile "c_dim")))
(setq d_dim (atof (get_tile "d_dim")))

(setq strfunc (get_tile "equation"))
)

(defun list-pick ()
(setq listval (get_tile "list3"))
(setq curve_recipe (nth (atoi listval) data))

(set_tile "equation" (nth 2 curve_recipe))
(set_tile "xmin" (nth 3 curve_recipe))
(set_tile "xmax" (nth 4 curve_recipe))
(set_tile "xinc" (nth 5 curve_recipe))
(set_tile "a_dim" (nth 6 curve_recipe))
(set_tile "b_dim" (nth 7 curve_recipe))
(set_tile "c_dim" (nth 8 curve_recipe))
(set_tile "d_dim" (nth 9 curve_recipe))
)

;code same as set_graph_vars, keeping them separate for now
(defun set_catalog_vars ()
(if xmin
(set_tile "xmin" (rtos xmin 2 2))
(set_tile "xmin" "-3.0") )

(if xmax
(set_tile "xmax" (rtos xmax 2 2))
(set_tile "xmax" "3.0") )

(if xinc
(set_tile "xinc" (rtos xinc 2 2))
(set_tile "xinc" "0.1") )

(if a_dim
(set_tile "a_dim" (rtos a_dim 2 2))
(set_tile "a_dim" "2") )

(if b_dim
(set_tile "b_dim" (rtos b_dim 2 2))
(set_tile "b_dim" "3") )

(if c_dim
(set_tile "c_dim" (rtos c_dim 2 2))
(set_tile "c_dim" "4") )

(if d_dim
(set_tile "d_dim" (rtos d_dim 2 2))
(set_tile "d_dim" "5") )

;initial equation ax^2 + bx + c
(if (null strfunc)
(set_tile "equation" "(+ (* a X X) (* b X) c)")
(set_tile "equation" strfunc) )
)

```

and last, the DCL file for Catalog, again much of its length is repeating operations for the many listboxes

```
catalog:dialog {
label = "Curve Catalog";

:row {
:list_box {
label ="Notes";
key = "list1";
height = 35;
width = 35;
multiple_select = false;
fixed_width_font = true;
value = "0"; }

:list_box {
label ="Description";
key = "list2";
height = 35;
width = 35;
multiple_select = false;
fixed_width_font = true;
value = "0"; }

:list_box {
label ="Function - *** PICK FROM THIS LIST ***";
key = "list3";
height = 35;
width = 50;
multiple_select = false;
fixed_width_font = true;
value = "0"; }

:list_box {
label ="Xmin";
key = "list4";
height = 35;
width = 7;
multiple_select = false;
fixed_width_font = true;
value = "0"; }

:list_box {
label ="Xmax";
key = "list5";
height = 35;
width = 7;
multiple_select = false;
fixed_width_font = true;
value = "0"; }

:list_box {
label ="Xinc";
key = "list6";
height = 35;
width = 7;
multiple_select = false;
fixed_width_font = true;
value = "0"; }

:list_box {
label ="A_Dim";
key = "list7";
height = 35;
width = 7;
multiple_select = false;
fixed_width_font = true;
value = "0"; }

:list_box {
label ="B_Dim";
key = "list8";
height = 35;
width = 7;
multiple_select = false;
fixed_width_font = true;
value = "0"; }

:list_box {
label ="C_Dim";
key = "list9";
height = 35;
width = 7;
multiple_select = false;
fixed_width_font = true;
value = "0"; }

:list_box {
label ="D_Dim";
key = "list10";
height = 35;
width = 7;
multiple_select = false;
fixed_width_font = true;
value = "0"; }
}

:row {
:edit_box {
label = "Xmin";
key = "xmin";}
:edit_box {
label = "Xmax";
key = "xmax";}
:edit_box {
label = "Xinc";
key = "xinc";}

:edit_box {
label = "A_dim";
key = "a_dim";}
:edit_box {
label = "B_dim";
key = "b_dim";}
:edit_box {
label = "C_dim";
key = "c_dim";}
:edit_box {
label = "D_dim";
key = "d_dim";}
}

:row {
:edit_box {
label = "Y = ";
key = "equation";}
}

:row {
: button {
label = "OK";
key = "ok";
is_default = true; }

: button {
label = "Cancel";
key = "cancel";
is_default = false;
is_cancel = true; }
}

}
```