# Category Archives: bezier

Being able to draw smooth lines that connect arbitrary points is something that I find myself needing very frequently. This is a port of an old snippet that does just that. By averaging control points of a quadratic bezier curve we ensure that our resulting Bezier curves are always smooth.

The key can be seen here with the `bezierSkin` function. It draws either a closed or open curve.

```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 // array of xy coords, closed boolean function bezierSkin(bez, closed = true) { var avg = calcAvgs(bez), leng = bez.length, i, n;   if (closed) { c.moveTo(avg, avg); for (i = 2; i < leng; i += 2) { n = i + 1; c.quadraticCurveTo(bez[i], bez[n], avg[i], avg[n]); } c.quadraticCurveTo(bez, bez, avg, avg); } else { c.moveTo(bez, bez); c.lineTo(avg, avg); for (i = 2; i < leng - 2; i += 2) { n = i + 1; c.quadraticCurveTo(bez[i], bez[n], avg[i], avg[n]); } c.lineTo(bez[leng - 2], bez[leng - 1]); } }     // create anchor points by averaging the control points function calcAvgs(p) { var avg = [], leng = p.length, prev; for (var i = 2; i < leng; i++) { prev = i - 2; avg.push((p[prev] + p[i]) / 2); } // close avg.push((p + p[leng - 2]) / 2); avg.push((p + p[leng - 1]) / 2); return avg; }```

The control points are then averaged to ensure that the curve contains no sharp angles.

Also posted in Graphics, Math, arrays, graphics algorithms, html5, javascript | Tagged , , , , | Leave a comment

Actionscript:
1. [SWF(backgroundColor=0x333333, width=800, height=600)];
2. x = stage.stageWidth / 2;
3. y = stage.stageHeight / 2;
4. var verts:Vector.<Number>  = new Vector.<Number>();
5. var tVerts:Vector.<Number> = new Vector.<Number>();
6. var pVerts:Vector.<Number> = new Vector.<Number>();
7. var uvts:Vector.<Number> = new Vector.<Number>();
8.
9. var igraph:Vector.<IGraphicsData> = new Vector.<IGraphicsData>();
10.
11. var tVect:Vector3D = new Vector3D();
12. var m:Matrix3D = new Matrix3D();
13. for (var i:int = 0; i<200; i++){
14.     for (var j:int = 0; j<3; j++){
15.         tVect.x = Math.random() * 0.15;
16.         m.identity();
17.         m.appendRotation(Math.random()*360, Vector3D.X_AXIS);
18.         m.appendRotation(Math.random()*360, Vector3D.Y_AXIS);
19.         m.appendRotation(Math.random()*360, Vector3D.Z_AXIS);
20.         tVect = m.transformVector(tVect);
21.         verts.push(tVect.x, tVect.y, tVect.z);
22.     }
23.
24.     var stroke:GraphicsStroke = new GraphicsStroke();
25.
26.     var col:int = [0xFFFFFF, 0x000000, 0xFFCC00, 0xFF0000][int(Math.random() * 4)];
27.
28.     stroke.thickness = 2+(Math.random()*Math.random())*8;
29.     var mg:Matrix = new Matrix();
32.
33.     var bez:GraphicsPath = new GraphicsPath();
34.     bez.commands = Vector.<int>([1, 3]);
35.     igraph.push(stroke);
36.     igraph.push(bez);
37. }
38.
39. var perspective:PerspectiveProjection = new PerspectiveProjection();
40. perspective.fieldOfView = 45;
41. var trans:Matrix3D = new Matrix3D();
42. var proj:Matrix3D = perspective.toMatrix3D();
43. var dx:Number = 0, dy:Number = 0;
44.
46. function onLoop(evt:Event):void {
47.     dx += (mouseX - dx) / 4;
48.     dy += (mouseY - dy) / 4;
49.
50.     trans.identity();
51.     trans.appendRotation(dy, Vector3D.X_AXIS);
52.     trans.appendRotation(dx, Vector3D.Y_AXIS);
53.     trans.appendTranslation(0,0,0.5);
54.     trans.transformVectors(verts, tVerts);
55.     Utils3D.projectVectors(proj, tVerts, pVerts, uvts);
56.
57.     var inc:int = 0;
58.     for (var i:int = 1; i<igraph.length; i+=2){
59.         GraphicsPath(igraph[i]).data = pVerts.slice(inc, inc + 6);
60.         inc += 6;
61.     }
62.
63.     graphics.clear();
64.     graphics.drawGraphicsData(igraph);
65. }

A variation on yesterdays post - this makes use of GraphicsGradientFill to add some depth...

Check out the swf... ## 3D Bezier

Actionscript:
1. [SWF(backgroundColor=0x000000, width=800, height=600)];
2. x = stage.stageWidth / 2;
3. y = stage.stageHeight / 2;
4. var verts:Vector.<Number>  = new Vector.<Number>();
5. var tVerts:Vector.<Number> = new Vector.<Number>();
6. var pVerts:Vector.<Number> = new Vector.<Number>();
7. var uvts:Vector.<Number> = new Vector.<Number>();
8.
9. var igraph:Vector.<IGraphicsData> = new Vector.<IGraphicsData>();
10.
11. var tVect:Vector3D = new Vector3D();
12. var m:Matrix3D = new Matrix3D();
13. for (var i:int = 0; i<300; i++){
14.     for (var j:int = 0; j<3; j++){
15.         tVect.x = Math.random() * 0.15;
16.         m.identity();
17.         m.appendRotation(Math.random()*360, Vector3D.X_AXIS);
18.         m.appendRotation(Math.random()*360, Vector3D.Y_AXIS);
19.         m.appendRotation(Math.random()*360, Vector3D.Z_AXIS);
20.         tVect = m.transformVector(tVect);
21.         verts.push(tVect.x, tVect.y, tVect.z);
22.     }
23.
24.
25.     var stroke:IGraphicsData = new GraphicsStroke();
26.
27.     var col:int = [0xFFFFFF, 0x000000, 0xFFCC00, 0xFF0000][int(Math.random() * 4)];
28.     with (stroke) thickness = (Math.random()*Math.random())*10, fill = new GraphicsSolidFill(col);
29.
30.     var bez:GraphicsPath = new GraphicsPath();
31.     bez.commands = Vector.<int>([1, 3]);
32.     igraph.push(stroke);
33.     igraph.push(bez);
34. }
35.
36. var perspective:PerspectiveProjection = new PerspectiveProjection();
37. perspective.fieldOfView = 45;
38. var trans:Matrix3D = new Matrix3D();
39. var proj:Matrix3D = perspective.toMatrix3D();
40. var dx:Number = 0, dy:Number = 0;
41.
43. function onLoop(evt:Event):void {
44.     dx += (mouseX - dx) / 4;
45.     dy += (mouseY - dy) / 4;
46.
47.     trans.identity();
48.     trans.appendRotation(dy, Vector3D.X_AXIS);
49.     trans.appendRotation(dx, Vector3D.Y_AXIS);
50.     trans.appendTranslation(0,0,0.5);
51.     trans.transformVectors(verts, tVerts);
52.     Utils3D.projectVectors(proj, tVerts, pVerts, uvts);
53.
54.     var inc:int = 0;
55.     for (var i:int = 1; i<igraph.length; i+=2){
56.         GraphicsPath(igraph[i]).data = pVerts.slice(inc, inc + 6);
57.         inc += 6;
58.     }
59.
60.     graphics.clear();
61.     graphics.drawGraphicsData(igraph);
62. }

After a few hours of trying to get a super optimized fp10 z-sorting demo happening, I gave up (for now) and decided to just let loose with something easy. The result is this 3D Bezier example...

Check out the swf... Also posted in 3D, Graphics | Tagged , , , | 3 Comments

## Recursive 2D Structure

Actionscript:
1. [SWF(width = 600, height = 700, frameRate=24)]
2. var canvas:BitmapData = new BitmapData(stage.stageWidth,stage.stageHeight,false, 0xFFFFFF);
4.
5. var maxBranches:int = 600;
6. var branches:int = 0;
7. var startX:Number = 300
8. makeBranch(startX,690,30,-60, 60);
9.
10. function makeBranch(xp:Number, yp:Number, step:Number, min:Number, max:Number):void {
11.     var vectors:Shape = Shape(addChild(new Shape()));
12.     var cX:Number, cY:Number, eX:Number, eY:Number
13.     var dcX:Number=xp, dcY:Number=yp, deX:Number=xp, deY:Number=yp;
14.     var theta:Number = (min + Math.random()*(max-min) - 90) * Math.PI / 180;
15.     cX = xp + step * Math.cos(theta);
16.     cY = yp + step * Math.sin(theta);
17.     theta = (min + Math.random()*(max-min)-90) * Math.PI / 180;
18.     eX = cX + step * Math.cos(theta);
19.     eY = cY + step * Math.sin(theta);
20.     var run:Function = function():void{
21.          dcX +=  (cX - dcX) / 2;
22.          dcY +=  (cY - dcY) / 2;
23.          deX +=  (eX - deX) / 8;
24.          deY +=  (eY - deY) / 8;
25.          with(vectors.graphics){
26.               clear();
27.               beginFill(0xFFFFFF,0.8);
28.               lineStyle(0,0x000000,0.8);
29.               moveTo(startX, yp);
30.               lineTo(xp, yp);
31.               curveTo(dcX, dcY, deX, deY);
32.               lineTo(startX, deY);
33.          }
34.          if (Math.abs(dcX - cX) <1 && Math.abs(deX - eX) <1 && Math.abs(dcY - cY) <1 && Math.abs(deY - eY) <1){
35.              canvas.draw(vectors);
36.              removeChild(vectors);
37.              if (branches <maxBranches){
38.                  setTimeout(makeBranch, 10, deX, deY, step - Math.random(), -90, 90);
39.                  branches++;
40.                  if (int(Math.random()*2) == 1){
41.                     setTimeout(makeBranch, 10, deX, deY, step - Math.random()*3, -90, 90);
42.                     branches++;
43.                  }
44.              }
45.          }else{
46.              setTimeout(arguments.callee,  1000 / 24);
47.          }
48.     }();
49. }

This snippet uses a technique similar to what you might use to create a recursive tree. A bit of additional logic is added for bezier branches, filled shapes and animation.

WARNING: may run slow on older machines

Have a look at the swf... Also posted in BitmapData, functions, misc, motion | Tagged , , | 7 Comments

• 