Beispiel #1
0
 /// <summary>
 /// 2つの座標をセットするコンストラクタ
 /// <para>指定した座標の大小関係からマップの座標を自動的に決定します。</para>
 /// </summary>
 /// <param name="x1">座標1</param>
 /// <param name="x2">座標2</param>
 public MapField(Pos x1, Pos x2)
 {
     this.param = new FieldParameter();
     this.param.leftX = this.param.rightX = x1.x;        // 座標をセットしておく
     this.param.upperY = this.param.lowerY = x1.y;
     SetPos(x2, ref this.param);                         // もう一点は判定ののちに追加する
     return;
 }
Beispiel #2
0
 /// <summary>
 /// DEMファイルを管理するための構造体のコンストラクタ
 /// </summary>
 /// <param name="mapName">地図名<para>例:熊本</para></param>
 /// <param name="id">ID番号</param>
 /// <param name="size">マップサイズ</param>
 /// <param name="field">コーナーの座標</param>
 /// <param name="model">DEMモデル名</param>
 public Info(string mapName, int id, Pos size, RectangleField field, Model model = Model.Unknown)
     : this()
 {
     this.MapName = mapName;
     this.ID = id;
     this.Size = size;
     this.Field = field;
     this.MapModel = model;
 }
Beispiel #3
0
 /* メソッド ************************************/
 /// <summary>
 /// 引数で渡した座標との距離を返す
 /// </summary>
 /// <param name="origin">始点</param>
 /// <returns>距離</returns>
 public double GetDistance(Pos origin)
 {
     return Math.Sqrt((this.x - origin.x) * (this.x - origin.x) + (this.y - origin.y) * (this.y - origin.y));
 }
Beispiel #4
0
 /// <summary>
 /// 渡されたマップを用いて初期化する
 /// <para>呼び出すのは一回きりにしてください</para>
 /// </summary>
 /// <param name="info">マップの情報</param>
 private void Init(Info info)
 {
     if (this.dict.Count == 0)
     {
         this.mapSize = info.Field.Size;
         this.amountOfMeshInMap = info.Size;
         this.meshSize = new Blh(this.mapSize.B / (double)this.amountOfMeshInMap.y, this.mapSize.L / (double)this.amountOfMeshInMap.x);
         this.offset = this.GetMapOffset(info);
     }
     return;
 }
Beispiel #5
0
 /// <summary>
 /// 指定されたマップアドレスから、そのアドレスのマップの領域情報を返す
 /// </summary>
 /// <param name="address">マップアドレス</param>
 /// <returns>領域</returns>
 private RectangleField GetFieldFromAddress(Pos address)
 {
     double lowerLeftLat = (double)address.y * this.mapSize.B + this.offset.B;
     double lowerLeftLon = (double)address.x * this.mapSize.L + this.offset.L;
     return new RectangleField(new Blh(lowerLeftLat, lowerLeftLon), new Blh(lowerLeftLat + this.mapSize.B, lowerLeftLon + this.mapSize.L));
 }
Beispiel #6
0
        /// <summary>
        /// 指定領域のDEMを可能ならばロードする
        /// </summary>
        /// <param name="field">指定領域</param>
        public void Load(RectangleField field)
        {
            //System.Diagnostics.Stopwatch sw2 = System.Diagnostics.Stopwatch.StartNew();

            Pos upperRightPos = this.GetMapAddress(field.UpperRight);
            Pos lowerLeftPos = this.GetMapAddress(field.LowerLeft);
            /*
            for (int x = lowerLeftPos.x; x <= upperRightPos.x; x++)
            {
                for (int y = lowerLeftPos.y; y <= upperRightPos.y; y++)
                {
                    Pos address = new Pos(x, y);
                    if (this.dict.ContainsKey(address) == true)
                    {
                        if (this.dict[address].IsLoaded == false && this.dict[address].Error == false)
                        {
                            this.dict[address].Load();                          // まだデータを読み込んでいなければ読み込みを実施します。
                        }
                    }
                }
            }*/

            // 並列処理で書くならこうかく。あとで速度のテストをする予定。

            Parallel.For(lowerLeftPos.x, upperRightPos.x + 1, x =>              // 可能なら並列処理でデータを格納する
            {
                Parallel.For(lowerLeftPos.y, upperRightPos.y + 1, y =>
                {
                    Pos address = new Pos(x, y);
                    if (this.dict.ContainsKey(address) == true)
                    {
                        if (this.dict[address].IsLoaded == false && this.dict[address].Error == false)
                        {
                            this.dict[address].Load();                          // まだデータを読み込んでいなければ読み込みを実施します。
                        }
                    }
                });
            });

            //sw2.Stop();                                                         // ストップウォッチを止める
            //Console.WriteLine("マップの読み込みにかけた処理時間: " + sw2.Elapsed); // 結果を表示する
            return;
        }
Beispiel #7
0
        /// <summary>
        /// 指定領域のカバー率を返す
        /// <para>指定された領域全てのDEMマップを保持している場合は1.0を返します。</para>
        /// </summary>
        /// <param name="field">指定領域</param>
        /// <returns>カバー率</returns>
        public double GetCoverRate(RectangleField field)
        {
            Pos upperRightPos = this.GetMapAddress(field.UpperRight);
            Pos lowerLeftPos = this.GetMapAddress(field.LowerLeft);

            double coverCount = 0;
            for (int x = lowerLeftPos.x; x <= upperRightPos.x; x++)
            {
                for (int y = lowerLeftPos.y; y <= upperRightPos.y; y++)
                {
                    Pos address = new Pos(x, y);
                    if (this.dict.ContainsKey(address) == true) coverCount += 1.0;
                }
            }
            return coverCount / (double)((upperRightPos.x - lowerLeftPos.x + 1) * (upperRightPos.y - lowerLeftPos.y + 1));
        }
Beispiel #8
0
        /// <summary>
        /// 指定領域でマップを作成します
        /// <para>指定領域を含むマップを結合することでマップを生成します。</para>
        /// <para>該当データが存在しない領域はfloat.NaNで埋めます。</para>
        /// </summary>
        /// <param name="field">指定領域</param>
        /// <returns>Mapオブジェクト</returns>
        public MapDem CreateMap(RectangleField field)
        {
            this.Load(field);

            //System.Diagnostics.Stopwatch sw2 = System.Diagnostics.Stopwatch.StartNew();

            Pos upperRightPos = this.GetMapAddress(field.UpperRight);
            Pos lowerLeftPos = this.GetMapAddress(field.LowerLeft);
            Pos fieldMaxIndex = upperRightPos - lowerLeftPos;                                   // マップ単位でカウントした領域サイズ - 1
            Pos mapSize = new Pos((fieldMaxIndex.x + 1) * this.amountOfMeshInMap.x,
                (fieldMaxIndex.y + 1) * this.amountOfMeshInMap.y);                              // 生成するマップのサイズを決定する
            MapDem ansMap = new MapDem(new RectangleField(this.GetFieldFromAddress(lowerLeftPos).LowerLeft,
                this.GetFieldFromAddress(upperRightPos).UpperRight), mapSize);                  // マップを生成
            ansMap.Initialize(float.NaN);                                                       // 非値で初期化することで値が存在しない領域をはっきりさせる

            //int count = 0;
            Parallel.For(lowerLeftPos.x, upperRightPos.x + 1, x =>                              // 可能なら並列処理でデータを格納する
            //for (int x = lowerLeftPos.x; x < upperRightPos.x + 1; x++)
            {
                Parallel.For(lowerLeftPos.y, upperRightPos.y + 1, y =>
                //for (int y = lowerLeftPos.y; y < upperRightPos.y + 1; y++)
                {
                    Pos address = new Pos(x, y);
                    if (this.dict.ContainsKey(address) == true)
                    {
                        if (this.dict[address].Error == false && this.dict[address].IsLoaded)
                        {
                            //count++;
                            Pos relativeAddress = new Pos(x - lowerLeftPos.x, y - lowerLeftPos.y);
                            /*
                            for (int localX = 0; localX < this.amountOfMeshInMap.x; localX++)
                            {
                                for (int localY = 0; localY < this.amountOfMeshInMap.y; localY++)
                                {
                                    int globalX = relativeAddress.x * this.amountOfMeshInMap.x + localX;
                                    int globalY = (fieldMaxIndex.y - relativeAddress.y) * this.amountOfMeshInMap.y + localY;
                                    ansMap[globalX, globalY] = this.dict[address].DemMap[localX, localY];
                                }
                            }
                            */
                            Parallel.For(0, this.amountOfMeshInMap.x, localX =>
                            {
                                Parallel.For(0, this.amountOfMeshInMap.y, localY =>
                                {
                                    int globalX = relativeAddress.x * this.amountOfMeshInMap.x + localX;
                                    int globalY = (fieldMaxIndex.y - relativeAddress.y) * this.amountOfMeshInMap.y + localY;
                                    ansMap[globalX, globalY] = this.dict[address].map[localX, localY];
                                });
                            });
                        }
                    }
                });
            });

            //sw2.Stop();                                                             // ストップウォッチを止める
            //Console.WriteLine("マップの統合にかけた処理時間: " + sw2.Elapsed);    // 結果を表示する
            //Console.WriteLine("マップの結合数: " + count.ToString());
            return ansMap;
        }
        /// <summary>
        /// マップのサイズ情報の支援を受けた上で、指定されたテキストよりDEM値を読み出して返す
        /// </summary>
        /// <param name="fileName">解析対象ファイルのパス</param>
        /// <param name="size">マップサイズ</param>
        /// <returns>読み出されたDEM値(float型の2次元配列)<para>読み出しに失敗するとnullを返します。</para></returns>
        public float[,] GetValues(string fileName, Pos size)
        {
            if (System.IO.File.Exists(fileName) == false) return null;
            /*
            string txt = "";
            using (System.IO.StreamReader sr = new System.IO.StreamReader(fileName, System.Text.Encoding.GetEncoding("shift_jis")))
            {
                txt = sr.ReadToEnd();
            }
            MatchCollection mc = this.data.Matches(txt);                        // 文字コードが合わなければヒットしない
            // デバッグコード
            //foreach (Match m in mc)
            //{
            //    Console.WriteLine(m.Groups["kind"].Value + m.Groups["value"].Value);
            //}

            if (mc.Count != size.x * size.y) return null;
            float[,] height = new float[size.x, size.y];                        // 配列サイズを調整
            Parallel.For(0, size.x * size.y, i =>
            //for(int i = 0; i < size.x * size.y; i++)
            {
                int k = i % size.x;
                int j = i / size.x;
                height[k, j] = float.Parse(mc[i].Groups["value"].Value);        // データを取得&浮動小数点型の数値変換
                if (height[k, j] == -9999.0) height[k, j] = float.NaN;
            });
            */
            // 上の処理方法と比べると、下の処理は20倍くらい早い。正規表現によるマッチングがかなりボトルネックとなっていた。。。
            float[,] height = new float[size.x, size.y];                        // 配列サイズを調整
            int i = 0;
            using (System.IO.StreamReader sr = new System.IO.StreamReader(fileName, System.Text.Encoding.GetEncoding("shift_jis")))
            {
                while (sr.EndOfStream == false)
                {
                    string line = sr.ReadLine();
                    string[] field = line.Split(',');
                    if (field.Length == 2)
                    {
                        float value;
                        if (i >= size.x * size.y) return null;                  // 大きすぎる
                        if (float.TryParse(field[1], out value))                // 浮動小数点型の数値変換
                        {
                            int k = i % size.x;
                            int j = i / size.x;
                            if (value == -9999.0) value = float.NaN;
                            height[k, j] = value;                               // データを設定
                            i++;
                        }

                    }
                }
            }
            if (i != size.x * size.y) return null;                              // サイズミスマッチ
            return height;
        }
        // もう少しマッチの条件をスマートに書きたいんだけどなぁ。
        /* メソッド *****************************************************/
        /// <summary>
        /// 引数で渡されたテキストを走査してDEM情報クラスオブジェクトを返す
        /// <para>フォーマット不一致の場合はnew Info()を返します。</para>
        /// </summary>
        /// <param name="fileName">解析対象のファイルへのパス</param>
        /// <returns>正常に読み出せた場合はDEM情報クラスオブジェクトを返す</returns>
        public Info GetHeader(string fileName)
        {
            if (System.IO.File.Exists(fileName) == false) return new Info();
            string txt = "";
            using (System.IO.StreamReader sr = new System.IO.StreamReader(fileName, System.Text.Encoding.GetEncoding("shift_jis")))
            {
                StringBuilder sb = new StringBuilder(2000);             // 予め大きなメモリ容量を確保しておく
                for (int i = 0; i < 50; i++)                            // ヘッダー部分だけに限ると、処理時間が半分になる。正規表現のマッチングが時間がかかっているみたいだ。
                    sb.Append(sr.ReadLine());
                txt = sb.ToString();
                //txt = sr.ReadToEnd();
            }

            string mapName = "";                                        // 地点名は2012/5/22時点では未対応
            int ID = 0;                                                 // ID番号
            Pos size = new Pos();                                       // マップサイズ(縦方向と横方向のメッシュ数)
            Blh upperRight = new Blh(), lowerLeft = new Blh();

            Match m;
            m = this.meshID.Match(txt);
            if (m.Success) ID = int.Parse(m.Groups["ID"].Value);
            m = this.lowerCorner.Match(txt);
            if (m.Success) upperRight = new Blh(double.Parse(m.Groups["lat"].Value), double.Parse(m.Groups["lon"].Value));
            m = this.upperCorner.Match(txt);
            if (m.Success) lowerLeft = new Blh(double.Parse(m.Groups["lat"].Value), double.Parse(m.Groups["lon"].Value));
            m = this.size.Match(txt);
            if (m.Success) size = new Pos(int.Parse(m.Groups["width"].Value) + 1, int.Parse(m.Groups["hight"].Value) + 1);

            RectangleField corner = new RectangleField(upperRight, lowerLeft);
            return new Info(mapName, ID, size, corner, Model.JPGIS2x_GML);
        }
Beispiel #11
0
 /// <summary>
 /// 1つの座標をセットするコンストラクタ
 /// <para>自動的にPos(0, 0)をもう一点として張ります。</para>
 /// <para>マップのサイズを表すのに便利かと思います。</para>
 /// </summary>
 public MapField(Pos pos)
 {
     this.param = new FieldParameter();
     SetPos(pos, ref this.param);
     return;
 }
Beispiel #12
0
 /// <summary>
 /// 座標をセットする
 /// <para>引数で渡された座標を検査して、領域を増やすことができれば拡張が実行されます。</para>
 /// </summary>
 /// <param name="pos">追加・検査する座標</param>
 /// <param name="param">領域のパラメータ(参照渡し)</param>
 private static void SetPos(Pos pos, ref FieldParameter param)
 {
     if (param.upperY > pos.y) param.upperY = pos.y;
     if (param.lowerY < pos.y) param.lowerY = pos.y;
     if (param.leftX > pos.x) param.leftX = pos.x;
     if (param.rightX < pos.y) param.rightX = pos.x;
     return;
 }
Beispiel #13
0
 /// <summary>
 /// 領域を平行移動させる
 /// <para>破壊的メソッド(オブジェクト自身の値を変更します)</para>
 /// </summary>
 /// <param name="shiftAmount">シフト量<para>x成分は正値で右へ,y成分は正値で下方へ領域が平行移動します。</para></param>
 public void Translate(Pos shiftAmount)
 {
     this.param.leftX += shiftAmount.x;
     this.param.lowerY += shiftAmount.y;
     this.param.rightX += shiftAmount.x;
     this.param.upperY += shiftAmount.y;
     return;
 }
Beispiel #14
0
 /// <summary>
 /// 座標をセットして領域を再設定・拡張する
 /// <para>領域の中の座標を設定しても無視します。</para>
 /// </summary>
 /// <param name="pos">指定座標</param>
 public void Set(Pos pos)
 {
     SetPos(pos, ref this.param);
     return;
 }
Beispiel #15
0
 /// <summary>
 /// 任意の地点が領域内にあるか確認する
 /// </summary>
 /// <param name="pos">検査座標</param>
 /// <returns>true: 領域内にある。</returns>
 public Boolean CheckInclusion(Pos pos)
 {
     if (this.UpperY < pos.y && this.LowerY > pos.y && this.LeftX < pos.x && this.RightX > pos.x)
         return true;
     else
         return false;
 }
Beispiel #16
0
        /// <summary>
        /// 引数で渡された領域と重ね合わせ、共通の領域を返す
        /// </summary>
        /// <param name="field">ターゲットの領域</param>
        /// <returns>共通領域</returns>
        public MapField And(MapField field)
        {
            List<int> xbuff = new List<int>();
            List<int> ybuff = new List<int>();

            if (this.UpperY <= field.UpperY && this.LowerY >= field.UpperY) ybuff.Add(field.UpperY);    // 2つの領域が重なるかどうかをチェック
            if (this.UpperY <= field.LowerY && this.LowerY >= field.LowerY) ybuff.Add(field.LowerY);
            if (field.UpperY < this.UpperY && field.LowerY > this.UpperY) ybuff.Add(this.UpperY);
            if (field.UpperY < this.LowerY && field.LowerY > this.LowerY) ybuff.Add(this.LowerY);

            if (this.RightX >= field.RightX && this.LeftX <= field.RightX) xbuff.Add(field.RightX);
            if (this.RightX >= field.LeftX && this.LeftX <= field.LeftX) xbuff.Add(field.LeftX);
            if (field.RightX > this.RightX && field.LeftX < this.RightX) xbuff.Add(this.RightX);
            if (field.RightX > this.LeftX && field.LeftX < this.LeftX) xbuff.Add(this.LeftX);

            Pos p1, p2;                                                                                 // 抽出されたz,yの組を2つ作って領域を作る
            if (xbuff.Count >= 2 && ybuff.Count >= 2)
            {
                p1 = new Pos(xbuff[0], ybuff[0]);
                p2 = new Pos(xbuff[1], ybuff[1]);
            }
            else
            {
                p1 = new Pos();
                p2 = new Pos();
            }
            return new MapField(p1, p2);
        }