2011-06-28 121 views
4

我想绘制一个基于数组数组的静态图。这个图应该是很好的光滑的窦状。底部值应始终为零,上限值在数组数组中指定。如何绘制正弦曲线图?

sample

我一直在努力实现与curveTo()这样的效果,但没有任何运气。

编辑:价值观是这样的:10,15,40,28,5,2,27等

谁能帮助吗?

回答

3

curveTo()仅绘制二次贝塞尔曲线,其实质上是抛物线段。因此,如果你想绘制一个幅度可变的正弦曲线,你必须设想一些棘手的算法。

我建议你应该用直线段绘制曲线。这将需要在循环中进行很多迭代,但是只需几分钟就可以编写一个非常简单的方法。你真的需要更精细的东西吗?

另外,看看http://code.google.com/p/bezier/:他们的演示很酷。

如果您想要创建一些无法用一个方程式轻松定义的内容,您可能需要查看拉格朗日近似:它将给定点插入到平滑函数中。

编辑拉格朗日近似例如

下面的代码绘制如下:

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; 
     } 
    } 
} 

逼近类

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 (a.x < b.x) { 
       return -1; 
      } 
      if (a.x > b.x) { 
       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]; 
      } 
     } 
    } 
} 
+0

这看起来不错,但我不能安装 该SWC到Flash CS5 :(如果这可以作为一个单一的等式解决这将是很好的。它将仅用于给定数据的简短可视化。 – MaRmAR

+0

它会是非常特定的数据还是会一直是不同的数据? –

+0

如果数据总是不同,我愿意为您设计拉格朗日插值方法。如果(并且只有!)只是绘制一组数据,并且它始终是数据,那么我可以通过计算来运行数字,并在一个方程中给出一个非常好的近似图。 –