2023,江端さんの技術メモ

pgr_dijkstra()で、ダイクストラの順番を壊さずにルートの座標を得る方法(getDijkstraPath())

ノードの切断を発生させず、ノード10~ノード20と、ノード30~ノード40を回避するダイクストラ計算を行うPostGISのクエリー

をベースとしたGo言語のプログラムになります。

// C:\Users\ebata\tomioka3B\src\others\main23.go
package main

import (
	"database/sql"
	"fmt"
	"log"
	"m/src/ldarp"
	"strconv"

	_ "github.com/lib/pq"
)

func main() {
	db, err := sql.Open("postgres",
		"user=postgres password=password host=192.168.0.23 port=15432 dbname=tomioka_db_c sslmode=disable")
	if err != nil {
		log.Fatal("OpenError: ", err)
	}
	defer db.Close()

	/*
		以下のldarp.LocInfoの内容は、
		type LocInfo struct {
			Lon    float64
			Lat    float64
			Source int
		}
		となっています。
		このプログラムファイルでは、上記を定義して、ldarp.LocInfoを、LocInfoと変換すれば動きます

		ただ、前提とするpostgresqlのpostGISが取り扱うデータベースは、
		mapconfig_for_cars.xml をベースとして構築しているものになりますので、ご留意下さい
		https://github.com/pgRouting/osm2pgrouting/blob/main/mapconfig_for_cars.xml
	*/

	var a_Point, b_Point ldarp.LocInfo

	a_Point.Source = 1  // 出発ノード
	b_Point.Source = 50 // 到着ノード

	var del_start1, del_end1, del_start2, del_end2 ldarp.LocInfo
	//var del_start3, del_end3 ldarp.LocInfo

	del_start1.Source = 10 // 1つ目の無効としたいノード番号(開始番号)
	del_end1.Source = 20   // 1つ目の無効としたいノード番号(終了番号)
	del_start2.Source = 30 // 2つ目の無効としたいノード番号(開始番号)
	del_end2.Source = 40   // 2つ目の無効としたいノード番号(開始番号)
	//del_start3.Source = 30
	//del_end3.Source = 35

	array1 := []ldarp.LocInfo{del_start1, del_end1} // 上記の無効としたいノード番号を登録する
	array2 := []ldarp.LocInfo{del_start2, del_end2} // 上記の無効としたいノード番号を登録する
	//array3 := []ldarp.LocInfo{del_start3, del_end3}

	//delSourceArray := [][]ldarp.LocInfo{array1, array2, array3}
	delSourceArray := [][]ldarp.LocInfo{array1, array2} // 登録したノード番号をarraysの変数に纏める
	//delSourceArray = [][]ldarp.LocInfo{}

	// arrays変数への挿入
	//for _, arr := range arrays {
	//	delSourceArray = append(delSourceArray, arr)
	//}

	// fmt.Println(delSourceArray)

	path, dist := getDijkstraPath(db, a_Point, b_Point, delSourceArray)

	fmt.Println("path:", path)
	fmt.Println("dist:", dist)

}

// 江端再修正版(2023/09/29)
/*
出発ノードと到着ノードと、通過したくないノード(無効したいノード)を登録して、ダイクストラ計算によるルートを選ぶ
*/

func getDijkstraPath(dbMap *sql.DB, locInfoStart, locInfoGoal ldarp.LocInfo, delSourceArray [][]ldarp.LocInfo) ([]ldarp.LocInfo, float64) {
	log.Println("getDijkstraPath", locInfoStart, locInfoGoal)

	sql_str := "" // SQL文を作る文字列の初期値

	// delSourceArray の解析
	fmt.Println("delSourceArray:", delSourceArray)

	if len(delSourceArray) != 0 { // delSourceArrayに要素が入っていれば

		// forとrangeを使用して各要素のSource値を取得
		sql_str = "WHERE "

		for _, arr := range delSourceArray {
			/*
				for _, loc := range arr {
					fmt.Printf("Sourceの値: %d\n", loc.Source)
				}
			*/
			fmt.Println(arr[0].Source, arr[1].Source)
			//str += "( source NOT BETWEEN " + arr[0].Source + " AND " + arr[1].Source + " AND target NOT BETWEEN " + arr[0].Source + " AND " + arr[1].Source + ")"
			sql_str += "(source NOT BETWEEN " + strconv.Itoa(arr[0].Source) + " AND " + strconv.Itoa(arr[1].Source) + " AND target NOT BETWEEN " + strconv.Itoa(arr[0].Source) + " AND " + strconv.Itoa(arr[1].Source) + ") AND "
			//fmt.Println(str)
		}
		strlen := len(sql_str)
		sql_str = sql_str[:strlen-5] // ラストの" AND "の5文字を削除する
		//fmt.Println(str)
	}

	sql_str = "SELECT seq,source, target, x1, y1, x2, y2, agg_cost FROM pgr_dijkstra('SELECT gid as id, source, target, cost, reverse_cost FROM ways " + sql_str + "', $1::bigint , $2::bigint , directed:=false ) a INNER JOIN ways b ON (a.edge = b.gid) ORDER BY seq"

	//fmt.Println(sql_str)

	var path []ldarp.LocInfo // 経路 (返り値の一つ目)
	var totalDistanceKm float64

	rowsDijkstra, errDijkstra := dbMap.Query(
		//"SELECT seq,source, target, x1, y1, x2, y2, agg_cost FROM pgr_dijkstra('SELECT gid as id, source, target, length_m as cost FROM ways', $1::bigint , $2::bigint , directed:=false ) a INNER JOIN ways b ON (a.edge = b.gid) ORDER BY seq",
		//"SELECT seq,source, target, x1, y1, x2, y2, agg_cost FROM pgr_dijkstra('SELECT gid as id, source, target, length_m as cost FROM ways WHERE (source NOT BETWEEN 10 AND 20 AND target NOT BETWEEN 10 AND 20) AND (source NOT BETWEEN 30 AND 40 AND target NOT BETWEEN 30 AND 40)', $1::bigint , $2::bigint , directed:=false ) a INNER JOIN ways b ON (a.edge = b.gid) ORDER BY seq",
		sql_str,
		locInfoStart.Source,
		locInfoGoal.Source)

	if errDijkstra != nil {
		log.Fatal(errDijkstra)
	}
	defer rowsDijkstra.Close()

	var agg_cost float64

	var loc ldarp.LocInfo
	var x1, y1, x2, y2 float64
	var seq int
	var target int
	var source int

	isFirstCheck := true
	isSourceCheck := true

	for rowsDijkstra.Next() {

		// まずnodeを読む
		if err := rowsDijkstra.Scan(&seq, &source, &target, &x1, &y1, &x2, &y2, &agg_cost); err != nil {
			fmt.Println(err)
		}

		// 最初の1回だけチェックのために入る これについては、https://wp.kobore.net/江端さんの技術メモ/post-7668/を参照のこと
		// もし rowsDijkstra.Scanで最初のsource値を読みとり、locInfoStart.Source の値と同じであれば、x1,y1をベースとして、異なる値であれば、x2,y2をベースとする

		if isFirstCheck {
			if source == locInfoStart.Source {
				isSourceCheck = true // x1, y1をベースとする処理になる
			} else {
				isSourceCheck = false // x2,y2をベースとする処理になる
			}
			isFirstCheck = false // 最初の1回をチェックすることで、2回目はこのループには入らなくなる
		}

		//var loc ldarp.LocInfo

		if isSourceCheck { // x1, y1をベースとする処理
			loc.Source = source
			loc.Lon = x1
			loc.Lat = y1
		} else { // x2,y2をベースとする処理
			loc.Source = target
			loc.Lon = x2
			loc.Lat = y2
		}
		path = append(path, loc)
	}

	// ラストノードだけはsourceとtargetを引っくり返す
	if isSourceCheck { // x1, y1をベースとする処理
		loc.Source = target
		loc.Lon = x2
		loc.Lat = y2
	} else { // x2,y2をベースとする処理
		loc.Source = source
		loc.Lon = x1
		loc.Lat = y1
	}

	path = append(path, loc)

	totalDistanceKm = agg_cost / 1000.0
	return path, totalDistanceKm
}

2023,江端さんの技術メモ

C:\Users\ebata\tomioka3B\src\others\main21.goでバトル中 

tomioka_db_c=# SELECT seq, node, edge, source, target, b.cost FROM pgr_dijkstra('SELECT gid as id, source, target, cost, reverse_cost FROM ways WHERE (source NOT BETWEEN 10 AND 20 AND target NOT BETWEEN 10 AND 20) AND (source NOT BETWEEN 30 AND 40 AND target NOT BETWEEN 30 AND 40)',1, 50, directed := false) a INNER JOIN ways b ON (a.edge = b.gid) ORDER BY seq;

seq | node | edge | source | target | cost
-----+------+------+--------+--------+------------------------
1 | 1 | 2 | 1 | 2 | 8.518550262944415e-05
2 | 2 | 3 | 2 | 3 | 0.0009420518456308501
3 | 3 | 4 | 3 | 4 | 0.00026662995399998605
4 | 4 | 5 | 4 | 5 | 0.00021389117484400878
5 | 5 | 6 | 5 | 6 | 4.656362881781325e-05
6 | 6 | 7 | 6 | 7 | 0.00013184236987589488
7 | 7 | 8 | 7 | 8 | 6.438782425766514e-05
8 | 8 | 1254 | 8 | 897 | 1.2290752319372595e-05
9 | 897 | 1380 | 897 | 969 | 0.00038637624148597305
10 | 969 | 1938 | 969 | 1389 | 2.250777644883257e-05
11 | 1389 | 694 | 1389 | 542 | 0.0002978010745492113
12 | 542 | 1251 | 542 | 895 | 0.00015951582993150323
13 | 895 | 1815 | 895 | 1305 | 0.0001303909506021454
14 | 1305 | 1021 | 1305 | 753 | 3.9356066874244885e-05
15 | 753 | 1381 | 753 | 971 | 0.0002850072862639029
16 | 971 | 1382 | 976 | 971 | 0.001276712172995213
17 | 976 | 1388 | 977 | 976 | 0.0004267486614026622
18 | 977 | 1389 | 986 | 977 | 0.0006757336753520132
19 | 986 | 1404 | 906 | 986 | 0.0003707891314505199
20 | 906 | 1275 | 906 | 907 | 0.0001959266189093194
21 | 907 | 1277 | 907 | 908 | 9.052734394018332e-05
22 | 908 | 1921 | 908 | 1376 | 5.400925846418281e-05
23 | 1376 | 1279 | 1376 | 909 | 1.8504323815069496e-05
24 | 909 | 1057 | 909 | 773 | 6.840328939622445e-05
25 | 773 | 1069 | 773 | 781 | 0.000535513050350553
26 | 781 | 1071 | 781 | 784 | 0.00014276168953525706
27 | 784 | 1087 | 784 | 793 | 0.0004430493335842619
28 | 793 | 1682 | 793 | 1192 | 7.9895243915049e-05
29 | 1192 | 1111 | 1192 | 808 | 0.0005876979547862221
30 | 808 | 1125 | 808 | 816 | 0.00047564125136792903
31 | 816 | 51 | 816 | 49 | 3.10328360877585e-05
32 | 49 | 52 | 49 | 50 | 0.00028187114581170033

一応、QGISで調べて、ノード切れが発生していないことは確認しました。


新規に作ったノード182~413を、ちゃんと無視できるかの実験。ベースは以下のメモの内容。

pgr_dijkstra()で、ダイクストラの順番を壊さずにルートの座標を得る方法(getDijkstraPath())

■無視前

tomioka_db_c=# SELECT seq, source, target, x1, y1, x2, y2 FROM pgr_dijkstra('SELECT gid as id, source, target, cost, reverse_cost FROM ways',1036, 1320, directed := false) a INNER JOIN ways b ON (a.edge = b.gid) ORDER BY seq;
seq | source | target | x1 | y1 | x2 | y2
-----+--------+--------+-----------------+----------------+-----------------+----------------
1 | 1036 | 182 | 139.6295688 | 35.3660511 | 139.62956342765 | 35.36605302299
2 | 182 | 183 | 139.62956342765 | 35.36605302299 | 139.62952386387 | 35.36602637499
3 | 183 | 184 | 139.62952386387 | 35.36602637499 | 139.62949515388 | 35.36599335049
4 | 184 | 185 | 139.62949515388 | 35.36599335049 | 139.62949783814 | 35.3658805722
5 | 185 | 186 | 139.62949783814 | 35.3658805722 | 139.629505074 | 35.36583679324
6 | 186 | 187 | 139.629505074 | 35.36583679324 | 139.62955514143 | 35.36580196041
7 | 187 | 188 | 139.62955514143 | 35.36580196041 | 139.62972133265 | 35.36574533322
8 | 188 | 189 | 139.62972133265 | 35.36574533322 | 139.62969285571 | 35.3656615823
9 | 189 | 190 | 139.62969285571 | 35.3656615823 | 139.62929978548 | 35.36461811112
10 | 190 | 191 | 139.62929978548 | 35.36461811112 | 139.62923349573 | 35.3644776355
11 | 191 | 192 | 139.62923349573 | 35.3644776355 | 139.62887730502 | 35.36401128513
12 | 192 | 193 | 139.62887730502 | 35.36401128513 | 139.62881288258 | 35.36394808968
13 | 193 | 194 | 139.62881288258 | 35.36394808968 | 139.62878113819 | 35.36393552673
14 | 194 | 195 | 139.62878113819 | 35.36393552673 | 139.62874285819 | 35.36391763403
15 | 195 | 196 | 139.62874285819 | 35.36391763403 | 139.62711549003 | 35.36370406459
16 | 196 | 1320 | 139.62711549003 | 35.36370406459 | 139.6270944 | 35.3636816
(16 rows)

■無視後

tomioka_db_c=# SELECT seq, source, target, x1, y1, x2, y2 FROM pgr_dijkstra('SELECT gid as id, source, target, cost, reverse_cost FROM ways WHERE (source NOT BETWEEN 182 AND 413 AND target NOT BETWEEN 182 AND 413) AND (source NOT BETWEEN 182 AND 413 AND target NOT BETWEEN 182 AND 413)',1036, 1320, directed := false) a INNER JOIN ways b ON (a.edge = b.gid) ORDER BY seq;
seq | source | target | x1 | y1 | x2 | y2
-----+--------+--------+-------------+------------+-------------+------------
1 | 1034 | 1036 | 139.6297237 | 35.365746 | 139.6295688 | 35.3660511
2 | 1034 | 1033 | 139.6297237 | 35.365746 | 139.6297007 | 35.3656671
3 | 1033 | 1325 | 139.6297007 | 35.3656671 | 139.6287884 | 35.3639297
4 | 1325 | 1320 | 139.6287884 | 35.3639297 | 139.6270944 | 35.3636816

うん、これを見ている限りは、大丈夫そうに見える。

 

2023,江端さんの技術メモ

■通常のバスルートを作ったが、表示ノードが停留所のみとなり、シミュレータが不自然になる問題の解決法
   → 強制的にタグを付ける

mapconfig_for_cars_rail_cart_bus.xml

の変更も忘れないこと。

Keyword : osm, tag, node, ダイクストラ、

 

2023,江端さんの技術メモ

QGISでノード番号のある場所を見つける方法が分からなくて困っていましたが、ようやく方法を見つけましたので、メモを残します。

この場合、180以下のノード番号が表示されていますが、特定の番号を指定したければ、(例えば、id=3)と入力すれば、そのノードだけが表示されます。

以上

2023,江端さんの技術メモ

SELECT seq, node, edge, b.cost
FROM pgr_dijkstra(
    'SELECT gid as id, source, target, cost, reverse_cost FROM ways WHERE source NOT BETWEEN 10 AND 20 AND target NOT BETWEEN 10 AND 20',
    1, 50, directed := false
) a
INNER JOIN ways b ON (a.edge = b.gid)
ORDER BY seq;

出力結果
seq | node | edge | cost
-----+------+------+------------------------
1 | 1 | 2 | 8.518550262944416e-06
2 | 2 | 3 | 9.420518456308501e-05
3 | 3 | 4 | 2.6662995399998606e-05
4 | 4 | 6 | 2.1389117484400878e-05
5 | 5 | 7 | 4.6563628817813256e-06
6 | 6 | 1313 | 7.188606587820858e-06
7 | 863 | 126 | 1.0007051975223507e-05
8 | 99 | 127 | 1.450451593740212e-05
9 | 100 | 129 | 7.160567611289415e-06
10 | 101 | 131 | 4.109420419283505e-05
11 | 102 | 133 | 2.934679929904221e-05
12 | 103 | 135 | 1.5514200871555155e-05
13 | 104 | 137 | 1.2955240951715268e-05
14 | 105 | 139 | 3.932409601088787e-05
15 | 106 | 141 | 3.756326743314803e-05
16 | 107 | 143 | 6.437495269868342e-05
17 | 108 | 145 | 3.580138401404371e-05
18 | 109 | 147 | 5.81727588604755e-05
19 | 110 | 148 | 4.310761927462597e-05
20 | 651 | 1196 | 0.00021148735186994806
21 | 780 | 995 | 0.00017553851429442523
22 | 653 | 997 | 5.381635439655622e-05
23 | 654 | 996 | 3.9727662820583996e-05
24 | 21 | 24 | 6.931684268013142e-06
25 | 22 | 25 | 7.70969814835397e-06
26 | 23 | 26 | 1.2029326750062135e-05
27 | 24 | 27 | 3.163056561909417e-05
28 | 25 | 28 | 3.715561627508799e-05
29 | 26 | 29 | 1.6759949788587843e-05
30 | 27 | 30 | 1.3935943447597369e-05
31 | 28 | 31 | 7.276956035534738e-06
32 | 29 | 32 | 1.2096545992840006e-05
33 | 30 | 33 | 4.534133154905821e-05
34 | 31 | 34 | 1.8836761764769703e-05
35 | 32 | 35 | 8.806681794688408e-06
36 | 33 | 36 | 7.526055852520615e-06
37 | 34 | 37 | 1.0243676427727028e-05
38 | 35 | 38 | 1.5622874238716658e-05
39 | 36 | 39 | 6.894091782961944e-06
40 | 37 | 40 | 1.786596350373829e-05
41 | 38 | 41 | 1.796453895498639e-05
42 | 39 | 42 | 6.566793603978039e-05
43 | 40 | 43 | 4.0144224056584715e-05
44 | 41 | 44 | 2.037304658526977e-05
45 | 42 | 45 | 1.643518634972223e-05
46 | 43 | 46 | 1.1916705412252495e-05
47 | 44 | 47 | 1.0031152210412222e-05
48 | 45 | 48 | 1.1949163674231717e-05
49 | 46 | 49 | 1.7529822253810993e-05
50 | 47 | 50 | 1.9115799546536715e-05
51 | 48 | 51 | 5.101757589403705e-05
52 | 49 | 53 | 2.8187114581170035e-05

2023,江端さんの技術メモ

送信プログラム(send_data.c):

#include <stdio.h>
#include <stdint.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>

int main() {
    int sockfd;
    struct sockaddr_in server_addr;
    uint32_t data = 0x12345678; // 4バイトのデータ(0x12345678)

    // ソケットの作成
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
        perror("socket");
        return 1;
    }

    // 送信先サーバの情報を設定
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(12345); // 送信先ポート番号
    server_addr.sin_addr.s_addr = INADDR_LOOPBACK; // ループバックアドレス (127.0.0.1)
    # INADDR_LOOPBACK で動かなければ、INADDR_ANY を使う

    // データを送信
    if (sendto(sockfd, &data, sizeof(uint32_t), 0, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
        perror("sendto");
        close(sockfd);
        return 1;
    }

    printf("Data sent: 0x%X\n", data);

    close(sockfd);

    return 0;
}

受信プログラム(receive_data.c):

#include <stdio.h>
#include <stdint.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>

int main() {
    int sockfd;
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    socklen_t client_addr_size = sizeof(client_addr);
    uint32_t received_data;

    // ソケットの作成
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
        perror("socket");
        return 1;
    }

    // サーバの情報を設定
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(12345); // 受信ポート番号
    server_addr.sin_addr.s_addr = INADDR_ANY;

    // ソケットとポートを結びつける
    if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
        perror("bind");
        close(sockfd);
        return 1;
    }

    printf("UDP Server is waiting for messages...\n");

    while (1) {
        // データを受信
        if (recvfrom(sockfd, &received_data, sizeof(uint32_t), 0, (struct sockaddr *)&client_addr, &client_addr_size) == -1) {
            perror("recvfrom");
            close(sockfd);
            return 1;
        }

        printf("Received Data: 0x%X\n", received_data);
    }

    close(sockfd);

    return 0;
}

2023,江端さんの技術メモ

■ダイクストラ計算を使った方法(一般的なやりかた)
tomioka_db_b=# SELECT seq, node, edge, b.cost FROM pgr_dijkstra('SELECT gid as id, source, target, cost, reverse_cost FROM ways',1, 11) a INNER JOIN ways b ON (a.edge = b.gid) ORDER BY seq;
seq | node | edge | cost
-----+------+------+------------------------
1 | 1 | 2 | 8.518550262944416e-06
2 | 2 | 3 | 9.420518456308501e-05
3 | 3 | 4 | 2.6662995399998606e-05
4 | 4 | 6 | 2.1389117484400878e-05
5 | 5 | 7 | 4.6563628817813256e-06
6 | 6 | 8 | 1.3184236987589488e-05
7 | 7 | 9 | 6.438782425766514e-06
8 | 8 | 10 | 3.92599380897713e-05
9 | 9 | 11 | 3.1320245670872654e-05
10 | 10 | 12 | 1.7193010226696205e-05

■ところが、こうすると、2番目の最短距離が算出できます。

tomioka_db_b=# SELECT seq, node, edge, b.cost FROM pgr_ksp('SELECT gid as id, source, target, cost, reverse_cost FROM ways',1, 11, 2) a INNER JOIN ways b ON (a.edge = b.gid) ORDER BY seq;
seq | node | edge | cost
-----+------+------+------------------------
1 | 1 | 2 | 8.518550262944416e-06
2 | 2 | 3 | 9.420518456308501e-05
3 | 3 | 4 | 2.6662995399998606e-05
4 | 4 | 6 | 2.1389117484400878e-05
5 | 5 | 7 | 4.6563628817813256e-06
6 | 6 | 8 | 1.3184236987589488e-05
7 | 7 | 9 | 6.438782425766514e-06
8 | 8 | 10 | 3.92599380897713e-05
9 | 9 | 11 | 3.1320245670872654e-05
10 | 10 | 12 | 1.7193010226696205e-05
12 | 1 | 2 | 8.518550262944416e-06
13 | 2 | 1214 | 7.368115779153013e-06
14 | 792 | 118 | 8.976775615866592e-06
15 | 95 | 119 | 9.423341104506603e-05
16 | 96 | 121 | 2.578196166482512e-05
17 | 97 | 123 | 2.35136729002621e-05
18 | 98 | 125 | 6.587696385101331e-06
19 | 99 | 126 | 1.0007051975223507e-05
20 | 863 | 1313 | 7.188606587820858e-06
21 | 6 | 8 | 1.3184236987589488e-05
22 | 7 | 9 | 6.438782425766514e-06
23 | 8 | 10 | 3.92599380897713e-05
24 | 9 | 11 | 3.1320245670872654e-05
25 | 10 | 12 | 1.7193010226696205e-05

10番目までを出したかったら、上記の"2"を、"10"にすれば出てきます。
綺麗に直す方法については、がんばって下さい。

 

 

 

2023,江端さんの忘備録

メンタルヘルスに対する研究や理解は、日々進んでいると思います。

I believe that research and understanding of mental health is advancing every day.

もちろん、まだまだ十分ではないことは分かっています。

Of course, I know that it is still not enough.

メンタル疾患が誰にでも簡単に発生することは、「自分」で理解しています。

I understand that mental illness can quickly occur in anyone.

加えて、私は、メンタル疾患の被害者でもありますが、加害者でもあったという自覚もあります。

In addition, I am aware that I have been both a victim and a perpetrator of mental illness.

私なら、『今でも報復を諦めていない』くらいのことは言うと思う。

現在のメンタルヘルス研究は、『加害者としての自己』という観点がスッポリ抜けているような気がします。

I feel that current mental health research is missing the perspective of 'self as perpetrator.'

-----

私、最近、

I recently, want someone to try

―― 歴史上の人物(特に日本史)における、特に戦国武将のメンタル疾患についての研究

"Research on mental illness in historical figures (especially Japanese history), especially warlords of the Warring States period"

を、誰かにやってもらいたいと思っています。

一応、Google Scholarで調べてみたのですが、ドンピシャと思われる研究論文は見つけられませんでした。

In the meantime, I checked Google Scholar but could not find any research papers that seemed to be downloadable.

-----

YouTubeで、大河ドラマのビデオクリップを見ているのですが、戦国武将の日常は、殺戮と裏切りと身内の粛清のオンパレードです。

I have been watching video clips of the Taiga drama on YouTube, and the daily life of the warlords was a parade of carnage, betrayal, and purges of their team.

そんな状態で、「武士道」だの「武人の誉れ」などと、綺麗ごとを言えるメンタルが、全然理解できません。

In such a state, I cannot understand the mentality of having said beautiful words such as "bushido" and "honor of the warrior."

ダブルスタンダードもいいところです。

That was typical double standards.

戦国武将は、多重人格障害をデフォルトで持っているとしか思えないです。

I can only assume that warlords have dissociative identity disorder by default.

私は、日本でもっとも著名な戦国武将について『双極性障害』であったと決めつけていますが、他の戦国武将はどうだったのかなぁ、と興味があります。

I have determined that the most famous warlord in Japan was "bipolar," but I am curious to know what other warlords were like.

―― 何やってんだろうなあ、桶狭間合戦場跡は

-----

限られた歴史文献だけを使って、戦国武将たちのメンタルを推定する、というのは、相当難しい研究だとは思います。

I think it is quite a problematic study to estimate the mentality of warlords using only limited historical documents.

しかし、その研究は、現在の私たちのメンタル疾患の治療法に寄与する、と思っています。

However, I believe the research contributes to treating our mental illnesses.

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