Previous Bezier Spline examples have illustrated how to draw a spline directly with pre-generated data in MXML. In some applications, it is desirable to define the Bezier Spline in MXML, but generate knots (control points) dynamically.
The following diagram shows our infamous arrow generated one segment at a time.
The demo allows one knot to be added or deleted (starting with the minimum of three) until the full set is defined. You may optionally close the spline to complete the drawing. Once the spline is closed, however, it is not recommended to remove and add knots because of the internal bookkeeping inside the Bezier Spline.
The control points are dynamically redrawn based on the internally generated propertyChange event, which also controls the spline redraw. This should illustrate the basics of defining a spline in MXML and dynamically generating knots via script. Download the MXML file here.
One of the many features I like about Degrafa is the ability to draw the same object in multiple targets. Let’s take our friendly arrow spline from the introduction to spline series. If an arrow is worth drawing once, we know the design team will eventually want to draw multiple arrows 🙂
This is a beginner tutorial on how to draw into multiple targets and add a simple rotation transform. You should understand how to setup a Flex project and work with Degrafa. Since this example works with splines, you will also need at least Degrafa Beta 3.
If you followed the introudction to splines series, you noticed that the ‘target’ that Degrafa draws objects into was actually an array. This allows multiple targets to be specified for the same drawing. Give the following code a try,
Since the transform is applied inside the BezierSpline tag, it is applied to the spline drawn into each individual target. As the transform is modified, the modification is propagated to all targets without any direct action on your part.
Notice that the original arrow is drawn pointing downward. The following screen shot shows how all four arrows are modified by the slider (some of the screen space was cropped to save space here).
That’s all you need to do to draw multiple copies of the same item and manipulate all of the targets with a single transform. Experiment and have fun!
Continuing from Part IX, one of the features of building the Bezier spline with cubic segments (individual cubic Bezier curves) is some flexibility in how the control cages are constructed. The mathematical details are discussed in this TechNote. At a high level, consider the spline as a rope that is passed through rings at each knot. Suppose you could ‘pull’ on the rope at any ring. What would happen to the rope?
We would expect the rope to get tighter and tighter until it reached some point that it could not be pulled any further (without breaking). Intuitively, we would call this tension. Bezier curves (individual or composite) do not naturally have tension parameters (as say a cardinal spline). We can fake a tension setting as a natural consequence of assigning control points.
In the Singularity Bezier spline, the tension setting is a map of a tension scale to parameter values. The tension scale varies from 1 (loose) to 5 (tight). The internal parameter map is open for experimentation and some limitations are discussed in the above TechNote.
From a usability standpoint, all the average user need be concerned with is the tension setting from 1-5. The default value is 1, which can be thought of as having the rope pass ‘loosely’ through the rings. On average, the spline appears to have more curvature when passing through the knots.
The tension parameter is exposed to MXML, and the following illustrates setting to it maximum value of 5,
As you work through the code, you may notice a parameter or two such as ‘quality’ that appear to have no effect on the output. This parameter in particular was an artifact of the Singularity cubic Bezier spline that was built on top of the FastBezier class. The quality parameter controlled the number of subdivision steps (used to approximate the cubic Bezier with a small number of quadratic Bezier). This parameter allowed render quality to be traded for performance. It will be removed from future versions of the Degrafa Bezier Spline.
This completes the basic introduction to splines in Degrafa. Future posts will provide demos of more advanced usage of the Degrafa splines and illustration of new features as they are added.
Continuing from Part VIII, what happens if we want to close the arrow outline? We have discussed auto-closure for the Bezier spline in a previous post and this feature is available in the Degrafa spline. Not only is it available, it is exposed to direct manipulation in MXML. Simply modify the <BezierSpline> tag as follows,
There was a small bug in the initial port, so make sure you first update the code from SVN. This produces the following drawing,
Degrafa splines are ‘open’ by default. You must specify closure (if it is supported by a particular spline) by setting the autoClose parameter to true. The closure is automatic; no additional knots or programming action are required. The diagram below illustrates construction of the individual cubic Bezier control points.
An additional knot is automatically added to the data set to be interpolated. The added knot is a duplicate of the first interpolation point. An additional segment (cubic Bezier curve) is added to the spline. Recall that the spline is sometimes called a composite Bezier curve as it is composed of independent cubic Bezier curves with continuity conditions imposed at the joins.
The control points for the final cubic Bezier curve in the composition are computed so that the slope of the in-tangent to the final knot matches that of the out-tangent of the first knot. The same condition is applied to the in- and out-tangents of the final knot. This preserves continuity at all joins.
Another parameter is available to adjust the visual characteristics of the interpolated spline. In the spirit of a weekend cliffhanger, think about a rope that is threaded through a ring at each knot location. What would happen if you pulled that rope tighter?
Continuing from Part VII, the BezierSpline tag provides a means to set inputs to the Degrafa BezierSpline class. All splines in Degrafa that are explicitly called splines are purely interpolative; that is they interpolate an arbitrary set of points. It is okay to call a quadratic or cubic Bezier curve a spline. These parametric curves interpolate the first and last points in a set. Interior points influence the shape of the curve, but they are not interpolated. Even so, quad and cubic Beziers are still essentially splines.
So, when we specifically call a Degrafa curve a ‘spline’, the reference will always be to a parametric curve that completely interpolates an arbitrary point set. That point set is described in the ‘data’ attribute of the tag and drawn into a target that is bound to the Flex Canvas with the id of ‘theTarget.’
The <stroke> tag describes how to draw the Bezier spline as it is contained inside the BezierSpline tag. In typical Degrafa fashion, we could add a <fill> tag after the <stroke> to specify a fill for the drawing. Alternatively, we can create arbitrary sets of fills and bind them to a ‘fill’ attribute to create reusable fills. For example,
Notice that mathematically, the spline does what it is told; it interpolates the input points and Degrafa draws the spline with the specified stroke. Degrafa also dutifully draws the fill based on the stroke outline and specified point set, but there is an implied closure to the fill that is not present in the spline outline.
The next post will discuss the topics of closure and spline tension.
Continuing from Part VI, it’s time to have some fun. Let’s draw a cubic Bezier spline using nothing but MXML. As an old-school assembly language programmer, I find this a bit exciting. All the complexity and detail from both a mathematical and programming standpoint are completly hidden. What might traditionally be exposed to programmers through a documented API is now exposed to people who may have little traditional programming experience entirely through an XML-style syntax.
First of all, you need Degrafa Beta 3. You also need a bit of experience with how to setup a Degrafa project and a minimal amount of Flex experience. Fortunately, there are a great number of samples at multiple levels of complexity at the Degrafa learning page.
Let’s start with a simple outline of a curvy arrow, created by Jason Hawryluk. Jason did the initial cubic Bezier spline port, starting from a standalone code base I created that was divorced from any dependency on non-essential classes in the Singularity package. For not having a computational geometry background, he did an incredible job and deserves some serious props for getting this effort off the ground.
Create a new Flex project and try the following code,
If you run the application, your output should appear similar to the following.
I ran the same data against the Singularity cubic Bezier spline which has additional capability to display the knots and control cages for the individual cubic Bezier curves comprising the spline. These are illustrated below.
Notice how we were able to draw a relatively complex shape by specifying only a few knots through which the spline must pass. The spline computations do all the work and the Degrafa framework exposes relevant properties to control the spline through MXML.
Well, that’s enough to get started. In subsequent posts, we will deconstruct the basic code and make some modifications.