2011-06-28 24 views
4

私は、数値の配列に基づいて静的グラフを描画しようとしています。このグラフは滑らかな洞様でなければなりません。下の値は常にゼロでなければならず、上位の値は数値の配列に指定されます。シヌソイド線グラフを描くにはどうすればよいですか?

sample

I)は、(curvetoといったてこの効果を達成しようとしているが、任意の運なしてきました。

EDIT:値はのようなもの:10、15、40、28、5、2、27等

誰も助けてくださいことはできますか?

答えて

3

curveTo()は、基本的に放物線のセグメントである2次ベジェ曲線のみを描画します。したがって、可変振幅のサインを描きたい場合は、複雑なアルゴリズムを考えなければなりません。

曲線を直線セグメントで描画することをお勧めします。ループの中ではかなりの反復が必要ですが、ほんの数分でコード化できる非常に簡単なアプローチです。もっと精巧なものが本当に必要ですか?

また、http://code.google.com/p/bezier/をご覧ください:デモはクールです。

単一の方程式で簡単に定義できないものを作成したい場合は、ラグランジュ近似を見てみましょう。与えられた点を滑らかな関数に補間します。

EDITラグランジュの近似例

は、以下のコードは、次の描画:

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

データが常に異なる場合は、Lagrange補間法を考案します。 1つのデータセットをプロットするだけであれば、それは常にそのデータになります。私は計算で数値を実行し、単一の式でグラフの非常に良い近似を得ることができます。 –

関連する問題