ホーム » OpenLayers

OpenLayers」カテゴリーアーカイブ

GeoServerのSQLビューに渡す引数について

複数引数を必要とするSQLビューにOpenLayersから引数を渡す

[code]
select
geometry
from
shops
where
shop_code = ‘%shop_code%’
and
owner_no = %owner_no%
[/code]

上記のSQLビューに引数を渡すには以下のように引数「key:value」をセミコロンで連結
[code]
var params = "shop_code:123456789;owner_no:54321";
var layer = new OpenLayers.Layer.WMS(
"layer name",
"../geoserver/ワークスペース名/wms",
{
LAYERS: ‘レイヤ名’,
format: ‘image/png’,
transparent: true,
viewparams: params
},
{
singleTile: false
}
);
[code]

in句を使った条件に複数の引数を渡す
[code]
select
geometry
from
shops
where
shop_code in (%shop_code%)
[/code]

[code]
var params = "shop_code:’123456789’\\,’987654321’";
var layer = new OpenLayers.Layer.WMS(
"layer name",
"../geoserver/ワークスペース名/wms",
{
LAYERS: ‘レイヤ名’,
format: ‘image/png’,
transparent: true,
viewparams: params
},
{
singleTile: false
}
);
[/code]

OpenLayersでOSMが表示されない

OpenLayersでOSMの地図を表示していたのがだ、なぜか表示されなくなった。
7月にMapQuestが使えなくなり、OSMに切り替えたのだがOSMもとは・・・
OpenLayersのsampleをサイトを見ると表示されている。

表示される
[code]
layer_base = new OpenLayers.Layer.OSM();
[/code]

表示される

[code]
layer_base = new OpenLayers.Layer.OSM( "Simple OSM Map");
[/code]

google map の距離計測機能についての再考

以前、googlemapとopenlayersの距離計測について投稿。

googlemap APIもV3になり距離計算のAPIも変更されたようなので弊社の距離計算ツールとgooglemapの距離計算機能の差についてあらためて再考。

西武池袋線の清瀬駅とひばりが丘駅の距離をベースに調査。

清瀬駅の座標
139.51989499999999111、35.77196299999999951

ひばりが丘駅の座標
139.54577000000000453、35.75142900000000168

※座標は国土数値情報より入手

googlemapの距離測定機能で測ると3.26kmと表示される。

clip_2

※googlemapの地図はAPIを介して表示しないと著作権的に問題があるのでぼやかして表示

地図上のポイントをクリックして距離計測を行なうので誤差の発生を考慮して、google map apiでも計測。

[code]
var from = new google.maps.LatLng( 35.77196299999999951,139.51989499999999111);
var to = new google.maps.LatLng( 35.75142900000000168,139.54577000000000453);
var distance = google.maps.geometry.spherical.computeDistanceBetween(from, to);
[/code]

clip3

やはりこちらも3269mと表示される。

弊社のの距離計測TOOLで計算すると3265mになる。

スクリーンショット 2016-08-10 11.36.09

[code]
コード,緯度,経度,名称,名称,コード,緯度,経度,名称,名称,距離,円半径
1,35.77196299999999951,139.51989499999999111,清瀬駅,清瀬駅,2,35.75142900000000168,139.54577000000000453,ひばりが丘,ひばりが丘,3265,10000
2,35.75142900000000168,139.54577000000000453,ひばりが丘,ひばりが丘,1,35.77196299999999951,139.51989499999999111,清瀬駅,清瀬駅,3265,10000
[/code]

その差は4m、約0.1%の差が発生する。

国土地理院の距離と方位角の計算でもやはり3269mとなる。

スクリーンショット 2016-08-10 12.30.05

google.maps.geometry.spherical.computeDistanceBetweenは3番目の引数に半径を渡すことができる。
つまり地球を楕円体ではなく球体として計算をしていることが分かる。
※デファルトでは半径を6378137mとしているようだ。

その為、誤差が発生している。

OpenLayersに表示したGeoServerのPOINT(シンボル)のFeatureInfo(情報)をクリックして照会(WMSGetFeatureInfoです)

OpenLayersのWMSGetFeatureInfoを使用するとクリックした位置にある地物(Obejct)の情報を照会できる。

以下の画像は学校を旗(32×32のPNG画像)で表示。
clip_1

OpenLayers.Mapにコントロ-ル「WMSGetFeatureInfo」を追加してeventListenersのコールバック関数「getfeatureinfo」で
クリックした位置にある地物の情報を取得。
[code]
var selectControl = new OpenLayers.Control.WMSGetFeatureInfo({
url: "../geoserver/ワークスペース/wms",
title: "",
maxFeatures: 50,
queryVisible: true,
vendorParams: {
buffer: 100
},
infoFormat: "application/json",
eventListeners: {
getfeatureinfo: function(event){
var j = JSON.parse(event.text);
console.log(j, j.features, event);
}
}
});
map.addControl(selectControl);
selectControl.activate();
[/code]
シンボル、ポイントのように領域を持たない地物を選択する時は、vendorParamsのbufferまたはradiusでバッファ範囲を指定する。(単位はピクセル)
vendorParamsの詳細

上記の設定ではWMSGetFeatureInfoは表示されている全てのレイヤを照会の対象とする。

照会対象の項目はGeoServerで指定(以下はSQLViewで作成したLayersの時)
clip_3

注意点
GeoServerのLayersでGeometryのSRIDが正しく指定されていないとエラーになる

ドキュメント

OpenLayersでGoogleMap上にGeoServerのWMSを表示

道路データ(数年前のデータで旧日本則地形)をGeoServerで配信してGoogleMap上に表示。
同様のことを電子国土でやった経験から簡単にできると思ったが、
意外にてこずり、時間がかかったのでメモ。

GeoServerの設定

特別な設定はしていない「Native SRS」、「Declared SRS」共に旧日本則地形を指定
※表示されない時はSRSを色々と変更したが、結局このまま。

clip_13

OpenLayersのコード

GoogleMap、OSMをOpenLayersで表示する時はmapの投影にEPSG:900913を使用する。
但し、以下のように投影を敢えて明記せずに使用することがある。
もちろん、これは正しく動作する。

var map = new OpenLayers.Map('id_div_map');
var gmap = new OpenLayers.Layer.Google("Google ROADMAP",{numZoomLevels: 20});
map.addLayer(gmap);

しかし、ここにwmsのレイヤーを追加しても正しく表示されない。
OpenLayers.Mapに正しく投影の情報や最大のExtentを明示的に指定する必要がある。

var map = new OpenLayers.Map('id_div_map', {
	maxExtent: new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34),
	maxResolution: 156543.0399,
	numZoomLevels: "auto",
	units: 'm',
	projection: new OpenLayers.Projection("EPSG:4326"),
	displayProjection: new OpenLayers.Projection("EPSG:900913")
	});
var gmap = new OpenLayers.Layer.Google("Google ROADMAP",{numZoomLevels: 20});
map.addLayer(gmap);
var road = new OpenLayers.Layer.WMS("LOCAL_ROADS",
	"http://192.9.200.25/geoserver/road/wms?",
	{
		LAYERS: 'road:ROAD5439',
		format: 'image/png',
         	transparent: 'true',
         	isBaseLayer: 'false',
         	projection: 'EPSG:4301',
         	reproject: 'true',
		styles: ''
	});
map.addLayer(road);

※maxExtentに指定した値は(-180、-90)、(180、90)を座標変換した値
-20037508.34,-20037508.34,20037508.34,20037508.34

表示結果

clipll

OpenLayersで著作権等を表示

OpenLayersでMapQuest-OSMタイルを無償で使用するためには著作権表示が必要。

改めてOpenLayersにおける著作権表示について調査。

コントロールを空でOpenLayers.Map作成すると

var map = new OpenLayers.Map('map', {controls:[]});

拡大縮小等のコントロールは何も表示されない。

clipc

OpenLayers.Control.Attributionコントロールを追加すると

map.addControl(new OpenLayers.Control.Attribution());

勝手に著作権情報が表示される

Googleの場合

clipg

OSMの場合

clipo

MapQuest-OSMの場合

clipo2

OSMの著作権だけ表示されてMapQuestが要求する著作権表示になっていない!

オプションで明示的に指定

var mapQuestOption = {
attribution:'Tiles Courtesy of MapQuest'
};
var layer_osm_mapquest = new OpenLayers.Layer.OSM("MapQuest-OSM", mapQuestArray,mapQuestOption);

期待した結果になった

clipo3

OpenLayersでMapQuest-OSMタイル表示

OpenLayers.Layer.OSMで使用可能なタイルサーバーは以下に記載
TMS
MapQuestは比較的シンプルで見栄えがよい
「TMS」にはMapQuestはFREEと記載しているが改めて確認。

MapQuestのサイトには
「利用規約
マップクエストのオープンタイルは、以下の条件で無料で使用できます。
マップクエスト、OSMのタイルを使用する場合は、OpenStreetMapは、データのためのクレジットが与えられなければなりません-を参照して、この項の詳細は、OSMの法的FAQのを。
マップクエストオープンエアリアルタイルを使用している場合は、属性をお願いとして、「一部の礼儀はNASA / JPL-Caltechの、米国発農業、農業サービス庁 “。
」のタイル礼儀に置かないでくださいマップクエストを “あなたのページ上、またはマップの著作エリアのワードリンク」にマップクエスト ” を http://www.mapquest.com 。 以下は、サイトで使用できるコードスニペットは次のとおりです。

Tiles Courtesy of MapQuest

アプリケーションが(現在は毎秒4,000以上のタイルとして定義される)重い使用状況を取得する場合は、私達は私達に電子メールを送信することにより、お知らせくださいopen@mapquest.com 。 私たちが知っておくと余分なトラフィックに対応するように、使用目的の推定値を記載してください。
(例えば-プレスリリースや企業の発表)の発表があるだろう場合は、マップクエストでご連絡くださいopen@mapquest.com私たちは良いニュースとマップタイルの使用量の任意の期待のジャンプを知っているように。
これらのタイルの使用はご自身の責任である。
これらのタイルの使用法は、私たちに支配されている利用規約 。
OpenStreetMapのデータは下でライセンスされてオープン·データ·コモンズオープンデータベースライセンス(ODbLの)。」と記載されており、著作について記載すればフリーで使用可能。

clip_1

OpenLayersの地図ドラッグでスクロールしすぎ!

OpenLayersの地図をdrug panすると、暫くスクロールが続いて予想以上はなれた位置まで飛んでしまう。
これを防ぐ方法はいかのようにenableKineticを無効にする
map_canvas = new OpenLayers.Map(id_map, { controls: [] });
map_canvas.addControl(new OpenLayers.Control.Navigation(dragPanOptions: {enableKinetic: false}}));

※上記の記述ではNavigation以外の全てのコントロールが無効になるため必用なコントロールを適時追加

map_canvas = new OpenLayers.Map(id_map, { controls: [] });
map_canvas.addControl(new OpenLayers.Control.Navigation({mouseWheelOptions: {interval: 1000},dragPanOptions: {enableKinetic: false}}));
//map_canvas.addControl(new OpenLayers.Control.DradPan({interval: 0}));
map_canvas.addControl(new OpenLayers.Control.PanZoomBar());
map_canvas.addControl(new OpenLayers.Control.KeyboardDefaults());

OpenLayersの円の半径

半径100mの円を表示

GoogleMap

var p = new google.maps.LatLng(y,x);
var options = {
	clickable: false,
	strokeColor: "#FF0000",
	strokeOpacity: 1.0,
	strokeWeight: 4,
	fillOpacity: 0.0,
	center: p,
	radius: Number(100)
 };
var circle = new google.maps.Circle(options);
circle.setMap(get_map());

google

OpenLayers(その1)

var style = { 
	strokeColor: '#FF0000', 
	strokeOpacity: 1.0,
	strokeWidth: 5,
	fillOpacity: 0
};

var lonlat =  layer_lonlat_to_map_lonlat(x, y);
var circle = OpenLayers.Geometry.Polygon.createRegularPolygon
(
	new OpenLayers.Geometry.Point(lonlat.lon, lonlat.lat),
	100,
	20,
	0
);
var feature= new OpenLayers.Feature.Vector(circle, null, style);
layer_vector.addFeatures(feature);

osm1

何か半径が違う!

OpenLayers(その2)

以下にしたがって各頂点の座標を求めてVectorとして表示

var apex = 40;
var latlon = new OpenLayers.LonLat(x, y);
var angle;
var new_lonlat;
var points = [];
for (var i = 0; i < apex+1; i++) {
	angle = (i * 360 / apex) + 0;
	new_lonlat = OpenLayers.Util.destinationVincenty(latlon, angle, radius);
	points.push([new_lonlat.lon, new_lonlat.lat]);
}

黒い円(ちょっと切れているが)

osm2
どうやら、こちらのほうがよい。
OpenLayers.Util.destinationVincentyは測地線からの距離と角度を指定して座標を求めるらしい。
今度、値を確認しよう

GeoServer上のラインをOpenLayersに色分け表示

GeoServer上に鉄道のデータをインポート

これを鉄道会社の種別(1~5)ごとに色分けしてOpenLayers上に表示

当初はOpenLayersのスタイルで対応を行おうとしたが、どうもこれはOpenLayers.Layer.WMSには使えないみたい

結局、GeoServerの機能でスタイルを作成してレイヤにスタイルを設定して解決

以下のスタイルを作成
[code]
<?xml version="1.0" encoding="ISO-8859-1"?>
<StyledLayerDescriptor version="1.0.0"
xsi:schemaLocation="http://www.opengis.net/sld StyledLayerDescriptor.xsd"
xmlns="http://www.opengis.net/sld"
xmlns:ogc="http://www.opengis.net/ogc"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<NamedLayer>
<Name>railroad ex</Name>
<UserStyle>
<Title>SLD Cook Book: railroad ex</Title>
<FeatureTypeStyle>
<Rule>
<Name>rail-1</Name>
<ogc:Filter>
<ogc:PropertyIsEqualTo>
<ogc:PropertyName>n02_002</ogc:PropertyName>
<ogc:Literal>1</ogc:Literal>
</ogc:PropertyIsEqualTo>
</ogc:Filter>
<LineSymbolizer>
<Stroke>
<CssParameter name="stroke">#009933</CssParameter>
<CssParameter name="stroke-width">2</CssParameter>
</Stroke>
</LineSymbolizer>
</Rule>
</FeatureTypeStyle>
<FeatureTypeStyle>
<Rule>
<Name>rail-2</Name>
<ogc:Filter>
<ogc:PropertyIsEqualTo>
<ogc:PropertyName>n02_002</ogc:PropertyName>
<ogc:Literal>2</ogc:Literal>
</ogc:PropertyIsEqualTo>
</ogc:Filter>
<LineSymbolizer>
<Stroke>
<CssParameter name="stroke">#0055CC</CssParameter>
<CssParameter name="stroke-width">3</CssParameter>
</Stroke>
</LineSymbolizer>
</Rule>
</FeatureTypeStyle>
<FeatureTypeStyle>
<Rule>
<Name>rail-3</Name>
<ogc:Filter>
<ogc:PropertyIsEqualTo>
<ogc:PropertyName>n02_002</ogc:PropertyName>
<ogc:Literal>3</ogc:Literal>
</ogc:PropertyIsEqualTo>
</ogc:Filter>
<LineSymbolizer>
<Stroke>
<CssParameter name="stroke">#FF0000</CssParameter>
<CssParameter name="stroke-width">6</CssParameter>
</Stroke>
</LineSymbolizer>
</Rule>
</FeatureTypeStyle>
<FeatureTypeStyle>
<Rule>
<Name>rail-4</Name>
<ogc:Filter>
<ogc:PropertyIsEqualTo>
<ogc:PropertyName>n02_002</ogc:PropertyName>
<ogc:Literal>4</ogc:Literal>
</ogc:PropertyIsEqualTo>
</ogc:Filter>
<LineSymbolizer>
<Stroke>
<CssParameter name="stroke">#FF0000</CssParameter>
<CssParameter name="stroke-width">6</CssParameter>
</Stroke>
</LineSymbolizer>
</Rule>
</FeatureTypeStyle>
<FeatureTypeStyle>
<Rule>
<Name>rail-5</Name>
<ogc:Filter>
<ogc:PropertyIsEqualTo>
<ogc:PropertyName>n02_002</ogc:PropertyName>
<ogc:Literal>5</ogc:Literal>
</ogc:PropertyIsEqualTo>
</ogc:Filter>
<LineSymbolizer>
<Stroke>
<CssParameter name="stroke">#FF0000</CssParameter>
<CssParameter name="stroke-width">6</CssParameter>
</Stroke>
</LineSymbolizer>
</Rule>
</FeatureTypeStyle>
</UserStyle>
</NamedLayer>
</StyledLayerDescriptor>
[/code]
上記のスタイルをレイヤに関連付けて対応
スクリーンショット 2014-01-15 18.07.18

念の為、OpenLayersのスタイルについて

参考サイト

[code]
new OpenLayers.StyleMap({
"default": new OpenLayers.Style({
strokeColor: "white",
strokeWidth: 1
}, {
rules: [
new OpenLayers.Rule({
filter: new OpenLayers.Filter.Comparison({
type: OpenLayers.Filter.Comparison.LESS_THAN,
property: "shape_area",
value: 3000
}),
symbolizer: {
fillColor: "olive"
}
}),
new OpenLayers.Rule({
elseFilter: true,
symbolizer: {
fillColor: "navy"
}
})
]
})
})
[/code]

スタイルの変更
スタイルはGeoServer上で予めレイヤに設定する。
以下の書式でJavaScript側からも変更が可能
※GeoServer上でrailroad2というスタイルを作成済み
[code]
railroad = new OpenLayers.Layer.WMS(
"Tokyo:railroad", "../geoserver/Tokyo/wms",
{
STYLES: ‘railroad2’,
LAYERS: ‘Tokyo:VIEW_RAILROAD’,
format: ‘image/png’,
transparent: true,
viewparams: ‘road_type:2’
},
{
singleTile: true,
ratio: 1,
isBaseLayer: false,
yx : {‘EPSG:4326’ : true}
}
);
[/code]