QuirkyPolyline: exposing foolish programmers

In AutoCAD, the AcDbCurve class defines a general parametrized curve. On a parametrized curve, points in space are mapped to real numbers (parameters) by an arbitrary function F(p) for values of p from the curve start parameter to the curve end parameter. Defining a curve this way simplifies working with complex 3D curves because one can work in the curve’s one dimensional “parameter space” instead of the more complex three dimensional cartesian space.

The choice for how to parametrize a curve entity is up to the implementor. Parameters are designed to be opaque, so consumers of parametrized curves must make no assumptions about how a specific curve implements them. The only thing guaranteed about the parameters of a curve is that all points on the curve map to a unique parameter in a continuous range from the starting parameter to the ending parameter.

AutoCAD entities such as lines, circles, arcs, polylines, rays, and others are derived from AcDbCurve. These basic curve entities have very simple and straighforward parameter mappings that can be reverse engineered with very little effort, so lazy programmers sometimes make assumptions that are not guaranteed to always be true. Even smart programmers often get tripped up on parametrized curves because they use parameter space when they should be using distance space (that is, distance along the curve). The AcDbCurve interface provides functions to translate from parameter space back and forth to distance space, as well as back and forth to three dimensional cartesian space.

Wise programmers always let the curve itself perform all translations to or from distance space or cartesian space so that their code never relies on the actual value of a parameter. Foolish programmers take shortcuts by making assumptions about parameter values. For example, it happens that in all past versions of AutoCAD, the parameter of the midpoint of a polyline segment is exactly halfway between the segment starting parameter and the segment ending parameter, and the segment starting and ending parameters are always equal to the index number of the corresponding vertex. A foolish programmer (e.g. here and here) may use this knowledge to calculate the midpoint of the segment by guessing it’s parameter. The foolish programmer’s code will fail when a case arises where that guess is wrong. It is the purpose of QuirkyPolyline to provide such a case.

QuirkyPolyline defines a QPOLY command that prompts for a selection set of lightweight polylines in AutoCAD, then converts the selected polylines to “quirky polylines” that expose a completely different parameter scheme. Quirky polylines look and act perfectly normal in all respects. If you save quirky polylines, they will be stripped of their quirkiness. There are no long term effects of making polylines quirky; it’s just a temporary change that wears off on its own.

Making quirky polylines is useful for testing code that works with parametrized curves. If your code makes assumptions that it shouldn’t, quirky polylines will expose the error of your ways. Over the years, I have had arguments with people who insisted that their assumption had been validated by extensive testing. My counterargument is that someone, somewhere (possibly even Autodesk itself) already has or eventually will generate a derived entity where the assumption is not true. In addition to providing a proving ground, QuirkyPolyline is designed to demonstrate to the naysayers that unusual parametrization implementations can exist in the wild.

The download contains ARX modules for AutoCAD 2000 through AutoCAD 2013. To use QuirkyPolyline, just load the module that matches your version and architecture of AutoCAD. Create a lightweight polyline with the PLINE command, then use the QPOLY command to convert the normal polyline to a quirky polyline. You can use the LIST command to verify that it did become quirky, but you should notice no other detectable changes.

QuirkyPolyline.zip [100 kb]

Here is a useful little lisp function that defines a PP command for displaying the parameter value of a picked point on a selected curve entity. You can use this to explore other curve entities, and to see how the polyline’s parametrization changes after it becomes quirky.

(defun C:PP (/ sel pointoncurve param)
  (if (setq sel (entsel))
      (setq pointoncurve (apply 'vlax-curve-getclosestpointto sel))
      (setq param (vlax-curve-getparamatpoint (car sel) pointoncurve))
      (princ (strcat "\nParam = " (rtos param)))

I hope this helps you avoid the pitfalls of parametric curve code. Remember, don’t be a foolish programmer!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>