2011-06-28 118 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

如果數據總是不同,我願意爲您設計拉格朗日插值方法。如果(並且只有!)只是繪製一組數據,並且它始終是數據,那麼我可以通過計算來運行數字,並在一個方程中給出一個非常好的近似圖。 –