Add experimental tool for condensing POI.
This commit is contained in:
parent
6001479eaf
commit
3e68fd6f9a
1 changed files with 119 additions and 0 deletions
119
cmd/condense/main.go
Normal file
119
cmd/condense/main.go
Normal file
|
@ -0,0 +1,119 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/ray1729/gpx-utils/pkg/placenames"
|
||||
)
|
||||
|
||||
func main() {
|
||||
log.SetFlags(0)
|
||||
maxPOI := flag.Int("max-poi", 0, "Maximum number of points of interest")
|
||||
minDist := flag.Float64("min-dist", 0, "Minimum distance between points of interest")
|
||||
flag.Parse()
|
||||
if flag.NArg() != 1 {
|
||||
log.Fatalf("Usage: %s [--max-poi=N] ANALYSIS.json", os.Args[0])
|
||||
}
|
||||
summary, err := readTrackSummary(flag.Arg(0))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
poi := summary.PointsOfInterest
|
||||
if *minDist > 0 {
|
||||
poi = condenseMinDist(poi, *minDist)
|
||||
}
|
||||
if *maxPOI > 0 {
|
||||
poi = condenseMaxPoi(summary.PointsOfInterest, *maxPOI)
|
||||
}
|
||||
result := make([]string, len(poi))
|
||||
for i, x := range poi {
|
||||
result[i] = x.Name
|
||||
}
|
||||
fmt.Println(strings.Join(result, ", "))
|
||||
}
|
||||
|
||||
func readTrackSummary(filename string) (*placenames.TrackSummary, error) {
|
||||
log.Println("Reading summary from", filename)
|
||||
data, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var summary placenames.TrackSummary
|
||||
err = json.Unmarshal(data, &summary)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &summary, nil
|
||||
}
|
||||
|
||||
var locationTypePriority = map[string]int{
|
||||
"City": 5,
|
||||
"Town": 4,
|
||||
"Village": 3,
|
||||
"Hamlet": 2,
|
||||
}
|
||||
|
||||
func condenseMinDist(xs []placenames.POI, minDist float64) []placenames.POI {
|
||||
log.Printf("Condensing by min distance %f", minDist)
|
||||
cont := true
|
||||
for cont {
|
||||
cont = false
|
||||
for i := 0; i < len(xs)-1; i++ {
|
||||
if xs[i+1].Distance-xs[i].Distance < minDist {
|
||||
p1 := locationTypePriority[xs[i].Type]
|
||||
p2 := locationTypePriority[xs[i+1].Type]
|
||||
if i == 0 || p2 < p1 {
|
||||
xs = deleteElement(xs, i+1)
|
||||
cont = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return xs
|
||||
}
|
||||
|
||||
func condenseMaxPoi(xs []placenames.POI, maxPoi int) []placenames.POI {
|
||||
log.Printf("Condensing %d to %d points", len(xs), maxPoi)
|
||||
for len(xs) > maxPoi {
|
||||
var minI int
|
||||
var minD float64
|
||||
for i := 0; i < len(xs)-1; i++ {
|
||||
d := xs[i+1].Distance - xs[i].Distance
|
||||
if i == 0 || d < minD {
|
||||
minI = i
|
||||
minD = d
|
||||
}
|
||||
}
|
||||
p1 := locationTypePriority[xs[minI].Type]
|
||||
p2 := locationTypePriority[xs[minI+1].Type]
|
||||
if minI == 0 || p2 < p1 {
|
||||
xs = deleteElement(xs, minI+1)
|
||||
continue
|
||||
}
|
||||
if minI == len(xs)-2 || p1 < p2 {
|
||||
xs = deleteElement(xs, minI)
|
||||
continue
|
||||
}
|
||||
// p1 == p2
|
||||
d1 := xs[minI].Distance - xs[minI-1].Distance
|
||||
d2 := xs[minI+1].Distance - xs[minI].Distance
|
||||
if d1 < d2 {
|
||||
xs = deleteElement(xs, minI)
|
||||
} else {
|
||||
xs = deleteElement(xs, minI+1)
|
||||
}
|
||||
}
|
||||
return xs
|
||||
}
|
||||
|
||||
func deleteElement(xs []placenames.POI, i int) []placenames.POI {
|
||||
log.Printf("Deleting %s (%0.1f)", xs[i].Name, xs[i].Distance)
|
||||
return append(xs[0:i], xs[i+1:]...)
|
||||
}
|
Loading…
Reference in a new issue