2023,江端さんの技術メモ

keyword: postgres postgis st_geomfromtext ST_Covers POLYGON LINESTRING

早い話、

postgres=# \c yama_db
psql (13.4, server 12.5 (Debian 12.5-1.pgdg100+1))
You are now connected to database "yama_db" as user "postgres".

yama_db=# SELECT ST_Covers(st_geomfromtext('POLYGON((34.15131035 131.5194525, 34.16270729 131.5152409, 34.16516798 131.5115994, 34.16898442 131.5047413, 34.17907707 131.5010998, 34.18354557 131.4989149, 34.18561453 131.5025188, 34.18856404 131.5058416, 34.18909138 131.5050188, 34.19687848 131.5103978, 34.19927298 131.5072766, 34.20121465 131.510747, 34.20300086 131.5120785, 34.20536452 131.5096798, 34.20975399 131.5068729, 34.20709501 131.5009018, 34.20388724 131.5048315, 34.20194564 131.5047294, 34.19785124 131.4988093, 34.20194564 131.4969721, 34.20528011 131.4932975, 34.20114366 131.4948286, 34.19802009 131.4962576, 34.19894873 131.4931955, 34.19705211 131.4916877, 34.19973769 131.4886834, 34.19579714 131.490747, 34.19717761 131.4888048, 34.19802009 131.4962576, 34.20061613 131.483555, 34.19383935 131.482506, 34.19306821 131.4800321, 34.18962489 131.4802896, 34.20041552 131.4735871, 34.19870882 131.4691668, 34.19193378 131.4719122, 34.19281714 131.4631425, 34.18750372 131.4649829, 34.18208468 131.4692086, 34.17814677 131.4619382, 34.18089338 131.4606752, 34.18352048 131.465583, 34.18537135 131.4575717, 34.18358019 131.4532773, 34.17689286 131.4597008, 34.17568909 131.4574644, 34.17805351 131.453254, 34.18115671 131.4490436, 34.18094562 131.4462621, 34.17766341 131.4457491, 34.17637565 131.444856, 34.17452943 131.4472807, 34.17400259 131.4457099, 34.1745741 131.4435783, 34.17591761 131.4391215, 34.17349927 131.4370465, 34.171469 131.4367036, 34.17997306 131.4313284, 34.17831615 131.4270193, 34.16993073 131.4276566, 34.17045141 131.4197235, 34.16662955 131.4242344, 34.17054098 131.4093664, 34.16585321 131.4150321, 34.16292695 131.4256418, 34.16209086 131.4305497, 34.15853738 131.4324262, 34.1555247 131.431539, 34.1368104 131.4231705, 34.13155312 131.4262604, 34.13252285 131.4303061, 34.12981919 131.4361751, 34.12994592 131.4412276, 34.13256509 131.4488319, 34.13167796 131.4539864, 34.13486474 131.4591635, 34.13933143 131.4660729, 34.14099198 131.4710403, 34.14447279 131.4734114, 34.14677254 131.4766944, 34.14983145 131.488296, 34.14860698 131.5025144, 34.15034783 131.5173554, 34.15131035 131.5194525))'),st_geomfromtext('LINESTRING(34.17282136235268 131.4810495539796, 34.17234106467595 131.47746432882846)'));

というSQL文をGoプログラムで作る。

(1)csvファイル(84点)からなる領域を作っておいて、エリアデータ
(2)ODデータを直線として取り込み、直線データ
(3)上記(2)の直線が、上記(1)の領域に入っているかどうかを調べて、入っている場合は標準出力で出力する


// ~/yamaguchi/src_try1/others/main6.go

package main

import (
	"database/sql"
	"encoding/csv"
	"fmt"
	"log"
	"os"

	_ "github.com/lib/pq"
)

func main() {
	file, err := os.Open("yamaguchi_area.csv")
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()

	r := csv.NewReader(file)
	rows, err := r.ReadAll() // csvを一度に全て読み込む
	if err != nil {
		log.Fatal(err)
	}

	str := "SELECT ST_Covers(st_geomfromtext('POLYGON(("

	// 行ごとに
	for i, row := range rows {
		if i == 0 {
			continue // CSVのヘッダー行を無視
		}

		str += row[1] + " " + row[2] + ", " // rowのままで取り出せば、文字列になっている

	}
	str1 := str[:len(str)-2] + "))'),st_geomfromtext('LINESTRING(" // 上記の最後の", "を削除して、文字列を追加

	dbMap, err := sql.Open("postgres",
		"user=postgres password=password host=192.168.0.23 port=15432 dbname=yama_db sslmode=disable")
	// log.Println("------------------ map db open ------------------")
	if err != nil {
		log.Fatal("OpenError: ", err)
	}
	defer dbMap.Close()

	///////////////////////////////////////

	file2, err2 := os.Open("20220518weekday.csv")
	if err2 != nil {
		log.Fatal(err2)
	}
	defer file2.Close()

	r2 := csv.NewReader(file2)
	rows2, err2 := r2.ReadAll() // csvを一度に全て読み込む
	if err != nil {
		log.Fatal(err2)
	}

	for _, row := range rows2 {
		//if i == 0 {
		//	continue // CSVのヘッダー行を無視
		//}

		str2 := str1 + row[0] + " " + row[1] + ", " + row[2] + " " + row[3]

		str2 += ")'))"

		//fmt.Println(str2)

		rows1, err := dbMap.Query(str2)
		if err != nil {
			log.Fatal(err)
		}
		defer rows1.Close()

		//var dt string
		var dt bool

		for rows1.Next() {
			if err := rows1.Scan(&dt); err != nil {
				fmt.Println(err)
			}
			// fmt.Println(dt)
			if dt {
				output := row[0] + "," + row[1] + "," + row[2] + "," + row[3] + "," + row[4]
				fmt.Println(output)
			}

		}

	}
}

2023,江端さんの技術メモ

まずGISのDBにアクセスしておきます(必要なのかどうかは不明です)。

C:\Users\ebata>psql -U postgres -h 192.168.0.23 -p 15432
Password for user postgres:
psql (13.4, server 12.5 (Debian 12.5-1.pgdg100+1))
Type "help" for help.
postgres=# \c kitaya_db
psql (13.4, server 12.5 (Debian 12.5-1.pgdg100+1))
You are now connected to database "kitaya_db" as user "postgres".
(1)領域の中に領域が含まれている場合です。

kitaya_db=# SELECT ST_Covers(st_geomfromtext('POLYGON((35.66776966314929 139.6895046225338,35.657947599160494 139.69091202947678,35.65865130959591 139.70318173103095,35.66885441403114 139.70307346895845,35.66776966314929 139.6895046225338))'), st_geomfromtext('POLYGON((35.66527761205352 139.6953146870933,35.66246296668681 139.69387119279278,35.66316663733071 139.70036691714503,35.66527761205352 139.6953146870933))'));
st_covers
-----------
t
(1 row)

(2)領域の中に領域が含まれていない場合です。

kitaya_db=# SELECT ST_Covers(st_geomfromtext('POLYGON((35.66776966314929 139.6895046225338,35.657947599160494 139.69091202947678,35.65865130959591 139.70318173103095,35.66885441403114 139.70307346895845,35.66776966314929 139.6895046225338))'), st_geomfromtext('POLYGON((35.66527761205352 139.6953146870933,35.66246296668681 139.69387119279278, 35.662818 139.7050018, 35.66527761205352 139.6953146870933))'));
st_covers
-----------
f
(1 row)

(3)領域の中に点が入っている場合です。

kitaya_db=# SELECT ST_Covers(st_geomfromtext('POLYGON((35.66776966314929 139.6895046225338,35.657947599160494 139.69091202947678,35.65865130959591 139.70318173103095,35.66885441403114 139.70307346895845,35.66776966314929 139.6895046225338))'), st_geomfromtext('POINT(35.66527761205352 139.6953146870933)'));
st_covers
-----------
t
(1 row)

(4)領域の中に点が入っていない場合です。

kitaya_db=# SELECT ST_Covers(st_geomfromtext('POLYGON((35.66776966314929 139.6895046225338,35.657947599160494 139.69091202947678,35.65865130959591 139.70318173103095,35.66885441403114 139.70307346895845,35.66776966314929 139.6895046225338))'), st_geomfromtext('POINT(35.662818 139.7050018)'));
st_covers
-----------
f
(1 row)

以上

 

2023,江端さんの忘備録

経済産業省出身の秘書官(55)が、3日夜、性的少数者(LGBTなど)や同性婚に関し「見るのも嫌だ。隣に住んでいたらやっぱり嫌だ」と、述べたそうです。

A secretary (55) from the Ministry of Economy, Trade, and Industry (METI) said on the evening of March 3, "I don't even want to look at sexual minorities (LGBT, etc.) and same-sex marriagem", and "I would also hate it if I lived next door".

―― またか

"Not again"

と思いました。

I thought that.

-----

2つあります。

There are two issues.

(1)性的少数者(LGBTなど)や同性婚を、そのようなことに慣れてこなかった私たちジジイやババアが理解するのは難しいです。

(1) It is difficult for us old geezers and old ladies to understand sexual minorities (e.g. LGBT) and same-sex marriage, as we have not been used to such things.

だから、感覚で理解できないのであれば、ニュース、ドキュメンタリー、コンテンツ(マンガから論文に至るまで)から知識を得て、理解するしかないのです。

So if you can't understand it by feel, then you have to gain knowledge and understanding from news, documentaries, and content (ranging from comics to papers).

■「高齢者を組織のトップから、ナチュラルに排除」する技術

長い時間をかけて、少しずつでも勉強し続けることで、自分のもっている感性(「偏見」を含む)を変えていくことはできます。

Over a long period of time, by continuing to study, even gradually, you can change the sensibilities (including "prejudices") that you have.

私(江端)は「できた」と思います(この件に関してだけですが)。

I (Ebata) think I did it (only in this case).

逆にいえば、それをやらずに、自分の感性に固執しつづける人間は ―― 勉強をしていないのです。

Conversely, those who don't do it and continue to cling to their own sensibilities -- they are not studying.

-----

私は、誰もが、辛い勉強をしなければならないとは思っていません。

I do not believe that anyone should have to learn the hard way.

が、

However,

―― 日本国総理大臣の秘書官

"Secretary to the Prime Minister of Japan"

は、不断の勉強を続けなけばならない人間の一人だと思っています。

is one of those who must continue to study tirelessly.

故に、彼が「無知」で居続けたことは「罪」です。

Hence, his continued "ignorance" is "harmful".

-----

(2)"オフレコ"を前提として自分の考えを語ってしまったようですが、正直『脇が甘いなぁ』と思いました。

(2) He spoke his mind on the premise of "off the record," but to be honest, I thought he was a bit naive.

一サラリーマンに過ぎない私ですら、「オフレコ」なんぞ信じていません。

Even I, a just businessman, do not believe in "off the record".

例えば、会社で実施されるアンケートには、本当のことは書きません。

For example, we do not write the truth in questionnaires conducted by the company.

一例ですが、JMI(心の定期健康診断)では、『宇宙から声が聞こえる』という質問に、毎回「はい」と答えています。

As an example, at JMI (periodic mental health checkup), I answer 'yes' to the question 'I can hear voices from the universe' every time.

JMI(心の定期健康診断)

今年もやってきました。私の神経を逆撫でする、あの"JMI"が。

ましてや、会社の方針の批判なんぞ、論外です ―― まあ、会社の方針は、比較的、私には納得できるものが多くて助かっていますが。

Criticism of company policy is out of the question -- well, I'm glad to say that many of the company's policies are relatively acceptable to me.

----

『性的少数者(LGBTなど)や同性婚に関し「見るのも嫌だ。隣に住んでいたらやっぱり嫌だ」』という自分の思いを、(自分の勉強不足で)晒した点は、正直なところ

He was exposed to his own feelings of "I don't even like to look at them and I would still hate it if I lived next door", through my lack of study. To tell you the truth, I had to think,

―― "お坊ちゃん"だなぁ

"He was a little boy"

と思わずにはいられませんでした。

-----

『自分の仕える主人(例:首相)の主張に反することは、(どう考えていようが)口にしない』――

"I will not say anything that contradicts the claims of my master (e.g. the prime minister), no matter what I think"

これは、サラリーマンの金科玉条(きんかぎょくじょう)です。

This is the golden rule for businessmen.

2023,江端さんの技術メモ

宿題が出ました。

A Homework is coming .

交通量の少ない通り(200台/時程度)を信号のない場所から選ぶ。
1時間の間に車がある地点を通過する時刻を記録する。時刻は1秒か2秒の単位で 秒単位で記録する。
1. 時刻tまでに観測点を通過した車両の累積台数A(t)を描画する。図の横軸は時間 図の横軸は時間、縦軸はA(t)とする。
2. A(t)のうち、ほぼ線形(平均到着率が一定)の部分を選択する。この時間帯のカウント数から この時間帯のカウントから、1分間と5分間の連続したカウントのヒストグラムを作成する。そして、そのヒストグラムをポアソン分布と比較する。

Select a street with low traffic volume (about 200 cars/hour) from a location without a traffic light.
Record the time at which a car passes a certain point during a one-hour period. Record the time in seconds, in increments of 1 or 2 seconds.
Draw the cumulative number of vehicles A(t) that passed the observation point by time t. The horizontal axis of the figure is time, and the vertical axis is A(t). 2.
Select a portion of A(t) that is nearly linear (constant average arrival rate). From the counts during this time period. From the counts during this time period, create a histogram of consecutive counts for 1 minute and 5 minutes. The histogram is then compared to the Poisson distribution

Translated with www.DeepL.com/Translator (free version)

近日中に防寒着を着込んで、道路の近くで自動車の通過時刻をノートにメモすることになりそうです。
I will be putting on my winter clothes in the coming days and noting down in my notebook the time of passing cars near the road.

―― これをノートに記載するのは面倒くさいな
-- I can't be bothered to note this.

―― この手のアプリは絶対にあるはずだ
-- there should definitely be an app for this kind of thing.

と思ったのですが、iPad用のアプリが見つからず、しぶしぶ自分でJavaScriptを組み出しました。
But I could not find an app for the iPad, so I reluctantly put together my own JavaScript.

しかし、表示が上手くいかず、今度はiPadに限定せずに探し捲りました。
However, the display did not work, and this time I searched around without limiting myself to the iPad.

で、見つけたのがこれです。
This is what I found

時刻カウンター (タイムスタンプの記録ができるカウンター)
Time counters (counters that can record time stamps)

アイコン画像

Android端末専用でしたが、私の部屋にはSIMカードの入っていないスマホがゴロゴロしていますので、そのうちの一台にインストールしました。
It was for Android devices only, but I have a bunch of phones without SIM cards in my room, so I installed it on one of them.

2画面のイメージはこちらです(6画面までできるようです)
Here is an image of two screens (it seems to be possible to have up to 6 screens)

これで、左方向、右方向バラバラで台数計測できそうです。
This will allow me to measure the number of units in the left and right directions separately.

交通量を計測するので、計測時間は十分に短くないと困ります。
Since I am measuring traffic, the measurement time must be short enough.

ですので、[設定]→[再カウントまでの時間]を1000ms→10msに変更しました。
Therefore, I changed [Settings] -> [Time until recount] from 1000 ms to 10 ms.

[音をならす]、[振動させる]も解除しておきました。
I also deactivated [Make Sound] and [Vibrate].

で、計測結果をメールで自分のアドレスに送ってみました
And I emailed the measurement results to my address.

1,1,"カウンター1",2023-01-24 23:19:03,2023,1,24,23,19,3,0
2,2,"カウンター2",2023-01-24 23:19:06,2023,1,24,23,19,6,0
3,1,"カウンター1",2023-01-24 23:19:09,2023,1,24,23,19,9,0
4,1,"カウンター1",2023-01-24 23:19:12,2023,1,24,23,19,12,0
5,2,"カウンター2",2023-01-24 23:19:14,2023,1,24,23,19,14,0
6,1,"カウンター1",2023-01-24 23:19:19,2023,1,24,23,19,19,0
7,2,"カウンター2",2023-01-24 23:19:26,2023,1,24,23,19,26,0
8,2,"カウンター2",2023-01-24 23:19:28,2023,1,24,23,19,28,0
9,2,"カウンター2",2023-01-24 23:19:29,2023,1,24,23,19,29,0
10,1,"カウンター1",2023-01-24 23:19:31,2023,1,24,23,19,31,0

csv形式というのもいいです。加工しやすそうです。
I also like that it is in csv format. It seems to be easy to process.

これでフィールドワークはなんとかなりそうです。
So, I will able to do my homework.

 

2023,江端さんの技術メモ

出典を忘れてしまいましたが、どなたかが作られたコードを丸パクリさせて頂きました。→たぶん"これ"

ノード1 → "A", ノード2 → "B", ノード3 → "C", ノード4 → "D", ノード5 → "E" として取り扱います。

package main

import (
	"errors"
	"fmt"
)

// ノード
type Node struct {
	name  string  // ノード名
	edges []*Edge // 次に移動できるエッジ
	done  bool    // 処理済みかを表すフラグ
	cost  int     // このノードにたどり着くのに必要だったコスト
	prev  *Node   // このノードにたどりつくのに使われたノード
}

func NewNode(name string) *Node {
	node := &Node{name, []*Edge{}, false, -1, nil}
	return node
}

// ノードに次の接続先を示したエッジを追加する
func (self *Node) AddEdge(edge *Edge) {
	self.edges = append(self.edges, edge)
}

// エッジ
type Edge struct {
	next *Node // 次に移動できるノード
	cost int   // 移動にかかるコスト
}

func NewEdge(next *Node, cost int) *Edge {
	edge := &Edge{next, cost}
	return edge
}

// 有向グラフ
type DirectedGraph struct {
	nodes map[string]*Node
}

func NewDirectedGraph() *DirectedGraph {
	return &DirectedGraph{
		map[string]*Node{}}
}

// グラフの要素を追加する (接続元ノード名、接続先ノード名、移動にかかるコスト)
func (self *DirectedGraph) Add(src, dst string, cost int) {
	// ノードが既にある場合は追加しない
	srcNode, ok := self.nodes[src]
	if !ok {
		srcNode = NewNode(src)
		self.nodes[src] = srcNode
	}

	dstNode, ok := self.nodes[dst]
	if !ok {
		dstNode = NewNode(dst)
		self.nodes[dst] = dstNode
	}

	// ノードをエッジでつなぐ
	edge := NewEdge(dstNode, cost)
	srcNode.AddEdge(edge)
}

// スタートとゴールを指定して最短経路を求める
func (self *DirectedGraph) ShortestPath(start string, goal string) (ret []*Node, err error) {
	// 名前からスタート地点のノードを取得する
	startNode := self.nodes[start]

	// スタートのコストを 0 に設定することで処理対象にする
	startNode.cost = 0

	for {
		// 次の処理対象のノードを取得する
		node, err := self.nextNode()

		// 次に処理するノードが見つからなければ終了
		if err != nil {
			return nil, errors.New("Goal not found")
		}

		// ゴールまで到達した
		if node.name == goal {
			break
		}

		// 取得したノードを処理する
		self.calc(node)
	}

	// ゴールから逆順にスタートまでノードをたどっていく
	n := self.nodes[goal]
	for {
		ret = append(ret, n)
		if n.name == start {
			break
		}
		n = n.prev
	}

	return ret, nil
}

// つながっているノードのコストを計算する
func (self *DirectedGraph) calc(node *Node) {
	// ノードにつながっているエッジを取得する
	for _, edge := range node.edges {
		nextNode := edge.next

		// 既に処理済みのノードならスキップする
		if nextNode.done {
			continue
		}

		// このノードに到達するのに必要なコストを計算する
		cost := node.cost + edge.cost
		if nextNode.cost == -1 || cost < nextNode.cost {
			// 既に見つかっている経路よりもコストが小さければ処理中のノードを遷移元として記録する
			nextNode.cost = cost
			nextNode.prev = node
		}
	}

	// つながっているノードのコスト計算がおわったらこのノードは処理済みをマークする
	node.done = true
}

func (self *DirectedGraph) nextNode() (next *Node, err error) {
	// グラフに含まれるノードを線形探索する
	for _, node := range self.nodes {

		// 処理済みのノードは対象外
		if node.done {
			continue
		}

		// コストが初期値 (-1) になっているノードはまだそのノードまでの最短経路が判明していないので処理できない
		if node.cost == -1 {
			continue
		}

		// 最初に見つかったものは問答無用で次の処理対象の候補になる
		if next == nil {
			next = node
		}

		// 既に見つかったノードよりもコストの小さいものがあればそちらを先に処理しなければいけない
		if next.cost > node.cost {
			next = node
		}
	}

	// 次の処理対象となるノードが見つからなかったときはエラー
	if next == nil {
		return nil, errors.New("Untreated node not found")
	}

	return
}

func main() {
	// 有向グラフを作る
	g := NewDirectedGraph()

	// グラフを定義していく
	g.Add("A", "B", 2)
	g.Add("A", "C", 7)
	g.Add("A", "D", 5)

	g.Add("B", "D", 4)

	g.Add("C", "E", 2)

	g.Add("D", "C", 1)
	g.Add("D", "E", 4)

	g.Add("E", "C", 2)

	// "s" ノードから "z" ノードへの最短経路を得る
	path, err := g.ShortestPath("A", "E")

	// 経路が見つからなければ終了
	if err != nil {
		fmt.Println("Goal not found")
		return
	}

	// 見つかった経路からノードとコストを表示する
	for _, node := range path {
		fmt.Printf("ノード: %v, コスト: %v\n", node.name, node.cost)
	}
}

 

出力結果

C:\Users\ebata> go run .\dijkstra.go
ノード: E, コスト: 8
ノード: C, コスト: 6
ノード: D, コスト: 5
ノード: A, コスト: 0

ラベル修正法の練習(だけ)

2023,江端さんの技術メモ

「Golangでcsvファイルを読み出す」の記事は多いのですが、特定の行まで引っ張り出す情報があまりないので、メモを残しておきます。

/*
以下のcsvファイル(kai_20220522holyday18.csv)の中身を取り出す
id,age,type,departure_name,departure_number,departure_lat,departure_lng,arrival_name,arrival_number,arrival_lat,arrival_lng
0,43,resident,,,34.173408,131.470684,,,34.155862,131.501246
1,24,resident,,,34.179449,131.482543,,,34.164116,131.471791
2,42,resident,,,34.168739,131.470768,,,34.160989,131.491124
3,21,resident,,,34.169494,131.469934,,,34.173498,131.471351
4,58,resident,,,34.185295,131.47414,,,34.191481,131.49456
5,48,resident,,,34.150778,131.480747,,,34.16536,131.471872
6,56,resident,,,34.16536,131.471872,,,34.174066,131.479312
7,73,resident,,,34.155731,131.500845,,,34.16776,131.472831
8,47,resident,,,34.167237,131.471785,,,34.155775,131.476531
9,21,resident,,,34.154931,131.50468,,,34.156678,131.49581
10,37,resident,,,34.16727,131.472899,,,34.171253,131.471177
11,40,resident,,,34.147241,131.474921,,,34.150675,131.486268
12,67,resident,,,34.173683,131.476347,,,34.173643,131.471027
13,28,resident,,,34.183079,131.484303,,,34.174245,131.474592
14,46,resident,,,34.146154,131.472711,,,34.159611,131.491548
15,25,resident,,,34.162497,131.489283,,,34.147212,131.475984
*/

package main

import (
	"encoding/csv"
	"fmt"
	"log"
	"os"
	"strconv"
)

func main() {
	file, err := os.Open("kai_20220522holyday18.csv") // 先ほど入手した郵便番号データをos.Openで開く
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()

	r := csv.NewReader(file)
	rows, err := r.ReadAll() // csvを一度に全て読み込む
	if err != nil {
		log.Fatal(err)
	}

	// 行ごとに
	for i, row := range rows {
		if i == 0 {
			continue // CSVのヘッダー行を無視
		}

		age := row[1]

		departure_lat, err := strconv.ParseFloat(row[5], 64)
		if err != nil {
			log.Fatal(err)
		}
		departure_lng, err := strconv.ParseFloat(row[6], 64)
		if err != nil {
			log.Fatal(err)
		}

		arrival_lat, err := strconv.ParseFloat(row[9], 64)
		if err != nil {
			log.Fatal(err)
		}

		arrival_lng, err := strconv.ParseFloat(row[10], 64)
		if err != nil {
			log.Fatal(err)
		}

		fmt.Println(age, departure_lat, departure_lng, arrival_lat, arrival_lng)

	}
}

 

出力結果

C:\Users\ebata\yamaguchi\src_try1\others> go run main5.go
43 34.173408 131.470684 34.155862 131.501246
24 34.179449 131.482543 34.164116 131.471791
42 34.168739 131.470768 34.160989 131.491124
21 34.169494 131.469934 34.173498 131.471351
58 34.185295 131.47414 34.191481 131.49456
56 34.16536 131.471872 34.174066 131.479312
73 34.155731 131.500845 34.16776 131.472831
47 34.167237 131.471785 34.155775 131.476531
21 34.154931 131.50468 34.156678 131.49581
37 34.16727 131.472899 34.171253 131.471177
40 34.147241 131.474921 34.150675 131.486268
67 34.173683 131.476347 34.173643 131.471027
28 34.183079 131.484303 34.174245 131.474592
46 34.146154 131.472711 34.159611 131.491548
25 34.162497 131.489283 34.147212 131.475984

 

2023,江端さんの技術メモ

公共交通指向型開発(TOD: Transit Oriented Development) - 公共交通機関に基盤を置き、自動車に依存しない社会を目指した都市開発。
「交通隣接型開発」(TAD:‘transit-adjacent development’) 公共交通拠点と隣接して、高密度、大規模開発を行うが、機能上に、互い協調的な開発モードが不足である。

2023,江端さんの技術メモ

https://www.marble-lab.com/item_3412.html

を参考にさせていただき、自分用の手順書(マニュアル)を作成。

(Step 1) CSVファイルの作成
1行目に、各列の名前が入っていなければならない。
ファイルはこちら → test_user_list_14.csv

ファイルはこちら → test_user_list_14.csv

(Step 2) Google MAPの立ち上げ

(Step 3) Google MAPの立ち上げ

↓の赤丸をクリック

今は、こっちのインタフェースに、なっているようです。

(Step 4) 「マイプレイス」を選択

(Step 5) 「マイマップ」→「地図を作成」

(Step 6) 「インポート」を選択

(Step 7) ファイル(test_user_list_14.csv)をドラッグ

(Step 8) 緯度、経度を選択

(Step 9) マーカーのタイトルを選択

(Step 10) マーカーの色を変更する(→黒)

(Step 11) マーカーをクリックすると情報が表示される

以上

KeyWord: Google MAP、 マーカー、 アイコン、 csv, エクセル

2023,江端さんの技術メモ

PostgreSQLで、新規のデータならinsert, 書き換えならupdate をしようと思ったのですが、なんか面倒くさいので、初期テーブルを沢山作っておくことで対応することしました。

というか、そういうメソッドを準備しておいて欲しい→あるみたいですが、上手く動かせませんでした。

package main

import (
	"database/sql"
	"fmt"
	"log"

	_ "github.com/lib/pq" // ←これを追記
)

func main() {
	// user_log, bike_logへのアクセス
	dbAgent, err := sql.Open("postgres", "user=postgres password=password host=192.168.0.23 port=15432 dbname=agent_db sslmode=disable")
	if err != nil {
		log.Fatal("dbAgent OpenError: ", err)
	}
	defer dbAgent.Close()
	err = dbAgent.Ping()
	if err != nil {
		log.Fatal(err, "\nHint: dbAgent Database may not have started")
	}
	// user_logテーブルの内容の全削除
	dbAgent.Query("delete from bike_log;")

	// insertのテスト
	for i := 0; i < 10; i++ {
		str := fmt.Sprintf("insert into bike_log (stationid, num_bikes) values(%d, -1)", i)
		fmt.Println(str)
		dbAgent.Query(str)
	}

	// updateのテスト
	for i := 0; i < 10; i = i + 2 {
		str := fmt.Sprintf("update bike_log set num_bikes = %d where stationid = %d", i*2, i)
		fmt.Println(str)
		dbAgent.Query(str)
	}
}

出力結果

C:\Users\ebata\yamaguchi\src_try1\others> go run main4.go
insert into bike_log (stationid, num_bikes) values(0, -1)
insert into bike_log (stationid, num_bikes) values(1, -1)
insert into bike_log (stationid, num_bikes) values(2, -1)
insert into bike_log (stationid, num_bikes) values(3, -1)
insert into bike_log (stationid, num_bikes) values(4, -1)
insert into bike_log (stationid, num_bikes) values(5, -1)
insert into bike_log (stationid, num_bikes) values(6, -1)
insert into bike_log (stationid, num_bikes) values(7, -1)
insert into bike_log (stationid, num_bikes) values(8, -1)
insert into bike_log (stationid, num_bikes) values(9, -1)
update bike_log set num_bikes = 0 where stationid = 0
update bike_log set num_bikes = 4 where stationid = 2
update bike_log set num_bikes = 8 where stationid = 4
update bike_log set num_bikes = 12 where stationid = 6
update bike_log set num_bikes = 16 where stationid = 8

データベースの中身

agent_db=# select * from bike_log;
stationid | num_bikes
-----------+-----------
1 | -1
3 | -1
5 | -1
7 | -1
9 | -1
0 | 0
2 | 4
4 | 8
6 | 12
8 | 16
(10 rows)