– 続 – ArcGIS for Serverフィーチャの受取



これの続き

とりあえずコードだけ。
もうちょい早くはなりそうですが。

適当にProtoBuffer用の値保持用の構造体やクラスを設定しておく
試したのはポリゴンのみなので適当

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using ProtoBuf;

namespace ProtoItems
{
  [Serializable()]
  [ProtoContract]
  public struct Point
  {
    private double _x;

    private double _y;

    [ProtoMember(1)]
    public double X
    {
      get { return this._x; }
      set { this._x = value; }
    }//end prop

    [ProtoMember(2)]
    public double Y
    {
      get { return this._y; }
      set { this._y = value; }
    }//end prop

    public void PutCoords(ref double x, ref double y)
    {
      this._x = x;
      this._y = y;
    }//end method

    public static Point Create(ref double x, ref double y)
    {
      Point result;
      result._x = x;
      result._y = y;

      return result;
    }//end method
  }//end struct

  [Serializable()]
  [ProtoContract]
  public struct PointCollection
  {
    [ProtoMember(1)]
    public Point[] Points;

    public static PointCollection Create(Point[] pts)
    {
      PointCollection result;
      result.Points = pts;
      return result;
    }//end method
  }//end struct

  [Serializable()]
  [ProtoContract]
  public struct Polygon
  {
    [ProtoMember(1)]
    public PointCollection[] Rings;

    public static Polygon Create(PointCollection[] rings)
    {
      Polygon result;
      result.Rings = rings;

      return result;
    }//end method

    public static Polygon CreateEmpty()
    {
      Polygon result;
      result.Rings = null;
      return result;
    }

  }//end struct

  [Serializable()]
  [ProtoContract]
  public struct Feature
  {
    [ProtoMember(1)]
    public Polygon Geometry;

    [ProtoMember(2)]
    public Dictionary<string, string> Attributes;
  }//end struct

  [Serializable()]
  [ProtoContract]
  public struct FeatureSet
  {
    [ProtoMember(1)]
    public Feature[] fetures;
  }//end struct

}//end namespace

サーバ側レスポンス返却部

    [WebGet(UriTemplate = "protobuf")]
    public Stream GetProtoBuf()
    {
      WebOperationContext.Current.OutgoingResponse.ContentType = "application/x-protobuf";

      Dac.ProtoUtil util = new Dac.ProtoUtil();

      DateTime start = DateTime.Now;
      DateTime now = DateTime.Now;

      DataTable dt = Dac.JPNDac.Test();

      Debug.Print("GET DT:{0}", (DateTime.Now - now).TotalMilliseconds);
      now = DateTime.Now;

      FeatureSet fset = util.formDataTable(dt);

      Debug.Print("TO RESULT:{0}", (DateTime.Now - now).TotalMilliseconds);
      now = DateTime.Now;

      using (MemoryStream memSt = new MemoryStream())
      {
        ProtoBuf.Serializer.Serialize(memSt, fset);
        //application/x-protobuf

        Debug.Print("ProtoBuf.Serializer.Serialize:{0}", (DateTime.Now - now).TotalMilliseconds);
        Debug.Print("TOTAL:{0}", (DateTime.Now - start).TotalMilliseconds);

        return new MemoryStream(memSt.ToArray());
      }
    }//end method

一応変換クラス

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

using ProtoItems;
using Microsoft.SqlServer.Types;
using System.Data.SqlTypes;
using System.Data;

namespace WcfRestService.Dac
{
  public class ProtoUtil
  {
    public FeatureSet formDataTable(DataTable dt)
    {

      List<Feature> features = new List<Feature>(dt.Rows.Count);

      foreach (DataRow row in dt.Rows)
      {
        Polygon gon = Polygon.CreateEmpty();
        Dictionary<string, string> attr = new Dictionary<string,string>();
        Feature f;

        foreach (DataColumn col in dt.Columns)
        {
          if (col.DataType == typeof(SqlGeometry))
            gon = this.fromSQLPolygon((SqlGeometry)row[col]);
          else if (!(row[col] is DBNull) || row[col] != null)
            attr.Add(col.ColumnName, row[col].ToString());

        }//end loop

        f.Attributes = attr;
        f.Geometry = gon;
        features.Add(f);

      }//end loop

      FeatureSet result;
      result.fetures = features.ToArray();
      return result;
    }//end method

    private Polygon fromSQLPolygon(SqlGeometry geom)
    {
      SqlInt32 numgeom = geom.STNumGeometries();
      if (numgeom.IsNull)
        return Polygon.CreateEmpty();

      int count = numgeom.Value;

      List<PointCollection> rings = new List<PointCollection>(count);

      for (int i = 1; i < count + 1; i++)
      {
        SqlGeometry child = geom.STGeometryN(i);
        SqlInt32 pntCnt = child.STNumPoints();
        if (pntCnt.IsNull)
          continue;

        int pcnt = pntCnt.Value;
        if (pcnt < 3)
          continue;

        List<Point> pts = new List<Point>(pcnt);

        for (int pnt = 1; pnt < pcnt + 1; pnt++)
        {
          SqlGeometry pointGeom = child.STPointN(pnt);
          double x, y;
          x = pointGeom.STX.Value;
          y = pointGeom.STY.Value;
          Point pt = Point.Create(ref x, ref y);
          pts.Add(pt);
        }//end polygon

        PointCollection poiCol = PointCollection.Create(pts.ToArray());
        rings.Add(poiCol);
      }//end loop geom
      return Polygon.Create(rings.ToArray());

    }//end method

  }//end class
}//end namespace

クライアント側

private void ProtoTest()
{
  string url = "http://localhost/service1/protobuf";
  HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(url);
  httpRequest.Method = "GET";

  DateTime dt = DateTime.Now;

  WebResponse webResponce = httpRequest.GetResponse();

  Debug.Print("ProtoGetResponse:{0} msec", (DateTime.Now - dt).TotalMilliseconds);

  ProtoItems.FeatureSet fset;
  fset.fetures = null;

  using (Stream strm = webResponce.GetResponseStream())
  {
    dt = DateTime.Now;

    fset = ProtoBuf.Serializer.Deserialize<ProtoItems.FeatureSet>(strm);

    Debug.Print("ProtoBuf.Serializer.Deserialize:{0} msec", (DateTime.Now - dt).TotalMilliseconds);
  }

  List<Graphic> graphics = new List<Graphic>();

  foreach (ProtoItems.Feature item in fset.fetures)
  {
    Graphic gra = this.getGraphics(item);
    graphics.Add(gra);
  }

  Debug.WriteLine(graphics.Count);

  Debug.Print("ProtoBuf graphics:{0} msec", (DateTime.Now - dt).TotalMilliseconds);
}
カテゴリー: 開発 タグ: , パーマリンク