Lisp Setup

To make pretty math graphs with lineweights, colors, background and good looking fonts with math symbols, we will need some basic setup tools.

Everybody has a lisp setup. This is the easy way, using the command function from lisp, but a DCL dialog cannot call the command function. It exits with error “unhandled exception.” Twas ever thus and evermore shall be.

(defun setup ()
(setq LT "continuous" LW "0.35")

(makelayer "Axis" 1 LT LW)
(makelayer "Directrix" 5 LT LW)
(makelayer "Focus" 5 LT LW)
(makelayer "Asymptote" 5 LT "Default")
(makelayer "Graph" 7 LT LW)

(makelayer "1" 1 LT LW)
(makelayer "2" 2 LT LW)
(makelayer "3" 3 LT LW)
(makelayer "4" 4 LT LW)
(makelayer "5" 5 LT LW)
(makelayer "6" 6 LT LW)
(makelayer "7" 7 LT LW)
(makelayer "8" 8 LT LW)
(makelayer "9" 9 LT LW)

(command "layer" "s" "graph" "")
(command "units" "2" "4" "1" "2" "0" "N" )
(command "setvar" "LWDISPLAY" 1)

(maketextstyle "Arial" "Arial")
(maketextstyle "Arial Narrow" "Arial Narrow")
(maketextstyle "Calibri" "Calibri")
(maketextstyle "Calibri Light" "Calibri Light")
(maketextstyle "Courier New" "Courier New")

(maketextstyle "Table1" "Arial Narrow")
(c:romans)
)


(defun makelayer (name color linetype lineweight )
(command "layer" "m" name "c" color "" "L" linetype "" "LW" lineweight "" "") )

(defun maketextstyle (name fontname )
(command "style" name fontname "0" "1.0" "0" "No" "No" ))

(defun c:romans()
(command "style" "RomanS" "romans" "0" "0.75" "0" "No" "No" "No"))


; background shades of gray
(defun bkg (rgbnum)
(setq hexnum (rgbhex rgbnum))

(setq acadobject (vlax-get-acad-object))
(setq acadpref (vlax-get-property acadobject 'preferences))
(setq acaddisp (vlax-get-property acadpref 'display))
(vlax-put-property acaddisp 'GraphicsWinmodelBackgrndColor hexnum) )


  (defun RGBhex (RGBnum / r g b)
    (setq r (lsh RGBnum 16))
    (setq g (lsh RGBnum 8))
    (setq b RGBnum)
    (+ (+ r g) b)  )

to run code above from a DCL dialog we need to replace the command functions with entmake or visual lisp activeX methods.

for textstyle creation
http://adndevblog.typepad.com/autocad/2012/12/how-to-programmatically-create-a-new-text-style-with-truetype-fonts-in-lisp.html

autolisp layer entmake search yields many results.

for reference get the dxf codes returned for objects –

Command: (entget (tblobjname “layer” “0”))
((-1 . )
(0 . “LAYER”)
(5 . “10”)
(102 . “{ACAD_XDICTIONARY”)
(360 . )
(102 . “}”)
(330 . )
(100 . “AcDbSymbolTableRecord”)
(100 . “AcDbLayerTableRecord”)
(2 . “0”)
(70 . 0)
(62 . 7)
(6 . “Continuous”)
(290 . 1)
(370 . -3)
(390 . )
(347 . )
(348 . ))

Command: (entget (tblobjname “style” “arial”))
((-1 . )
(0 . “STYLE”)
(330 . )
(5 . “21B”)
(100 . “AcDbSymbolTableRecord”)
(100 . “AcDbTextStyleTableRecord”)
(2 . “Arial”)
(70 . 0)
(40 . 0.0)
(41 . 1.0)
(50 . 0.0)
(71 . 0)
(42 . 0.2)
(3 . “Arial”)
(4 . “”))

makelayer and maketextstyle are remade with the same argument list –

(DEFUN makelayer (name color Linetype Lineweight)
(entmake (list (cons 0 “LAYER”)
(cons 100 “AcDbSymbolTableRecord”)
(cons 100 “AcDbLayerTableRecord”)
(cons 2 name)
(cons 70 0)
(cons 62 color)
(cons 6 Linetype)
(cons 290 1)
(cons 370 Lineweight))))

(DEFUN maketextstyle (name fontname)
(entmake (list (cons 0 “STYLE”)
(cons 100 “AcDbSymbolTableRecord”)
(cons 100 “AcDbTextStyleTableRecord”)
(cons 2 name)
(cons 3 fontname)
(cons 70 0)
(cons 40 0.0)
(cons 41 1.0)
(cons 50 0.0)
(cons 71 0))))

autocad will let us know if DXF does not like the structure of the DXF code. We have to find the actual font name and suffix the extension.

(maketextstyle “Arial” “Arial.ttf”)
(maketextstyle “Arial Narrow” “ArialN.ttf”)
(maketextstyle “Calibri” “Calibri.ttf”)
(maketextstyle “Calibri Light” “CalibriL.ttf”)
(maketextstyle “Courier New” “Cour.ttf”)
(maketextstyle “Symbol” “Symbol.ttf”)

similarly the lineweight must be changed from 0.35 to 35, there may be other minor differences, such as the value for “Default” that has to be figured out. query the actual object in the drawing with the entget function above.

Fonts consist of 256 characters. a table 16 X 16 can display them all. Addtable works closely with the Tablestyle creation program. I have a statement to load Make_Ts at the head of the FontTable program. The tablestyle program uses the current textstyle and names itself the same way. to make a font table with a different font, i change the current textstyle, then re-run fonttable. This is a good reference for viewing the entire table for symbols and also i expect it to be handy for cut and paste to find greek symbols.

The original verson of the lisp tablestyle creation was taken from Lee Ambrosius’ blog
http://hyperpics.blogs.com/beyond_the_ui/2012/07/creating-a-table-style-with-autolisp-and-the-activex-api.html

(vl-load-com)

(defun c:Fonttable()
    
(load "c:\\LISP\\Table\\Make_TS.LSP")
(make_ts)

(setq numrows 17 numcolumns 16 rowheight 0.25 colwidth 0.375)

   (setq acadObj (vlax-get-acad-object))
   (setq doc (vla-get-ActiveDocument acadObj))

   (setq pt (vlax-3d-point 0 0 0))

   (setq modelSpace (vla-get-ModelSpace doc))
   (setq fTable (vla-Addtable modelSpace pt numrows numcolumns rowheight colwidth))
  
   (vla-settext fTable 0 0 (getvar "textstyle"))
    
   (vla-put-HeaderSuppressed ftable :vlax-true)

   (setq rownum 1 colnum 0 chrnum 0)

(repeat 16

  (repeat 16
      (vla-settext fTable rownum colnum (chr chrnum))
      (setq colnum (1+ colnum))
      (setq chrnum (1+ chrnum))) 

     (setq rownum (1+ rownum))
     (setq colnum 0)
  )
)


(defun Make_TS()
;original version from 
;;http://hyperpics.blogs.com/beyond_the_ui/2012/07/creating-a-table-style-with-autolisp-and-the-activex-api.html
; some of his code i changed i commented out as this file changes a lot depending on specific requirements
; and it is helpful to keep alternate methods and settings available.

;tablestyle uses and is named by current textstyle
(setq textstyle (getvar "textstyle"))

    ;; Get the AutoCAD application and current document
    (setq acadobj (vlax-get-acad-object))
    (setq doc (vla-get-ActiveDocument acadobj))

    ;; Get the Dictionaries collection and the TableStyle dictionary
    (setq dicts (vla-get-Dictionaries doc))
    (setq dictObj (vla-Item dicts "acad_tablestyle"))
    
    ;; Create a custom table style
    (setq key textstyle
          class "AcDbTableStyle")
    (setq custObj (vla-AddObject dictObj key class))

    ;; Set the name and description for the style
    (vla-put-Name custObj textstyle)
    (vla-put-Description custObj "Font named table style")

    ;; Sets the bit flag value for the style
    (vla-put-BitFlags custObj 1)

    ;; Sets the direction of the table, top to bottom or bottom to top
    (vla-put-FlowDirection custObj acTableTopToBottom)

    ;; Sets the supression of the table header
    ;; Does not seem to do anything in tablestyle
    ;; same statement using created table object must be in addtable
    (vla-put-HeaderSuppressed custObj :vlax-true)

    ;; Sets the horizontal margin for the table cells
    (vla-put-HorzCellMargin custObj 0.03)

    ;; Sets the supression of the table title
    (vla-put-TitleSuppressed custObj :vlax-false)

    ;; Sets the vertical margin for the table cells
    (vla-put-VertCellMargin custObj 0.03)

    ;; Set the alignment for the Data, Header, and Title rows
    ;; (vla-SetAlignment custObj (+ acDataRow acTitleRow) acMiddleLeft)
    (vla-SetAlignment custObj acDataRow acMiddlecenter)
    (vla-SetAlignment custObj acHeaderRow acMiddleCenter)
    (vla-SetAlignment custObj acTitleRow acMiddleCenter)

    ;; Set the background color for the Header and Title rows
    
    (setq colObj (vlax-create-object "AutoCAD.AcCmColor.21"))
    
    ;(vla-SetRGB colObj 98 136 213)
    ;(vla-SetBackgroundColor custObj (+ acHeaderRow acTitleRow) colObj)

    ;; Clear the background color for the Data rows
    (vla-SetBackgroundColorNone custObj acDataRow :vlax-true)

    ;; Set the bottom grid color for the Title row
    ;;63 is all gridlinetypes and 7 is all rowtypes
    (vla-SetRGB colObj 0 0 255)
    (vla-SetGridColor custObj 63 7 colObj)

;;     to set individual - bottom grid color for the Title row
;;    (vla-SetGridColor custObj acHorzBottom acTitleRow colObj)

   ;; Set the bottom grid lineweight for the Title row
    (vla-SetGridLineWeight custobj acHorzBottom acTitleRow acLnWt025)

    ;; Set the inside grid lines visible for the data and header rows
    (vla-SetGridVisibility custObj acHorzInside  (+ acDataRow acHeaderRow) :vlax-true)

    ;; Set the text height for the Title, Header and Data rows
    (vla-SetTextHeight custObj acTitleRow 0.25)
    (vla-SetTextHeight custObj acHeaderRow 0.125)
    (vla-SetTextHeight custObj acDataRow 0.125)

    ;; Set the text style
    ;;(vla-SetTextStyle custObj (+ acDataRow acHeaderRow acTitleRow) "Standard")
    (vla-SetTextStyle custObj (+ acDataRow acHeaderRow acTitleRow) (getvar "textstyle"))

    ;; Release the color object
    (vlax-release-object colObj)
   (setvar "ctablestyle" textstyle)

  (princ)
)

Advertisements

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.
http://www.lee-mac.com/readcsv.html

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)
(eval (read strfunc)) returns 8.82

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
  (load (strcat graph_progdir "catalog.lsp"))

 (setq dcl_id (load_dialog (strcat graph_progdir "graph.dcl")))
  (if (< dcl_id 0)
    (progn
      (alert "The graph.DCL file could not be loaded.")
      (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))
  (unload_dialog dcl_id)
  (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"))

;;*********************************************
;; Read CSV code from
;;http://www.lee-mac.com/readcsv.html
;;*********************************************
(setq data (LM:readcsv file))


(setq theList1  (mapcar 'car data))
(setq theList2  (mapcar 'cadr data))
(setq theList3  (mapcar 'caddr 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)
    (progn  (alert "The catalog.DCL file could not be loaded.")
      (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)
  (mapcar 'add_list theList1)
  (end_list)

  (start_list "list2" 3)
  (mapcar 'add_list theList2)
  (end_list)

  (start_list "list3" 3)
  (mapcar 'add_list theList3)
  (end_list)

  (start_list "list4" 3)
  (mapcar 'add_list theList4)
  (end_list)

  (start_list "list5" 3)
  (mapcar 'add_list theList5)
  (end_list)

  (start_list "list6" 3)
  (mapcar 'add_list theList6)
  (end_list)

  (start_list "list7" 3)
  (mapcar 'add_list theList7)
  (end_list)

  (start_list "list8" 3)
  (mapcar 'add_list theList8)
  (end_list)

  (start_list "list9" 3)
  (mapcar 'add_list theList9)
  (end_list)

  (start_list "list10" 3)
  (mapcar 'add_list theList10)
  (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))
  (unload_dialog dcl_id)

  ;(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; }
                   }
    	
           }

Lisp Parabola

This is pretty simple. Its a start. Func1 defines the equation ax^2 + bx + c with the specific values of a b and c and returns the value when passed the current value of X.  C:para calls the parabola function and sets the x minimum, maximum and x increment.

screenshot from the visual lisp editor.
2017-03-05_2

if instead of unconnected lines, we want to graph with a 2D Polyline, the command is PLine, it takes the same point list. We start the Pline command with the first point, then enter the loop and calculate the next point each time through the loop, leaving the command processor running and just feeding it one point each time.

2017-03-05_4

For graphing polar equations – Polar Coordinates – P(R,Ɵ) – A point is defined by how far it is from the origin (R – Radius) and what angle (Ɵ – Theta) a line from the origin to the point makes with the horizontal axis. (I am using A for angle instead of Ɵ in the code)

To change the command from separate lines to connected polyline, we start the pline command outside the loop and only calculate one point in the loop, just as for the rectangular cartesian program.

Creating the Graph Point Data

Autocad AddLightWeightPolyline method requires an array of doubles. It does not require the lowerbound of the array to be zero. An array simply has to have an even number of elements, one element for each X and each Y alternating. (x1, y1, x2, y2, x3, y3…) For indexes and loops I typically use the counting numbers, which do not include zero. I am evaluating an autocad work-alike program that is similar but requires arrays to be zero-based. It does not throw an error with a one-based array but results are a failure. it creates zero values for non-existent indexes that it expects. However there is no reason the arrays cannot be zero-based so they run in both packages. To that end for that reason i am re-doing the graph loops.

Only the array needs to be zero based. The loop still executes one time for each point. The index of the array starts with zero.

Calculation of points for Coordinate XY graphing –

2016-10-03_1

Autocad does not care what indexes the array pt (below) was created with. The work-alike absolutely requires a starting index of zero.

Dim plineobj As AcadLWPolyline
Set plineobj = acadDoc.ModelSpace.AddLightWeightPolyline(pt)

in line drawing mode, subtracting lbound from ubound adding one and dividing by two will give the number of points in the array. There is one less line. Since we know lbound is zero we could remove that. The loop iterates once for each line drawn. We could do the loop to handle any lbound value, but it would be a little messy with no immediate benefit. For now we expect a zero base array.

Sub draw_lines(ByRef pt() As Double)
Dim lineobj As AcadLine
Dim i As Integer, numpts As Integer, numlines As Integer
Dim x1 As Double, x2 As Double, y1 As Double, y2 As Double
Dim pt1(0 To 2) As Double
Dim pt2(0 To 2) As Double

numpts = (UBound(pt) - LBound(pt) + 1) / 2
numlines = numpts - 1

'this requires a zero base array
For i = 1 To numlines
x1 = pt(i * 2 - 2)
y1 = pt(i * 2 - 1)
x2 = pt(i * 2)
y2 = pt(i * 2 + 1)

pt1(0) = x1: pt1(1) = y1: pt1(2) = 0
pt2(0) = x2: pt2(1) = y2: pt2(2) = 0
Set lineobj = acadApp.ActiveDocument.ModelSpace.AddLine(pt1, pt2)

Next i

Update
End Sub

Lines w/limits mode we use when the Y value approaches infinity, such as y=1/x near x=0. It is otherwise the same.

Sub draw_lines_wlimits(xlim As Double, ylim As Double, ByRef pt() As Double)
Dim lineobj As AcadLine
Dim i As Integer, numpts As Integer, numlines As Integer
Dim x1 As Double, x2 As Double, y1 As Double, y2 As Double
Dim pt1(0 To 2) As Double
Dim pt2(0 To 2) As Double

numpts = (UBound(pt) - LBound(pt) + 1) / 2
numlines = numpts - 1

'this requires a zero base array
For i = 1 To numlines
x1 = pt(i * 2 - 2)
y1 = pt(i * 2 - 1)
x2 = pt(i * 2)
y2 = pt(i * 2 + 1)

If Abs(x1) < xlim And Abs(y1) < ylim And Abs(x2) < xlim And Abs(y2) < ylim Then
pt1(0) = x1: pt1(1) = y1: pt1(2) = 0
pt2(0) = x2: pt2(1) = y2: pt2(2) = 0
Set lineobj = acadApp.ActiveDocument.ModelSpace.AddLine(pt1, pt2)
End If
Next i

Update
End Sub

point mode


Sub draw_points(ByRef pt() As Double)
Call pointmode
Dim pointobj As AcadPoint
Dim i As Integer, numpts As Integer
Dim x1 As Double, y1 As Double

Dim pt1(0 To 2) As Double
numpts = (UBound(pt) - LBound(pt) + 1) / 2

'this requires a zero base array
For i = 1 To numpts
x1 = pt(i * 2 - 2)
y1 = pt(i * 2 - 1)
pt1(0) = x1: pt1(1) = y1: pt1(2) = 0
Set pointobj = acadDoc.ModelSpace.AddPoint(pt1)
Next i

Update
End Sub

Autocad Graphing Calculator

Autocad has Euclidean roots. Its a classic geometry tool. And it has VBA. It is not necessary to download and install the VBA module to have full access to VBA through Excel.

this blog online 1 year with 100 pages, approx, More to come.

i apologize for the old posts with messed up links and code mangling. wordpress changed their editor last year and between them and me changing the theme, we messed up a few pages that were ok when first published. i just noticed some new broken links.

2016-09-05_1

Lissajous curves gone wrong. I unchecked the convert to Radians button in the Parametric form before graphing, so that Sin(360) is interpreted by VBA not as Sin(2 pi) but Sin(360) or in radians Sin(57 * 2 pi) approx, but more importantly the step increment between points instead of being 1 degree is 1 radian or 57 degrees.

2016-09-05_2

the Cochleoid

the Cochleoid is a polar spiral that spirals in on itself, because Sin A varies between -1 and 1, but A gets ever larger.

2016-08-29_1

at point 8 A is 210, not 30, but because the Sin is negative, R is negative. The graph passes thru 0,0 every time the sin is zero.

2016-08-29_2

running the graph from negative 1080 (-6 pi) to -1 (to avoid divide by zero error) draws the mirror image graph from the inside out.

2016-08-29_3

2016-08-29_4

wolfram reference
http://mathworld.wolfram.com/Cochleoid.html