9.その他のアルゴリズム 9.1 曜日を求める ツェラー(Zeller)の公式を使うと西暦の年月日から曜日を求めることができます。

Slides:



Advertisements
Similar presentations
オブジェクト指向 言語 論 第八回 知能情報学部 新田直也. 多相性(最も単純な例) class A { void m() { System.out.println( “ this is class A ” ); } } class A1 extends A { void m() { System.out.println(
Advertisements

山元進.  for 文  while 文  do ~ while 文  文のネスト  break 文  continue 文.
初年次セミナー 第13回 2次元グラフィックス(1).
情報処理演習 (9)グラフィックス システム科学領域 日浦 慎作.
初年次セミナー 第14回 2次元グラフィックス(2).
プログラミング演習3 李 亜民クラス 第2回 ラスタライズ.
第3回:ボールを上下に動かそう! (オブジェクトの移動、一次元)
・力のモーメント ・角運動量 ・力のモーメントと角運動量の関係
Applet 岡部 祐典 鈴木 敬幸.
アルゴリズムとデータ構造 2013年6月18日
6.3 2次元DFT (1)2次元DFTとは 画像のような2次元信号をサンプリングしたデータを 2次元DFTを
CGプログラミング論 平成28年6月1日 森田 彦.
第4回:ボールを画面内で弾ませよう! (オブジェクトの移動、二次元)
Excelによる3-D/等高線グラフの描画 2変数関数の描画 Excel によるグレイスケールマップ風描画
Excelによる3-D/等高線グラフの描画 2変数関数の描画 Excel によるグレイスケールマップ風描画
第2回:Javaの変数と型の宣言 プログラミングII 2007年10月2日.
アルゴリズムとデータ構造 2012年6月14日
アルゴリズムとデータ構造 2011年6月13日
アルゴリズムとプログラミング (Algorithms and Programming)
計算機プログラミングI 第12回 2003年1月23日(木) インターフェース スレッド 最後に お知らせ クイズ 授業アンケート
CGプログラミング論 平成28年4月27日 森田 彦.
アルゴリズムとデータ構造 2011年6月14日
CGと形状モデリング 授業資料 長井 超慧(東京大学)
C 言語について 補足資料 資料および授業の情報は :
SystemKOMACO Jw_cad 基本操作(6) Ver.1
CGプログラミング論 平成28年5月25日 森田 彦.
JAVA入門後期⑩ 情報処理試験例題解説.
アルゴリズムとプログラミング (Algorithms and Programming)
CGプログラミング論 平成28年6月8日 森田 彦.
フォームのデザイン Labelコントロール変更点 (name): labelDate Font Size: 18pt
第10回関数 Ⅱ (ローカル変数とスコープ).
電界中の電子の運動 シミュレータ作成 精密工学科プログラミング基礎 資料.
TCanvas BCB:TCanvasクラスでグラフィックを扱う。 TFormなどもプロパティとして持っている。
OpenGLライブラリを用いた3次元フラクタルの描画
前回の練習問題.
計算機プログラミングI 第11回 再帰 再帰的なメソッド定義 帰納的定義 再帰的なデータ構造 計算機プログラミングI (増原) 2003年度.
オブジェクト指向言語論 第十一回 知能情報学部 新田直也.
アルゴリズムとデータ構造1 2005年7月5日
アルゴリズムとデータ構造1 2005年6月24日
アルゴリズムとデータ構造 2010年6月21日
CGと形状モデリング 授業資料 1,2限: 大竹豊(東京大学) 3,4限: 俵 丈展(理化学研究所)
オブジェクト指向言語論 第十一回 知能情報学部 新田直也.
疑似乱数, モンテカルロ法によるシミュレーション
計算機プログラミングI 第5回 配列 文字列(Stringクラス) mainの引数 配列の利用例
アルゴリズムとプログラミング (Algorithms and Programming)
プログラミング言語論 第十三回 理工学部 情報システム工学科 新田直也.
プログラミング言語論 第十一回 理工学部 情報システム工学科 新田直也.
計算機プログラミングI 第3回 プリミティブ値 クラスメソッド クラス変数 式と演算 変数の利用
Excelによる3-D/等高線グラフの描画 2変数関数の描画 Excel によるグレイスケールマップ風描画
アルゴリズムとデータ構造 2012年6月11日
アルゴリズムとプログラミング (Algorithms and Programming)
地理情報システム論(総)/ 国民経済計算論(商)
地理情報システム論 第4回 コンピュータシステムおける データ表現(2)
アルゴリズムとデータ構造1 2006年6月23日
画面への描画 Graphics オブジェクト 紙 ペン Pen オブジェクト Brush オブジェクト 画面のピクセルをカプセル化
第6回:得点を表示しよう! (文字の表示、乱数)
計算機プログラミングI 第4回 2002年10月31日(木) 問題解決とアルゴリズム クラスメソッドと手続きの抽象化 最大公約数
アルゴリズムとデータ構造1 2009年6月15日
高度プログラミング演習 (11).
CGプログラミング論 平成28年5月18日 森田 彦.
cp-15. 疑似乱数とシミュレーション (C プログラミング演習,Visual Studio 2019 対応)
Cプログラミング演習 ニュートン法による方程式の求解.
アルゴリズムとデータ構造 2010年6月17日
ソフトウェア工学 知能情報学部 新田直也.
8.文字列処理 8.1 C#の文字列 C#では, “ABCD”のように文字列を2重引用符で挟んで指定します。ASCIIコード体系のとき,以下のような内部形式となります。 1 1 文字 ‘A’ ナル文字 1 1 文字 ‘B’ A B C D \ 文字 ‘C’ 1 1 文字 ‘D’ ナル文字‘\0’
CGと形状モデリング 授業資料 1,2限: 大竹豊(東京大学) 3,4限: 俵 丈展(理化学研究所)
7.集合 7.1 集合とは [集合と要素] 関東の都道府県 群馬県 栃木県 要素 埼玉県 茨城県 東京都 千葉県 神奈川県
計算機プログラミングI 第2回 2002年10月17日(木) 履習登録 複習 ライブラリの利用 (2.6-7) 式・値・代入 (2.6-8)
計算機プログラミングI 第10回 2002年12月19日(木) メソッドの再定義と動的結合 クイズ メソッドの再定義 (オーバーライド)
計算機プログラミングI 第5回 2002年11月7日(木) 配列: 沢山のデータをまとめたデータ どんなものか どうやって使うのか
Presentation transcript:

9.その他のアルゴリズム 9.1 曜日を求める ツェラー(Zeller)の公式を使うと西暦の年月日から曜日を求めることができます。 9.その他のアルゴリズム 9.1 曜日を求める ツェラー(Zeller)の公式を使うと西暦の年月日から曜日を求めることができます。 例題では,その日が日曜日であれば0,月曜日であれば1,…,土曜日であれば6を返却する関数を示します。なお,2月の日数が一定でないので,1月・2月は前年の13月,14月とみなします。 なお,うるう年は4で割れる年ですが,100で割れるが400で割れない年は平年です。

例題 private int WeekDay(int Y, int M, int D) // ツェラー(Zeller)の公式 { int YY=Y; int MM=M; if (M<3){YY=Y-1; MM=M+12;} return (YY +(YY/4)-(YY/100)+(YY/400)+(13*MM + 8)/5+D) % 7; } private void button1_Click(object sender, System.EventArgs e) int Y=int.Parse(textBox1.Text); int M=int.Parse(textBox2.Text); int D=int.Parse(textBox3.Text); int R=WeekDay(Y,M,D); string X="日月火水木金土"; label4.Text = X[R]+"曜日";

9.2 等高線の描画 横Δx,縦Δyの長方形の各辺にhとなる点を見つけて, 線を引くと等高線を描くことができる。 Z3 Δx Z2 Δy 9.2 等高線の描画 横Δx,縦Δyの長方形の各辺にhとなる点を見つけて, 線を引くと等高線を描くことができる。 Z3 Δx Z2 f(x, y)=h の 等高線 Δy h-Z1 Δy Z2-Z1 Z0 Z1 h-Z0 Δx Z1-Z0

9.2 等高線の描画 以下のような等高線の場合,点線のように描くことになるが, 格子を十分小さくとれば,実用上問題は生じない。

例題 フォーム定義 Name : textBox1 Name : button2 Name : openFileDialog1

実行例 初期画面 数値地図読込み表示 (国土地理院発行50mメッシュ)

例題 (以下のネームスペースを追加) using System.Drawing.Drawing2D; using System.IO;

例題 (データの宣言) private int numX=201; private int numY=201; private double dx=1.0; private double dy=1.0; private double X0, Y0; private string pbA; private double Hstep; private double[,] Z=new double[201,201]; private Matrix matrix=new Matrix(); private Image image;

例題 public double 補間(double H, double Z1, double Z2) {   return ((H-Z1)/(Z2-Z1)); }

例題 public void Contour(Graphics g, int j, int k, double H){ double Z0=Z[j , k ]; double Z1=Z[j+1, k ];   double Z2=Z[j+1, k+1]; double Z3=Z[j , k+1];   bool P01 = (Z0> H) ^ (Z1 > H); bool P12 = (Z1> H) ^ (Z2 > H);   bool P23 = (Z2> H) ^ (Z3 > H); bool P30 = (Z3> H) ^ (Z0 > H);   if( P01 || P12 || P23 || P30) { float x0=0; float y1=0; float x2=0; float y3=0; Pen pen = new Pen(Color.Black,0.01F); if(P01) x0 =(float)( dx*(((double)j)+補間(H, Z0,Z1))); if(P12) y1 =(float)( dy*(((double)k)+補間(H, Z1,Z2))); if(P23) x2 =(float)( dx*(((double)j)+補間(H, Z3,Z2))); if(P30) y3 =(float)( dy*(((double)k)+補間(H, Z0,Z3))); float yk =(float)(dy*(double)(k )); float yk1=(float)(dy*(double)(k+1)); float xj =(float)(dx*(double)(j )); float xj1=(float)(dx*(double)(j+1)); if(P01 && P12) g.DrawLine(pen, x0 , yk , xj1, y1 ); if(P12 && P23) g.DrawLine(pen, xj1, y1 , x2 , yk1); if(P23 && P30) g.DrawLine(pen, x2 , yk1, xj , y3 ); if(P30 && P01) g.DrawLine(pen, xj , y3 , x0 , yk ); if(P01 && P23) g.DrawLine(pen, x0 , yk , x2 , yk1); if(P12 && P30) g.DrawLine(pen, xj1, y1 , xj , y3 );   } } 例題

例題 public void Contours(Graphics g, double v1, double v2, double dv) { for(int j=0; j<numX-1; j++) for(int k=0; k<numY-1; k++) for(double v=v1; v<=v2; v +=dv) Contour(g,j,k,v); } public void ColorMap(Graphics g, double v1, double v2, double dv) Color color; float w =(float) dx; float h =(float) dy; double DD=(v2-v1)/20; for(int k=0; k<numY-1; k++){ float x1 =(float)( dx*((double)(j))); float y1 =(float)( dy*((double)(k))); int ID=(int)((Z[j,k]-v1)/DD); switch(ID) case 0 : color=Color.FromArgb( 0, 63, 0); break; case 1 : color=Color.FromArgb( 0, 95, 0); break; case 2 : color=Color.FromArgb( 0,127, 0); break; case 3 : color=Color.FromArgb( 0,159, 0); break; case 4 : color=Color.FromArgb( 0,191, 0); break; case 5 : color=Color.FromArgb( 0,223, 0); break; 例題

例題 case 6 : color=Color.FromArgb( 0,255, 0); break; default: color=Color.FromArgb(255, 0, 0); break; } Brush brush = new SolidBrush(color); g.FillRectangle(brush,x1,y1,w,h); 例題

例題 public double minZ() { double R=Z[0,0]; for(int j=0; j<numX-1; j++) for(int k=0; k<numY-1; k++) if(Z[j,k]<R) R=Z[j,k]; return R; } public double maxZ() for(int k=0; k<numY-1; k++) if(Z[j,k]>R) R=Z[j,k];

例題 private void 描画() { image =new Bitmap(1000,1000); Graphics g=Graphics.FromImage(image); g.Clear(this.BackColor); g.Transform=matrix; double V1=minZ(); double V2=maxZ(); if(Math.Abs(V2-V1)<0.0000001) V2=V1+1; ColorMap(g, V1, V2, 0.1); Contours(g, V1, V2, Hstep); } protected override void OnPaint(PaintEventArgs e) base.OnPaint(e); e.Graphics.DrawImage(image,0,0); 例題

例題 private void window(double X1, double Y1, double X2, double Y2) { double W=this.ClientSize.Width; double H=this.ClientSize.Height; float SX=(float)(W/(X2-X1)); float SY=(float)(H/(Y2-Y1)); matrix.Scale(SX,SY); matrix.Translate(-(float)X1,-(float)Y1); } private void Form1_Load(object sender, System.EventArgs e) double XX=((double) numX)*0.5; double YY=((double) numY)*0.5; X0 = dx * XX; Y0= dy * YY; double C = 0.02; //倍率 Hstep=double.Parse(textBox1.Text); for(int i=0; i<numX; i++) for(int j=0; j<numY; j++) double x=C*(((double)i)-XX); double y=C*(((double)j)-YY); Z[i,j]=(x-y)*Math.Exp(-(x*x+y*y))*5000; window(-20,240,220,-50); 描画(); 例題

例題 private void button1_Click(object sender, System.EventArgs e) { openFileDialog1.ShowDialog(); } private string midStr(string DT, int ist,int N) string S="";int k=ist-1; for(int i=1 ;i<=N;i++){S = S + DT[k]; k=k+1;} return S;

例題 private void openFileDialog1_FileOk (object sender, System.ComponentModel.CancelEventArgs e) { StreamReader DTS; int ii, pbII; string FName=openFileDialog1.FileName; if(FName == "") return; DTS=new StreamReader(FName,System.Text.Encoding.Default); pbA=DTS.ReadLine(); pbII=0;string DT=DTS.ReadLine(); while(DT !=null) ii = 5; for(int j=0;j<200;j++) ii = ii + 5; Z[pbII, j] = int.Parse(midStr(DT, ii, 5)); } DT=DTS.ReadLine(); pbII++; DTS.Close(); 描画();  this.Invalidate(); 例題

例題 private void textBox1_TextChanged(object sender, System.EventArgs e) { Hstep=double.Parse(textBox1.Text); } private void button2_Click(object sender, System.EventArgs e) 描画(); this.Invalidate();

9.3 陰線消去 等高線は,3次元形状を数値的に正確に表示するという意味では有効だが,直感的に図形を把握するのが困難 普段,見慣れた形で表示

ワイヤフレーム 3次元図形を単純に平行投影してみると, 本来は見えない部分まで表示されてしまう。 見えない部分の線を消す処理(陰線消去)を入れる

例題データ 2次元配列に以下のデータを入れて高さデータとします。

3次元データの平行投影 次のように変換します。

浮動水平線アルゴリズム ■ 一番,手前から描く。 ■ 現在描いている曲線の1点のY座標が, それ以前に描かれた曲線の最大値より大きければ,   それ以前に描かれた曲線の最大値より大きければ,   (水平線より上に位置すれば),   その点が見えるものとして描く。 ■ 描画の進行に伴って,   水平線がYの正の方向に上がっていくので, 浮動水平線アルゴリズムと呼ばれる。

浮動水平線アルゴリズム 曲線が描かれていく様子 z y x 曲線を 描く順序

例題 (以下のネームスペースを追加) using System.Drawing.Drawing2D;

例題 (データ宣言) public double Hidden_dlx; // 表示刻み幅(dl) public double Hidden_alpha; // x軸と水平軸との角度(α) public double Hidden_beta; // y軸と水平軸との角度(β)  public double Hidden_dx; // x軸方向の単位メッシュの長さ(dx) public double Hidden_dy; // y軸方向の単位メッシュの長さ(dy) public double[,] 高さ=new double[51,51]; // 高さ(z値) public double[] YMax=new double[2000]; // Y座標値の最大値(上の浮動水平線) public double[] YMin=new double[2000]; // Y座標値の最小値(下の浮動水平線) public double Hidden_Xlen;     // 表示上のX方向長さ=(numX-1)*dx*cos(α) public double Hidden_Ylen;     // 表示上のX方向長さ=(numY-1)*dx*cos(β) public int Hidden_NR;     // 浮動水平線用配列の長さ public double beforX; // 現在ペン位置X public double beforY; // 現在ペン位置Y public int numX=51; // x方向メッシュ数 public int numY=51; // y方向メッシュ数 public double Hidden_dxCosA; // dx*cos(α) public double Hidden_dyCosB; // dy*cos(β) public double Hidden_dxSinA; // dx*sin(α) public double Hidden_dySinB; // dy*sin(β) public double Hidden_dlxTanA; // dl*tan(α) public double Hidden_dlxTanB; // dl*tan(β) public Matrix matrix= new Matrix(); // グローバル座標系への変換マトリックス 例題

(陰線処理) public bool Hidden_Draw(PaintEventArgs e,Pen pen,double px,double py,           int p, bool Visible, bool Update) {  // 陰線かどうかを判断し,陰線でない場合,線を描く。   // 関数値 : 表示後の可視フラグ   // e : 描画用引数   // pen : ペン属性   // px : 補間されたX座標値(平面座標系)   // py : 補間されたY座標値(平面座標系)   // p : 比較する浮動水平線の位置   // Visible : 現ペン位置が見えているかどうかを示すフラグ(可視フラグ)   // Update : 陰線でないとき,浮動水平線を更新するかどうかを示すフラグ   if((py>=YMax[p])||(py<=YMin[p])){ if(Update && py >=YMax[p])YMax[p]=py; if(Update && py <=YMin[p])YMin[p]=py; if(Visible){ float fx1=(float)beforX; float fy1=(float)beforY; float fx2=(float)px ; float fy2=(float)py; e.Graphics.DrawLine(pen,fx1,fy1,fx2,fy2); } beforX=px;beforY=py; return true;    }    else{ beforX=px;beforY=py; return false; 例題

例題 (OnPaintのオーバーライド(その1)) protected override void OnPaint(PaintEventArgs e ) {   bool 可視フラグ=true;   base.OnPaint(e);   e.Graphics.Clear(Color.White);   Pen pen=new Pen(Color.Black,0.02F);   e.Graphics.Transform=matrix;   for (int j=0;j<Hidden_NR;j++){ YMax[j]=-1E20; YMin[j]=1E20;} // 浮動水平線の初期化   double X0=80; // 表示始点位置    double Y0=100;   for(int k=0;k<numY;k++) { 可視フラグ=false; for(int j=0;j<numX-1;j++){ // X軸方向描画    int p1=(int)((0.5+(Hidden_Ylen+Hidden_GroundX(j,k)) /Hidden_dlx)); int p2=(int)((0.5+(Hidden_Ylen+Hidden_GroundX(j+1,k))/Hidden_dlx));  for(int p=p1; p<=p2;p++){ // 補間    double PH=(double)(p-p1);    double fp = 高さ[j,k]+(高さ[j+1,k]-高さ[j,k]) * PH * Hidden_dlx / Hidden_dxCosA; double px = PH*Hidden_dlx + Hidden_GroundX(j,k)+ X0; double py = PH*Hidden_dlxTanA + Hidden_GroundY(j,k) + fp + Y0; if((j<numX-2 && p<p2) || (j == numX-2)) 可視フラグ=Hidden_Draw(e, pen, px, py, p,可視フラグ, true); } 例題

例題 ( OnPaintのオーバーライド(その2)) for(int j=0;j<numX && k<numY-1;j++) { // Y軸方向描画 可視フラグ=false;   int p1=(int)((0.5+(Hidden_Ylen+Hidden_GroundX(j,k)) /Hidden_dlx));   int p2=(int)((0.5+(Hidden_Ylen+Hidden_GroundX(j,k+1))/Hidden_dlx));   for(int p=p1; p>=p2;p--){ // 補間     double PH=(double)(p-p1);     double fp=高さ[j,k]-(高さ[j,k+1]-高さ[j,k])*PH*Hidden_dlx                    / Hidden_dyCosB;     double px = PH*Hidden_dlx + Hidden_GroundX(j,k) + X0;     double py =-PH*Hidden_dlxTanB + Hidden_GroundY(j,k) + fp + Y0;     可視フラグ=Hidden_Draw(e, pen, px, py, p,可視フラグ, p!=p2);   } }    }

(初期座標値) private double Hidden_GroundX(int j, int k) // X0=Y0=0のときのX座標 { return (double)j * Hidden_dxCosA - (double) k * Hidden_dyCosB;} private double Hidden_GroundY(int j, int k) // X0=Y0=0のときのY座標 { return (double)j * Hidden_dxSinA + (double) k * Hidden_dySinB;} (変換マトリックスの設定) private void window(double X1, double Y1, double X2, double Y2) { float W=this.ClientSize.Width; float H=this.ClientSize.Height; float SX=W/((float)(X2-X1)); float SY=H/((float)(Y2-Y1)); matrix.Scale(SX,SY); matrix.Translate(-(float)X1,-(float)Y1); } 例題

例題 (初期化) private void Form1_Load(object sender, System.EventArgs e){  double DNX2= ((double)numX)/2; double DNY2= ((double)numY)/2; // 高さデータの設定 double X,Y,R,fxy;  for(int j=0; j<numX; j++){   X=0.3*((double)j-DNX2);   for(int k=0; k<numY; k++){ Y=0.3*((double)k-DNY2); R=Math.Sqrt(X*X+Y*Y); if(R==0.0) fxy=1.0; else fxy=Math.Sin(R)/R; 高さ[j,k]=40.0*fxy; }  Hidden_dlx = 0.1; Hidden_alpha = Math.PI/12; // 表示用パラメータの設定 Hidden_beta = Math.PI/8; Hidden_dx = 2; Hidden_dy = 1.4; Hidden_dxCosA=Hidden_dx*Math.Cos(Hidden_alpha); // 計算に用いる値の設定 Hidden_dyCosB=Hidden_dx*Math.Cos(Hidden_beta); Hidden_dxSinA=Hidden_dx*Math.Sin(Hidden_alpha); Hidden_dySinB=Hidden_dx*Math.Sin(Hidden_beta); Hidden_Xlen=(numX-1)*Hidden_dxCosA; Hidden_Ylen=(numY-1)*Hidden_dyCosB; Hidden_dlxTanA=Hidden_dlx*Math.Tan(Hidden_alpha); Hidden_dlxTanB=Hidden_dlx*Math.Tan(Hidden_beta); Hidden_NR=(int)((Hidden_Xlen+Hidden_Ylen)/Hidden_dlx)+1; // 表示座標マトリックスの設定 window(-10,200,200,60); // 表示座標マトリックスの設定

9.4 ランダムドット (1)立体視とは 3次元的な物体を2次元平面上に描いて, その2次元平面の図形から元の3次元物体を 9.4 ランダムドット (1)立体視とは 3次元的な物体を2次元平面上に描いて, その2次元平面の図形から元の3次元物体を 再構成してみること 2枚の絵を左右別々に見ることで 立体視ができる 左目には青が消えて見え, 右目には赤が消えて見える ので立体に見える

(2)ランダムドット・ステレオグラム 1枚の図で立体視が可能な絵 ■ 見えている物体面が紙面に対して平行であると仮定。 ■ ある基準となる面から物体面の距離をdとすると,   紙面上の間隔Tは以下の式で近似することができる。      T=C-R・d   ここで, C:物体が基準となる位置にある場合に対応する 紙面上の点の間隔, R:ずらすための定数(値が大きいとき,飛び出し方や 引っ込み方が大きくなる)

ランダムドット・ステレオグラムの見方 ランダムドット・ステレオグラムの上方に,以下の(a)のような2つの点があるので, 目をリラックスさせた状態で紙面に視線を向ける。 平行法の場合は,紙面より先のほうへ,交差法の場合は,紙面より手前のほうに焦点を合わせるように見ると,これがぼやけて見える。 ぼやけた円が2個,中央にはっきりした円が1個に見えるように 目の焦点をずらすと,ステレオグラムが立体に見えてくる。 (a)最初の状態 (ぼやけてみえる) 焦点をずらす (b)立体視できる状態

例 Sin(R)/R

例 半球

例 双曲放物面

プログラム フォーム定義 Name:comboBox1 Name:textBox1

例題 (以下のネームスペースを追加) using System.Drawing.Drawing2D;

例題 (データ宣言) public Matrix matrix =new Matrix(); public string 処理; (各種関数その1) private double SinR_dev_R(double X, double Y) { double R = Math.Sqrt(X*X+Y*Y); if(R<=0.0000001) return 1.0; return Math.Sin(R)/R; } private double 半球(double X, double Y) if(R>5) return -1.0; else { R=R/5; return Math.Sqrt(1-R*R)-1;} } private double 円筒(double X, double Y) { double R = Math.Abs(X); else { R=R/5; return Math.Sqrt(1-R*R)-1;} private double ピラミッド(double X, double Y) { double XX = Math.Abs(X); double R = Math.Abs(Y); if(XX>R) R=XX; if(R>5) return -1; else { R=R/2.5; return 1 - R; }

例題 (各種関数その2) private double fmod(double D, double M) { return D- (int)(D/M)*M; } private double 上下開き(double X, double Y) { double R = Math.Sqrt(X*X+Y*Y); if(R>=10) return 0; else if (fmod(R, 4.0)>2.0) return Y/10; else return -Y/10; } private double 双曲放物線(double X, double Y) { return (X*X-Y*Y)/50;} private double 二次錘面(double X, double Y) { return 1- Math.Sqrt(X*X+Y*Y)/5;} private double 十字(double X, double Y) { double XX=Math.Abs(X) ; double YY=Math.Abs(Y); if (XX>5 || YY>5) return -1; else if(XX<1 || YY<1) return 1; else return -1; private double Def_Exp(double X, double Y) { double XX=X/5 ; double YY=Y/5; double R=XX*XX+YY*YY; return (XX-YY) *Math.Exp(-R);

例題 (各種関数その3) private double mult_R(double X, double Y) { double XX=fmod(X,4)-2 ; double YY=fmod(Y,4)-2; double R=Math.Sqrt(XX*XX+YY*YY); if (R>1) return 0; else return Math.Sqrt(1-R*R); } private double func10(double X, double Y) { return (Math.Cos(X/1.5)+Math.Sin(Y/1.5))/2;} private double func11(double X, double Y) { double XX=X/3 ; double YY=Y/3; if( XX>0) XX=-XX; if(YY>0) YY=-YY; return Math.Exp(XX+YY)*2-1;

例題 (各種関数呼出処理) private double 関数呼出(double X, double Y) { int ID=comboBox1.SelectedIndex; switch(ID) case 0:return SinR_dev_R(X,Y); case 1:return 半球(X,Y); case 2:return 円筒(X,Y); case 3:return ピラミッド(X,Y); case 4:return 上下開き(X,Y); case 5:return 双曲放物線(X,Y); case 6:return 二次錘面(X,Y); case 7:return 十字(X,Y); case 8:return Def_Exp(X,Y); case 9:return mult_R(X,Y); case 10:return func10(X,Y); case 11:return func11(X,Y); } return 0;

例題 (ドットの表示) public void ドット表示(PaintEventArgs e) { double X1 = -12; double X2 = 12; double Y1 = 10; double Y2 = -10; double R0 = double.Parse(textBox1.Text); double UNIT = 6; double XY =1; int Loop=3000; double Period=(X2-X1)/6; double Z0=R0*Period; double R, X, Y, Z; Pen pen = new Pen(Color.Black,0.001F); Brush brush =new SolidBrush(Color.Black); e.Graphics.Clear(Color.White); float XX=(float)(Period/6.0);float YY=(float)(Y1*1.1); e.Graphics.DrawEllipse(pen, -XX, YY, 0.1F, 0.1F); e.Graphics.DrawEllipse(pen, XX, YY, 0.1F, 0.1F); Random RD = new Random(); for(int i=0;i<Loop;i++) { R=RD.NextDouble(); Y=R*(Y2-Y1)+Y1; Z=関数呼出(X1,Y); R=RD.NextDouble(); X=(Period + Math.Abs(Z0*Z))*R+X1; while(X<=X2) { double XP=(X - (X1+X2)*0.5)*UNIT; double YP=(Y - (Y1+Y2)*0.5)*UNIT; e.Graphics.FillRectangle(brush,(float)(X-0.025),(float)(Y-0.025),0.1F,0.1F); Z = 関数呼出(X + Period * 0.5, Y); X = X + Period - XY * Z0 * Z; } } } 例題

例題 ( OnPaint のオーバーライド) protected override void OnPaint(PaintEventArgs e ) { base.OnPaint(e ); e.Graphics.Clear(Color.White); e.Graphics.Transform = matrix; if (処理!="")ドット表示(e); Pen pen = new Pen(Color.Black,0.001F); e.Graphics.DrawLine(pen, -12F, 10F,12F, 10F); e.Graphics.DrawLine(pen, -12F,-10F,12F,-10F); e.Graphics.DrawLine(pen, -12F,10F,-12F,-10F); e.Graphics.DrawLine(pen, 12F,10F, 12F,-10F); }

例題 (関数の選択時の処理) private void comboBox1_SelectedIndexChanged(object sender, System.EventArgs e) { 処理="Exe"; this.Invalidate(); } (座標変換マトリックスの設定) private void window(float X1, float Y1, float X2, float Y2) {   float W= this.Width; float H=this.Height;   float SX=W/(X2-X1); float SY=H/(Y2-Y1);   matrix.Scale(SX,SY); matrix.Translate(-X1,-Y1); }

例題 (初期設定) private void Form1_Load(object sender, System.EventArgs e) { 処理=""; window(-12F*1.2F, 12F*1.4F, 10F*1.4F,-10F*1.4F); comboBox1.Items.Clear(); comboBox1.Items.Add("sin(R)/R"); comboBox1.Items.Add("半球");   comboBox1.Items.Add("円筒");   comboBox1.Items.Add("ピラミッド"); comboBox1.Items.Add("上下開き");   comboBox1.Items.Add("双曲放物面");   comboBox1.Items.Add("二次錘面"); comboBox1.Items.Add("十字");   comboBox1.Items.Add("(x-y)exp(-(x*x+y*y))"); comboBox1.Items.Add("繰返し"); comboBox1.Items.Add("cos(x)+sin(y)"); comboBox1.Items.Add("exp(-(abs(x)+abs(y))"); comboBox1.SelectedIndex=0; }

9.5 スプライン曲線とベジェ曲線 GraphicsクラスのDrawCurveメソッドや DrawBezierメソッドを使うとスプライン曲線や,ベジェ曲線を描くことができます。

9.5 スプライン曲線とベジェ曲線 スプライン曲線では,閉曲線も描くことができます。 9.5 スプライン曲線とベジェ曲線 スプライン曲線では,閉曲線も描くことができます。 さらにメソッドにテンションを引数で受け渡すことで,歪曲度を変更することができます。

9.5 スプライン曲線とベジェ曲線 以下の例は,テンションを連続的に変化させ,テンションの値によって線の色を変えたものです。

プログラム フォーム定義 Name:button1 Name:button2 Name:button3 Name:button3

確認用プログラム (追加するUsing) using System.Drawing.Drawing2D; (データ宣言) private string 曲線="ベジェ曲線"; private Point[] 構成点={ new Point(200,100),new Point(250,200),        new Point(350,150), new Point(400,250)}; private Pen pen1 = new Pen(Color.Black,2); private Pen pen2 = new Pen(Color.Blue ,1); private Pen pen3 = new Pen(Color.Green,1); private Pen pen4 = new Pen(Color.Red ,1); private Pen pen5 = new Pen(Color.Black,1); (ベジェ曲線を描く) private void ベジェ曲線(PaintEventArgs e ) { base.OnPaint(e); e.Graphics.DrawBezier(pen1,構成点[0],構成点[1],構成点[2],構成点[3]); e.Graphics.DrawLines(pen4,構成点); }

確認用プログラム (スプライン曲線) private void スプライン曲線(PaintEventArgs e ) { base.OnPaint(e); e.Graphics.DrawCurve(pen1,構成点); e.Graphics.DrawLines(pen4,構成点); } private void 閉曲線(PaintEventArgs e ) e.Graphics.DrawClosedCurve(pen1,構成点); private void 閉曲線テンション指定(PaintEventArgs e ) e.Graphics.DrawClosedCurve(pen2,構成点,0.0F,FillMode.Alternate); e.Graphics.DrawClosedCurve(pen3,構成点,0.5F,FillMode.Alternate); e.Graphics.DrawClosedCurve(pen4,構成点,1.0F,FillMode.Alternate); e.Graphics.DrawClosedCurve(pen5,構成点,2.0F,FillMode.Alternate);

確認用プログラム private void テンション指定(PaintEventArgs e ) { base.OnPaint(e); e.Graphics.DrawCurve(pen2, 構成点, 0.0F); e.Graphics.DrawCurve(pen3, 構成点, 0.5F); e.Graphics.DrawCurve(pen4, 構成点, 1.0F); e.Graphics.DrawCurve(pen5, 構成点, 2.0F); } private void 閉図形(PaintEventArgs e )  base.OnPaint(e);  for(int i=0;i<255;i++)  {  Pen pen =new Pen(Color.FromArgb(i,0,0));    e.Graphics.DrawClosedCurve(pen, 構成点,              (float)i * 0.5F/255F,FillMode.Alternate);  }  { Pen pen =new Pen(Color.FromArgb(255,i,0)); e.Graphics.DrawClosedCurve(pen, 構成点, 0.5F+(float)i *              0.5F/255F,FillMode.Alternate); for(int i=0;i<255;i++)  { Pen pen =new Pen(Color.FromArgb(255-i,255,0)); e.Graphics.DrawClosedCurve(pen, 構成点, 1F+(float)i *            0.5F/255F,FillMode.Alternate);   } 確認用プログラム

確認用プログラム for(int i=0;i<255;i++)   { Pen pen =new Pen(Color.FromArgb(0,255,i)); e.Graphics.DrawClosedCurve(pen, 構成点, 1.5F+(float)i *   0.5F/255F,FillMode.Alternate); } for(int i=0;i<255;i++) { Pen pen =new Pen(Color.FromArgb(0,255-i,255)); e.Graphics.DrawClosedCurve(pen, 構成点, 2.0F+(float)i * 0.5F/255F,FillMode.Alternate); { Pen pen =new Pen(Color.FromArgb(i,0,255)); e.Graphics.DrawClosedCurve(pen, 構成点, 2.5F+(float)i * { Pen pen =new Pen(Color.FromArgb(255,0,255-i)); e.Graphics.DrawClosedCurve(pen, 構成点, 3.0F+(float)i * { Pen pen =new Pen(Color.FromArgb(255-i,0,0)); e.Graphics.DrawClosedCurve(pen, 構成点, 3.5F+(float)i *

確認用プログラム private void 図形(PaintEventArgs e ) { base.OnPaint(e); for(int i=0;i<255;i++) { Pen pen =new Pen(Color.FromArgb(i,0,0)); e.Graphics.DrawCurve(pen, 構成点, (float)i * 0.5F/255F); } { Pen pen =new Pen(Color.FromArgb(255,i,0)); e.Graphics.DrawCurve(pen, 構成点, 0.5F+(float)i * 0.5F/255F); { Pen pen =new Pen(Color.FromArgb(255-i,255,0)); e.Graphics.DrawCurve(pen, 構成点, 1F+(float)i * 0.5F/255F); { Pen pen =new Pen(Color.FromArgb(0,255,i)); e.Graphics.DrawCurve(pen, 構成点, 1.5F+(float)i * 0.5F/255F); { Pen pen =new Pen(Color.FromArgb(0,255-i,255)); e.Graphics.DrawCurve(pen, 構成点, 2.0F+(float)i * 0.5F/255F);

確認用プログラム for(int i=0;i<255;i++) { Pen pen =new Pen(Color.FromArgb(i,0,255)); e.Graphics.DrawCurve(pen, 構成点, 2.5F+(float)i * 0.5F/255F); } { Pen pen =new Pen(Color.FromArgb(255,0,255-i)); e.Graphics.DrawCurve(pen, 構成点, 3.0F+(float)i * 0.5F/255F); { Pen pen =new Pen(Color.FromArgb(255-i,0,0)); e.Graphics.DrawCurve(pen, 構成点, 3.5F+(float)i * 0.5F/255F); protected override void OnPaint(PaintEventArgs e ) { switch (曲線) case "ベジェ曲線"   : ベジェ曲線(e)  ;break; case "スプライン曲線" : スプライン曲線(e);break; case "テンション指定" : テンション指定(e);break; case "図形" : 図形(e);break; case "閉曲線" : 閉曲線(e);break; case "閉曲線テンション": 閉曲線テンション指定(e);break; case "閉図形" : 閉図形(e);break;

確認用プログラム private void button1_Click(object sender, System.EventArgs e) { 曲線=“ベジェ曲線”; Invalidate();} private void button2_Click(object sender, System.EventArgs e) { 曲線="スプライン曲線"; Invalidate(); } private void button3_Click(object sender, System.EventArgs e) { 曲線="テンション指定"; Invalidate();} private void button4_Click(object sender, System.EventArgs e) { 曲線=“図形”; Invalidate();} private void button5_Click(object sender, System.EventArgs e) { 曲線="閉曲線"; Invalidate(); } private void button6_Click(object sender, System.EventArgs e) { 曲線=“閉曲線テンション”; Invalidate();} private void button7_Click(object sender, System.EventArgs e) { 曲線="閉図形"; Invalidate();}

(2) C曲線 以下のような曲線を各プログラムである。現在位置から相対座標に至るC曲線を描くプログラムである。

確認用プログラム① private Image image; private Point currentPoint=new Point(); private System.Windows.Forms.TextBox textBox1; private Point nextPoint=new Point(); private double maxLength=2; private int lineWidth=1; protected override void OnPaint(PaintEventArgs e ) { base.OnPaint(e); e.Graphics.DrawImage(image,0,0); } private void drawRelative(int X, int Y) nextPoint.X=currentPoint.X+X; nextPoint.Y=currentPoint.Y+Y; Graphics g =Graphics.FromImage(image); Pen pen = new Pen(Color.Black,lineWidth); g.DrawLine(pen,currentPoint,nextPoint); currentPoint=nextPoint;

確認用プログラム② private void moveAbsolute(int X, int Y) { currentPoint.X=X; currentPoint.Y=Y;} private void C_Curve(double X, double Y) { if(X*X+Y*Y<=maxLength*maxLength) drawRelative((int)X, (int)Y); else{ C_Curve((X+Y)/2,(Y-X)/2); C_Curve((X-Y)/2,(Y+X)/2);} } private void button1_Click(object sender, System.EventArgs e) { Graphics g =Graphics.FromImage(image); g.Clear(BackColor); maxLength=double.Parse(textBox1.Text); int X=int.Parse(textBox2.Text); int Y=int.Parse(textBox3.Text); lineWidth=int.Parse(textBox4.Text); moveAbsolute(X,Y); C_Curve(500,0); this.Invalidate();

確認用プログラム③ private void moveAbsolute(int X, int Y) { currentPoint.X=X; currentPoint.Y=Y;} private void C_Curve(double X, double Y) { if(X*X+Y*Y<=maxLength*maxLength) drawRelative((int)X, (int)Y); else{ C_Curve((X+Y)/2,(Y-X)/2); C_Curve((X-Y)/2,(Y+X)/2);} } private void button1_Click(object sender, System.EventArgs e) { Graphics g =Graphics.FromImage(image); g.Clear(BackColor); maxLength=double.Parse(textBox1.Text); int X=int.Parse(textBox2.Text); int Y=int.Parse(textBox3.Text); lineWidth=int.Parse(textBox4.Text); moveAbsolute(X,Y); C_Curve(500,0); this.Invalidate();

確認用プログラム④ private void button2_Click(object sender, System.EventArgs e) { Graphics g =Graphics.FromImage(image); g.Clear(BackColor); this.Invalidate(); }

(3) コッホ曲線 長さ1の線分を三等分し,中央の1/3を削除し,そこに1/3の長さの正三角形を挿入する操作を何回も繰り返して得られる曲線をコッホ曲線と呼びます。

描画例 [例]

プログラム例① (追加するusing) using System.Drawing.Drawing2D; (データ宣言) public struct 位置データ {  public double X; public double Y; } public 位置データ 現在位置 = new 位置データ();  public double 角度; public void t_position(double X, double Y) {  現在位置.X=X; 現在位置.Y=Y;} public void t_Degree(double Theta) {  角度=Theta; } public void t_turn(double Theta) {  角度 += Theta; }

プログラム例② public void t_forward(PaintEventArgs e, double length) {   double TH = 角度 * 3.1415926/180; double X=現在位置.X+length * Math.Cos(TH); double Y=現在位置.Y+length * Math.Sin(TH);   Pen pen =new Pen(Color.Black);   e.Graphics.DrawLine(pen, (int)現在位置.X, 300-(int)現在位置.Y, (int)X,300-(int)Y); 現在位置.X=X; 現在位置.Y=Y; } (以下のように再帰的に表現できる) public void koch( PaintEventArgs e,int n,double length) { if(n<=0) t_forward(e,length); else { int nn=n-1; double len=length/3; koch(e, nn,len); t_turn(60); koch(e, nn,len); t_turn(-120); koch(e, nn,len);

(4) 立ち枯れ木立 コッホ曲線では,長さを1/3にして,60度向きを変えて,3回再帰的呼出しを行っているが,長さの比率,向きを色々と変えて再帰呼び出しを行うと色々な図形が得られる。 ここでは,以下のように進行方向,比率を変えた例を示す。    向き  比率     0 0.28 88 0.28  -176  0.28 88 0.7   (向きの合計が 0+88-176+88=0 となることに注意)

実行例 [例] public double[,] element   =new double[,]{{ 0.0, 0.28},{88.0, 0.28},      {-176.0, 0.28},{88.0, 0.70}}; public void frctl( PaintEventArgs e, double length) {  int j;   if (length <=2.0) t_forward(e,length);   else{    for(j=0; j<4; j++){       t_turn(element[j,0]);       frctl(e, length*element[j,1]);   }} }

(5) シェルピンスキーのギャスケット シェルピンスキーのギャスケットとは, (5) シェルピンスキーのギャスケット シェルピンスキーのギャスケットとは, 三角形の中に1辺の長さ1/2の三角形を順次描くことによって得られます。これもコッホ曲線と同様,自己相似を内部に持つ形になります。

プログラムとギャスケットの例 public void 三角形(PaintEventArgs e,double X, double Y, double L) {   Pen pen =new Pen(Color.Black);   int IX1=(int)X; int IX2=(int)(X + L ); int IX3=(int)(X + L / 2);   int IY1=300-(int)Y; int IY2=300-(int)(Y- L*Math.Sin(60*3.1415926/180));   e.Graphics.DrawLine(pen, IX1,IY1, IX2,IY1);   e.Graphics.DrawLine(pen, IX1,IY1, IX3,IY2);   e.Graphics.DrawLine(pen, IX2,IY1, IX3,IY2); } public void sier( PaintEventArgs e, int n, double X, double Y, double L)   if(n==0) return;   double H = L * Math.Sin(60*3.1415926/180);   三角形(e, X + L / 4, Y + H / 2, L/2);   sier(e, n-1, X , Y , L / 2);   sier(e, n-1, X + L/2, Y , L / 2);   sier(e, n-1, X + L/4, Y + H / 2, L / 2); public void sier( PaintEventArgs e) 三角形(e,290.0,10.0,-280.0);   sier(e, 6, 10.0, 10.0, 280.0);

プログラム例① (追加するusing) using System.Drawing.Drawing2D; (データ宣言) public struct 位置データ {  public double X; public double Y; } public 位置データ 現在位置 = new 位置データ();  public double 角度; public Matrix matrix=new Matrix(); public string 処理; public void t_position(double X, double Y) {  現在位置.X=X; 現在位置.Y=Y;} public void t_Degree(double Theta) {  角度=Theta; } public void t_turn(double Theta) {  角度 += Theta; }

プログラム例② public void t_forward(PaintEventArgs e, double length) {   double TH = 角度 * 3.1415926/180; double X=現在位置.X+length * Math.Cos(TH); double Y=現在位置.Y+length * Math.Sin(TH);   Pen pen =new Pen(Color.Black);   e.Graphics.DrawLine(pen, (int)現在位置.X, 300-(int)現在位置.Y, (int)X,300-(int)Y); 現在位置.X=X; 現在位置.Y=Y; } public void koch( PaintEventArgs e,int n,double length) { if(n<=0) t_forward(e,length); else { int nn=n-1; double len=length/3; koch(e, nn,len); t_turn(60); koch(e, nn,len); t_turn(-120); koch(e, nn,len);

プログラム例③ public double[,] element =new double[,]{{ 0.0, 0.28},{88.0, 0.28}, {-176.0, 0.28},{88.0, 0.70}}; public void frctl( PaintEventArgs e, double length) {   int j;   if (length <=2.0) t_forward(e,length);   else   {      for(j=0; j<4; j++){ t_turn(element[j,0]);frctl(e, length*element[j,1]);}   } }

プログラム例④ public void 三角形(PaintEventArgs e,double X, double Y, double L) {   Pen pen =new Pen(Color.Black);   int IX1=(int)X; int IX2=(int)(X + L ); int IX3=(int)(X + L / 2);   int IY1=300-(int)Y; int IY2=300-(int)(Y- L*Math.Sin(60*3.1415926/180));   e.Graphics.DrawLine(pen, IX1,IY1, IX2,IY1);   e.Graphics.DrawLine(pen, IX1,IY1, IX3,IY2);   e.Graphics.DrawLine(pen, IX2,IY1, IX3,IY2); } public void sier( PaintEventArgs e, int n, double X, double Y, double L)   if(n==0) return;   double H = L * Math.Sin(60*3.1415926/180);   三角形(e, X + L / 4, Y + H / 2, L/2);   sier(e, n-1, X , Y , L / 2);   sier(e, n-1, X + L/2, Y , L / 2);   sier(e, n-1, X + L/4, Y + H / 2, L / 2); public void sier( PaintEventArgs e) 三角形(e,290.0,10.0,-280.0);   sier(e, 6, 10.0, 10.0, 280.0);

プログラム例⑤ protected override void OnPaint( PaintEventArgs e) {   base.OnPaint(e);   e.Graphics.Clear(Color.WhiteSmoke);   Pen pen =new Pen(Color.Red);   Rectangle rect = new Rectangle(0,0,300,300);   e.Graphics.Transform=matrix; e.Graphics.DrawRectangle(pen, rect);   t_position(0.0,40.0); t_Degree(0.0); switch (処理)   { case "" : break; case "koch" : koch(e, 6, 300.0); break; case "frctl": frctl(e, 300.0) ; break; case "sier" : sier(e) ; break;   } } public void window(float X1,float Y1,float X2,float Y2, float R)   float W=ClientSize.Width; float H=ClientSize.Height;   float SX=W/(X2-X1); float SY=H/(Y2-Y1);   matrix.Scale(SX,SY);   matrix.Rotate(R);   matrix.Translate(-X1,-Y1);

プログラム例⑥ private void Form1_Load(object sender, System.EventArgs e) {  処理=“”; window(-10F,-10F,310F,310F,0); this.Invalidate(); } private void button1_Click(object sender, System.EventArgs e) {  処理="koch"; this.Invalidate();} private void button2_Click(object sender, System.EventArgs e) {  処理="frctl"; this.Invalidate();} private void button3_Click(object sender, System.EventArgs e) { 処理="sier"; this.Invalidate(); }

(6)反復関数系 自己相似図形があれば,その図形を構成する 反復関数系を見つけ,各関数に確率を割り振って, 乱数で得られた座標に点を打つことで, 色々な図形を生成可能 もちろんシェルピンスキーのギャスケットも, この方法で表現できます。 ここでは,別の例を示す。

プログラム例① (追加するusing) using System.Drawing.Drawing2D; (データ宣言) public double [,,] Fsys1=new double[,,] {{{ 0.856, 0.0414}, {-0.0205, 0.858}}, {{ 0.244,-0.3850}, { 0.1760, 0.224}}, {{-0.144, 0.3900}, { 0.1810, 0.259}}, {{ 0.000, 0.0000}, { 0.3550, 0.216}}}; public double [,] Fsys2 = new double [,]  {{0.07,0.147},{0.393,0.102},{0.527,-0.014},{0.486,0.05}}; public bool[,] 点=new bool[1001,1001]; public Matrix matrix=new Matrix(); private Image image;

プログラム例① public void 描画() { Brush brush = new SolidBrush(Color.DarkGreen); Graphics g=Graphics.FromImage(image); g.Clear(Color.White); for(int i=0; i<1000; i++) for(int j=0; j<1000; j++) if(点[i,j]) g.FillRectangle(brush,i,(1000-j),1,1); } protected override void OnPaint(PaintEventArgs e) base.OnPaint(e); e.Graphics.Transform=matrix; e.Graphics.DrawImage(image,100,100);

プログラム例① private void window(float X1,float Y1,float X2, float Y2, float R) { float W =ClientSize.Width; float H=ClientSize.Height; float SX=W/(X2-1); float SY = H / (Y2 -Y1); float MX= -SX *X1; float MY = - SY * Y1; matrix.Scale(SX,SY); matrix.Rotate(R); matrix.Translate(MX,MY); } private void 初期化() for(int i=0; i<1001; i++) for(int j=0; j<1001; j++) 点[i,j]=false; 描画(); private void Form1_Load(object sender, System.EventArgs e) { 初期化(); window(0,0,1000,1000,0);}

プログラム例① private void button1_Click(object sender, System.EventArgs e) { int ID;double X1,Y1; Random RD = new Random(); double X0=1.0; double Y0=1.0; for(int i=0; i<20000; i++) { double R=RD.NextDouble(); if (R < 0.73) ID = 0; else if (R < 0.86) ID = 1; else if (R < 0.99) ID = 2; else ID = 3; X1=Fsys1[ID,0,0]*X0+Fsys1[ID,0,1]*Y0+Fsys2[ID,0]; Y1=Fsys1[ID,1,0]*X0+Fsys1[ID,1,1]*Y0+Fsys2[ID,1]; if(X1<1.0 && Y1<1.0 && X1>=0 && Y1>=0) 点[(int) (X1*1000.0),(int) (Y1*1000.0)]=true; X0=X1;Y0=Y1; } 描画(); this.Invalidate();