Author Topic: how to use CADCAL as a Lisp code generator  (Read 904 times)

0 Members and 1 Guest are viewing this topic.

berger@archtools.de

  • Mosquito
  • Posts: 11
how to use CADCAL as a Lisp code generator
« on: July 05, 2024, 06:10:40 AM »
CADCAL (attached t this post) has been developed as a full replacement for AutoCAD's GeomCAL, but now has been enhanced to do parametric scripting, and to automatically generate full working Lisp code, whith which you can build complex Lisp applications.

CADCAL can be used just the same as GeomCAL, and so you can call the same math expressions as in GeomCAL, and use the results of that expressions as input for your CAD work, i.e.
(cal "(2*cur+cur)/3")
returns the point at 1/3 of the distance between the two points, which the user must pick with the curser.

But internally CADCAL is working a little bit different than GeomCal. CADCAL's parser (the part of the program that converts the input string to something that a computer can understand) first translates the string to a Lisp expression, which then is evaluated. Parsing is very computing intensive and therefore time consuming, and when CADCAL once has translated a math expression during the same drawing session, then it stores the Lisp expression for futire use. When in a loop the same math expression ist called 1000 times, CADCAL only needs to parse it a single time, and 999 times it can use the Lisp expression directly. This makes CADCAL really fast.

The user can use this translation for his own purposes. Simply use the CC-STR->LISP function:
(CC-STR->LISP "(2*cur+cur)/3")
returns
(§§/ (§§+ (LIST (§§* 2 (§§CUR)) (§§CUR))) 3)

The Lisp functions used in this Lisp expression are predefined in CADCAL. Since VisualLisp/AutoLisp doesn't allow macro programming (this is what makes Lisp to a "real" Lisp), there is no way to defun a function like +. The + function allows an arbitrary number of arguments, and AutoLisp only allows defining functions with a fix number of arguments. So the §§+ function from CADCAL, which can add any number of numbers or vectors, has only one single argument: a list, containing all arguments.

Now with the DCL frontend for CADCAL or GeomCAL (accessible by the command DDCAL) we also get a history of the last 30 math expressions used by CAL in this DWG file. Download CADCAL (see link below) and open the ./demo/nickshouse.scr, and call the DDCAL command to see what this means. Such a history of CAL calls is nothing else than a script. We can calculate the relevant coordinate points of any part, and let it draw automatically. The first solution was, to integrate the drawing work too into CAL calls. So there ist a CADCAL function PLINE(p1,p2,p3 ...) which creates a polyline over all the points in the argument list. And in this argument list the user can also integrate program options like "_a" for an arc, or "_cl" for "close".

But then it turned out that many companies since decades already defined the drawing of their parts as scripts. They used GeomCAL for the calculations, and ordinary command scripts for the drawing work.

So CADCAL now can translate not only the CAL calls in scripts to Lisp, but the whole script, including lines with Lisp code and all direct command calls.

There are two ways to do a translation. The function (CC-SCRIPTCORE->LISP <scriptfilename>) creates a 1:1 translation of the script, combining the translation of each single script line into a LAMBDA. There also is a command function SCRIPTCORE, which asks you for the scriptfilename before. I.e. this script
Code - Python: [Select]
  1. (if (not origin) (setq origin '(0 0 0)))
  2. (if (not long) (setq long 80))
  3. (if (not wide) (setq wide 100))
  4. ;;
  5. (setq p1 ORIGIN)
  6. CAL P2=P1+[long,0]
  7. CAL P3=P1+[long,wide]
  8. CAL P4=P1+[0,wide]
  9. ._pline !p1 !p2 !p3 !p4 _cl
  10. ._line !p1 !p3
  11. ._line !p2 !p4
  12.  

is translated to that LAMBDA:
Code - Auto/Visual Lisp: [Select]
  1. (LAMBDA NIL
  2.   (IF (NOT ORIGIN)
  3.     (SETQ ORIGIN '(0 0 0))
  4.   )
  5.   (IF (NOT LONG)
  6.     (SETQ LONG 80)
  7.   )
  8.   (IF (NOT WIDE)
  9.     (SETQ WIDE 100)
  10.   )
  11.   (SETQ P1 ORIGIN)
  12.   (SETQ P2 (§§+ (LIST P1 (LIST LONG 0))))
  13.   (SETQ P3 (§§+ (LIST P1 (LIST LONG WIDE))))
  14.   (SETQ P4 (§§+ (LIST P1 (LIST 0 WIDE))))
  15.   (COMMAND "._pline" P1 P2 P3 P4 "_cl")
  16.   (COMMAND "._line" P1 P3 "")
  17.   (COMMAND "._line" P2 P4 "")
  18. )
  19.  


But there is another, much more powerful way. It requires that the parameters of the script before are defined by the special CADCAL expression
CAL IMPORT(long,80,wide,120)
This has the very same effect as declaring the variables LONG and WIDE with default values as in Lisp or in a CAL expression. But this single extra line enables CADCAL to define a much more complex Lisp function with LONG and WIDE as arguments. And this function then can create a drawing, which can be modified parametrically any time later.

Now the script looks like that:
Code - Python: [Select]
  1. CAL IMPORT(long,80,wide,120)
  2. ;;
  3. (setq p1 ORIGIN)
  4. CAL P2=P1+[long,0]
  5. CAL P3=P1+[long,wide]
  6. CAL P4=P1+[0,wide]
  7. ._pline !p1 !p2 !p3 !p4 _cl
  8. ._line !p1 !p3
  9. ._line !p2 !p4
  10.  
BTW: ORIGIN is a predefined variable for CADCAL scripts. When the user did not define it before the script execution, then ORIGIN will be set to (0 0 0). The user can use the CALSCRIPT command to execute the script, but similar as with a block insertion now he will be asked for an insertion point (=ORIGIN), the rotation, and the values for the arguments LONG and WIDE.

Now the user can call the CADCAL function (CC-CALSCRIPT->LISP <scriptfilename>) or the command function CALSCRIPT->LISP to get this more complex LAMBDA:
Code - Auto/Visual Lisp: [Select]
  1. (LAMBDA (LONG WIDE / OLDCMDECHO LISPLST RESULT IMPORTDATA CC:IMPORT P2 P3 P4 NEWSSET LASTENT LST CC:LAMBDAFUNCTION)
  2. ... <too long for a post>
  3. )
  4.  

This LAMBDA takes the arguments LONG and WIDE which have been defined in the IMPORT() declaration in the script, and all variables defined in the script using the CAL expression "varname=..." are defined as local variables.
This LAMBDA is directly executable and will create the same parametrical drawing part as the CALSCRIPT command.

When you download the current beta version of CADCAL (attached to this post) and available for free from www.archtools.de/cadcal.zip), you can see the demo file NICKSHOUSE.LSP (attached), which has been created automatically from the NICKSHOUSE.SCR (attached). Only the word "LAMBDA" has been replaced py "DEFUN NICKSHOUSE", and then a C:NICKSHOUSE command function asks the user for insertion point, rotation, and the values for the arguments, and then calls the automatically created function, now renamed to (nickshouse long wide).

Please let me know what you think of CADCAL. And please let me know if it works as well in AutoCAD as it does in BricsCAD. I am developing in BricsCAD only and dont't have access to AutoCAD.

Download: (attached to this post), always newest version from www.archtools.de/cadcal.zip
Installation: extract the ZIP file to any directory and, if not already done so, add this directory to the search path for support files of your CAD system.






VovKa

  • Water Moccasin
  • Posts: 1636
  • Ukraine
Re: how to use CADCAL as a Lisp code generator
« Reply #1 on: July 05, 2024, 08:28:43 AM »
no offence berger@archtools.de, but not many users will risk running 300 kB vlx of a newcomer

berger@archtools.de

  • Mosquito
  • Posts: 11
Re: how to use CADCAL as a Lisp code generator
« Reply #2 on: July 05, 2024, 09:11:07 AM »
no offence berger@archtools.de, but not many users will risk running 300 kB vlx of a newcomer

What's dangerous with a VLX file?

And newcomer? Yes, new in this forum, but I am programming AutoLisp since AutoCAD V9, and I am in the market now for over 35 years. I am the author of applications like ArchTools and objectiveCAD.

EDIT: Sorry, I saw your member info too late: Slava Ukraini




It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8922
  • AKA Daniel
Re: how to use CADCAL as a Lisp code generator
« Reply #3 on: July 05, 2024, 09:23:39 AM »
Wow, a big project! Thanks for sharing!

VovKa

  • Water Moccasin
  • Posts: 1636
  • Ukraine
Re: how to use CADCAL as a Lisp code generator
« Reply #4 on: July 05, 2024, 09:55:56 AM »
no offence berger@archtools.de, but not many users will risk running 300 kB vlx of a newcomer

What's dangerous with a VLX file?

And newcomer? Yes, new in this forum, but I am programming AutoLisp since AutoCAD V9, and I am in the market now for over 35 years. I am the author of applications like ArchTools and objectiveCAD.

EDIT: Sorry, I saw your member info too late: Slava Ukraini
Героям слава! - thank you for your support

compiled files are not necessarily dangerous and it is not bad that you are a newcomer, it's a combination of both that can scare people off

berger@archtools.de

  • Mosquito
  • Posts: 11
Re: how to use CADCAL as a Lisp code generator
« Reply #5 on: July 05, 2024, 10:14:40 AM »

compiled files are not necessarily dangerous and it is not bad that you are a newcomer, it's a combination of both that can scare people off

Vovka, a VLX file is not really a "compiled" file. It still is Lisp, just as a BricsCAD DES file. But of course any Lisp source can contain a shell command "format C:\", but most people don't understand Lisp either. You need to use protection anyhow, and the threat from VLX is negletable.



berger@archtools.de

  • Mosquito
  • Posts: 11
Re: how to use CADCAL as a Lisp code generator
« Reply #6 on: July 05, 2024, 10:36:55 AM »
Wow, a big project! Thanks for sharing!

Indeed this is not as big a project as it looks like. I wrote CADCAL as GeomCAL replacement already 15 years ago, and it took me just one week of work. It was fun, because I always wanted to write a parser, and because I had an application which needed GeomCAL and my customer wanted to move to BricsCAD, I had to do it.

And since then I always wanted to write a DCL frontend for CADCAL/GeomCAL, but I only found the inspiration for it after my retirement. And then it turned out to be a work of just 2 days. But then I saw that the history of previous called CAL expressions is nothing else than a script, and that brought me to the idea to do parametric scripting. And to keep all the "intelligence" of these CALSCRIPT objects and to enable the user to give a DWG file away and the receiver still to CC-MODIFY these objects, I got the idea of "compiling" these scripts to Lisp and to store this Lisp code as xdictionary with the object. Another two weeks work, but now I have this working beta version.

Do a test and CALSCRIPT the NICKSHOUSE.SCR file. And then use (xdictionary-get (car (entsel)) "CALSCRIPT") and pick the object. There are XDATA too: (xdata-get (car (entsel)) "CALSCRIPT"). Anyhow: You can store almost any kind of Lisp data via (XDATA-PUT <ename> <appname> <data>), or (XDICTIONARY-PUT <ename> <appname> <data>) - even entity names, Lisp symbols, any list, or dotted pairs. CADCAL contains the collection of my Lisp library over 35 years.
 
Next step will be to implement an inter-object communication. CALSCRIPT objects should be able to talk to each other, thus enabling to design complex simulations or to do automatic optimization of systems made of many CALSCRIPT objects. Whenever an object is modified, it will call the dependend objects and they too will be updated, and they will change their look according to the information they get from the dominant object.

BTW - could you run this in AutoCAD and tell me if it works? I am developing in BricsCAD only and don't have access to AutoCAD.


d2010

  • Bull Frog
  • Posts: 330
Re: how to use CADCAL as a Lisp code generator
« Reply #7 on: July 10, 2024, 08:41:48 AM »
The main future of GeomCAL.arx is the speed-of-calculation of math.
Replacing GeomCAL.arx  with a cloneCAL.vlx,
 Do you not downgrade too much the speed-of-math into many vlx'programs?
 How to CPU'function/s mmx directly inside vlisp?
 :tongue2:



berger@archtools.de

  • Mosquito
  • Posts: 11
Re: how to use CADCAL as a Lisp code generator
« Reply #8 on: July 10, 2024, 11:19:30 AM »
The main future of GeomCAL.arx is the speed-of-calculation of math.
Replacing GeomCAL.arx  with a cloneCAL.vlx,
 Do you not downgrade too much the speed-of-math into many vlx'programs?
 How to CPU'function/s mmx directly inside vlisp?
 :tongue2:

Hi d2010,

why don't you do a benchmark test by yourself?
According to my test under AutoCAD 2012 CADCAL is about 10% slower than GeomCAL. But this changes when i.e. in a loop the same math expression is called repeatedly. CADCAL always translates the math expression to a Lisp expression, which then is executed. All this translations within one drawing session are stored, and when the same math expression is called again, it doesn't need to be parsed again, the Lisp then is called directly. Parsing is quite computing intensive, and CADCAL needs to parse an expression only once.

BTW  - the BricsCAD Lisp interpreter is very much faster than that of AutoCAD, at least 10 times ore more. So CADCAL under BricsCAD ist much faster than GeomCAL under AutoCAD. And while GeomCAL is available only for AutoCAD, CADCAL supports BricsCAD too.

And then CADCAL has much more predefined functions than GeomCAL. Just one example: PCT(ratio) asks the user to pick a curve entity (line, polyline, 3Dpoly, spline, circle, arc, ellipse, elliptic arc) and returns the point on that curve that divides the curve's length at the given ratio. Or the predefined PGR(p1,p2) which returns a point that divides the distance between p1 and p2 in the golden ratio.

And then CADCAL has a very comfortable DCL frontend, which can be called (even transparently) with the command DDCAL. And this DCL frontend stores the history of the last 30 CADCAL expressions together with their results. Even when you close the DWG and reopen it days later, the history will still be there. You can re-use the results any time later. And you can export the history to a script file.

And then CADCAL allows parametric scripting, very similar to dynamic blocks. And these paremetrically defined drawing parts can be edited later and change their look according to the new property values which you give them.

And with the next BETA comming tomorrow these parametrically defined objects can talk to each other. This allows you to build simple modells for simulations. As an example there will be a switch object which can change it's property "power" from "on" to "off", and when this switch object is connected to lamp objects, these will immediately reflect the state of the switch.

And these scripts which can define parametric drawing parts which can communicate to each other can be translated to Lisp functions, which can become the heart of your own application for AutoCAD or BricsCAD.

You see, that there is much more to CADCAL. The GeomCAL functionality is just a small part of the whole thing.



d2010

  • Bull Frog
  • Posts: 330
Re: how to use CADCAL as a Lisp code generator
« Reply #9 on: July 12, 2024, 03:28:33 AM »
You?10="the BricsCAD Lisp interpreter is very much faster than that of AutoCAD, at least 10 times ore more. So CADCAL under BricsCAD ist much faster than GeomCAL under AutoCAD. And while GeomCAL is available only for AutoCAD, CADCAL supports BricsCAD too."
I10answer=Yes, very good  news, thank/s  good news :smitten:
               I will test your vlx very soon.
« Last Edit: July 12, 2024, 04:06:14 AM by d2010 »