2023,江端さんの忘備録

ここ2~3日は、食事を取ることすら、面倒です。

昨日の続きなんですけど、

This is a continuation of yesterday's story,

―― 大麻というのは、疲れ果てて、何もやる気がでないサラリーマンにも効きそうですか?

"Does marijuana seem to work for exhausted business people who are not motivated to do anything?"

と、某大学の運動部の方にインタビューしたいです。

I want to interview a certain university athletic department.

皮肉でも、批判でもなくて、「本気」です。

I am not being sarcastic or critical, but I am "serious."

-----

使用の予定はないんですけど、『ラストラインに大麻がある』と思うことでこの状態を踏ん張れるならいいな、と思っています。

I don't plan to use it, but I hope that thinking 'there is marijuana on the last line' will help me trudge through this situation.

大丈夫。

It's OK.

サラリーマンが大麻を使用すれば、それだけで、社会人としては終わりです(日本では違法行為です)。

If a salaryman uses marijuana, that is the end of a business person (it is illegal in Japan).

大麻を使う前に、仕事を辞めてしまえばいい ―― と考えられる程度には理性は残っています。

I am still rational enough to think I should quit my job before using marijuana.

『コロラドに戻る』という手もあるかなぁ、とか考えています。

I'm thinking about the possibility of 'going back to Colorado.'

―― 大麻を試したいなら、なぜ、栽培、乾燥、製粉までの全行程を、DIYで実現しようとしないのか?

2023,江端さんの忘備録

最近、これまで見たことがないような減量が続いています。

Recently, we have been experiencing weight loss like we have never seen before.

基本的には、難しい仕事が、同時に3つ落ちてきて、常に疲労を感じ、睡眠が浅く、なにより

Three complex tasks fell upon me simultaneously: I felt constantly tired, my sleep was shallow, and most of all,

―― 食欲がない

"Lack of appetite"

自分がやりたい仕事ではなくて、他人からやらされる、または、自分に意義が見えない仕事は、本当に辛く、メンタルをやられます。

Work that others make you do or work that you do not see the significance in is complex and can cause mental damage.

-----

ここ2~3日は、食事を取ることすら、面倒です。

Even getting a meal has been a chore for the past couple of days.

しかし、食べないと、さらに体調が悪くなっていくことは、以前自分でも調べました。

However, I have previously investigated that I will become even sicker if I don't eat.

まあ、仕事→ストレスは、時間とともに解決することがあるので、現在は様子見ですが、あまり長く続くようであれば、気力のある内に手を打たないと、と思っています。

Well, work -> stress can resolve itself over time, so I am currently waiting to see how it goes, but if it continues for too long, I will have to do something while I have the energy to do it.

『限界で叫んでも、手遅れ』は、私が娘たちに言い続けたことですからね。

Because 'screaming at the limit, but it's too late' is what I kept telling my daughters.

でもね、「本日中の復旧断念」というアナウンスを、今(23時)に出して、どーする。

2023,江端さんの忘備録

私のコラムを読んで頂ける人には自明でしょうが、私はフォーマットを気にせず文章を量産するタイプです。

As should be evident to readers of my columns, I am the type of person who mass-produces sentences without regard to format.

『文章は、原則、未来の自分の為に作成し、運が良ければ他人の役に立てばいい』が、私のポリシーです。

My policy is, "As a rule, I create my writing for my future self, and if I'm lucky, for the benefit of others."

体裁を気にして、記載量を減らすくらいなら、体裁を無視して、残しておけるものは残しておく方がマシ、と考えています。

It is better to ignore formats and keep what I can leave than to reduce the information with care in the formats.

もっとも、これに対して真逆の考え方もありますし、それはそれで意義があります。

There is, however, an opposing view to this, and it is significant.

まあ、これは「ミーイズム(自己中心主義)」と「コスモポリタリズム(世界市民主義)」の違いとも言えるかもしれません。

Well, one might say that this is the difference between "me-ism (self-centeredness)" and "cosmopolitanism (world citizenship).

-----

私がフォーマットを病的に気にするのは、通信プロトコルのプログラムぐらいですかね。

The only thing I am morbidly concerned about formatting is communication protocol programs.

たった1ビットのプロトコルエラーで、通信ができなくなるからです。

This is because a protocol error of just one bit will result in the loss of communication.

つまり、フォーマットを厳密に守らないと1mmも動かせない世界では、そうせざるを得ないのです。

In other words, in a world where we can't move a millimeter without strict adherence to a format, we must.

-----

『世界が(緩くて、雑な)私のポリシーのフォーマットに合わせてくれればいいんだけど』と思うことはあるのですが ―― こればかりは、どうしようもないです。

'I wish the world would adapt to my (loose, messy) policy format' -- but I can't help myself with this one.

それでも、"ちんけ"な研究員&エンジニアには、"ちんけ"なりの人類への貢献方法があるんですよ。

2023,江端さんの技術メモ

package main
/*

f:\しゅらばしゅう\有吉先生データ\Transfer(2018)\N07-11_14_GML>go run nearest_node3.go 

golangで、以下のbus_stop_modified.csvというファイル名から読み取った位置情報ごとに、
以下のtsuzuki_bus.osmファイルのnodeに記載された位置情報と50メートル以内のnodeと
その距離を算出するプログラムを作って下さい。

[bus_stop_modified.csv]
35.522547,139.590950
35.522547,139.590950
35.564881,139.580736
35.566768,139.583192
35.569075,139.584080

[tsuzuki_bus.osm]
<?xml version='1.0' encoding='UTF-8'?>
<osm version='0.6' generator='JOSM'>
<node id='200000' visible='true' version='1' lat='35.568239' lon='139.552822' />
<node id='200001' visible='true' version='1' lat='35.568164' lon='139.5528' />
<node id='200002' visible='true' version='1' lat='35.568321' lon='139.551491' />
<node id='200003' visible='true' version='1' lat='35.568338' lon='139.55136' />
<node id='200004' visible='true' version='1' lat='35.568355' lon='139.551264' />
</osm>

*/
import (
"encoding/csv"
"encoding/xml"
"fmt"
"math"
"os"
"strconv"
)


type Node struct {
XMLName xml.Name `xml:"node"`
ID      string   `xml:"id,attr"`
Lat     string   `xml:"lat,attr"`
Lon     string   `xml:"lon,attr"`
}


func haversine(lat1, lon1, lat2, lon2 float64) float64 {
radius := 6371.0 // Earth's radius in kilometers
latRad1 := lat1 * (math.Pi / 180)
latRad2 := lat2 * (math.Pi / 180)
deltaLat := (lat2 - lat1) * (math.Pi / 180)
deltaLon := (lon2 - lon1) * (math.Pi / 180)


a := math.Sin(deltaLat/2)*math.Sin(deltaLat/2) +
math.Cos(latRad1)*math.Cos(latRad2)*
math.Sin(deltaLon/2)*math.Sin(deltaLon/2)
c := 2 * math.Atan2(math.Sqrt(a), math.Sqrt(1-a))


distance := radius * c
return distance
}


func main() {
// Read CSV file
csvFile, err := os.Open("bus_stop_modified.csv")
if err != nil {
fmt.Println("Error opening CSV file:", err)
return
}
defer csvFile.Close()


csvReader := csv.NewReader(csvFile)
positions, err := csvReader.ReadAll()
if err != nil {
fmt.Println("Error reading CSV:", err)
return
}


// Read OSM file
xmlFile, err := os.Open("tsuzuki_bus.osm")
if err != nil {
fmt.Println("Error opening OSM file:", err)
return
}
defer xmlFile.Close()


var nodes struct {
XMLName xml.Name `xml:"osm"`
Nodes   []Node   `xml:"node"`
}


// Parse OSM XML
decoder := xml.NewDecoder(xmlFile)
err = decoder.Decode(&nodes)
if err != nil {
fmt.Println("Error decoding OSM XML:", err)
return
}


// Find nodes within 50 meters for each position
for _, position := range positions {
lat, _ := strconv.ParseFloat(position[0], 64)
lon, _ := strconv.ParseFloat(position[1], 64)


fmt.Printf("For Position (%s, %s):\n", position[0], position[1])


for _, node := range nodes.Nodes {
nodeLat, _ := strconv.ParseFloat(node.Lat, 64)
nodeLon, _ := strconv.ParseFloat(node.Lon, 64)


dist := haversine(lat, lon, nodeLat, nodeLon)
if dist <= 0.05 { // 50 meters in kilometers
fmt.Printf("Node ID: %s\n", node.ID)
fmt.Printf("Node Coordinates: %s, %s\n", node.Lat, node.Lon)
fmt.Printf("Distance to Node: %.2f km\n", dist)
}
}
fmt.Println("--------------------------")
}
}

出力結果

go run nearest_node3.go
For Position (35.522547, 139.590950):
Node ID: 216067
Node Coordinates: 35.522356, 139.591082
Distance to Node: 0.02 km
Node ID: 216068
Node Coordinates: 35.522885, 139.591253
Distance to Node: 0.05 km
Node ID: 253004
Node Coordinates: 35.522356, 139.591082
Distance to Node: 0.02 km
Node ID: 253005
Node Coordinates: 35.522885, 139.591253
Distance to Node: 0.05 km
Node ID: 287056
Node Coordinates: 35.522885, 139.591253
Distance to Node: 0.05 km
Node ID: 287057
Node Coordinates: 35.522356, 139.591082
Distance to Node: 0.02 km
Node ID: 335005
Node Coordinates: 35.522356, 139.591082
Distance to Node: 0.02 km
Node ID: 335006
Node Coordinates: 35.522885, 139.591253
Distance to Node: 0.05 km
Node ID: 350106
Node Coordinates: 35.522885, 139.591253
Distance to Node: 0.05 km
Node ID: 350107
Node Coordinates: 35.522356, 139.591082
Distance to Node: 0.02 km
Node ID: 351568
Node Coordinates: 35.522356, 139.591082
Distance to Node: 0.02 km
Node ID: 351569
Node Coordinates: 35.522885, 139.591253
Distance to Node: 0.05 km
--------------------------
For Position (35.522547, 139.590950):
Node ID: 216067
Node Coordinates: 35.522356, 139.591082
Distance to Node: 0.02 km
Node ID: 216068
Node Coordinates: 35.522885, 139.591253
Distance to Node: 0.05 km
Node ID: 253004
Node Coordinates: 35.522356, 139.591082
Distance to Node: 0.02 km

2023,江端さんの忘備録

私は、「風評被害」と「健康被害」を説明するパラダイムとして、故小田島隆さんのエッセイを引用することが多いです。

I often cite the late Takashi Odajima's essay as a paradigm to explain "harmful rumors" and "health hazards."

(1)ハエが止まったケーキは、それを目撃した後に即時に食べれば、健康被害は絶無です。

(1) A fly-stopped cake poses no health hazard if eaten immediately after witnessing it.

(2)問題は、その「健康被害の絶無のケーキ」を、どれだけの人が食べられるか、です。

(2) How many people can eat that "cake with absolutely no health risks"?

-----

中国は日本と同レベルまたはそれ以上の放射性濃度の原発の処理水を海洋放出しています。

China has been discharging into the ocean treated water from nuclear power plants with the same or higher levels of radioactivity than Japan.

ただ、中国の原発の処理水は、「通常の原発運用」によるものです。

However, the treated water from China's nuclear power plants is from "normal nuclear power plant operations."

比して、今回、我が国の処理水は、「原発事故」によるものです。

In comparison, the treated water in our country this time is due to a "nuclear accident."

エンジニアとしての私は、上記の2つに差がないことを「科学的」には理解しているつもりです。

As an engineer, I believe I understand "scientifically" that there is no difference between the above two.

しかし、もしかしたら、上記の2つには、今現在分っていないとんでもない『違い』がある可能性を、100&否定できるものでもありません。

However, the possibility that there may be a tremendous "difference" between the above two that we do not currently know about cannot be 100% denied.

----

忘れてはならないのは、我が国は「原発事故による処理水」という「ハエ」を作ってしまったということです。

We must not forget that our country has created a "fly" called "treated water from nuclear accidents."

この「ハエ」を誰が作ったのか、そして、誰がその責を負うべきなのかについては、今日のところは論じません。

I will not discuss today who created this "fly" and who is to blame.

しかし、私たち日本人は、このことを忘れてはならないとは思うのです。

However, I do not think we Japanese should forget this.

-----

ちなみに、私(江端)は、ハエが止まったケーキを、それを目撃した直後に食べたことがあります。

By the way, I (Ebata) once ate a cake that a fly had stopped on.

全く抵抗ありませんでした。

There was no psychological resistance at all.

風評被害を作ったのは誰か

2023,江端さんの忘備録

私は、他人へのアドバイスをしない人間ですが、特に「恋愛」に関しては、絶対しません。

I am a person who never advises others, especially when it comes to "love affairs."

なぜなら、「恋愛」が「ロジック」の対義語だからです。

This is because "love affairs" is synonymous with "logic."

あんな非線形でやっかいなもの、相談されても答えようがありません。

Even if I were consulted, there is no way to answer such a non-linear and tricky question.

まあ、多くは語りませんが、以前、人の恋愛相談に巻き込まれて酷い目にあった、という過去もあるからですが。

Well, I won't say much, but I have a history of getting involved in people's love affairs and having a terrible time in the past.

-----

もし『彼/彼女と心中したい』と相談されれば、苦しみが少ないと推定される自殺方法を教えてあげるつもりです。

If they ask me for advice on how to kill themself, I will tell them about a suicide method that is presumed to cause less suffering.

または、「心中相手だけを死なせる」という事件を何度も繰り返した、くそったれな日本の文豪の話でもしてやろうと思います。

Or, I could tell you about a damned Japanese writer who repeatedly "let only his heart partner die."

まあ、家族でもない赤の他人が何しようが、私は構いません。

I don't care what strangers who are not family members do.

「その男性をずっと見守って、ホームから落ちていく様(さま)を、じっくりと観察する」

2023,江端さんの技術メモ

OSMファイルからバスルート情報を取り出して、同じバス停留所の名前が同じの場合、位置情報の平均値を計算して算出する方法

(以下、"私だけが分かればいい"メモ)

/*

F:\しゅらばしゅう\有吉先生データ\Transfer(2018)>go run bus_route_try_10.go

Golangで、以下のXML分の中から、<tag k="route" v="bus"/>を発見した時に、refの要素を参照にして位置情報を取り出すプログラム

そんで、同じ名前の停留所があったら、その座標の平均値として出力する

*/

package main

import (
	"encoding/xml"
	"fmt"
	"io/ioutil"
	"log"
	"os"
)

type Osm struct {
	XMLName   xml.Name   `xml:"osm"`
	Nodes     []Node     `xml:"node"`
	Relations []Relation `xml:"relation"`
}

type Node struct {
	ID   int64   `xml:"id,attr"`
	Lat  float64 `xml:"lat,attr"`
	Lon  float64 `xml:"lon,attr"`
	Tags []Tag   `xml:"tag"`
}

type Relation struct {
	ID      int64    `xml:"id,attr"`
	Members []Member `xml:"member"`
	Tags    []Tag    `xml:"tag"`
}

type Member struct {
	Type string `xml:"type,attr"`
	Ref  string `xml:"ref,attr"`
	Role string `xml:"role,attr"`
}

type Tag struct {
	K string `xml:"k,attr"`
	V string `xml:"v,attr"`
}

func main() {

	// XMLファイルの読み込み
	xmlFile, err := os.Open("tsuzuki.osm") // これがベースとなるosmファイル
	if err != nil {
		log.Fatal(err)
	}
	defer xmlFile.Close()

	// XMLデータの読み込み
	xmlData, err := ioutil.ReadAll(xmlFile)
	if err != nil {
		log.Fatal(err)
	}

	var osmData Osm

	// XMLデータのUnmarshal
	err = xml.Unmarshal(xmlData, &osmData)
	if err != nil {
		log.Fatal(err)
	}

	for _, relation := range osmData.Relations {

		//hasBusRouteTag := false

		for _, tag := range relation.Tags {

			if tag.K == "route" && tag.V == "bus" {

				for _, tag := range relation.Tags { // Tagの中で再度tagを回してnameを取得する(こんなことができるとは知りませんでした)
					if tag.K == "name" {
						fmt.Println("=========================")
						fmt.Printf("Route Name: %s\n", tag.V)
						break
					}
				}

				count := 0
				start_flag := 0
				//end_flag := 0
				pre_node := "ddd"
				sum_Lat := 0.0
				sum_Lon := 0.0

				for i, member := range relation.Members {

					if i == len(relation.Members)-1 { // 最後のノードを検知したら、その時点で纏めて計算して出力する
						//end_flag = 1

						fmt.Printf("Re:Bus Stop: %s\n", pre_node)
						fmt.Printf("Re:Coordinates: Lat %f, Lon %f\n\n", sum_Lat/float64(count), sum_Lon/float64(count))
					}

					if member.Type == "node" {
						node := getNodeByID(member.Ref, osmData.Nodes)
						if node != nil {

							if pre_node == getNodeName(node) || start_flag == 0  { // 停留所名が前回と同じであるなら

								count++
								sum_Lat += node.Lat
								sum_Lon += node.Lon

								start_flag = 1

							} else {

								fmt.Printf("Re:Bus Stop: %s\n", pre_node)
								fmt.Printf("Re:Coordinates: Lat %f, Lon %f\n\n", sum_Lat/float64(count), sum_Lon/float64(count))

								count = 1
								sum_Lat = node.Lat
								sum_Lon = node.Lon
							}

							pre_node = getNodeName(node)

						} 					   
					}
				}

			}
		}
	}
}

func getNodeByID(ref string, nodes []Node) *Node {
	for _, node := range nodes {
		if fmt.Sprintf("%d", node.ID) == ref {
			return &node
		}
	}
	return nil
}

func getNodeName(node *Node) string {
	for _, tag := range node.Tags {
		if tag.K == "name" {
			return tag.V
		}
	}
	return ""
}

出力はこんな感じになります。

F:\しゅらばしゅう\有吉先生データ\Transfer(2018)>go run bus_route_try_10.go
=========================
Route Name: IKEAシャトルバス 新横浜駅前-IKEA前
Re:Bus Stop: IKEAシャトルバス IKEA前
Re:Coordinates: Lat 35.522547, Lon 139.590950

=========================
Route Name: IKEAシャトルバス IKEA前-新横浜駅前
Re:Bus Stop: IKEAシャトルバス IKEA前
Re:Coordinates: Lat 35.522547, Lon 139.590950

=========================
Route Name: すみれが丘線
Re:Bus Stop: すみれが丘
Re:Coordinates: Lat 35.564881, Lon 139.580736

Re:Bus Stop: すみれが丘公園
Re:Coordinates: Lat 35.566768, Lon 139.583192

Re:Bus Stop: 有馬変電所
Re:Coordinates: Lat 35.569075, Lon 139.584080

Re:Bus Stop: 中有馬
Re:Coordinates: Lat 35.571500, Lon 139.584235

Re:Bus Stop: 神明社前
Re:Coordinates: Lat 35.571684, Lon 139.580940

Re:Bus Stop: 地区センター前
Re:Coordinates: Lat 35.560333, Lon 139.595547

Re:Bus Stop: 北山田駅
Re:Coordinates: Lat 35.561022, Lon 139.592536

Re:Bus Stop: 山田富士
Re:Coordinates: Lat 35.561428, Lon 139.590315

Re:Bus Stop: 重代
Re:Coordinates: Lat 35.563485, Lon 139.584835

Re:Bus Stop: 北山田小学校入口
Re:Coordinates: Lat 35.563816, Lon 139.582279

Re:Bus Stop: 東山田営業所
Re:Coordinates: Lat 35.561115, Lon 139.606000

Re:Bus Stop: 東山田営業所前
Re:Coordinates: Lat 35.561358, Lon 139.604353

Re:Bus Stop: 山田小学校
Re:Coordinates: Lat 35.560874, Lon 139.602905

Re:Bus Stop: 長泉寺
Re:Coordinates: Lat 35.560052, Lon 139.597552

=========================
Route Name: 鷺沼線;有馬線
Re:Bus Stop: 神明社前

2023,江端さんの技術メモ

sharpファイルで得られたバスルートのデータを力づくでosmファイルにする

上記の方法で作成したOSMファイルでは、OSMにした時に、Nodeがバスルートの終端ににしかできないことが分かり、正直愕然としていました。これでは、バスの乗客は、バスの出発と到着地点でしか乗降できないことになるからです。

なんとかNodeを作り出せないか、色々試していたまま、いたずらに時間が過ぎていったのですが、ようやく、分かりました。

答えは、Tag情報を付与すること、でした。

作成したOMSファイルはこんな感じ

<?xml version='1.0' encoding='UTF-8'?>
<osm version='0.6' generator='JOSM'>
<node id='200000' visible='true' version='1' lat='35.568239' lon='139.552822' />
<node id='200001' visible='true' version='1' lat='35.568164' lon='139.5528' />
<node id='200002' visible='true' version='1' lat='35.568321' lon='139.551491' />
<node id='200003' visible='true' version='1' lat='35.568338' lon='139.55136' />
<node id='200004' visible='true' version='1' lat='35.568355' lon='139.551264' />
<node id='200005' visible='true' version='1' lat='35.568406' lon='139.550885' />
<node id='200006' visible='true' version='1' lat='35.568423' lon='139.550768' />
<node id='200007' visible='true' version='1' lat='35.568445' lon='139.550568' />
<node id='200008' visible='true' version='1' lat='35.568462' lon='139.550513' />
<node id='200009' visible='true' version='1' lat='35.568507' lon='139.550154' />
<node id='200010' visible='true' version='1' lat='35.568564' lon='139.549755' />
<node id='200011' visible='true' version='1' lat='35.568603' lon='139.549438' />
<node id='200012' visible='true' version='1' lat='35.568665' lon='139.548962' />
<node id='200013' visible='true' version='1' lat='35.568671' lon='139.54888' />
<node id='200014' visible='true' version='1' lat='35.56871' lon='139.548563' />
<node id='200015' visible='true' version='1' lat='35.568817' lon='139.54744' />
<node id='200016' visible='true' version='1' lat='35.568851' lon='139.547054' />
<node id='200017' visible='true' version='1' lat='35.568879' lon='139.546737' />
<node id='200018' visible='true' version='1' lat='35.568924' lon='139.546475' />
<node id='200019' visible='true' version='1' lat='35.568986' lon='139.546241' />
<node id='200020' visible='true' version='1' lat='35.569071' lon='139.545979' />
<node id='200021' visible='true' version='1' lat='35.569094' lon='139.545918' />
<node id='200022' visible='true' version='1' lat='35.569057' lon='139.54587' />
<node id='200023' visible='true' version='1' lat='35.568969' lon='139.54582' />
<node id='200024' visible='true' version='1' lat='35.568586' lon='139.545565' />
<node id='200025' visible='true' version='1' lat='35.568372' lon='139.545373' />
<node id='200026' visible='true' version='1' lat='35.567171' lon='139.543939' />
<node id='200027' visible='true' version='1' lat='35.566558' lon='139.543161' />
<node id='200028' visible='true' version='1' lat='35.566434' lon='139.543016' />
<node id='200029' visible='true' version='1' lat='35.56622' lon='139.542644' />
<node id='200030' visible='true' version='1' lat='35.565938' lon='139.542162' />
<node id='200031' visible='true' version='1' lat='35.565519' lon='139.541454' />
<node id='200032' visible='true' version='1' lat='35.565482' lon='139.541383' />

QGISの表示はこんな感じ

Nodeが全然表われません。

今度は、これに、適当に

'/>  → '> <tag k='highway' v='bus_stop'/> 

と、適当に変換・追加してしてみました。

<?xml version='1.0' encoding='UTF-8'?>
<osm version='0.6' generator='JOSM'>
<node id='200000' visible='true' version='1' lat='35.568239' lon='139.552822'/>
<node id='200001' visible='true' version='1' lat='35.568164' lon='139.5528'/>
<node id='200002' visible='true' version='1' lat='35.568321' lon='139.551491'/>
<node id='200003' visible='true' version='1' lat='35.568338' lon='139.55136'>
<tag k='highway' v='bus_stop'/>
</node>
<node id='200004' visible='true' version='1' lat='35.568355' lon='139.551264'/>
<node id='200005' visible='true' version='1' lat='35.568406' lon='139.550885'/>
<node id='200006' visible='true' version='1' lat='35.568423' lon='139.550768'/>
<node id='200007' visible='true' version='1' lat='35.568445' lon='139.550568'/>
<node id='200008' visible='true' version='1' lat='35.568462' lon='139.550513'/>
<node id='200009' visible='true' version='1' lat='35.568507' lon='139.550154'/>
<node id='200010' visible='true' version='1' lat='35.568564' lon='139.549755'/>
<node id='200011' visible='true' version='1' lat='35.568603' lon='139.549438'/>
<node id='200012' visible='true' version='1' lat='35.568665' lon='139.548962'/>
<node id='200013' visible='true' version='1' lat='35.568671' lon='139.54888'>
<tag k='highway' v='bus_stop'/>
</node>
<node id='200014' visible='true' version='1' lat='35.56871' lon='139.548563'/>
<node id='200015' visible='true' version='1' lat='35.568817' lon='139.54744'/>
<node id='200016' visible='true' version='1' lat='35.568851' lon='139.547054'/>
<node id='200017' visible='true' version='1' lat='35.568879' lon='139.546737'/>
<node id='200018' visible='true' version='1' lat='35.568924' lon='139.546475'/>
<node id='200019' visible='true' version='1' lat='35.568986' lon='139.546241'/>
<node id='200020' visible='true' version='1' lat='35.569071' lon='139.545979'/>
<node id='200021' visible='true' version='1' lat='35.569094' lon='139.545918'/>
<node id='200022' visible='true' version='1' lat='35.569057' lon='139.54587'/>
<node id='200023' visible='true' version='1' lat='35.568969' lon='139.54582'/>
<node id='200024' visible='true' version='1' lat='35.568586' lon='139.545565'>
<tag k='highway' v='bus_stop'/>
</node>
<node id='200025' visible='true' version='1' lat='35.568372' lon='139.545373'/>

その結果、このOSMファイル(tsuzuki_bus_trial2.osm)を、QGISで表示してみたら、こんな感じになりました。

Nodeが追加されています。

しかし、問題は、postGISでダイクストラ計算ができことが重要ですので、まずは、このosmをPostgresql にインポートしてみます。手順はいつも通りですが、ざっと記載しておきます。

C:\Users\ebata>psql -U postgres -h 192.168.0.23 -p 15432
postgres=# create database tsuzuki_bus;
CREATE DATABASE
tsuzuki_bus=# create extension postgis;
CREATE EXTENSION
tsuzuki_bus=# create extension pgrouting;
CREATE EXTENSION

で、postGISが動くDBの作成を完了しました。
で次に、

まだ試してないけど、バス停の追加は多分、これで可能となるはず

で作成した、mapconfig_for_cars_rail_busstop.xml 

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <tag_name name="highway" id="1">
    <tag_value name="bus_stop"/>
    <tag_value name="motorway"          id="101" priority="1.0" maxspeed="130" />
    <tag_value name="motorway_link"     id="102" priority="1.0" maxspeed="130" />
    <tag_value name="motorway_junction" id="103" priority="1.0" maxspeed="130" />
    <tag_value name="trunk"             id="104" priority="1.05" maxspeed="110" />
    <tag_value name="trunk_link"        id="105" priority="1.05" maxspeed="110" />    
    <tag_value name="primary"           id="106" priority="1.15" maxspeed="90" />
    <tag_value name="primary_link"      id="107" priority="1.15" maxspeed="90" />    
    <tag_value name="secondary"         id="108" priority="1.5" maxspeed="90" />
    <tag_value name="secondary_link"    id="109" priority="1.5" maxspeed="90"/>  
    <tag_value name="tertiary"          id="110" priority="1.75" maxspeed="90" />
    <tag_value name="tertiary_link"     id="111" priority="1.75" maxspeed="90" />  
    <tag_value name="residential"       id="112" priority="2.5" maxspeed="50" />
    <tag_value name="living_street"     id="113" priority="3" maxspeed="20" />
    <tag_value name="service"           id="114" priority="2.5" maxspeed="50" />
    <tag_value name="unclassified"      id="117" priority="3" maxspeed="90"/>
    <tag_value name="road"              id="100" priority="5" maxspeed="50" />
  </tag_name> 
  <tag_name name="railway" id="1">
    <tag_value name="subway"              id="101" priority="1.0" maxspeed="40" />
    <tag_value name="rail"              id="101" priority="1.0" maxspeed="40" />
  </tag_name> 
</configuration>

重要なのは、 <tag_value name="bus_stop"/>の部分です。

このXMLファイルを使って、

F:\しゅらばしゅう\有吉先生データ\Transfer(2018)\N07-11_14_GML>osm2pgrouting -f tsuzuki_bus_trial2.osm -c mapconfig_for_cars_rail_busstop.xml -d tsuzuki_bus -U postgres -h 192.168.0.23 -p 15432 -W password

(tsuzuki_bus_trial2.osm は、変更後のOSMファイル)

を実施し、QGISでDBの内容を表示してみました。

ちゃんとNodeが追加されているようです。

しかし、ダイクストラ計算ができるかどうかは、まだ分かりませんので、QGISの地物情報でNode番号を把握して、計算を試みてみました。

 

tsuzuki_bus=# SELECT seq, node, edge, cost FROM pgr_dijkstra('SELECT gid as id,source, target,length as cost, reverse_cost FROM ways',2, 7);
seq | node | edge | cost
-----+------+------+-----------------------
1 | 2 | 25 | 0.002503402202160114
2 | 3 | 1 | 0.003623692651717509
3 | 4 | 26 | 0.0073121202899935804
4 | 5 | 27 | 0.006205490305965455
5 | 6 | 28 | 0.0048274159495506515
6 | 7 | -1 | 0
(6 rows)

ちゃんと出力されているようです。

ようやく、目処がついてきました ―― ヘナヘナと座り込みそうです。

本当にしんどくて辛い夏季休暇でした。

2023,江端さんの忘備録

A new approach for me, who cannot prepare "20 million yen for retirement" - Consideration

本日リリースされました。

Released today.

-----

ぶっちゃけ『世の中に裏切られたような気持ち』です。

Honestly, I feel as if the world has betrayed me.

私と同様に「老後の2000万円」を準備できていない人に警告します。

I warn those not prepared for "20 million yen for retirement" as I am.

あなたの回りは「嘘吐な友人」だらけです。

You are surrounded by "lying friends."

やつら、2000万円近くの貯蓄を持っていますよ ―― ちなみに"平均"で2000万円ですからね。

By the way, they have close to 20 million yen in savings --- 20 million yen on average.

一方、もしこれが、厚生労働省が恣意的に作成したデータだったりしたら ―― 流石に"タダですます"気には、到底なれませんね ・・・ ふっふっふっふ・・・

On the other hand, if this data were arbitrarily created by the Ministry of Health, Labor, and Welfare, I would not forgive them.

未分類

Golangで、以下のXML分の中から、<tag k="route" v="bus"/>を発見した時に、refの要素を参照にして位置情報を取り出すプログラムを書いて

<osm>
  <node id="2197214759" lat="35.5714149" lon="139.5880043" version="1" timestamp="2013-03-12T09:31:19Z" changeset="15336763" uid="1258339" user="k___0e0">
    <tag k="highway" v="bus_stop"/>
    <tag k="name" v="有馬第二団地前"/>
  </node>
  <node id="2197214762" lat="35.5715628" lon="139.5875429" version="1" timestamp="2013-03-12T09:31:19Z" changeset="15336763" uid="1258339" user="k___0e0">
    <tag k="highway" v="bus_stop"/>
    <tag k="name" v="有馬第二団地前"/>
  </node>
  <relation id="2814953" version="38" timestamp="2023-06-14T08:20:58Z" changeset="137316398" uid="1687166" user="U20">
   <member type="node" ref="2197214759" role="backward_stop"/>
    <member type="node" ref="2197214762" role="forward_stop"/>
    <tag k="route" v="bus"/>
  </relation>
</osm>

ChatGPTの回答

指定されたXMLデータから を検出し、それに対応する ref 要素を参照にして位置情報を取得するGolangのプログラムを以下に示します。このプログラムは、encoding/xml パッケージを使用してXMLを解析します。

package main

import (
	"encoding/xml"
	"fmt"
	"log"
	"strings"
)

type OSM struct {
	XMLName xml.Name `xml:"osm"`
	Nodes   []Node   `xml:"node"`
	Relations []Relation `xml:"relation"`
}

type Node struct {
	ID       int64   `xml:"id,attr"`
	Lat      float64 `xml:"lat,attr"`
	Lon      float64 `xml:"lon,attr"`
	Tags     []Tag   `xml:"tag"`
}

type Relation struct {
	ID       int64   `xml:"id,attr"`
	Members  []Member `xml:"member"`
	Tags     []Tag    `xml:"tag"`
}

type Member struct {
	Type string `xml:"type,attr"`
	Ref  string `xml:"ref,attr"`
	Role string `xml:"role,attr"`
}

type Tag struct {
	K string `xml:"k,attr"`
	V string `xml:"v,attr"`
}

func main() {
	xmlData := `
	<osm>
		<node id="2197214759" lat="35.5714149" lon="139.5880043" version="1" timestamp="2013-03-12T09:31:19Z" changeset="15336763" uid="1258339" user="k___0e0">
			<tag k="highway" v="bus_stop"/>
			<tag k="name" v="有馬第二団地前"/>
		</node>
		<node id="2197214762" lat="35.5715628" lon="139.5875429" version="1" timestamp="2013-03-12T09:31:19Z" changeset="15336763" uid="1258339" user="k___0e0">
			<tag k="highway" v="bus_stop"/>
			<tag k="name" v="有馬第二団地前"/>
		</node>
		<relation id="2814953" version="38" timestamp="2023-06-14T08:20:58Z" changeset="137316398" uid="1687166" user="U20">
			<member type="node" ref="2197214759" role="backward_stop"/>
			<member type="node" ref="2197214762" role="forward_stop"/>
			<tag k="route" v="bus"/>
		</relation>
	</osm>
	`

	var osmData OSM
	err := xml.Unmarshal([]byte(xmlData), &osmData)
	if err != nil {
		log.Fatal(err)
	}

	for _, relation := range osmData.Relations {
		for _, tag := range relation.Tags {
			if tag.K == "route" && tag.V == "bus" {
				for _, member := range relation.Members {
					if member.Type == "node" {
						node := getNodeByID(member.Ref, osmData.Nodes)
						if node != nil {
							fmt.Printf("Bus Stop: %s\n", getNodeName(node))
							fmt.Printf("Coordinates: Lat %f, Lon %f\n\n", node.Lat, node.Lon)
						}
					}
				}
			}
		}
	}
}

func getNodeByID(ref string, nodes []Node) *Node {
	for _, node := range nodes {
		if fmt.Sprintf("%d", node.ID) == ref {
			return &node
		}
	}
	return nil
}

func getNodeName(node *Node) string {
	for _, tag := range node.Tags {
		if tag.K == "name" {
			return tag.V
		}
	}
	return ""
}

このプログラムは、与えられたXMLデータから を見つけ、それに関連する ref 要素を参照してバス停の位置情報を取得して表示します。XMLデータは xmlData 変数に直接格納されていますが、実際のプログラムではファイルから読み込むこともできます。コード内のコメントに従って、XMLデータ構造やタグを調整してください。


世界が変わる

生成AIを使わない奴は、"死ぬ" ―― 文字通りの意味で。