teratail header banner
teratail header banner
質問するログイン新規登録

質問編集履歴

1

前回質問から一部解決できたので、解決できない部分に絞った質問に変えました。

2021/02/08 12:40

投稿

tatsu3
tatsu3

スコア11

title CHANGED
@@ -1,1 +1,1 @@
1
- GoogleMapsのDirectionsService、DirectionsRenderer、ルート上のよりかい座標を取得できなか?
1
+ GoogleMapsAPI取得した詳座標配列(legs/step/path)から、一定距離の地点にマーカー立てた
body CHANGED
@@ -3,129 +3,69 @@
3
3
  歩いた距離は、活動量トラッカーFitbitのAPIを使ってタイムリーに取得します。
4
4
 
5
5
  ##これまでできたこと
6
- あちこちサンプドなども参考にながらGoogle API使って以下通りコ書いました。
6
+ 起点から終点までのルートを取得し、下記のarrでそのルート上の座標配列取得。隣り合た座標の距離を次々足しいき、指定した距離に最近接座標にマカーることができました。
7
7
 
8
+ ```javascript
9
+ var arr = response.routes[0].overview_path;
8
- 起点と終点、34カ所の経由地を含む地図を取得して左半分に表示。起点からの歩いた距離分の地点を取得し、そのストリートビュー画像を右半分に表示する仕組みです。歩いた距離は、最終的にはFitBitから取得を目指しますが、とりあえずHTMLの入力欄<input id="mark">から入力する形にしてあります。
10
+ var between = gMaps.geometry.spherical.computeDistanceBetween;
11
+ var difference = Infinity;
12
+ var total = 0;
13
+ for (var i = 0, l = arr.length - 1; i < l; i++) {
14
+ var current = arr[i];
15
+ var distance = between(current, arr[i + 1]);
16
+ var dif = Math.abs(mark - (total + distance));
17
+ if (difference > dif) {
18
+ difference = dif;
19
+ total += distance;
20
+ }
21
+ else {
22
+ new gMaps.Marker({
23
+ position: current,
24
+ map: map,
25
+ title: total + 'm'
26
+ });
27
+ break;
28
+ }
9
29
 
30
+ ```
10
31
 
32
+ ##改善したこと、試みたこと
33
+ より誤差を小さくするため、ルート上のより多くの座標を取得できないか調べたところ、routesの下の、overview_pathプロパティ以外に、legs > steps > pathと辿って行ったところに、より詳細な座標が格納されていることが分かりました。これをfor文で回して取得し、全てをまとめてwhole_pathという座標配列にして見ました。座標の数(length)をみると、overview_pathの座標の数と比べて7倍くらい多く、精度が高いことが確認できました。
34
+ これをもとに、同じように隣り合った座標間の距離を次々足していき、指定した距離に最近接の座標にマーカーを立てようと以下のようなコードにしてみましたが、うまくいきませんでした。
11
35
 
12
- ```JavaScript
36
+ ```javascript
13
-
14
- <script>
15
- function initMap() {
16
- var gMaps = google.maps;
17
- var ds = new gMaps.DirectionsService;
18
- var map = new gMaps.Map(document.getElementById('map_canvas'));
19
- var stations = [
37
+ var whole_path = [];
20
- { lat: 43.16787133305725, lng: -1.2377224338793966, name: 'Saint-Jean-Pied-de-Port(サン・ジャン・ピエ・ド・ポー)' },
21
- ***中略。34カ所の経由地点が書かれています***
22
- { lat: 42.88081810734543, lng: -8.544630899970322, name: 'Santiago de Compostela(サンティアゴ・デ・コンポステーラ)' },
23
- ];
24
-
25
- var lngs = stations.map(function (station) { return station.lng; });
38
+ var legs = response.routes[0].legs;
26
- var lats = stations.map(function (station) { return station.lat; });
27
- map.fitBounds({
28
- west: Math.min.apply(null, lngs),
29
- east: Math.max.apply(null, lngs),
30
- north: Math.min.apply(null, lats),
31
- south: Math.max.apply(null, lats),
32
- });
33
-
34
- for (var i = 0; i < stations.length; i++) {
39
+ for (i = 0; i < legs.length; i++) {
35
- new google.maps.Marker({
36
- position: stations[i],
37
- map: map,
38
- title: stations[i].name
40
+ var steps = legs[i].steps;
41
+ for (j = 0; j < steps.length; j++) {
42
+ var nextSegment = steps[j].path;
43
+ for (k = 0; k < nextSegment.length; k++) {
39
- });
44
+ whole_path.push(nextSegment[k]);
40
45
  }
41
-
46
+ }
47
+ }
42
- // Divide route to several parts because max stations limit is 25 (23 waypoints + 1 origin + 1 destination)
48
+ var between = gMaps.geometry.spherical.computeDistanceBetween;
49
+ var difference = Infinity;
50
+ var total = 0;
43
- for (var i = 0, parts = [], max = 25 - 1; i < stations.length; i = i + max)
51
+ for (var i = 0, l = whole_path.length - 1; i < l; i++) {
52
+ var current = whole_path[i];
44
- parts.push(stations.slice(i, i + max + 1));
53
+ var distance = between(current, whole_path[i + 1]);
45
-
46
- var service_callback = function (response, status) {
54
+ var dif = Math.abs(mark - (total + distance));
47
- var mark = document.getElementById("mark").value;
48
- if (status != 'OK') {
55
+ if (difference > dif) {
49
- console.log('Directions request failed due to ' + status);
50
- return;
56
+ difference = dif;
57
+ total += distance;
51
58
  }
59
+ else {
60
+ new gMaps.Marker({
61
+ position: current,
62
+ map: map,
63
+ title: total + 'm'
64
+ });
65
+ break;
66
+ }
52
67
 
53
- //var m = 0;
68
+ ```
54
- //for (var h = 0; h < response.routes[0].legs.length; h++) {
55
- // m += response.routes[0].legs[h].distance.value;
56
- //} // ルートの距離(m)を取得できたが、ふたつに分割されている
57
69
 
58
- var disp = new gMaps.DirectionsRenderer;
59
- disp.setMap(map);
60
- disp.setOptions({
61
- suppressMarkers: true,
62
- preserveViewport: true,
63
- suppressInfoWindows: false,
64
- polylineOptions: {
65
- strokeColor: '#ff0000',
66
- strokeOpacity: 0.5,
67
- strokeWeight: 3
68
- }
69
- });
70
-
71
- var arr = response.routes[0].overview_path; //legs.step.path; ??//
72
- var between = gMaps.geometry.spherical.computeDistanceBetween;
73
- var difference = Infinity;
74
- var total = 0;
75
- for (var m = 0, l = arr.length - 1; m < l; m++) {
76
- var current = arr[m];
77
- var distance = between(current, arr[m + 1]);
78
- var dif = Math.abs(mark - (total + distance));
79
- if (difference > dif) {
80
- difference = dif; // 距離差を更新
81
- total += distance; // 合計距離を更新
82
- } else {
83
- var panorama = new google.maps.StreetViewPanorama(
84
- document.getElementById("pano"),
85
- {position: current,
86
- pov: {heading: 270,
87
- pitch: 0,
88
- },
89
- });
90
- map.setStreetView(panorama);
91
- break;
92
- }}
93
- disp.setDirections(response);
94
- };
95
- for (var i = 0; i < parts.length; i++) {
96
- var waypoints = [];
97
- for (var j = 1; j < parts[i].length - 1; j++)
98
- waypoints.push({ location: parts[i][j], stopover: false });
99
- var request = {
100
- origin: parts[i][0],
101
- destination: parts[i][parts[i].length - 1],
102
- waypoints: waypoints,
103
- travelMode: 'WALKING'
104
- };
105
- ds.route(request, service_callback);
106
- }
107
- }
108
- </script>
109
- <script async defer
110
- src="https://maps.googleapis.com/maps/api/js?key=xxxxxxxxxxx&callback=initMap"></script>
111
-
112
- ```##改善したいこと
113
- 前段として、数10kmのルート上で試している時は誤差が数10mくらいで、あまり気にならなかったのですが、このルートは全長800kmあるので(当たり前かもしれませんが)誤差が非常に大きくなります。
114
-
115
- 中盤の「var arr = response.routes[0].overview_path;」で得られる座標配列をコンソール画面で調べたところ、全長のうち計400カ所超のようです。必然的に数kmの誤差が出る計算です。
116
-
117
- 前段の数10kmのルート上で調べた時も得られた座標配列のlengthは200超だったので、取得できる座標の数は長さに比例して多くなるのではなく、一定程度に決められているのでしょうか??
118
-
119
- もしも、より細かい多くの座標を取得でのであれば誤差も少なくなる…初心者なりに考え試行錯誤していま
70
+ 途中までは上と同じうにうま行っているようなですが、最後にcurrentの座標を調べてみると、起点と同じ位置から動いていません
120
-
121
- ##試してみたこと
122
- 取得できたオブジェクトを見ると、「routes.overview_path」のほか、「routes.legs.step.path」というところにより細かい座標が入っているようだったので、「var arr = response.routes[0].legs.step.path;」と変えてみましたが、うまく行かず、おまけにレンダリングされたルートの線も消えてしまいました。
123
-
124
- ##さらにもう1点、お知恵を拝借したいこと
125
- Googlemapsには経由地(WayPoints)の数の制限があり、APIを取得していた場合でも起点・終点を含めて25カ所が上限と理解しています。巡礼路は、重要な巡礼地を経由してこそのルートなので、なんとかこれを回避する方法を模索しました。ネットのサンプルコードを参考に、詳しく仕組みは理解していませんが、ルートをDivideしてつなぎ合わせる形にしたのが上のコードです。
126
-
127
- 起点がふたつあるような形になっていて、「歩いた距離」の地点にマーカーを立つようにすると2カ所に立ちます。上のルート上の座標も約200カ所ずつに分かれて出力されます。総距離mも500数十kmと200数十kmのふたつに分かれて出ます。
128
-
129
- これをうまくつなぎ、全行程で本来の起点(サン・ジャン・ピエ・ド・ポー=フランス)から歩いた距離の地点をCurrentとして取得できる仕組みをつくりたいと考えています。いろいろ調べたり、考えたりしましたが、今のところ足がかりさえ見えなません。
130
-
131
- 向性だけご教示頂けると、とてもとてもありがたく思います。どうぞよろしくお願いいたします。
71
+ どうしたら良いのか(そもそも、この考え方で良いのかどうか)ご教示頂けると、とてもとてもありがたく思います。どうぞよろしくお願いいたします。