![]() |
|||||||||||||||||||||||||||||||||||
(1)考え方 等高線は,地形図等を表示する有力な方法です。 ここでは,等高線を描く簡便な方法について示します。 通常の数値地図等はメッシュデータで表現されます。 ここでは, 横Δx,縦Δyの長方形の各辺にhとなる点を見つけて, 線を引く方法を示します。 ![]() ただし,以下のように交点が3つあるような等高線の場合, 点線のように描くことになります。 ![]()
(2)フォーム定義と実行例 次のようなフォームを定義しておきます。 ![]() 提示するプログラムを実行すると,以下のような画面になります。 ![]() 右上の「数値地図読込み」ボタンをクリックして, 国土地理院発行の50mメッシュ数値地図(いわゆるMEMファイル)を 指定すると,例えば,次のように等高線が描かれます。 背景には,色地図を表示します。 ![]()
(3)プログラムの説明 2次元の絵を描くことになります。 また,数値地図を読み込みます。 したがって,以下のusingを追加しておきます。 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; ここで,matrixは,座標変換用のデータです。 補間のための関数は,以下のように記述することができます。 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 j=0; j<numX-1; j++) 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; case 7 : color=Color.FromArgb( 31,255, 0); break; case 8 : color=Color.FromArgb( 63,255, 0); break; case 9 : color=Color.FromArgb(127,255, 0); break; case 10 : color=Color.FromArgb(159,255, 0); break; case 11 : color=Color.FromArgb(191,255, 0); break; case 12 : color=Color.FromArgb(223,255, 0); break; case 13 : color=Color.FromArgb(255,255, 0); break; case 14 : color=Color.FromArgb(255,223, 0); break; case 15 : color=Color.FromArgb(255,191, 0); break; case 16 : color=Color.FromArgb(255,159, 0); break; case 17 : color=Color.FromArgb(255,127, 0); break; case 18 : color=Color.FromArgb(255, 63, 0); break; case 19 : color=Color.FromArgb(255, 31, 0); break; default: color=Color.FromArgb(255, 0, 0); break; } Brush brush = new SolidBrush(color); g.FillRectangle(brush,x1,y1,w,h); } } 上記の色地図,等高線を呼び出して,imageに描画します。 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() { 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; } 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); } ウインドウの描画が必要になると, ControlクラスのOnPaintメソッドが呼び出されますので, これをオーバライドします。 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); } ボタン2が押されたら,描画しなおします。 private void button2_Click(object sender, System.EventArgs e) { 描画(); this.Invalidate(); }
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() 上のタイトルをクリックします |
|||||||||||||||||||||||||||||||||||