AutoLISP Solutions: Draw a Sinusoidal Curve as a Spline or Polyline15 Mar, 2005 By: Tony Hotchkiss Cadalyst
Bypass the process of tracing a curve through many points that must be calculated or constructed
This month's request came from Ralph Ragan of Atlanta, Georgia. Ralph wants to draw a sinusoidal curve as a spline or polyline. This type of curve occurs in many situations, including a two-dimensional helix and screw threads. Normally this is quite time-consuming because it requires tracing a curve through many points that must be calculated or constructed.
The AutoLISP Solution is SINECURVE.LSP, and the corresponding dialog box file SINECURVE.DCL. The routine allows the user to select the periodic time (equivalent to the pitch of a thread), the amplitude (half the height for a thread), the number of cycles to display and the resolution or display accuracy of the curve.
Get the Code
Download the SINECURVE.LSP and SINECURVE.DCL files from Cadalyst's CAD Tips site. Save the file in AutoCAD's Support directory. Use the Appload facility by selecting Tools / Load Application, and then use the browser to select the file.
How to Use the SINECURVE Code
After you load the code, the system prompts you to enter SC to start the program. To see this prompt, you may need to set your Command window size to 3 lines by dragging the Command window splitter bar appropriately. After you enter SC, the Sine Curve dialog box pops up as shown (figure 1).
Figure 1. The Sine Curve dialog box with user-defined selections.
You can select the period, amplitude and numbers of cycles as shown in the figure by changing the values in the appropriate edit boxes. The Resolution is controlled by a slider bar as shown. Sliding the bar to the left (Lo) decreases the resolution and sliding it to the right (Hi) gives the highest accuracy. The resolution is actually the number of points per cycle that is used to define the curve. The lowest setting corresponds to 12 points per cycle, and the highest setting is 144 points per cycle. The initial default value is in the middle of the slider at 72 points per cycle.
In the example shown, the period is 1.0, the amplitude is 0.5 and 2 cycles are selected. The resolution is left at its initial value. When the OK button is selected the sine curve appears zoomed to its boundaries as shown (figure 2). The curve is a polyline with the FIT curve smoothing option.
Figure 2. The sine curve displayed as a polyline.
It's possible to convert the polyline to a spline curve, but that would not be as accurate as the fit curve because splines do not pass through their control points. The spline would always result in a curve that is smaller in amplitude than the polyline because the spline curve lies on the concave side of its control points.
The program was written in AutoCAD 2004, and has been tested in both AutoCAD 2004 and 2005, but it should work in any version of AutoCAD later than 2000. SINECURVE.LSP starts as usual with my error handler and system variable functions. The function SINE is the dialog box driver function that calls INIT-SINE to initialize the settings in the dialog box. If the program has already been run in the current session of AutoCAD, then all the dialog box data values are reused as new defaults because the period, amplitude, number of cycles and resolution are stored in global variables. Immediately following INIT-SINE, the DRAW-SINE-IMAGE function is called to create the image of a sine curve. I favor this method of creating images over using slides because there are fewer files to keep track of. Even if the LISP program is compiled, it is not possible to include slide libraries in the compiled set of data.
I have previously written functions to draw lines (vectors), arcs and circles in image tiles for dialog boxes, and in this case only the vector is required. The code to draw the sine curve takes a number of definition points NP, and runs a repeat loop as follows:
(repeat (fix np)
(setq y (- y0 (* A (sin (/ (* 2 pi (setq x (+ x xinc))) xmax))))
p2 (list x y)
) ;_ end of setq
(do-vector p1 p2 col)
(setq p1 p2)
) ;_ end of repeat
For this function, I set the number of points NP at 144, which gives a very smooth-looking image, as shown in figure 1. The code is written using the points p1 and p2, much the way that would be used to program lines between two points on the regular AutoCAD screen. This is possible because the function DO-VECTOR converts the points to the x- and y-integer values required by the AutoLISP VECTOR_IMAGE function.
A small inconvenience in drawing image tiles is caused by the reversed positive direction of the y-axis. The x- and y-origin of image tiles is at the top left instead of at the lower left. This has always struck me as a particularly silly decision that was clearly made by a graphically challenged mathematician with a matrix fetish.
Compare the above code to that of the main Sinecurve function that collects the points necessary to draw the polyline in the following fragment:
(repeat (* R n)
(setq y (* A (sin (/ (* 2 pi (setq x (+ x xinc))) P)))
p2 (list (+ x x0) (+ y y0))
) ;_ end of setq
(setq plist (append plist p2))
) ;_ end of repeat
(setq polyobj (make-LWpolyline plist)) ; polyline object
(vl-cmdf "Pedit" "L" "Fit" "")
Here there are no negative signs to turn the world upside down. After this repeat loop the function Make-LWpolyline is called to create the polyline, which is then converted to a FIT curve by the last line of code as shown. The (setq polyobj is not strictly necessary here, but I included it to ensure that the appropriate object was returned during coding and testing. The function Make-LWpolyline is shown here to illustrate the object-oriented approach to making a polyline in Visual LISP:
(defun make-LWpolyline (plst)
(setq arr (vlax-make-safearray 5 (cons 0 (- (length plst) 1))))
(vlax-safearray-fill arr plst)
(setq pline (vla-AddLightweightPolyline
) ;_ end of vla-AddLightweightPolyline
) ;_ end of setq
) ;_ end of make-LWpolyline
As always, I look forward to receiving your requests for AutoLISP Solutions. Contact me using the links below.