How to draw a sinusoidal linear diagram?

I am trying to draw a static graph based on an array of numbers. This graph should be nice, smooth sinus. The lower values ​​must always be zero, the upper values ​​are indicated in the array of numbers.

sample

I am trying to achieve this effect with curveTo (), but with no luck.

EDIT: values: 10, 15, 40, 28, 5, 2, 27, etc.

Can anyone help?

+4
source share
1 answer

curveTo () draws only quadratic Bezier curves, which are essentially parabolic segments. Therefore, you need to devise some kind of complex algorithm if you want to draw a sine with variable amplitude.

I suggest you draw your curve using straight lines. This will require quite a few iterations in a loop, but this is a very simple approach that can be encoded in just a few minutes. Do you really need something more complicated?

Alternatively check out http://code.google.com/p/bezier/ : their demo is cool.

If you want to create something that cannot be easily determined using one equation, you can look at the Lagrange approximation: it interpolates the given points into a smooth function.

EDIT Lagrange approximation example

The code below shows the following:

enter image description here

package { import flash.display.Graphics; import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.events.Event; import flash.geom.Rectangle; import org.noregret.math.LagrangeApproximator; [SWF(fps="31",width="600",height="600",backgroundColor="0xFFFFFF")] public class LagrangeTest extends Sprite { private const plot:Sprite = new Sprite(); private const approx:LagrangeApproximator = new LagrangeApproximator(); public function LagrangeTest() { super(); initialize(); } private function initialize():void { stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; stage.addEventListener(Event.RESIZE, onResize); onResize(); addChild(plot); // ADDING CONTROL POINTS (just took them at random) approx.addValue(0, 0); approx.addValue(50, -10); approx.addValue(100, 10); approx.addValue(150, -20); approx.addValue(200, -10); approx.addValue(250, -20); approx.addValue(300, -10); approx.addValue(350, 10); approx.addValue(400, -30); approx.addValue(450, 50); approx.addValue(500, 100); approx.addValue(550, 30); approx.addValue(600, 0); drawCurve(plot, 5, 0, 600); } private function drawCurve(target:Sprite, step:uint, fromArg:int, toArg:int):void { var gfx:Graphics = target.graphics; gfx.clear(); gfx.lineStyle(0, 0xCCCCCC, 1); gfx.moveTo(-50, 0); gfx.lineTo(50, 0); gfx.moveTo(0, -50); gfx.lineTo(0, 50); gfx.lineStyle(2, 0, 1); var minArg:int = Math.min(fromArg, toArg); var maxArg:int = Math.max(fromArg, toArg); if (step == 0) { step = 1; } var value:Number; for (var i:Number = minArg; i<=maxArg; i+=step) { value = approx.getApproximationValue(i); if (i) { gfx.lineTo(i, value); } else { gfx.moveTo(i, value); } } } private function onResize(event:Event = null):void { plot.x = 10; plot.y = stage.stageHeight/2; } } } 

Approximator class

 package org.noregret.math { import flash.geom.Point; import flash.utils.Dictionary; /** * @author Michael "Nox Noctis" Antipin (http://noregret.org) */ public class LagrangeApproximator { private const points:Vector.<Point> = new Vector.<Point>(); private const pointByArg:Dictionary = new Dictionary(); private var isSorted:Boolean; public function LagrangeApproximator() { } public function addValue(argument:Number, value:Number):void { var point:Point; if (pointByArg[argument] != null) { trace("LagrangeApproximator.addValue("+arguments+"): ERROR duplicate function argument!"); point = pointByArg[argument]; } else { point = new Point(); points.push(point); pointByArg[argument] = point; } point.x = argument; point.y = value; isSorted = false; } public function getApproximationValue(argument:Number):Number { if (!isSorted) { isSorted = true; points.sort(sortByArgument); } var listLength:uint = points.length; var point1:Point, point2:Point; var result:Number = 0; var coefficient:Number; for(var i:uint =0; i<listLength; i++) { coefficient = 1; point1 = points[i]; for(var j:uint = 0; j<listLength; j++) { if (i != j) { point2 = points[j]; coefficient *= (argument-point2.x) / (point1.x-point2.x); } } result += point1.y * coefficient; } return result; } private function sortByArgument(a:Point, b:Point):int { if (ax < bx) { return -1; } if (ax > bx) { return 1; } return 0; } public function get length():int { return points.length; } public function clear():void { points.length = 0; var key:*; for (key in pointByArg) { delete pointByArg[key]; } } } } 
+3
source

All Articles