I recently received this email privately, and thought the response was
probably worth sharing, so apologies to the OP. It was in reference to an
old message about drawing sin curves.
> Hi Danny, I'd love to see your code if you wouldn't mind. I'm
> looking for something similar too and Catmull-Rom splines are
> way beyond where I'm at.. :P
All right, the first answer is: here's the code (sorry, it's Lingo but it
should be easy enough to translate - note that Lingo arrays are 1-based
rather than 0-based) that converts a sequence of points cubic bezier curve:
on convertPointsToBezierCurve tCatmullPoints
-- add two dummy points to the end
tCatmullPoints.add(tCatmullPoints[tCatmullPoints.count])
tCatmullPoints.add(tCatmullPoints[tCatmullPoints.count])
-- and one at the beginning
tCatmullPoints.addAt(1,tCatmullPoints[1])
tVertexList = []
tNextControl = point(0,0)
repeat with i = 2 to tCatmullPoints.count-2
tNextControl = (tCatmullPoints[i] - tCatmullPoints[i+2])/6
tControl = (tCatmullPoints[i+1] - tCatmullPoints[i-1])/6
tVertexList.add([#vertex:tCatmullPoints[i], #handle2:tNextControl,
#handle1:tControl])
end repeat
tVertexList.add([#vertex:tCatmullPoints[i], #handle2:tNextControl,
#handle1:point(0,0)])
return tVertexList
end
Second answer is: here's a better way to convert a series of points into a
series of *quadratic* beziers. I'll assume that you already know the correct
tangent at each point (which is true if you're generating the points from a
function like sin). If not, you need to calculate some tangents first,
perhaps by using the function above. As I'm only writing this now, I'll do
it straight into AS. This function takes a list of N+1 points and N+1
tangents (each of which is a 2-element array rather than a point object,
although it would be easy to make them points instead), and returns a list
of N control points. I can give you the explanation if you want, but the
basic idea is that each control point must lie on the intersection of the
tangent from both neighbouring points. I've left out the error checking that
would be sensible to include!
function getBezierPoints(tPoints:Array, tTangents:Array):Array {
var tControls:Array = new Array()
for (var i=1; i<tPoints.length; i++) {
var tP1 = tPoints[i]
var tP0 = tPoints[i-1]
var tT1 = tTangents[i]
var tT0 = tTangents[i-1]
var s = ((tP1[0] - tP0[0])*tT0[1] - (tP1[1] - tP0[1])*tT0[0]) /
(tT1[0]*tT0[1] - tT1[1]*tT0[0])
tControls.push(new Array(tP1[0] - s*tT1[0], tP1[1] - s*tT1[1]))
}
return tControls
}
To test it, try this:
m = _root.createEmptyMovieClip("wave", 1)
m._x = 20
m._y = 200
drawSinCurve(m, 50,0,0.1) // experiment with these values to draw different
curves
function drawSinCurve(tMC:MovieClip, tAmp:Number, tPhase:Number,
tFrequency:Number):Void {
var tPoints:Array = new Array();
var tTangents:Array = new Array();
var tInc = 0.05/tFrequency // this value affects the accuracy of the
curve
for (var x = 0; x < 400; x += tInc) {
var tP = x * tFrequency + tPhase;
tPoints.push(new Array(x, tAmp * Math.sin(tP)));
tTangents.push(new Array(1, tAmp * tFrequency *
Math.cos(tP)));
}
var tControls:Array = getBezierPoints(tPoints, tTangents);
tMC.beginFill()
tMC.lineStyle(1)
tMC.moveTo(tPoints[0][0], tPoints[0][1]);
for (var i = 1; i < tPoints.length; i++) {
tMC.curveTo(tControls[i - 1][0], tControls[i - 1][1],
tPoints[i][0], tPoints[i][1]);
}
}
Best
Danny
_______________________________________________
[email protected]
To change your subscription options or search the archive:
http://chattyfig.figleaf.com/mailman/listinfo/flashcoders
Brought to you by Fig Leaf Software
Premier Authorized Adobe Consulting and Training
http://www.figleaf.com
http://training.figleaf.com