SQL Serverで防空識別圏を作ってみよう


あらかじめ日本の形状をデータとして持っておく必要がある。
第三段階と第4段階で、色々やっているので見どころはそこだが、途中で面倒になっている。

適当に座標値をインプット

DECLARE @geom AS GEOGRAPHY;
SET @geom = GEOGRAPHY::STGeomFromText('POLYGON ((138.7463888888890 45.7519444444444 ,132.9972222222220 40.6691666666667 ,132.9972222222220 37.2861111111111 ,130.4975000000000 36.0030555555556 ,129.7977777777780 35.2197222222222 ,126.9980555555560 33.0033333333333 ,124.9980555555560 33.0033333333333 ,124.9983333333330 30.0036111111111 ,122.9983333333330 28.0038888888889 ,122.9986111111110 24.7080555555556 ,122.9986111111110 24.2033333333333 ,122.9986111111110 23.0041666666667 ,131.9977777777780 23.0044444444444 ,131.9975000000000 30.0036111111111 ,134.9972222222220 30.0036111111111 ,140.3469444444440 31.6702777777778 ,143.2300000000000 33.1702777777778 ,144.3463888888890 35.2200000000000 ,144.9127777777780 40.2194444444444 ,146.3791666666670 42.7858333333333 ,145.7291666666670 43.2691666666667 ,145.8625000000000 43.3358333333333 ,145.8300000000000 43.3861111111111 ,145.8041666666670 43.4358333333333 ,145.5791666666670 43.4025000000000 ,145.3625000000000 43.5025000000000 ,145.3125000000000 44.0525000000000 ,145.7458333333330 44.4358333333333 ,145.7455555555560 45.7522222222222 ,138.7463888888890 45.7519444444444))', 4326);

--■第一段階■
SELECT @geom;

T1

--■第二段階■
--陸部をくり抜いてみる

--UnionAggregate (geography データ型)
--http://technet.microsoft.com/ja-jp/library/ff929095.aspx
DECLARE @jpn AS GEOGRAPHY;
SELECT @jpn = GEOGRAPHY::UnionAggregate(SHAPE) FROM gis.JPN71WGS1948

--STDifference (geography データ型)
--http://technet.microsoft.com/ja-jp/library/bb933819.aspx
DECLARE @p2 AS GEOGRAPHY
SET @p2 = @geom.STDifference(@jpn)

SELECT @p2

T2

--■第三段階■
--(24)の地点と(25)の地点との間及び(26)の地点と(27)の 地点との間については、北海道本島の海岸線から海上3海里の線)に よつて結ぶ線とする。 

DECLARE @hkd AS GEOGRAPHY;
SELECT @hkd = GEOGRAPHY::UnionAggregate(SHAPE) FROM gis.JPN71WGS1948 WHERE KEN='北海道';

--面積が一番デカいのが[北海道本島]のはずなので取り出す
DECLARE @hkd_main AS GEOGRAPHY;
 --STGeometryN (geography データ型)
 --http://technet.microsoft.com/ja-jp/library/bb933849.aspx
SET @hkd_main = @hkd.STGeometryN(1);

DECLARE @cnt AS INT
SET @cnt = 1;

--STNumGeometries (geography データ型)
--http://technet.microsoft.com/ja-jp/library/bb933886.aspx
DECLARE @geomCnt AS INT
SET @geomCnt = @hkd.STNumGeometries();

--WHILE (Transact-SQL)
--http://technet.microsoft.com/ja-jp/library/ms178642.aspx
WHILE (@geomCnt >= @cnt)
BEGIN
 --一つずつジオメトリを取り出して調べる
--STArea (geography データ型)
--http://technet.microsoft.com/ja-jp/library/bb933967.aspx
 if @hkd_main.STArea() < @hkd.STGeometryN(@cnt).STArea()
	SET @hkd_main = @hkd.STGeometryN(@cnt);
 SET @cnt = @cnt + 1;
END

--SELECT @hkd_main;

--北海道を3海里デカくする
--3海里 = 5556 メートル @ google検索 [3海里は何m]
--STBuffer (geography データ型)
--http://technet.microsoft.com/ja-jp/library/bb933965.aspx
--本当は24-25 / 26-27の間だけだがはみ出ないとたかをくくっていたがはみ出してしまう。 
--面倒になって来たので見なかったことにする。
DECLARE @hkd_main_3  AS GEOGRAPHY
SET @hkd_main_3 = @hkd_main.STBuffer ( 5556.0 )

--防空識別圏を合算する
--http://technet.microsoft.com/ja-jp/library/bb933914.aspx
--STUnion (geography データ型)
DECLARE @p3  AS GEOGRAPHY
SET @p3 = @hkd_main_3.STUnion(@geom);

--陸部をくり抜く
DECLARE @p3_ans  AS GEOGRAPHY
SET @p3_ans = @p3.STDifference(@jpn);

SELECT @p3_ans;
--■第4段階■
--(10)の 地点と(11)の地点との間については、与那国島に係る領海の基線)からその外側 14 海里の線 (昭和 52 年法律第 30 号)第2条第1項 に規定する基線をいう。)
--(ただし、(10)の 地点と(11)の地点とを直線によつて結んだ線の西側の線に限る。)

-- 資料を探すのが面倒になってきた
-- 領海=基線から最大12海里(約22.2km)までの範囲 14海里は空域用なのか?

DECLARE @ynk AS GEOGRAPHY;
SELECT @ynk = GEOGRAPHY::UnionAggregate(SHAPE) FROM gis.JPN71WGS1948 WHERE SIKUCHOSON='与那国町';

--与那国の最大/最小緯度を求める
DECLARE @pcnt AS INT;
SET @pcnt = 1;

--STNumPoints (geography データ型)
--http://technet.microsoft.com/ja-jp/library/bb933827.aspx
DECLARE @pt_count AS INT;
SET @pt_count = @ynk.STNumPoints();

DECLARE @ynk_pt AS GEOGRAPHY,
	    @min_lat AS float,
	    @max_lat AS float;

WHILE (@pt_count >= @pcnt)
BEGIN
 --STPointN (geography データ型)
 --http://technet.microsoft.com/ja-jp/library/bb933844.aspx
 SET @ynk_pt = @ynk.STPointN(@pcnt);

 IF @pcnt = 1 
 BEGIN
   SET @min_lat = @ynk_pt.Lat;
   SET @max_lat = @ynk_pt.Lat;
 END

 --Lat / Long 緯度/経度の拡張プロパティ
 --http://technet.microsoft.com/ja-jp/library/bb933806.aspx
 --http://technet.microsoft.com/ja-jp/library/bb933958.aspx
 IF @ynk_pt.Lat > @max_lat
  SET @max_lat = @ynk_pt.Lat;
 if  @ynk_pt.Lat < @min_lat
  SET @min_lat = @ynk_pt.Lat;

 SET @pcnt = @pcnt + 1;
END

DECLARE @stText AS Varchar(max);

SET @stText = 'POLYGON ((122.0 ' + STR(@min_lat,12,10) +  ' ,122.998611111111 ' + STR(@min_lat,12,10) +  ' ,122.998611111111 ' + STR(@max_lat,12,10) + 
				      ' ,122.0 '+ STR(@max_lat,12,10) + ' ,122.0 ' + STR(@min_lat,12,10) +  '))';

-- 10/11は経度 122.9986111111110 より西にはいかないので領域を作る
DECLARE @dif AS GEOGRAPHY;
SET @dif = GEOGRAPHY::STGeomFromText(@stText, 4326);

-- 14海里 = 25.92800 キロメートル  = 25 928 メートル
DECLARE @ynk14 AS GEOGRAPHY;
SET @ynk14 = @ynk.STBuffer( 25928.0 );

--合算
--STIntersection (geography データ型)
--http://technet.microsoft.com/ja-jp/library/bb933901.aspx
DECLARE @p4 AS GEOGRAPHY
SET @p4 = @ynk14.STIntersection(@dif);

--第三段階の状態と足す
SET @p4 = @p3.STUnion(@p4)

--日本でくり抜き
DECLARE @p4_ans  AS GEOGRAPHY
SET @p4_ans = @p4.STDifference(@jpn);

SELECT @p4_ans;

T4

カテゴリー: 開発 タグ: パーマリンク