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

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,江端さんの技術メモ

Posted by ebata