2012年12月25日火曜日

10mメッシュ標高データで地図を作成

「5mメッシュ標高データで地図を作成」では、1メッシュごとにRectangle オブジェクトを生成していましたが、ここではビットマップ画像を作成します。
1メッシュが1ピクセルになります。
標高は512mまでを256段階のグレースケールで表現し、512m以上は一律黒にします。
10mメッシュ標高データのXMLをみると、1125列×750行のメッシュになっているので、1125×750ピクセルの画像が生成されることになります。

サンプルは、沖縄県の辺野古あたりです。
XMLファイルは、「FG-GML-3928-60-dem10b-20090201.xml」です。





MainWindow.xaml

<Window x:Class="GisTest2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Height="250" Width="325">
    <Window.CommandBindings>
        <CommandBinding Command="Open" Executed="OpenCommandHandler"/>
    </Window.CommandBindings>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Menu Grid.Row="0">
            <MenuItem Command="Open" />
        </Menu>
        <ScrollViewer Grid.Row="1" HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible">
            <Canvas Name="canvas1" Margin="2"/>
        </ScrollViewer>
    </Grid>
</Window>

MainWindow.xaml.cs

using Microsoft.Win32;
using System;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Xml;

namespace GisTest2
{
    public partial class MainWindow Window
    {
        private static Color[] myColors = new Color[256];

        static MainWindow()
        {
            byte i = 0;
            while (true)
            {
                myColors[i] = Color.FromRgb(i, i, i);
                if (i == 255)
                {
                    break;
                }
                i++;
            }
        }

        public MainWindow()
        {
            InitializeComponent();
        }

        private void OpenCommandHandler(object sender, ExecutedRoutedEventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            if (ofd.ShowDialog() == true)
            {
                XmlDocument xdoc = new XmlDocument();
                xdoc.Load(ofd.FileName);

                XmlNamespaceManager xnm = new XmlNamespaceManager(xdoc.NameTable);
                xnm.AddNamespace("gml""http://www.opengis.net/gml/3.2");

                XmlElement dataXe = (XmlElement)xdoc.SelectSingleNode("//gml:tupleList", xnm);
                XmlElement lowXe = (XmlElement)xdoc.SelectSingleNode("//gml:low", xnm);
                XmlElement highXe = (XmlElement)xdoc.SelectSingleNode("//gml:high", xnm);

                string[] lowPoint = lowXe.InnerText.Split(' ');
                string[] highPoint = highXe.InnerText.Split(' ');
                int xSize = int.Parse(highPoint[0]) - int.Parse(lowPoint[0]) + 1;
                int ySize = int.Parse(highPoint[1]) - int.Parse(lowPoint[1]) + 1;
                string data = dataXe.InnerText;

                this.canvas1.Width = xSize;
                this.canvas1.Height = ySize;

                DrawMap(xSize, ySize, data);
            }
        }

        private void DrawMap(int xSize, int ySize, string data)
        {
            float[,] heights = new float[xSize, ySize];

            Regex regex = new Regex("[^,\\r\\n]+,[^,\\r\\n]+");
            MatchCollection mc = regex.Matches(data);
            int index = 0;
            foreach (Match in mc)
            {
                string[] unit = m.Value.Split(',');
                heights[index % xSize, index / xSize] = float.Parse(unit[1]);
                index++;
            }

            this.canvas1.Children.Clear();

            byte[] pixcels = new byte[xSize * ySize * 4];
            for (int y = 0; y < ySize; y++)
            {
                for (int x = 0; x < xSize; x++)
                {
                    double height = Math.Floor(heights[x, y] / 2.0);
                    Color fillColor;
                    if (height <= 0)
                    {
                        fillColor = Colors.LightSeaGreen;
                    }
                    else if (height > 255)
                    {
                        fillColor = Colors.Black;
                    }
                    else
                    {
                        fillColor = myColors[(byte)(255 - height)];
                    }
                    int pixcelIndex = xSize * 4 * y + x * 4;
                    pixcels[pixcelIndex] = fillColor.B;
                    pixcels[pixcelIndex + 1] = fillColor.G;
                    pixcels[pixcelIndex + 2] = fillColor.R;
                    pixcels[pixcelIndex + 3] = 0;
                }
            }
            Int32Rect rect = new Int32Rect(0, 0, xSize, ySize);

            WriteableBitmap bitmapImage = new WriteableBitmap(xSize, ySize, 96, 96, PixelFormats.Bgr32, null);
            bitmapImage.WritePixels(rect, pixcels, xSize * 4, 0);

            Rectangle rectangle = new Rectangle();
            rectangle.Width = xSize;
            rectangle.Height = ySize;
            rectangle.Fill = new ImageBrush(bitmapImage);
            this.canvas1.Children.Add(rectangle);
        }
    }
}

0 件のコメント:

コメントを投稿