PhilterPaper / Perl-PDF-Builder

Extended version of the popular PDF::API2 Perl-based PDF library for creating, reading, and modifying PDF documents
https://www.catskilltech.com/FreeSW/product/PDF%2DBuilder/title/PDF%3A%3ABuilder/freeSW_full
Other
6 stars 7 forks source link

[CTS 8] splines #61

Closed PhilterPaper closed 6 years ago

PhilterPaper commented 7 years ago

Subject: CTS 8 - splines April 12, 2017, 01:07:26 PM by Phil

Per bug RT 98576, PDF::Builder has a construction it calls a "spline", which is a cubic Bezier curve with two synthesized control points. Now, in most cases of splines that I've seen, the curve passes through all the control points, and what PDF::Builder offers may be better termed a "B-spline" or "approximation spline" (I'm not a mathematician, so I can't tell you for sure). I have clarified the spline documentation (POD) to reflect this. Possibly, we may want to offer one or more additional spline types, either as options on spline(), or new methods.

Any suggestions on what would be useful?

PhilterPaper commented 6 years ago

PDF defines three Bezier curve operators:

In all cases, the start point is the current point. I'm not sure if the v or y variants are considered "quadratic" Bezier curves (one control point) or are something different.

PDF::Builder currently offers two flavors of Bezier curves:

In all cases, curves with multiple sets of points are piecewise. That is, there is no attempt to make the tangent of the curve at one end point match the tangent of the next curve (as the start point). It is possible to draw such curves, but requires synthesis or adjustment of control points to force a common tangent at intermediate points.

There might be options (flags) to specify that the first (and/or last) point given is special:

It is also possible to draw a smooth curve which goes through all points, using cubic Bezier curves. For such a function, we need to decide what to do about the start and end points, to control the tangent of the curve at those points (if desired, to match up with other lines). See https://medium.com/@francoisromain/smooth-a-svg-path-with-cubic-bezier-curves-e37b49d46c74, which is SVG-oriented but still useful.

PhilterPaper commented 6 years ago

Both curve() and spline() permit multiple sets of control and end points, although code should be added to check for the right number of points. As stated before, these are piecewise continuous, so smooth continuous curves are not produced. For compatibility with existing uses, the default should be piecewise continuous. You might want that to show, say, output of a full wave rectifier (with sine wave input). For most purposes, you would want to draw a smoothly continuous curve, which may require the synthesis of new control points.

If the curve is intended to pass through all the given points, that's a whole 'nother beast, with multiple synthesized control points. It could be either cubic or quadratic. A flag to control whether to move to the first point could be given, in the style of arc() and other such curves.

It appears that spline()'s synthesis of two control points may be a normal quadratic-to-cubic Bézier curve conversion. I still need to look at it in detail, but it looks close, at least. I'm still not sure about the two PDF variants, where the second control point is one of the end points.

Per the tutorials, a quadratic curve is second power (with one control point), and a cubic curve is third power (with two control points). A quadratic (as given in spline()) can be converted to a cubic (the curve() call). Higher power curves (Nth power, with N-1 control points) may be defined; perhaps this could be useful in the future. We already have circular and elliptical arcs in PDF::Builder; I'm not sure there's any point in exploring other curve systems. That might best be left to specialized applications, such as drawing Bézier surfaces.

PhilterPaper commented 6 years ago

The "spline" call has been deprecated and is now named "qbspline", for Quadratic Bezier Spline. Note that its functionality has not been changed, and multiple point sets are still not piecewise continuous (not smoothly blending from one curve to another). It is only a name change and clarification in the POD.

The "bspline" call has been added to implement a smooth continuous curve through all given points, using Cubic Bezier curves. The user does not give any control points — they are all synthesized. This is unlike qbspline(), where you give one control point and the new end point for each curve section.

CTS 8 will be closed, as these functions basically satisfy the feature changes requested. It is possible that in the future, additional curves and splines could be added.