CADCAL & CALScript for AutoCAD and BricsCAD
  This is pure magic: create smart CAD objects and smart Lisp functions totally without any programming  
  Home CAL and DDCAL CALSCRIPT CALSCRIPT quickstart C+C and Lisp FAQ Pricing / Order Contact  
 

CADCAL was developed to integrate the full functionality of AutoCAD's GeomCAL into BricsCAD. Just like GeomCAL, CADCAL also allows you to evaluate complex mathematical expressions and use the results directly as input to CAD command prompts. This eliminates the need for many complex geometric constructions, significantly increasing CAD productivity.

But CADCAL uses a completely different approach than GeomCAL, providing extended functionality, including additional predefined functions, user-defined CAL functions, and significantly enhanced integration with AutoLisp.

Although CADCAL is written entirely in Lisp, it is usually as fast as GeomCAL. CADCAL particularly excels when a Lisp function is repeatedly calling CAL expressions within loops. In AutoCAD 2026, it is almost as fast as GeomCAL, and in BricsCAD V25, it is even about 10 times faster than GeomCAL in AutoCAD. Click the links below for more infos about effiency and benchmark tests.


Content
using the CAL command using the DDCAL command using CAL in Lisp  
list of CAL functions user defined CAL expressions translation of CAL expressions to Lisp  
CADCAL efficiency benchmark    



using the CAL command

From the command line:

You can either use CADCAL from your CAD system’s command line or call it from any self-defined toolbar icon or menu with the command CAL (if you have running GeomCAL parallel you can also use the command CCAL). CADCAL then asks you to enter a mathematical expression:

command: CAL

CC ?=help >> expression:

 

You can now either enter a question mark to call the html help file, or you can enter any mathematical expression using normal math syntax. CADCAL will then answer with the result of your expression:

 

CC ?=help >> expression: 2+3

5

 

You can also do calculations with vectors (or coordinate points of your CAD system). In CADCAL vectors are expressed either in cartesian or in polar coordinates or in clindical coordinates. All are symbolized by using rectangular brackets [x,y] or [distance<angle] or [distance<angle,height]. But you can also aquire coordinate points from your drawing: The CADCAL function CUR is a placeholder for a coordinate point that you have to enter from your drawing. And you can use mathematical expressions inside vector expressions (like in [2+3<asin(30)]].

Similar as CUR you can also use a predefined object snap, i.e. you can use the object snap names END, INT, MID, PER, CEN, QUA, TAN, NOD, INS, NEA to aquire a point by the cursor using the corresponding object snap, and use this point in you calculations. While an object snap is running, you can always change the object snap mode by simply entering another snap mode.

 

CADCAL enables you to use LISP variables in your mathematical expressions, and you can even asign the result of an expression directly to a variable that can be used in other equations: p1=cur+[1,0,0] asks you to show a coordinate point with your cursor, adds another vector [1,0,0] to it, and asigns the result to a variable named p1. In another expression you can then refer to this variable using it as a placeholder: cur+p1

 

Using CADCAL expressions transparently from a command:

You can call CADCAL transparently from any command of your CAD system, and the result of your mathematical expression will then be used directly as input to the running command. The only difference is that you need to call CADCAL with a preceding apostrophe:

command: line

enter first point: 'cal

CC ?=help >> expression: mee

 

The predefined function MEE asks you to show two coordinate points (osnap is temporarily switched to END) and returns the midpoint between them. You don’t need to draw a helpline between this points and use osnap MID to find that point.

 

When you use CADCAL transparently from a running command and asign the result of an expression to a variable, CADCAL continues to ask you for another expression. If you don’t want to enter another expression, then simply press <ENTER> and the result of the first expression will be passed as input to the command. You can, however, enter another expression using the variable of the first expression and continue to do more complex calculations. Only the result of the last expression is passed to the running command.

 

You can of course easily do calulations like (2*cur+cur)/3, which will ask you to show two points (one for each “cur” in this expression) , and return a point that is at 1/3 of the distance between the both points. However in CADCAL you will find many predefined functions that will speed up your work even more. The function PLT(1/3) will do just the same. It will ask you to show two points, and will return the point that is at 1/3 on the distance between them. PLT(2/3) will of course return the point that is 2/3 on the distance, and PLT(0.25) is at ¼ on the distance between the two points.

There is an important restriction for using CAL transparently. When an externally defined function aks the user to enter a coordinate point, then in AutoCAD you can't enter CAL transparently. Unfortunately the user mostly can't recognize wether the command in use is defined externally or is an internal AutoCAD command. In AutoCAD there is no solution for that problem, but to calculate the point before calling the externally defined command, and then enter the value manually. In AutoCAD this problem also applies to GeomCAL, but in BricsCAD CADCAL offers a solution. You can use the command 'TCAL transparently even with externally defined commands. So in BricsCAD the CAL icon in the CADCAL toolbar triggers the 'TCAL command.

 

Rules for expressions

 

The normal mathematical rules are valid for CADCAL too. Multiplication precedes addition and subtraction, exponentiation precedes multiplication, and grouped terms in brackets precede all others. So 2+3*4 is the same as 2+(3*4), and this makes 14, but (2+3)*4 equals to 20. It’s a good advice to use brackets when you are not absolutely sure about the order. You can also use spaces to make your expressions better readable.

 

Negative numbers are expressed with a simple minus-sign: -3+4 results to 1. You can also negate all CADCAL functions, predefined numbers and LISP variables by asigning them a minus-sign. When the vector [1,2,3] is asigned to a variable named p1 by using the expression p1= [1,2,3], then –p1 results to (–1 –2 –3) and can be used as –p1 in your expressions. The expression sin(30)) calculates the sine function for 30°, and this results to 0.5. So – –sin(30))will result to –0.5.will result to –0.5.

 

Rules for functions

 

CADCAL has a lot of built in mathematical functions, and many of them need arguments. The sine function i.e. needs an angle, from which to calculate the sine. These arguments are written in round brackets behind the function name. like in sin(30). If a function takes more than one argument, then the arguments are separated from each other by a comma, like in nor(p1,p2), which calculates the normal vector to the line between p1 and p2. Some functions can be used with a varifying number of arguments – you can calculate the normal vector to a vector v with nor(v), the normal vector to a line with nor(p1,p2), and the normal vector to a plane with nor(p1,p2,p3). And some functions can take an indefinite number of arguments like i.e. min(n1,n2,n3, ..) which returns the smallest number of all that are given as arguments. And then there are functions that don’t have any arguments at all (like cur or end or int for aquiring a coordinate point from the cursor, or like mee for the calculation of the midpoint between two points).

 

Rules for variables

 

You can asign the result of any calculation to a variable and use this variable later in other expressions. You can’t use names of CADCAL functions as variable names, and you should avoid to use names that are CAD commands or program functions. You should also avoid using names that begin with “§§” or with “cc-“ or “cc:”, since CADCAL’s internal functions are using names like that. Using variable names that start with a minus sign like –p1 will cause wrong results or program errors, since CADCAL would interprete this variable as the negation of the variable p1. Don’t use variable names that contain mathematical symbols: a variable named “p+p” would be interpreted as the addition of the variable p with itself.  Upper and lower case of variable names is ignored: P1 is the same variable name as p1.



-> back to top



using the DDCAL command

DDCAL is the dialog-driven version of the CAL command. Like the CAL command, DDCAL can be used transparently at the prompt of a CAD command. The same restrictions apply as for the CAL command form. When you enter the DDCAL command, this dialog box appears:


The most important element in this dialog box is the exec line. Enter any valid CAL expression in that line, and press the execute button. The result of that expression will immediately appear as input to a running CAD command, or at the command line.

Here you don't need to remember the sometimes awkward CAL function names, and how the arguments need to be given. Just select the function from the functions list box at the lower left. And if you don't know exactly, which function to use, then press the "?" button to get info about the selected function name.


With the ">" button you can simply copy the desired function to the execution line, where you can modify it as needed and then execute it. If no CAD command is active, DDCAL remains active, with the last executed expression being added to the history list and remaining in the execution line. It often happens that you want to use the same expression multiple times in a row. Here's a video showing how easy it is to use DDCAL to draw the cross-sectional area resulting from the penetration of a stone through a roof surface. Here we use the ILP function, which calculates the Intersection of a Line through a Plane. The ILP function takes 5 arguments, first two points to define the line, and then three points to define the plane. We want to draw a 3DPOLY through the 4 points, where the stone penetrates the roof. It is always the same surfce, so we first enter three points RP1, RP2 and RP3 for the roof surface. Then we enter the 3DPOLY command, and we use DDCAL to enter the CAL function ILP(end,end,RP1,RP2,RP3). For each "end" we are asked to enter a point on the line, and these lines are the vertical lines of the stone. We simply need to repeat to execute the same line 4 times.

DDCAL saves the history with all the results of the expressions used in the DWG, and it remains available there even after closing and reopening the DWG. You can click on any line in the history, which inserts it into the expression line, and its result into the line below. You can simply click to copy the contents of the expression line into the execution line, and the result can be copied to the clipboard or used as input to a running command.


-> back to top


using CAL Expressions in Lisp

Using CAL in your Lisp applications is absolutely easy. Simply create a Lisp call with the CAL function and give the math expression as a single argument. The expression must be a valid CAL expression in a string. Any CAL expression is allowed. The following expression calculates a point perpendicular from P1 to the plane through P1, P2 and P3. Would you know by heart how to calculate this vector in AutoLisp without any tools?

(setq nvec (CAL "p1+nor(p1,p2,p3)"))

Whenever a mathematical expression is used repeatedly in the same DWG session, CADCAL uses the already made internal translation to Lisp, which means that the working speed is exactly the same as when using a corresponding Lisp expression. When used in loops, CADCAL is almost twice as fast as GeomCAL. This typically eliminates the need to use other programming techniques to achieve higher performance. So the use of CAL calls with mathematical expressions in AutoLisp programs greatly increases the productivity of any AutoLisp programmer.

But if you are still concerned about performance, you can also use CADCAL's ability to translate mathematical expressions into fully usable Lisp code, which you can use in your AutoLisp programs just like the direct CAL calls. Just call (cc-str->lisp "p1+nor(p1,p2,p3)") and copy&paste the result (§§+ (LIST P1 (§§NOR (LIST P1 P2 P3)))) to your AutoLIsp code.



-> back to top


translating CAL expressions to Lisp

CADCAL was developed entirely in Lisp, and therefore naturally performs the calculations of mathematical expressions passed to the CAL command in Lisp. To do this, CADCAL first translates an expression into its Lisp equivalent before evaluating that Lisp expression. This functionality of translating a mathematical expression into Lisp is also available to the CADCAL users for their own use. Simply use
(CC-STR->LISP <expression>
)
to translate
a CAL expressions into Lisp for his own use. For example
(CC-STR->LISP "P4=P1+P2+P3")
yields the result
(SETQ P4 (§§+ (LIST P1 P2 P3)))

CADCAL can also simplify and combine the expressions mathematically correct
. This expression
(cc-str->lisp "p1+p2-2*p3+p4-p5")
is translated to
(§§- (LIST (§§+ (LIST P1 P2 P4)) (§§+ (LIST (§§* 2 P3) P5))))


This Lisp expressions can then easily be integrated into your Lisp code instead of a CAL call. This makes CADCAL particularly efficient, especially when using CAL expressions in Lisp programs with loops. If a CAL expression is used in a Lisp loop, the Lisp expression is always evaluated directly except for the first pass. CAL calls in Lisp loops are therefore practically as fast as using Lisp directly.

All implemented CADCAL functions like
§§+, §§-, §§* etc always take a list as a single argument. This argument list can contain as many elements as you like, and work with numbers just as well as with coordinate points. When you are mixing types of arguments which don't fit together, CADCAL triggers an error message. This enables CADCAL functions to use different numbers of arguments, like in PLD(p1,p2,distance) or PLD(distance).

For more info about using CADCAL+CALSCRIPT with Lisp, please see the special page C+C and Lisp



-> back to top


user defined CAL expressions

You can easily define your own commands and functions in CADCAL. When you store your own function definitions in a file named “cadcal-user.lsp” and place this file in your CAD system’s support path, CADCAL will automatically load all your definitions on startup. A sample is provided with your CADCAL+CALSCRIPT installation. Just rename the file --cadcal-user.lsp to cadcal-user.lsp, and oben this file in AutoCAD VLIDE or in BricsCAD BLADE.

 

A CADCAL definition is almost identically done as it is done in LISP. The only difference is that you need a slightly different syntax. In LISP you would define a function this way:

(defun MOB () 123)

This function calculates nothing, it just returns the value 123. In CADCAL you would write

(cc-defun ‘(MOB () 123))

Note that cc-defun only takes one list as a parameter, the first element of this list is the command or function name, the second is the list of parameters and local variables, and the rest is the stuff your function does do. Apart from that simple rules your Lisp function can contain anything that is possible in Lisp.

 

(cc-defun '(MOB (lst / p1 p2)

  (if (and (setq p1 (car lst))

           (setq p2 (cadr lst))

       )

       (list (+ (car p1) (car p2))

             (+ (cadr p1) (cadr p2))

        )

   )

))

 

When you define a function for CADCAL (a function takes parameters) like that, then all function parameters are passed to your program in one single list. From that argument list you can extract all the arguments which you really need in your function.The sample above extracts two points from the LST list, and this means that you then can call your function from CAL just like that:

CAL
CC ?=help >> expression: MOB(cur,cur)

>> enter point for CUR:
>> enter point for CUR:
(-401.68034313253 65.8312308433736)

 

 

 

-> back to top

 

 

List of CAL functions

 

predefined numbers

PI

the circular constant 3.141…., the ratio of a circle's circumference to its diameter

2PI

shortcut for (2 * PI)

PI2

shortcut for (PI / 2)

PI4

shortcut for (PI / 4)

EUL

the Eulerian number 2.71828…., the base of the natural logarithm (equal to ln(1))

simple math

+

addition (numbers only or vectors only)

-

subtraction (numbers only or vectors only)

*

multiplication (numbers and vectors, also mixed for scalar products like in 2*p1; p1*p2 is the scalar product)

/

division (numbers and vectors, also mixed for scalar divisions like in p1/2)

^

exponentiation (numbers only)
– 5^3 is the same as 5*5*5 and results to 125
10^-2 is the same as 1/(10*10) and returns 0.01

27^(1/3) is the cubic root of 27 and returns 3

&

vector product (vectors only)

=

asigns the result of the expression on the right side of the =sign to the variable on the left side.

myvar=sin(30) asigns the result of the expression sin(30) to the variable myvar.

math functions

SQRT(x)

returns the square root of x

EXP(x)

natural exponentiation: e^x, whith e being the Eulerian number 2.71828...

EXP10(x)

exponentiation to base 10: 10^x. EXP10(2) returns 100.0

LN(x)

the natural logarithm of x

LOG(x)

the decimal logarithm of x

SIN(x)

the sine function. The angle x is given in degrees or decimal degrees.

COS(x)

the cosine function. The angle x is given in degrees or decimal degrees.

TANG(x)

the tangent function (TAN is reserved for the tangent osnap).

ASIN(x)

the arcsine function, reverse function of sine. Allowed values are from -1 to 1. Output in degrees.

ACOS(x)

the arccosine function, reverse function of cosine. Allowed values are from -1 to 1. Output in degrees.

ATAN(x)

the arctangent function, reverse function of tangent. All numbers allowed as input. Output in degrees.

ROUND(x)

rounds x to the next integer:  round(1.8) -> 2

TRUNC(x)

returns the integer part of x: trunc(1.8) -> 1

REM(x)

returns the digits behind the decimal point:  rem(1.8) -> 0.8

minmax functions

MIN(n1,n2,n3, ...)

returns the smallest value among n1 ...nn. The number of arguments is not limited

MAX(n1,n2,n3, ...)

returns the highest value among n1 ...nn. The number of arguments is not limited

XMIN(p1,p2,p3, ...)

returns the smallest X-value among the vectors p1,p2,...pn

XMAX(p1,p2,p3, ...)

returns the highest X-value among the vectors p1,p2,...pn

YMIN(p1,p2,p3, ...)

returns the smallest Y-value among the vectors p1,p2,...pn

YMAX(p1,p2,p3, ...)

returns the highest Y-value among the vectors p1,p2,...pn

ZMIN(p1,p2,p3, ...)

returns the smallest Z-value among the vectors p1,p2,...pn

ZMAX(p1,p2,p3, ...)

returns the highest Z-value among the vectors p1,p2,...pn

XYMIN(p1,p2,p3, ...)

returns a vector that is composed of the smallest X- and the smallest Y-value of all vectors p1,p2,p3 ...

XYMAX(p1,p2,p3, ...)

returns a vector that is composed of the highest X- and the highest Y-value of all vectors p1,p2,p3 ...

cartesian coordinates

[x,y,z]

x,y, and z are numbers. This is a vector that is x units on the X-axis, y units on the Y-axis, and z units on the Z-axis from the origin [0,0,0].

[x,y] or [x,y,]

missing z-value is assumed to be 0.0

[x] or [x,] or [x,,]

missing y- and z-values are assumed to be 0.0

[] or [,] or [,,]

missing x-, y- and z-values are assumed to be 0.0

[,4] [1] [,2,3] [,,1]

missing coordinates are assumed to be 0.0

[1+sin(45),0,0]

you can also use mathematical expressions for x-, y- and z-values

[0,0,sin(PI/2)]

and you can use predefined and user defined  variables

polar coordinates

[distance<angle]

polar coordinates are described by a distance and an angle. Distance and angle can be given as positiv  and negative numbers. The distance is measured from the origin point, the angle is measured in degrees or decimal degrees counterclockwiese from the positive x-axis. The symbol '<' is used to mark the angle.

[distance<angle<angle]

polar coordinates can also be entered as 3D vectors.

A second angle is necessary to indicate the angle out of the XY-plane into the direction of the positive z-axis.

[100<45]

returns (70.7107 70.7107 0.0)

[100<45<30]

returns (61.2372 61.2372 50.0)

cylindrical coordinates

 

Cylindrical coordinates are desribed by a distance and an angle in the XY plane, and a height in the Z direction. The symbol '<' is used to mark the angle in the XY plane, and the Z-value is separated by a comma.
  [100<45,30]   returns (70.7107 70.7107 30.0)  
         

using coordinate points from the drawing

CUR

asks the user to pick a coordinate point with the cursor. Current osnap settings are used and can be modified while you are in pointing mode. The coordinates of the given point in it’s current UCS values will be used in the mathematical expression the very same way as if it would have been entered manually.

CUR and the following osnap variants of it will modify the LASTPOINT variable, which can be accessed with “@”.

END

the same as CUR but switches the osnap mode temporarily to ENDpoint

INT

the same as CUR but switches the osnap mode temporarily to INTersection

MID

the same as CUR but switches the osnap mode temporarily to MIDpoint

INS

the same as CUR but switches the osnap mode temporarily to INSertion point

CEN

the same as CUR but switches the osnap mode temporarily to CENter point

NEA

the same as CUR but switches the osnap mode temporarily to NEArest point

NOD

the same as CUR but switches the osnap mode temporarily to NODe

QUA

the same as CUR but switches the osnap mode temporarily to QUAdrant

PER

the same as CUR but switches the osnap mode temporarily to PERpendicular

TAN

the same as CUR but switches the osnap mode temporarily to TANgent

LASTPOINT

@

the ‘@’ symbol refers to the last entered point in the drawing editor. I.e. when you created a line with the line command, @ refers to the last point of the line. All CADCAL functions for coordinate input like CUR, END, INT etc are storing the entered point in the variable @. CADCAL Functions like MEE, PLD etc. store their resulting point in @.

filtering coordinates

RXOF(p)

returns the X-value of p

RYOF(p)

returns the Y-value of p

RZOF(p)

returns the Z-value of p

XOF(p)

returns a vector that is constructed from the X-value of p and 0 for Y and Z

YOF(p)

returns a vector that is constructed from the Y-value of p and 0 for X and Z

ZOF(p)

returns a vector that is constructed from the Z-value of p and 0 for X and Y

XYOF(p)

returns a vector that is constructed from the X- and Y-value of p and 0 for Z

XZOF(p)

returns a vector that is constructed from the X- and Z-value of p and 0 for Y

YZOF(p)

returns a vector that is constructed from the Y- and Z-value of p and 0 for X

@X

returns the X-value of the last point

@Y

returns the Y-value of the last point

@Z

returns the Z-value of the last point

predefined functions

distance and length

DIST(p1,p2)

distance between points p1 and p2

DPL(pt,p2,p3)

distance between point pt and a line through p2 and p3

DPP(pt,p2,p3,p4)

distance between point pt and a plane through p2,p3 and p4

ABS(pt)

length of vector pt

DEE

shortcurt for DIST(end,end)

LENGTH

asks to pick an object with a length (a line, arc, polyline, circle, ellipse, elliptic arc, spline) and returns it's length

finding intersection points

ILL(p1,p2,p3,p4)

returns the intersection point between the line through p1, p2 and the line through p3, p4

ILP(p1,p2,p3,p4,p5)

returns the intersection point between the line through p1, p2, and the plane through p3, p4, p5

ILLE

shortcut for ILL(end,end,end,end)

ILPE

shortcut for ILP(end,end,end,end,end)

ILPVE

shortcut for ILP(end,@+[0,0,1],end,end,end). The line through the plane is vertical on it's startpoint in the current UCS.

calculating coordinate points

PLD(p1,p2,distance)

returns the coordinate point that is on the line between p1 and p2 in the given distance from p1

PLD(distance)

same as PLD(end,end,distance)

asks the user to show two endpoints p1 and p2 with the cursor and returns the coordinate point that is on the line between p1 and p2 in the given distance from p1

PLDEE(distance)

same as PLD(distance)

(for compatibility with Autodesk’s GeomCAL)

PLT(p1,p2,fraction)

returns he coordinate point that is on the line between p1 and p2 and is in a distance from p1 that is defined by the distance between p1 and p2 and the given fraction.

PLT(p1,p2,1/3) returns the point that is at 1/3 of the distance between p1 and p2

PLT(fraction)

same as PLT(end,end,fraction)

asks to show two points p1 and p2 with the cursor and returns the coordinate point that is on the line between p1 and p2 and is in a distance from p1 that is defined by the distance between p1 and p2 and the given fraction.

PLTEE(fraction)

same as PLT(fraction)

(only for compatiblity with Autodesk’s GeomCAL)

PCD(ename,distance)   

returns he coordinate point that divides a curve in a given distance from the curve's start point. The distance is measured along the curve. The ename parameter can be given with the PICK function. The curve entity can be a line, a polyline, a spline, a circle, an ellipse, an arc or an elliptic arc.

PCD(distance)

same as PCD(ename,fraction), but the user is asked to pick a curve entity. This is a shortcut for PCD(pick,distance)

PCT(ename,fraction)

returns he coordinate point that divides a curve at the fraction of the curve's length. The parameter fraction must be between 0 and 1. 0 returns the startpoint of the curve, 1 returns the endpoint of the curve. The ename parameter can be given with the PICK function. The curve entity can be a line, a polyline, a spline, a circle, an ellipse, an arc or an elliptic arc.

PCT(fraction)

same as PCT(ename,fraction), but the user is asked to pick a curve entity. This is a shortcut for PCT(pick,fraction)

PCG(p1,p2,…pn)

returns the center of gravity over all points in the list

the number of points is not limited

PCGE

similar to PCG(end,end,end…end)

asks the user to show points with the cursor. The number of points is not limited. Returns the center of gravity over all points

PPL(pp,p1,p2)

returns the projection of point pp on a line between p1 and p2. The line between pp and the projection point is perpendicular on the line between p1,p2, and the distance between pp and the projection point is the shortest distance between the line and pp.

PPP(pp,p1,p2,p3)

returns the projection of point pp on a plane through the points p1,p2,p3. The line between pp and the projection point is perpendicular on the plane, and the distance between pp and the projection point is the shortest distance between the plane and pp.

ROT(rp,origin,angle)

returns the point that is the result of the 2D rotation of the point rp around the origin with the given rotation angle. The angle is given in degrees and/or decimal degrees and is measured counterclockwise.

ROT(rp,ax1,ax2,angle)

returns the point that is the result of the 3D rotation of point rp around the axis through ax1 and ax2 with the given rotation angle. The angle is given,in degrees and/or decimal degrees and is measured counterclockwise.

MEE

or 2EE

asks the user to show two endpoints and returns the midpoint between them. MEE is a shortcut for PLT(0.5)

3EE

asks the user to show two endpoints and returns the triple point between them. 3EE is a shortcut for PLT(1/3)

4EE

5EE ….10EE

similar to 3EE, but shortcut for PLT(1/4)

or PLT(1/5) …. PLT(0.1)

selecting objects, and getting length, area and radius from objects

PICK

asks the user to pick any drawing element and returns the entity name. You will probably want to store the entity name in a variable for further use, so PICK usually is called in a way like that: E1=PICK to store the entity name in variable E1

RAD

asks the user to pick a drawing element with a radius and returns the radius. The user can pick circles, arcs and polylines with arc segments.

LENGTH

asks the user to pick a drawing element with a length and returns the length. The user can pick lines, polylines, splines, circles, arcs, ellipses, elliptic arcs

AREA

asks the user to pick a drawing element with an area and returns the area. The user can pick circles, closed and open polylines, closed and open splines, ellipses, arcs, elliptic arcs, and regions. Open entities like arcs and open polylines are considered to be closed by a straight line between their endpoints.

OBJRAD(ename)

like RAD, but you need to give an entity name as an argument.

OBJLENGTH(ename)

like LENGTH, but you need to give an entity name as an argument.

OBJAREA(ename)

like AREA, but you need to give an entity name as an argument.  You can use the PICK function to force the user to pick en entity and store it in a variable, like in E1=PICK

angles

ANG(v

returns the angle (in degrees or decimal degrees) between the positive X-axis and the vector v.

ANG(p1,p2)

returns the angle (in degrees or decimal degrees) between the positive X-axis and the line through p1,p2

ANG(apex,p1,p2)

returns the angle (in degrees or decimal degrees) between the lines apex-p1 and apex-p2.

vectors

VEC(p1,p2)

returns the vector from coordinate point p1 to p2 (same as p2-p1)

VEC1(p1,p2

returns the normal vector from point p1 to p2

VEE

shortcut for vec(end,end)

VEE1

shortcut for vec1(end,end)

normal vectors

NOR(v)

returns the normal vetcor to the vector v

NOR(p1,p2)

returns the normal vector to the vector between p1 and p2

NOR(p1,p2,p3)

returns the normal vector to the plane through p1,p2,p3

NORE

asks the user to pick an entity and returns the normal vector to the construction plane of that entity

NEE

shortcut for nor(end,end)

misc

R2D(rad)

converts radians to degrees

D2R(angle)

converts degrees to radians

U2W(p)

converts the point p from the current UCS to WCS

W2U(p)

converts the point p from WCS to the current UCS

 


-> back to top


CADCAL efficiency


Although the basic functionality of CADCAL is ultimately the same as that of GeomCAL, CADCAL follows a fundamentally different approach. When CADCAL evaluates a mathematical expression using the CAL command, it first translates it into Lisp code, which it then evaluates. Because parsing - the translation of a text string containing a mathematical expression into a computer-executable instruction - is the most time-consuming process in evaluating CAL expressions, this is where the most time can be saved.

CADCAL only needs to parse an expression once within a drawing session.
It saves the Lisp expression and can access it later without reparsing the same expression. The user can use the function
(CC-STR->LISP <expression>
)
to translate CAL expressions into Lisp
for his own use.
For example
(CC-STR->LISP "P4=P1+P2+P3")
yields the result
(SETQ P4 (§§+ (LIST P1 P2 P3)))
This Lisp expression can then easily be integrated into your Lisp code instead of a CAL call. This makes CADCAL particularly efficient, especially when using CAL expressions in Lisp programs with loops. If a CAL expression is used in a Lisp loop, the Lisp expression is always evaluated directly except for the first pass. CAL calls in Lisp loops are therefore practically as fast as using Lisp directly. So for Lisp programmers CADCAL can increase programming productivity immensly, since there is almost no performance loss when in Lisp functionscalls to the CAL function are used instead of Lisp functions.
For more info about using CADCAL+CALSCRIPT with Lisp, please see the special page C+C and Lisp


See the benchmark tests below, which show that in AutoCAD 2026, CADCAL is almost as fast as GeomCAL.
But BricsCAD's extremely fast Lisp interpreter, in particular, makes a big difference here. The benchmark is processed about 10 times faster with CADCAL in BricsCAD V25 than with GeomCAL in AutoCAD 2026. You can run this benchmark yourself on your computer at any time.


-> back to top


CAL benchmark

I did run this Lisp benchmark in AutoCAD 2026 with GeomCAL and with CADCAL, and in BricsCAD V25 with CADCAL. To ensure that the comparison was performed independently of system load by other programs, I unloaded the CADCAL menu in both AutoCAD and BricsCAD using the _MENULOAD command and restarted AutoCAD and BricsCAD immediately before each test. I then loaded GeomCAL immediately before the first test using (arxload "geomcal"). After the GeomCAL test, I closed and restarted AutoCAD, and then manually loaded CADCAL immediately before the test using (load "cadcal.vlx")
Remarks: GeomCAL has a bug and renders AutoCAD in a weird state after doing a lot of iterations. To solve this problem, a (command) call is added after running the loop and determining the time needed.
GeomCAL is less precise than CADCAL, and so not much more than 5000 iterations are possible with GeomCAL. After that GeomCAL can't find a difference between P1 and P2, and throws error messages that in ROT(p2,p1,3.0) the point p2 is the same as p1, which obviously isn't true.

This is the benchmark function:
(defun bench (sooften / p1 p2 diff)
  (setvar "cmdecho" 0)
  (setvar "osmode" 0)
  (setq p1 '(0.0 0.0 0.0)
        p2 '(0.1 0.1 0.0)
        diff 1.0
     ;; lst (list p2)
  )
  (setq start (getvar "MILLISECS"))
  (repeat sooften
    (cal "p2=rot(p2,p1,3.0)")
    (cal "p2=plt(p1,p2,diff)")
    (cal "diff=diff*1.0000005")
  ;;(setq lst (cons p2 lst))
  )
  (print
    (strcat "seconds needed for "
    (itoa sooften)
    " iterations: "
    (rtos (/ (- (getvar "MILLISECS") start) 1000.0) 2 20)
   )
  )
  ;; GeomCAL is buggy and leaves AutoCAD in a weird state
  ;; the COMMAND call is necessary to make AutoCAD healthy again
  (if (= "AUTOCAD" (strcase (getvar "product"))) (command))

  ;; (command "._PLINE")
  ;; (foreach pt lst (command pt))
  ;; (command ""))
  (prin1)
)
These are the results:  
 
Running the benchmark with GeomCAL in AutoCAD 2026

Running the benchmark with CADCAL in AutoCAD 2026


And here the results running CADCAL in BricsCAD V25:

 

The lower calculation accuracy of GeomCAL leads to these error messages if the number of loop iterations is too high:


CADCAL’s higher calculation accuracy handles this without any problems:
     

By the way: this BENCH function calculates points along a spiral around the origin. If you remove the comments from the assignments that contain the global LST variable, you can plot the points collected in the LST list with a polyline after testing. To do this, simply enter the following in the AutoCAD/BricsCAD command line:
(command "._PLINE") (foreach pt lst (command pt)) (command "")

For (bench 1000) you will then receive the following image (you may need to apply _ZOOM _E):




-> back to top

     
  (c) 2025 Tom Berger
Feriendorfstraße 6c, D-34308 Bad Emstal, Germany
berger@archtools.de