A New Angle (ang.lsp)

AutoCAD has long had the Dist command to measure the distance between two points, but measuring the angle between two lines has meant inserting an angle dimension, reading it and then deleting it. ANG.LSP is a program that will prompt the user for two lines and then print the angles to the command line. 

Since there are two angles between any two lines, getting the program to determine which one the user is interested in would require an extra pick from the user. Printing both angles is quicker and easier. 

The angles are displayed according to the current setting of the Auprec Setvar (for decimal places) and in most cases honours the setting of the Aunits Setvar (for angular units). Since architectural and gradient units are not usually useful for measuring angles between lines, in these cases the display reverts to decimal degrees. 

The Listing

After the short program description, the DEFUN defines the program name and the variable names it uses are localised. We then select the two lines. 

Observant readers may note that the code to select the two lines is identical to that from MEND.LSP in the LISP File in CAD User August, 1996. There is no need to reinvent the wheel and it is always a good idea to cut and paste tried and proven code fragments. 

At first glance there may seem to be a lot of code just to select two lines but it's all needed to make the code bulletproof - the user cannot do anything but select two different lines. 

To select the first line we enter to a WHILE loop that will keep looping until variable ENT2 has a value. ENT2 is set to the list returned by the Entsel function unless a blank area of the drawing is picked, in which case nil is returned to ENT2. An If routine inside the While loop is used to ensure the user picks a line. 

This routine will run if an object has been picked and is not a line. 

The test statement for the IF uses nested code and combines two tests into one, linked by an AND function that will return T (true) to the IF only if both tests return T

The first part of the test will return T if ENT2 is bound to a value and the second part of the test will return T if the object selected is not a line. 

Although AutoLISP evaluates from left ,to right, it is often easier for humans to evaluate nested code from the inside out. In this case (car ENT2) returns the object name to the ENTGET function, which extracts the object data and returns it to the ASSOC function. This extracts the object type list, passing it back to CDR which extracts the object type from the list. This is then compared to the text string "LINE" and will return T if they do not match (it is not a line). 

Note that the test for the existence of a value bound to ENT2 is performed first. Since the second test would cause the program to crash if ENT2 had no value, testing for a value in ENT2 stops processing of further tests should it return nil (no object is selected). 

If both tests returned T, then an object that was not a line was selected. The code inside the If will inform the user that the object was not a line and set ENT2 to nil. This will cause the WHILE loop to run again and reprompt for an object. 

If the first test returned nil (no object selected), the code inside the IF would be skipped and the WHILE loop would run again since ENT2 has no value. If the second test returned nil (a line was selected), the IF function would be skipped and the WHILE loop would exit since ENT2 now has a value. 

Note the PROGN function immediately after the IF test statement. Since the IF function requires a test-expression, a then-expression and, optionally, an else-expression, multiple then-expressions and/or else-expressions need to be grouped into a single expression with the PROGN function. 

Once a line has been picked, we extract the object's name from ENT2 (Entsel returns a list of the object name and the point by which it was picked) and set it to OBJN2. The object is then highlighted to inform the user that the first line had been successfully selected. 

The code to select the second line is identical except that an additional IF is used to check that the first line was not picked again. Variable OBJN3 is then set to the name of the second line, concluding the object selection routine. 

The first selected line is then unhighlighted and the four endpoints are extracted from the two lines. They are stored in variables PT2 to PT5. 

The angle of the endpoints of the first line is stored in variable ANG2 and the angle of the endpoints of the second line is stored in variable ANG3. 

An IF then checks if the absolute value (no negative) of ANG3 subtracted from ANG2 is greater than p. If so, ANG4 is set to the absolute value of ANG2-ANG3-p , otherwise ANG4 is set to the absolute value of ANG2-ANG3. This results in ANG4 being set to the smaller of the two angles between the lines. This enables us to display the two angles in a consistent fashion, first the smaller angle and then the larger. 

The larger of the two angles, ANG5, is then set to p -ANG4. The same Setq sets the AU2 variable to the current value for the AUNITS Setvar, which controls the mode in which AutoCAD displays angular values. 

An IF then checks if the value stored in AU2 is a 1 (degrees, minutes, seconds) or 3 (radians). If so, its then-expression prints the two angles, as they are, to the screen, inside an informative message. If not, its else-expression displays the angles in decimal form - inside the same message. This check prevents the angles from being displayed in gradients or surveyor units. 

The Princ function prevents "nil" printing to screen as the program exits. 

©1996-2001 ZOTO Technologies