SQL Geometryを描画


今年は夏季休暇がとれるのだろうか。夏季休暇とって休日出勤と言う歪な状態になると予想。

日曜なので軽く遊ぶ。
下記コンポーネントで図形描画してみる。

WriteableBitmapEx
http://writeablebitmapex.codeplex.com/

ちなみにArcGIS Runtime for WPF Standardなるものを使えば描画コンポーネントがついてくるので別に必要ない。
ArcGIS Runtime for WPF Basicだっけ?を使えばなんと無料の…以下略

まあ、遊びなので適当、コードは以下

特に調整していないが全件でも1秒程度でデータ取得から描画可能、調整すればもう少し行けるか。
統計色塗りしたい程度の案件なら精度上げれば対応できそう。(ちなみ穴が開いてたりするが深追いしてない)

追記
穴が開いたのは、始終点が不一致だったから?
FillPolygonのIntに始点を追加で解消したような気がする。真面目には見てない。

スレッド化は以下

マルチスレッド描画

ArcGIS Runtime for WPFの直接描画レイヤ
SQL Serverから直でデータ取得する。
日本地図 ポリゴン( 白抜きをWebメルカトルで格納 )
Onlineサービスの背景と重畳

※Onlineサービス + WPF Basicと言うのは通るのだろうか?
なんらか費用発生する可能性があるので注意

using System;
using System.Collections.Generic;
using System.Diagnostics;

using System.Windows.Media.Imaging;
using System.Windows.Media;

using System.Data;
using System.Data.SqlClient;
using Microsoft.SqlServer.Types;

using ESRI.ArcGIS.Client;
using ESRI.ArcGIS.Client.Geometry;

namespace ArcGISWpfAppDraw.Layers
{
  public class SQLSrvDacLayer : DynamicLayer
  {

    protected override void GetSource(Envelope extent, int width, int height, DynamicLayer.OnImageComplete onComplete)
    {
      DateTime dt = DateTime.Now;

      WriteableBitmap bitmap = BitmapFactory.New(width, height);

      using (bitmap.GetBitmapContext(ReadWriteMode.ReadWrite))
      {

        bitmap.Clear(Colors.Transparent);

        this.DrawTable(extent, width, height, bitmap);
      }

      onComplete(bitmap, width, height, extent);

      Debug.WriteLine((DateTime.Now - dt).TotalMilliseconds + "ms ON DRAW");

    }//end method

    private void DrawTable(Envelope env, int width, int height, WriteableBitmap bmp)
    {
      string connectionSt = System.Configuration.ConfigurationManager.ConnectionStrings["DefaultDB"].ConnectionString;
      SqlConnection con = new SqlConnection(connectionSt);
      con.Open();

      string query = @"
SELECT 
 Shape AS SHP
FROM 
 JPN71WEB
WHERE
 Shape.STIntersects(@P1) = 1
";
      SqlParameter param = new SqlParameter("@P1", this.createGeomParams(env));
      param.UdtTypeName = "geometry";

      using (con)
      using (SqlCommand cmd = con.CreateCommand())
      {
        cmd.CommandType = CommandType.Text;
        cmd.CommandText = query;
        cmd.Parameters.Add(param);

        using (DataTable tab = new DataTable())
        using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
        {
          adapter.Fill(tab);

          this.DrawGeom(tab, env, width, height, bmp);
        }//end table

      }//end sql con
    }

    private void DrawGeom(DataTable dt, Envelope env, int width, int height, WriteableBitmap bmp)
    {
      DataColumn shpCol = dt.Columns["SHP"];
      foreach (DataRow row in dt.Rows)
      {
        SqlGeometry geom = row[shpCol] as
        SqlGeometry;

        if (geom == null || geom.STIsEmpty().IsTrue || geom.STNumGeometries().IsNull)
          continue;

        int numGeom = geom.STNumGeometries().Value;
        if (numGeom == 0)
          continue;

        for (int i = 1; i < numGeom + 1; i++)
        {
          SqlGeometry childGeom = geom.STGeometryN(i);

          if (childGeom == null ||
              childGeom.STIsEmpty().IsTrue)
            continue;

          this.DrawPoints(childGeom, env, width, height, bmp);
        }//end geom loop

      }//end row

    }

    private void DrawPoints(SqlGeometry geom, Envelope extent, int width, int height, WriteableBitmap bmp)
    {

      if (geom.STNumPoints().IsNull)
        return;

      int ptCount = geom.STNumPoints().Value;
      if (ptCount < 3)
        return;

      double wratio = width / extent.Width;
      double hratio = height / extent.Height;

      List<int> pts = new List<int>(ptCount);

      for (int i = 1; i < ptCount + 1; i++)
      {
        SqlGeometry pt = geom.STPointN(i);
        double ptx = pt.STX.Value;
        double pty = pt.STY.Value;

        int scX = Convert.ToInt32((ptx - extent.XMin) * wratio);
        int scY = Convert.ToInt32((extent.YMax - pty) * hratio);

        pts.Add(scX);
        pts.Add(scY);
      }//end pt loop

      bmp.FillPolygon(pts.ToArray(), this.getRndColor());
      pts.Clear();
      pts = null;

    }

    private Color getRndColor()
    {
      Random rnd = new Random();
      byte r = Convert.ToByte( rnd.Next(256) );
      byte g = Convert.ToByte( rnd.Next(256) );
      byte b = Convert.ToByte( rnd.Next(256) );

      return Color.FromRgb(r, g, b);

    }

    //Extent 2 SqlGeometry
    private SqlGeometry createGeomParams(Envelope env)
    {
      SqlGeometryBuilder builder = new SqlGeometryBuilder();

      builder.SetSrid(3857);

      builder.BeginGeometry(OpenGisGeometryType.Polygon);

      builder.BeginFigure(env.XMin, env.YMin);
      builder.AddLine(env.XMin, env.YMax);
      builder.AddLine(env.XMax, env.YMax);
      builder.AddLine(env.XMax, env.YMin);
      builder.AddLine(env.XMin, env.YMin);
      builder.EndFigure();
      builder.EndGeometry();

      return builder.ConstructedGeometry;
    }//end method
  }//end class

}//end namespace
カテゴリー: 開発 タグ: , , パーマリンク