Quad Bezier Refinement in Degrafa

De Casteljau subdivision is a procedure by which a Bezier curve is defined.  It is also used to subdivide a quadratic Bezier curve into two distinct quadratic Beziers representing individual segments of the original curve.  The first Bezier segment is in the interval [0,t] and the second lies in [t,1] for t in (0,1).  Some 3D graphics packages use the term refinement to describe to the process of subdividing or splitting a curve into two equivalent segments at some interior point.  Refinement is also used to describe a process of extracting the coefficients of an equivalent-degree curve at two interior points.  In this context, refining a quadratic Bezier curve produces another quadratic Bezier that represents the original curve in the interval [t1,t2] where t1 < t2 and both t1, t21 are in [0,1].

This is an infrequent operation, although I recently used it in the organic scroller, the boundary of which is a quadratic Bezier spline.  The process may also be used to extrude any segment of a path comprised of quadratic Beziers (such as a circle approximation).

The quad refinement algorithm is now in Degrafa.  I’m still in the process of conducting some unit tests for possible numerical issues.  I wanted to get a release out now, while I’m in between gigs, since I have the time and am thinking about it.  Otherwise, you know what happens.  It’s onto the next gig and I forget 🙂

A screen shot of the demo program is shown below.

Quadratic Bezier Refinement in the Interval [0.2, 0.6]

Not much to the demo.  The blue curve is the quad. Bezier that interpolates the three points, P0, P1, and P2 with chord-length parameterization.  The red curve is drawn from coefficients returned from the quadRefine() method of the BezierUtils class.  Above, the red curve illustrates refining the original quad in the interval [0.2, 0.6].

Drag the points to see how the refinement is modified.  Adjust the stepper thingies to modify the interval.  [t1,t2] can  be extended to a maximum of [0.1,0.9] in increments of 0.1.  Note that t2 must be strictly greater than t1.  Code has been committed to the Origin branch.

View demo.

View source.

Automatic Bezier Arcs in Degrafa

An interesting problem is to draw an eye-pleasing arc between two points.  This can be used for anything from drawing origin-destination route arcs to approximating trajectories in animation.  Since we already know how to interpolate a quadratic Bezier between three points, one possible solution is to parameterize the generation of a middle interpolation point given two initial points.

I’ve used an algorithm along these lines since about 1982.  It takes two parameters, one of which determines the concavity of the arc.  The second parameter controls the distance between the midpoint of the line segment from first to last point and the middle interpolation point.  This provides a large amount of control over the generated arc.

A closely related problem is animating the arc.  This is trivial with a quadratic Bezier as the section of arc at any parameter value can be drawn with a single curveTo command using deCasteljau subdivision.

The auto-arc generation is now in the BezierUtils class and the subdivision method has been added to the AdvancedQuadraticBezier class.  A screen shot from the rather plain and simple demo is shown below.

Quadratic Bezier auto-fit between two points

The code has been checked into the Origin branch.

View demo.

View source.

Speaking at Dallas TechFest

If you’re in the D/FW area and are interested in attending Dallas TechFest, then I hope to see you at the session on computational geometry in Flex and Degrafa. Little knowledge of Flex is required; only a desire to add cool geometry buzzwords to your vocabulary. I’ll introduce Degrafa, highlight some differences between Degrafa and FXG, and then launch into the low-level computational geometry capability in Degrafa. In addition to declarative drawing, you can see how to perform more advanced tasks in Actionscript ranging from possible charting applications to animating route arcs.

More on the conference below – see you at the end of July!


Degrafa and FlashBuilder Part II

Continuing from Part I of this series, there is still a bit more work to do in terms of project setup using the styles.css file from the standard Degrafa Template.  In the project settings, edit the Flex Compiler settings to ensure the Halo theme is used,

-locale en_US -theme=${flexlib}/themes/Halo/halo.swc

Next, insert the mx namespace into the styles.css file and reference the Application container and Button with mx|Application and mx|Button.  The fill woes continue here as using the cool Degrafa skinning of the Application container creates a conflict with ComplexFill.  We can get the Degrafa logo skinned into the application background with a quick hack … and I do mean hack 🙂

First, here is the styles.css file with some additional font changes and the new mx|Application styling.

/* CSS file */

@namespace s "library://ns.adobe.com/flex/spark";
@namespace mx "library://ns.adobe.com/flex/mx";

/*------------------------------------------------------------------------------ Fonts */

  src: url('../fonts/Myriad.swf');
  fontFamily: 'Myriad Pro';
  fontWeight: Regular;

  src: url('../fonts/Myriad.swf');
  fontFamily: 'Myriad Pro Semibold';
  fontWeight: Semibold;

  src: url("/Library/Fonts/Arial.ttf");
  fontFamily: 'Arial';
  fontWeight: Regular;
  embedAsCFF: false

/*------------------------------------------------------------------------------ Global */

  font-family: 'Myriad Pro';
  color: #CCCCCC;
  embedAsCFF: false

/*------------------------------------------------------------------------------ Text */

  fontSize: 14;
  color: #000000;
  fontWeight:	Semibold;

  font-size: 24;
  text-align: right;
  color: #CCCCCC;

/*------------------------------------------------------------------------------ Application */

  background-color: #222222;
  borderSkin: ClassReference("DegrafaBackground")

/*------------------------------------------------------------------------------ Button */

  fill-colors:  #222222, #222222;
  border-color:	#666666;
  color: #CCCCCC;
  corner-radius: 0;
  text-roll-over-color:	#FFFFFF;
  highlight-alphas:	0,0;
  border-alpha:	1;

And, here is the DegrafaBackground.as file, aka quick hack for the border skin,

  import flash.display.Graphics;
  import mx.skins.ProgrammaticSkin;
  import mx.utils.ColorUtil;
  import flash.display.BitmapData;
  import flash.display.Bitmap;

  public class DegrafaBackground extends ProgrammaticSkin
    private var DegrafaImage:Class;  

    public function DegrafaBackground()

    override public function get measuredWidth():Number
      return 8;

    override public function get measuredHeight():Number
      return 8;

    override protected function updateDisplayList(w:Number, h:Number):void
	super.updateDisplayList(w, h);

        var g:Graphics       = graphics;
        var fillColors:Array = getStyle("backgroundGradientColors");
        var fillAlphas:Array = getStyle("backgroundGradientAlphas");

	if (!fillColors)
	  var bgColor:uint = getStyle("backgroundColor");

	  if (isNaN(bgColor))
		bgColor = 0xFFFFFF;

	    fillColors = [];
            fillColors[0] = ColorUtil.adjustBrightness(bgColor, 15);
            fillColors[1] = ColorUtil.adjustBrightness(bgColor, -25);

	if (!fillAlphas)
	  fillAlphas = [1, 1];

        drawRoundRect(0, 0, w, h, 0, fillColors, fillAlphas, verticalGradientMatrix(0, 0, w, h));

        var backgroundImage:Bitmap       = new DegrafaImage();
        var backgroundBitmap:BitmapData  = new BitmapData( backgroundImage.width, backgroundImage.height, true, getStyle("backgroundColor") );
        backgroundBitmap.draw( backgroundImage );

        g.beginBitmapFill( backgroundBitmap );
        g.drawRect( 0, 0, backgroundImage.width, backgroundImage.height );

And, with that, I was able to get the AdvCubicBezier example up and running with the Degrafa logo skinned into the application background. With F4, Degrafa fills are bad news. Fortunately, splines and such do not involve fills, at least not the declarative type, so it’s clear sailing ahead for low-level Degrafa development.

If there is any interest, I’ll clean up the project and post a .zip to an FXP file for download.

Degrafa and FlashBuilder Part I

I’ve moved onto new gigs and part of that move is migrating my home office to the MacBook Pro and FlashBuilder (I still want to call it Flex 4).  I’ve been working with Jason on getting Degrafa setup with FlashBuilder and finding out what issues are involved with migration.  This is the first in a series of posts on this issue.

When importing the Origin branch from SVN [branches/Origin/Degrafa], setup the project as a Flex Library Project.   Under Project Properties, Flex Library Build Path | Classes Tab – Select classes to include in the library.  Make sure com is checked.  FB wants to setup the main source folder as src.  Leave it blank.

Select the Flex Library Compiler settings.  For now, we need to use the Flex 3.5 SDK.  Set the namespace url to http://www.degrafa.com/2007 .  On the next setting below Namespace URL, browse to the project manifest file and select it.

Click here to see a screenshot of my settings.

When you build the project, there should be a .swc in the bin folder.

When creating a new project, go to the Flex Build Path settings in Project Properties, Library Path.  Click Add Project and select your Degrafa source project.

Now, a few things have changed.  In the new FB 4 universe, Canvas is out and the spark BorderContainer is the new kid on the block.  Degrafa plays nicely with the new kid, but the Degrafa declarations should go inside the fx:Declarations tag.  Here is a minimal example,

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="600" minHeight="400">
    <degrafa:RegularRectangle width="100" height="100" graphicsTarget="{ [myCanvas] }">
      <degrafa:SolidStroke color="0xff0000" />
<s:BorderContainer id="myCanvas" width="300" height="300" />

There are some issues, currently with fills. Jason is looking into current issues and a full-on Flex 4-compatible release (ah, I like Flex 4 much better). I will expand on fills and style-related issues in future posts. Once I get some reasonable examples up and running, it will be time to return to spline goodies. Flex setup … boring … math stuff … fun 🙂