Commit e4459c14 authored by Thomas Albrecht's avatar Thomas Albrecht

- go back to -9999 if outside elev.xml

- xml writer cleanup
- analyse: area before height
- number format in building writer
parent 989cd64f
......@@ -92,7 +92,7 @@ def reset_nb():
global nb
nb = 0
def get_nodes_from_acs(objs, path_prefix):
def get_nodes_from_acs(objs, path_prefix, model_prefix):
"""load all .ac and .xml, extract nodes"""
# FIXME: use real ac3d reader: https://github.com/majic79/Blender-AC3D/blob/master/io_scene_ac3d/import_ac3d.py
# FIXME: don't skip .xml
......@@ -118,7 +118,7 @@ def get_nodes_from_acs(objs, path_prefix):
fname = b.name
#print "in objs <%s>" % b.name
if fname.endswith(".xml"):
if fname.startswith("city-"): continue
if fname.startswith(model_prefix): continue
fname = fname.replace(".xml", ".ac")
#print "now <%s> %s" % (fname, b.stg_typ)
......@@ -175,7 +175,7 @@ def test_ac_load():
#print s
def analyse(buildings, static_objects, transform, elev, facades, roofs):
def analyse(buildings, static_objects, transform, elev, facades, roofs, model_prefix):
"""analyse all buildings
- calculate area
- location clash with stg static models? drop building
......@@ -188,7 +188,7 @@ def analyse(buildings, static_objects, transform, elev, facades, roofs):
from scipy.spatial import KDTree
#s = get_nodes_from_acs(static_objects.objs, "e013n51/")
s = get_nodes_from_acs(static_objects.objs, "e011n47/")
s = get_nodes_from_acs(static_objects.objs, "e011n47/", model_prefix)
np.savetxt("nodes.dat", s)
# s = np.zeros((len(static_objects.objs), 2))
......@@ -220,6 +220,47 @@ def analyse(buildings, static_objects, transform, elev, facades, roofs):
b.nnodes_ground = len(b.refs)
# print nnodes_ground #, b.refs[0].lon, b.refs[0].lat
# -- get geometry right
# - transform to global coord
# - compute edge lengths
# - fix inverted faces
# - compute area
X = np.zeros((b.nnodes_ground+1,2))
lenX = np.zeros((b.nnodes_ground))
i = 0
for r in b.refs:
X[i,0], X[i,1] = transform.toLocal((r.lon, r.lat))
i += 1
# -- write nodes to separate debug file
for i in range(b.nnodes_ground):
tools.stats.debug1.write("%g %g\n" % (X[i,0], X[i,1]))
X[-1] = X[0] # -- we duplicate last node!
# -- fix inverted faces
crossX = 0.
for i in range(b.nnodes_ground):
crossX += X[i,0]*X[i+1,1] - X[i+1,0]*X[i,1]
lenX[i] = ((X[i+1,0]-X[i,0])**2 + (X[i+1,1]-X[i,1])**2)**0.5
if crossX < 0:
X = X[::-1]
lenX = lenX[::-1]
# -- renumber nodes such that longest edge is first
if b.nnodes_ground == 4:
if lenX[0] < lenX[1]:
X = np.roll(X, 1, axis=0)
lenX = np.roll(lenX, 1)
X[0] = X[-1]
# -- shapely: compute area
r = LinearRing(list(X))
p = Polygon(r)
b.area = p.area
level_height = random_level_height()
# try OSM height first
......@@ -231,14 +272,15 @@ def analyse(buildings, static_objects, transform, elev, facades, roofs):
height = 0.
pass
# failing that, try OSM levels
if height < 1:
# failing that, try levels
if float(b.levels) > 0:
pass
#print "have levels", b.levels
else:
# failing that, use random levels
b.levels = random_levels()
if b.area < 40: b.levels = min(b.levels, 2)
b.height = float(b.levels) * level_height
#print "hei", b.height, b.levels
......@@ -261,8 +303,8 @@ def analyse(buildings, static_objects, transform, elev, facades, roofs):
b.roof_separate = False
b.roof_flat = True
# -- model roof if we have 4 ground nodes
if b.nnodes_ground == 4:
# -- model roof if we have 4 ground nodes and area below 1000m2
if b.nnodes_ground == 4 and b.area < 1000:
b.roof_separate = True
b.roof_flat = False # -- gable roof
......@@ -281,40 +323,6 @@ def analyse(buildings, static_objects, transform, elev, facades, roofs):
requires.append('age:old')
requires.append('compat:roof-gable')
# -- get geometry right
# - transform to global coord
# - compute edge lengths
# - fix inverted faces
# - compute area
X = np.zeros((b.nnodes_ground+1,2))
lenX = np.zeros((b.nnodes_ground))
i = 0
for r in b.refs:
X[i,0], X[i,1] = transform.toLocal((r.lon, r.lat))
i += 1
# -- write nodes to separate debug file
for i in range(b.nnodes_ground):
tools.stats.debug1.write("%g %g\n" % (X[i,0], X[i,1]))
X[-1] = X[0] # -- we duplicate last node!
# -- fix inverted faces
crossX = 0.
for i in range(b.nnodes_ground):
crossX += X[i,0]*X[i+1,1] - X[i+1,0]*X[i,1]
lenX[i] = ((X[i+1,0]-X[i,0])**2 + (X[i+1,1]-X[i,1])**2)**0.5
if crossX < 0:
X = X[::-1]
lenX = lenX[::-1]
# -- renumber nodes such that longest edge is first
if b.nnodes_ground == 4:
if lenX[0] < lenX[1]:
X = np.roll(X, 1, axis=0)
lenX = np.roll(lenX, 1)
X[0] = X[-1]
# -- static objects nearby?
# FIXME: which radius? Or use centroid point?
......@@ -344,22 +352,10 @@ def analyse(buildings, static_objects, transform, elev, facades, roofs):
tools.stats.skipped_nearby += 1
continue
# -- shapely stuff
# - compute area
r = LinearRing(list(X))
p = Polygon(r)
b.area = p.area
# OBJECT_STATIC frauenkirche.ac 13.7416 51.05192 115.33 117
#fk = transform.toLocal((51.05192, 13.7416))
#if ((X[i,0] - fk[0])**2 + (X[i,1] - fk[1])**2) > 1000000:
# continue
# -- skipping 50% of under 200 sqm buildings
if b.area < 20. or (b.area < 200. and random.uniform(0,1) < 0.5):
if b.area < 30. or (b.area < 200. and random.uniform(0,1) < 0.5):
#if b.area < 20. : # FIXME use limits.area_min:
print "Skipping small building (area)"
#print "Skipping small building (area)"
tools.stats.skipped_small += 1
continue
......@@ -490,11 +486,9 @@ def write(b, out, elev, tile_elev, transform, offset, LOD_lists):
for x in X[:-1]:
z = ground_elev - 1
out.write("%g %g %g\n" % (-x[1], z, -x[0]))
out.write("%1.2f %1.2f %1.2f\n" % (-x[1], z, -x[0]))
for x in X[:-1]:
out.write("%g %g %g\n" % (-x[1], ground_elev + b.height, -x[0]))
out.write("%1.2f %1.2f %1.2f\n" % (-x[1], ground_elev + b.height, -x[0]))
write_and_count_numsurf(out, b, nsurf)
# -- walls
......@@ -546,7 +540,7 @@ def write(b, out, elev, tile_elev, transform, offset, LOD_lists):
write_and_count_numvert(out, b, nnodes_ground)
for x in X[:-1]:
z = ground_elev - 1
out.write("%g %g %g\n" % (-x[1], ground_elev + height, -x[0]))
out.write("%1.2f %1.2f %1.2f\n" % (-x[1], ground_elev + height, -x[0]))
write_and_count_numsurf(out, b, 1)
out.write("SURF 0x0\n")
out.write("mat %i\n" % mat)
......@@ -563,8 +557,7 @@ def write(b, out, elev, tile_elev, transform, offset, LOD_lists):
# -- 4 corners
for x in X[:-1]:
z = ground_elev - 1
#out.write("%g %g %g\n" % (y, z, x))
out.write("%g %g %g\n" % (-x[1], ground_elev + b.height, -x[0]))
out.write("%1.2f %1.2f %1.2f\n" % (-x[1], ground_elev + b.height, -x[0]))
# --
#mid_short_x = 0.5*(X[3][1]+X[0][1])
#mid_short_z = 0.5*(X[3][0]+X[0][0])
......@@ -576,8 +569,8 @@ def write(b, out, elev, tile_elev, transform, offset, LOD_lists):
len_roof_top = lenX[0] - 2.*inward
len_roof_bottom = 1.*lenX[0]
out.write("%g %g %g\n" % (-(0.5*(X[3][1]+X[0][1]) + tang[1]), ground_elev + height + roof_height, -(0.5*(X[3][0]+X[0][0]) + tang[0])))
out.write("%g %g %g\n" % (-(0.5*(X[1][1]+X[2][1]) - tang[1]), ground_elev + height + roof_height, -(0.5*(X[1][0]+X[2][0]) - tang[0])))
out.write("%1.2f %1.2f %1.2f\n" % (-(0.5*(X[3][1]+X[0][1]) + tang[1]), ground_elev + height + roof_height, -(0.5*(X[3][0]+X[0][0]) + tang[0])))
out.write("%1.2f %1.2f %1.2f\n" % (-(0.5*(X[1][1]+X[2][1]) - tang[1]), ground_elev + height + roof_height, -(0.5*(X[1][0]+X[2][0]) - tang[0])))
roof_texture_size_x = roof_texture.h_size_meters # size of roof texture in meters
roof_texture_size_y = roof_texture.v_size_meters
......
......@@ -33,6 +33,8 @@
# - rename textures
# - respect ac
# cmd line
# - skip nearby check
"""
osm2city.py aims at generating 3D city models for FG, using OSM data.
......@@ -84,7 +86,6 @@ import tools
import calc_tile
# -- defaults
ground_height = -20
no_elev = False # -- skip elevation interpolation
#no_elev = True # -- skip elevation interpolation
......@@ -94,20 +95,17 @@ use_pkl = True
#use_pkl = False
buildings = [] # -- master list, holds all buildings
first = True
tile_size=1000 # -- our tile size in meters
#infile = 'dd-altstadt.osm'; total_objects = 158
#infile = 'altstadt.osm'; total_objects = 10000 # 2172
#infile = 'xapi-buildings.osm'; total_objects = 100000 # huge!
#p.parse('xapi.osm') # fails
#p.parse('xapi-small.osm')
#infile = 'eddc-all.osm'; total_objects = 100000 # huge!
#infile = 'map.osm'; total_objects = 216 #
prefix="LOWI"
infile = prefix + '/buidings-xapi.osm'; total_objects = 40000 # huge!
infile = prefix + '/buidings-xapi.osm'; total_objects = 45000 # huge!
#infile = 'map.osm'; total_objects = 216 #
skiplist = ["Dresden Hauptbahnhof", "Semperoper", "Zwinger", "Hofkirche",
"Frauenkirche", "Coselpalais", "Palais im Großen Garten",
"Residenzschloss Dresden", "Fernsehturm", "Fernsehturm Dresden"]
......@@ -301,10 +299,8 @@ def write_ac_header(out, nb):
out.write("AC3Db\n")
# out.write("%s\n" % mats[random.randint(0,2)])
out.write(textwrap.dedent(
"""MATERIAL "" rgb 1 1 1 amb 1 1 1 emis 0.0 0.0 0.0 spec 0.5 0.5 0.5 shi 64 trans 0
MATERIAL "" rgb 1 0 0 amb 1 1 1 emis 0.0 0.0 0.0 spec 0.5 0.5 0.5 shi 64 trans 0
"""))
out.write("""MATERIAL "" rgb 1 1 1 amb 1 1 1 emis 0.0 0.0 0.0 spec 0.5 0.5 0.5 shi 64 trans 0\n""")
out.write("""MATERIAL "" rgb 1 0 0 amb 1 1 1 emis 0.0 0.0 0.0 spec 0.5 0.5 0.5 shi 64 trans 0\n""")
# MATERIAL "" rgb 1 1 1 amb 1 1 1 emis 0.0 0.0 0.0 spec 0.5 0.5 0.5 shi 64 trans 0
# MATERIAL "" rgb .95 1 1 amb 1 1 1 emis 0.0 0.0 0.0 spec 0.5 0.5 0.5 shi 64 trans 0
# MATERIAL "" rgb 1 0.95 1 amb 1 1 1 emis 0.0 0.0 0.0 spec 0.5 0.5 0.5 shi 64 trans 0
......@@ -347,32 +343,32 @@ def write_xml(fname, LOD_lists):
<type>range</type>
"""))
for name in LOD_lists[0]:
xml.write(" <object-name>%s</object-name>\n" % name)
xml.write(textwrap.dedent("""
<min-m>0</min-m>
xml.write(" <object-name>%s</object-name>\n" % name)
xml.write(textwrap.dedent(
""" <min-m>0</min-m>
<max-property>/sim/rendering/static-lod/bare</max-property>
</animation>
<animation>
<type>range</type>
<type>range</type>
"""))
for name in LOD_lists[1]:
xml.write(" <object-name>%s</object-name>\n" % name)
xml.write(textwrap.dedent("""
<min-m>0</min-m>
<max-property>/sim/rendering/static-lod/rough</max-property>
</animation>
xml.write(" <object-name>%s</object-name>\n" % name)
xml.write(textwrap.dedent(
""" <min-m>0</min-m>
<max-property>/sim/rendering/static-lod/rough</max-property>
</animation>
<!--
<animation>
<!--
<animation>
<type>range</type>
"""))
for name in LOD_lists[2]:
xml.write(" <object-name>%s</object-name>\n" % name)
xml.write(" <object-name>%s</object-name>\n" % name)
xml.write(textwrap.dedent("""
<min-m>0</min-m>
<max-property>/sim/rendering/static-lod/detailed</max-property>
</animation>
</animation>
-->
</PropertyList>
"""))
......@@ -449,7 +445,7 @@ if __name__ == "__main__":
# - analyze surrounding: similar shaped buildings nearby? will get same texture
# - set building type, roof type etc
# - decide LOD
buildings = building_lib.analyse(buildings, static_objects, transform, elev, tex.facades, tex.roofs)
buildings = building_lib.analyse(buildings, static_objects, transform, elev, tex.facades, tex.roofs, prefix+"city")
tools.stats.print_summary()
......@@ -483,6 +479,9 @@ if __name__ == "__main__":
tile_elev = elev(cl.center)
if tile_elev == -9999:
print "Skipping tile elev = -9999"
continue # skip tile with improper elev
#print "TILE E", tile_elev
center_lon, center_lat = transform.toGlobal((cl.center.x, cl.center.y))
......
......@@ -55,7 +55,7 @@ class Interpolator(object):
"""compute elevation at (x,y) by linear interpolation"""
if self.fake: return 0.
if p.x <= self.min_x or p.x >= self.max_x or \
p.y <= self.min_y or p.y >= self.max_y: return self.h[0,0] #-9999
p.y <= self.min_y or p.y >= self.max_y: return -9999
i = int((p.x - self.min_x)/self.dx)
j = int((p.y - self.min_y)/self.dy)
fx = (p.x - self.x[j,i])/self.dx
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment