gpx-utils/cmd/analyze-gpx/main.go

116 lines
3 KiB
Go
Raw Normal View History

2020-04-15 09:46:58 +01:00
package main
import (
"encoding/json"
2020-04-21 08:45:05 +01:00
"flag"
2020-04-15 09:46:58 +01:00
"fmt"
"io"
"io/ioutil"
2020-04-15 09:46:58 +01:00
"log"
"os"
"path"
2020-04-15 09:46:58 +01:00
"github.com/dhconnelly/rtreego"
"github.com/ray1729/gpx-utils/pkg/cafes"
"github.com/ray1729/gpx-utils/pkg/placenames"
2020-04-15 09:46:58 +01:00
)
func main() {
2020-04-18 14:26:48 +01:00
log.SetFlags(0)
2020-04-21 08:45:05 +01:00
stopNames := flag.String("stops", "", "Source for refreshment stops")
minDist := flag.Float64("min-dist", 0.2, "Minimum distance (km) between points of interest")
minSettlement := flag.String("min-settlement", "Other Settlement", "Exclude populated places smaller than this (City, Town, Village, Hamlet, Other Settlement)")
2020-04-21 08:45:05 +01:00
flag.Parse()
if flag.NArg() != 1 {
log.Fatal("Usage: %s [--stops=ctccambridge|cyclingmaps] [--min-dist X] [--min-settlement S] GPX_FILE_OR_DIRECTORY")
2020-04-18 14:26:48 +01:00
}
2020-04-21 08:45:05 +01:00
inFile := flag.Arg(0)
2020-04-18 14:26:48 +01:00
info, err := os.Stat(inFile)
if err != nil {
log.Fatal(err)
2020-04-15 09:46:58 +01:00
}
2020-04-21 08:45:05 +01:00
var stops *rtreego.Rtree
if *stopNames != "" {
var err error
stops, err = cafes.New().Get(*stopNames)
if err != nil {
log.Fatal(err)
}
}
gs, err := placenames.NewGPXSummarizer()
2020-04-15 09:46:58 +01:00
if err != nil {
log.Fatal(err)
}
gs.SetMinDistance(*minDist)
gs.SetMinSettlement(*minSettlement)
2020-04-18 14:26:48 +01:00
if info.IsDir() {
2020-04-21 08:45:05 +01:00
err = summarizeDirectory(gs, stops, inFile)
} else {
2020-04-21 08:45:05 +01:00
err = summarizeSingleFile(gs, stops, inFile)
}
if err != nil {
log.Fatal(err)
}
}
func summarizeDirectory(gs *placenames.GPXSummarizer, stops *rtreego.Rtree, dirName string) error {
files, err := ioutil.ReadDir(dirName)
if err != nil {
return err
}
for _, f := range files {
if f.IsDir() || path.Ext(f.Name()) != ".gpx" {
2020-04-15 09:46:58 +01:00
continue
}
filename := path.Join(dirName, f.Name())
r, err := os.Open(filename)
if err != nil {
return fmt.Errorf("error opening %s for reading: %v", filename, err)
}
log.Printf("Analyzing %s", filename)
summary, err := gs.SummarizeTrack(r, stops)
if err != nil {
return fmt.Errorf("error creating summary of GPX track %s: %v", filename, err)
}
outfile := filename[:len(filename)-4] + ".json"
wc, err := os.OpenFile(outfile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0644)
if err != nil {
return fmt.Errorf("error creating output file %s: %v", outfile, err)
}
err = writeSummary(summary, wc)
if err != nil {
wc.Close()
return fmt.Errorf("error marshalling JSON to %s: %v", outfile, err)
}
if err = wc.Close(); err != nil {
return fmt.Errorf("error closing file %s: %v", outfile, err)
2020-04-15 09:46:58 +01:00
}
}
return nil
}
func summarizeSingleFile(gs *placenames.GPXSummarizer, stops *rtreego.Rtree, filename string) error {
r, err := os.Open(filename)
if err != nil {
return fmt.Errorf("error opening %s for reading: %v", filename, err)
}
summary, err := gs.SummarizeTrack(r, stops)
if err != nil {
return fmt.Errorf("error creating summary of GPX track %s: %v", filename, err)
}
if err = writeSummary(summary, os.Stdout); err != nil {
return fmt.Errorf("error marshalling summary for %s: %v", filename, err)
}
return nil
}
func writeSummary(s *placenames.TrackSummary, w io.Writer) error {
enc := json.NewEncoder(w)
enc.SetIndent("", " ")
if err := enc.Encode(s); err != nil {
return err
}
return nil
2020-04-15 09:46:58 +01:00
}