Skip to content

Commit

Permalink
bbox simplified and recursion option
Browse files Browse the repository at this point in the history
removed itemgetter and attribute getter functions.
added recursion option to calculate bbox with and without recursive relation usage.
Added test cases with the border of Germany.
  • Loading branch information
werner2101 committed Oct 7, 2015
1 parent 2e89f5e commit 5e5b90c
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 33 deletions.
49 changes: 18 additions & 31 deletions src/osm/pyosm.py
Expand Up @@ -100,6 +100,9 @@ def attributes(self):
d.update(self.__attrs.get_all())
return d

def bbox(self, **kwargs):
return (self.lat, self.lat, self.lon, self.lon)

def __repr__(self):
return "Node(attrs=%r, tags=%r)" % (self.attributes(), self.__tags)

Expand All @@ -111,7 +114,6 @@ def __init__(self, attrs, tags=None, nodes=None, osm_parent=None, load_tags=True
self.__nodes = None
self.__attrs = None
self.__tags = None
self.__bbox = (None, None, None, None) # (min_lat, max_lat, min_lon, max_lon)

self.id = int(attrs.pop('id'))
self.osm_parent = osm_parent
Expand All @@ -130,8 +132,6 @@ def __getattr__(self, name):
return list(self.__nodes)
elif name == 'tags':
return self.__tags
elif name == 'bbox':
return self.get_bbox()
elif self.__attrs:
return self.__attrs.get(name)

Expand All @@ -144,8 +144,6 @@ def __getitem__(self, name):
return list(self.__nodes)
elif name == 'tags':
return self.__tags
elif name == 'bbox':
return self.get_bbox()

def __cmp__(self, other):
cmp_ref = cmp(self.tags.get('ref',''), other.tags.get('ref',''))
Expand All @@ -171,23 +169,21 @@ def distance(self):
"""
if len(self.nodes) < 2:
return 0.0
#print self.nodes[0]
lat = numpy.array([n.lat for n in self.nodes]) * numpy.pi / 180
lon = numpy.array([n.lon for n in self.nodes]) * numpy.pi / 180
lat1 = lat[:-1]
lat2 = lat[1:]
lon1 = lon[:-1]
lon2 = lon[1:]

#formula see: https://en.wikipedia.org/wiki/Great-circle_distance#Computational_formulas
dist = numpy.arctan(numpy.sqrt((numpy.cos(lat2)*numpy.sin(abs(lon1-lon2)))**2 + (numpy.cos(lat1)*numpy.sin(lat2) - numpy.sin(lat1)*numpy.cos(lat2)*numpy.cos(lon1-lon2))**2) / (numpy.sin(lat1)*numpy.sin(lat2) + numpy.cos(lat1)*numpy.cos(lat2)*numpy.cos(lon1-lon2)))
return numpy.sum(dist) * 6372795

def get_bbox(self):
if self.__bbox[0] == None:
lat = [n.lat for n in self.nodes]
lon = [n.lon for n in self.nodes]
self.__bbox = (min(lat), max(lat), min(lon), max(lon))
return self.__bbox
def bbox(self, **kwargs):
lat = [n.lat for n in self.nodes]
lon = [n.lon for n in self.nodes]
return min(lat), max(lat), min(lon), max(lon)

def __repr__(self):
return "Way(attrs=%r, tags=%r, nodes=%r)" % (self.attributes(), self.__tags, list(self.__nodes))
Expand All @@ -200,7 +196,6 @@ def __init__(self, attrs, tags=None, members=None, osm_parent=None, load_tags=Tr
self.__members = None
self.__attrs = None
self.__tags = None
self.__bbox = (None, None, None, None) # (min_lat, max_lat, min_lon, max_lon)

self.id = int(attrs.pop('id'))
self.osm_parent = osm_parent
Expand All @@ -219,8 +214,6 @@ def __getattr__(self, name):
return list(self.__members)
elif name == 'tags':
return self.__tags
elif name == 'bbox':
return self.get_bbox()
elif self.__attrs:
return self.__attrs.get(name)

Expand All @@ -233,8 +226,6 @@ def __getitem__(self, name):
return self.__members
elif name == 'tags':
return self.__tags
elif name == 'bbox':
return self.get_bbox()

def __cmp__(self, other):
cmp_ref = cmp(self.tags.get('ref',''), other.tags.get('ref',''))
Expand All @@ -257,7 +248,7 @@ def attributes(self):
def distance(self, roles=None, recursive=False):
"""
calculate the distance of a route with all given roles.
if roles is empty, the roles are not checked
if roles is empty, all members are measured
recursive calculation is for relations in relations
"""
dist = 0.0
Expand All @@ -275,19 +266,15 @@ def distance(self, roles=None, recursive=False):
dist += obj.distance(roles=roles, recursive=recursive)
return dist

def get_bbox(self):
if self.__bbox[0] == None:
members = self.members
## lat/lon of Nodes
lat = [m[0].lat for m in members if type(members[0]) == Node]
lon = [m[0].lon for m in members if type(members[0]) == Node]
## bbox data of ways and subrelations
lat.extend([m[0].bbox[0] for m in members if type(members[0]) != Node])
lat.extend([m[0].bbox[1] for m in members if type(members[0]) != Node])
lon.extend([m[0].bbox[2] for m in members if type(members[0]) != Node])
lon.extend([m[0].bbox[3] for m in members if type(members[0]) != Node])
self.__bbox = (min(lat), max(lat), min(lon), max(lon))
return self.__bbox
def bbox(self, recursive=False):
bboxes = []
for obj, role in self.members:
if recursive == False and type(obj) == Relation:
continue
bboxes.append(obj.bbox(recursive=recursive))

return min([b[0] for b in bboxes]), max([b[1] for b in bboxes]), \
min([b[2] for b in bboxes]), max([b[3] for b in bboxes]),

def __repr__(self):
if self.__members != None:
Expand Down
21 changes: 19 additions & 2 deletions tests/test_pyosm.py
Expand Up @@ -39,11 +39,11 @@ def test_osm_itemgetter(self):
for it in ['id','members','member_data','tags','bbox']:
log.info(' %s=%s', it, r[it])
log.info('way item test:')
w = list(self.osm.ways.values())[0] # get first relation
w = list(self.osm.ways.values())[0] # get first way
for it in ['id','nodes','nodeids','tags','bbox']:
log.info(' %s=%s', it, w[it])
log.info('node item test:')
n = list(self.osm.nodes.values())[0] # get first relation
n = list(self.osm.nodes.values())[0] # get first node
for it in ['id','lat', 'lon','tags']:
log.info(' %s=%s', it, n[it])

Expand All @@ -55,6 +55,23 @@ def test_merge_write(self):
log.info('osm2 stat after merge')
osm2.statistic()
osm2.write('testoutput/result_merge_write.osm')

def test_geometry(self):
log.info('geometry tests:')
w = list(self.osm.ways.values())[0] # get first way
log.info(' distance way0: %f' % w.distance())
log.info(' bbox way0: %s' % str(w.bbox()))
r = list(self.osm.relations.values())[0] # get first relation
log.info(' distance rel0: %f' % r.distance())
log.info(' bbox rel0: %s' % str(r.bbox()))
germany = pyosm.OSMXMLFile('osmfiles/germany_borders.osm')
rb = germany.relations[1111111]
log.info(' border bbox %s' % str(rb.bbox()))
log.info(' border bbox %s' % str(rb.bbox(recursive=True)))
log.info(' border length %f' % rb.distance())
log.info(' border length recursive %f' % rb.distance(recursive=True))
log.info(' border length recursive %f' % rb.distance(recursive=True, roles=['outer','']))


if __name__ == '__main__':
if not os.path.exists('testoutput'):
Expand Down

0 comments on commit 5e5b90c

Please sign in to comment.