1. npe
  2. gosim

Commits

npe  committed b740817

Initial commit, fixed Makefile, turned into package.

  • Participants
  • Parent commits f2a7c55
  • Branches default

Comments (0)

Files changed (2)

File Makefile

View file
 include $(GOROOT)/src/Make.inc
 
-TARG=readOSM
+TARG=bitbucket.org/npe/gosim
 GOFILES=\
-	readOSM.go\
+	osm.go\
 
-# fix this later
-all:
-	$(GC) $(GCIMPORTS) -o osm.$O osm.go
-	gopack crg osm.a osm.$O
-	$(GC) $(GCIMPORTS) -o readOSM.$O readOSM.go
-	$(LD) $(LDIMPORTS) -o readOSM readOSM.$O
-
-#include $(GOROOT)/src/Make.cmd
+include $(GOROOT)/src/Make.pkg
 
 #smoketest: $(TARG)
 #	(cd testdata; ./test.sh)

File osm.go

View file
-package osm
+package main
 
 import (
-	"math"
+	"encoding/xml"
+	"errors"
+	"flag"
+	"fmt"
+	"github.com/npe9/ellipsoid"
+	"io"
+	"log"
+	"math/rand"
+	"os"
+	"time"
 )
 
-type Osm struct {
-	Nodes	map[uint]Node
-	Ways	[]Way
+var (
+	ErrPlace = errors.New("Im a placeholder")
+)
+
+// XXX: I need to do my own version of ellipsoid
+
+var randomizer *rand.Rand
+var geo ellipsoid.Ellipsoid
+var people map[int]*Person
+var newPerson chan *Person
+
+func init() {
+	// osm
+	randomizer = rand.New(rand.NewSource(time.Nanoseconds()))
+	geo = ellipsoid.Init("WGS84", ellipsoid.Degrees, ellipsoid.Meter, ellipsoid.Longitude_is_symmetric, ellipsoid.Bearing_is_symmetric)
+	// person
+	ticker := time.NewTicker(1e9)
+	go func() {
+		for {
+			select {
+			case p := <-newPerson:
+				people[p.Id] = p
+			case <-ticker.C:
+				for _, p := range people {
+					// if person 
+					// average person (male) walks 1.56464 m/s
+					p.Move(1.56464)
+				}
+				// XXX: we should have some way to finish this
+				// case id := <-done:
+				// 	people[id] = nil, nil
+			}
+		}
+	}()
+}
+
+func usage() {
+	fmt.Fprintf(os.Stderr, "usage: osm [flags] [path ...]\n")
+	flag.PrintDefaults()
+	os.Exit(2)
+}
+
+var (
+	placeHolder = flag.Bool("place", false, "dont print final newline")
+)
+
+type Nd struct {
+	Ref int `xml:"attr"`
+}
+
+type Tag struct {
+	K string `xml:"attr"`
+	V string `xml:"attr"`
+}
+
+type Way struct {
+	Nd   []Nd
+	Node []*Node
+	Tag  []*Tag
+}
+
+func (w *Way) RandNode() Node {
+	return *w.Node[randomizer.Intn(len(w.Node))]
+}
+
+func (w *Way) Nodes() []*Node {
+	return w.Node
+}
+
+type Relation struct {
+
 }
 
 type Node struct {
-	Id	uint
-	Lat	float64 // Lat and Lon are stored in degrees
-	Lon	float64
+	Id  int     `xml:"attr"`
+	Lat float64 `xml:"attr"`
+	Lon float64 `xml:"attr"`
+	Way []*Way
 }
 
-type Way struct {
-	Id	uint
-	Nodes	[]uint // the IDs of the nodes in the way
-	Name	string // 4th Street, East Ave, etc.
-	Type	string // secondary, residential, etc.
+func (n Node) RandWay() *Way {
+	return n.Way[randomizer.Intn(len(n.Way))]
 }
 
-// Given an ID#, latitude, and longitude, create a new Node instance.
-func NewNode(id uint, lat, lon float64) (n *Node) {
-	n = new(Node)
-	n.Id = id
-	n.Lat = lat
-	n.Lon = lon
-
-	return n
+func (n Node) Distance(m Node) (float64, float64) {
+	return geo.To(n.Lat, n.Lon, m.Lat, m.Lon)
 }
 
-// Find all the ways which contain a given node ID.
-// Almost every node should be contained in at least one Way
-// Many are in 2 or 3 ways, very few are in more!
-func FindWays(ways []Way, node uint) (ret []Way) {
-	for _, w := range ways {
-		for _, id := range w.Nodes {
-			if id == node {
-				ret = append(ret, w)
-				break
-			}
-		}
-	}
+func (n Node) Move(dist, bearing float64) (m Node) {
+	m.Lat, m.Lon = geo.At(n.Lat, n.Lon, dist, bearing)
 	return
 }
 
-// Returns the distance between the two nodes in meters
-// Uses equirectangular approximation due to short distances
-func GetDist(n1, n2 Node) float64 {
-	const R float64 = 6371000
-	x := ((math.Pi/180)*(n2.Lon - n1.Lon)) * math.Cos((math.Pi/180)*n1.Lat)
-	y := (math.Pi/180)*(n2.Lat - n1.Lat)
-	return R * math.Sqrt(x*x + y*y)
+func (n Node) Eq(m Node) bool {
+	// XXX: probably need to be allow fuzziness here
+	return n.Lat == m.Lat && n.Lon == m.Lon
 }
+
+type Osm struct {
+	XMLName  xml.Name `xml:"osm"`
+	Node     []*Node
+	Way      []*Way
+	Relation []*Relation
+}
+
+func NewOsmXml(rd io.Reader) (o Osm, err error) {
+	err = xml.Unmarshal(rd, &o)
+	if err != nil {
+		return
+	}
+	idmap := make(map[int]*Node)
+	for _, n := range o.Node {
+		idmap[n.Id] = n
+	}
+	for _, w := range o.Way {
+		w.Node = make([]*Node, len(w.Nd))
+		for i, nd := range w.Nd {
+			n := idmap[nd.Ref]
+			w.Node[i] = n
+			n.Way = append(n.Way, w)
+		}
+	}
+
+	return
+}
+
+func (o *Osm) RandNode() Node {
+	return *o.Node[randomizer.Intn(len(o.Node))]
+}
+
+func (o *Osm) RandWay(n *Node) *Way {
+	return n.Way[randomizer.Intn(len(n.Way))]
+}
+
+type Person struct {
+	Id       int
+	loc      Node
+	dest     Node
+	bearing  float64
+	way      *Way
+}
+
+func NewPerson(n Node) (p Person) {
+	// XXX: how do you set a unique id?
+	return Person{loc: n}
+}
+
+/*
+we need to be able to figure out the person's bearing.
+
+if person is at waypoint.
+person is walking to waypoints.
+moving is easy.
+
+
+*/
+
+func (p *Person) Move(dist float64) {
+	// what happens with zero value?
+	p.SetLoc(p.loc.Move(dist, p.bearing))
+	// 1 meter accuracy
+	if dist, _ := p.loc.Distance(p.dest); dist < 1.0 {
+		p.loc = p.dest
+		// XXX: this needs to be setup in the way to allow it to pop a node
+//		p.dest = *p.way.Nodes()[0]
+//		p.way.Nodes()[1:]
+	}
+}
+
+func (p *Person) Loc() Node {
+	return p.loc
+}
+
+func (p *Person) SetLoc(n Node) {
+	p.loc = n
+}
+
+func (p *Person) SetWay(w *Way) {
+	p.way = w
+}
+
+func main() {
+	flag.Usage = usage
+	flag.Parse()
+	f, err := os.Open("test.osm")
+	defer f.Close()
+	if err != nil {
+		log.Fatal(err)
+	}
+	o, err := NewOsmXml(f)
+	if err != nil {
+		log.Fatal(err)
+	}
+	for {
+		// now we need to create people and give random ways to go
+		p := NewPerson(o.RandNode())
+		p.SetWay(p.Loc().RandWay())
+		newPerson <- &p
+	}
+	// how will this quit?
+	fmt.Printf("%#v\n", o.Way[0].RandNode())
+
+	os.Exit(0)
+}