Commit 62b76fd6 authored by Rick Gruber-Riemer's avatar Rick Gruber-Riemer

Refactor of roof ridge orientation to be done based on references instead of geometry.

parent e6f5cce7
This diff is collapsed.
......@@ -585,20 +585,20 @@ def _process_osm_building(nodes_dict: Dict[int, op.Node], ways_dict: Dict[int, o
def _make_building_from_way(nodes_dict: Dict[int, op.Node], all_tags: Dict[str, str], way: op.Way,
coords_transform: coordinates.Transformation,
inner_ways=None) -> Optional[building_lib.Building]:
inner_ways: List[op.Way] = None) -> Optional[building_lib.Building]:
if way.refs[0] == way.refs[-1]:
way.refs = way.refs[0:-1] # -- kick last ref if it coincides with first
name = ""
# -- funny things might happen while parsing OSM
try:
# -- make outer and inner rings from refs
outer_ring = _refs_to_ring(coords_transform, way.refs, nodes_dict)
outer_ring = op.refs_to_ring(coords_transform, way.refs, nodes_dict)
inner_rings_list = list()
inner_refs_list = list()
if inner_ways:
for _way in inner_ways:
inner_rings_list.append(_refs_to_ring(coords_transform, _way.refs, nodes_dict))
if _way.refs[0] == _way.refs[-1]:
_way.refs = _way.refs[0:-1] # -- kick last ref if it coincides with first
inner_rings_list.append(op.refs_to_ring(coords_transform, _way.refs, nodes_dict))
inner_refs_list.append(_way.refs)
except KeyError as reason:
logging.debug("ERROR: Failed to parse building referenced node missing clipped?(%s) WayID %d %s Refs %s" % (
reason, way.osm_id, all_tags, way.refs))
......@@ -608,20 +608,8 @@ def _make_building_from_way(nodes_dict: Dict[int, op.Node], all_tags: Dict[str,
way.refs))
return None
return building_lib.Building(way.osm_id, all_tags, outer_ring, name, None, inner_rings_list=inner_rings_list,
refs=way.refs)
def _refs_to_ring(coords_transform: coordinates.Transformation, refs,
nodes_dict: Dict[int, op.Node]) -> shg.LinearRing:
"""Accept a list of OSM refs, return a linear ring."""
coords = []
for ref in refs:
c = nodes_dict[ref]
coords.append(coords_transform.to_local((c.lon, c.lat)))
ring = shg.polygon.LinearRing(coords)
return ring
return building_lib.Building(way.osm_id, all_tags, outer_ring, None, inner_rings_list=inner_rings_list,
refs=way.refs, refs_inner=inner_refs_list)
def _clean_building_zones_dangling_children(my_buildings: List[building_lib.Building]) -> None:
......@@ -924,7 +912,7 @@ def write_buildings_in_lists(coords_transform: coordinates.Transformation,
tex_variability = 4
wall_tex_idx = random.randint(0, tex_variability - 1) # FIXME: should calc on street level or owbb
roof_tex_idx = wall_tex_idx
roof_orientation = b.analyse_roof_list_orientation()
roof_orientation = b.calc_roof_list_orientation()
line += ' {:.1f} {:.1f} {:.1f} {:.1f} {} {} {} {} {}'.format(b.width, b.depth, b.body_height,
b.roof_height, b.roof_shape.value,
roof_orientation, round(b.levels),
......
......@@ -702,6 +702,36 @@ def _sanitize_building_zones(building_zones: List[m.BuildingZone], text: str) ->
logging.info('Sanitize %s has deleted %i building zones', text, number_deleted)
def _relate_neighbours(buildings: List[bl.Building]) -> None:
"""Relates neighbour buildings based on shared references."""
neighbours = 0
len_buildings = len(buildings)
for i, first_building in enumerate(buildings, 1):
if i % 10000 == 0:
logging.info('Checked building relations for %i out of %i buildings', i, len_buildings)
potential_attached = first_building.zone.osm_buildings
ref_set_first = set(first_building.refs)
for second_building in potential_attached:
if first_building.osm_id == second_building.osm_id: # do not compare with self
continue
ref_set_second = set(second_building.refs)
if ref_set_first.isdisjoint(ref_set_second) is False:
for pos_i in range(len(first_building.refs)):
for pos_j in range(len(second_building.refs)):
if first_building.refs[pos_i] == second_building.refs[pos_j]:
if second_building.osm_id not in first_building.refs_shared:
first_building.refs_shared[second_building.osm_id] = set()
first_building.refs_shared[second_building.osm_id].add(pos_i)
if first_building.osm_id not in second_building.refs_shared:
second_building.refs_shared[first_building.osm_id] = set()
second_building.refs_shared[first_building.osm_id].add(pos_j)
for b in buildings:
if b.has_neighbours:
neighbours += 1
logging.info('%i out of %i buildings have neighbour relations ', neighbours, len(buildings))
def process(transformer: Transformation, airports: List[aptdat_io.Airport]) -> Tuple[Optional[List[Polygon]],
Optional[List[Polygon]],
Optional[List[bl.Building]]]:
......@@ -855,11 +885,25 @@ def process(transformer: Transformation, airports: List[aptdat_io.Airport]) -> T
my_zone.guess_building_zone_type(farm_places)
last_time = time_logging("Time used in seconds for guessing zone types", last_time)
# =========== See whether we can do more building relations ============================
# this is done as late as possible to reduce exec time by only looking in the building's same zone
# =========== Now let us do final calculations and relations as long as we have the nodes dict =================
# See whether we can do more building relations
# This is done as late as possible to reduce exec time by only looking in the building's same zone
bu.process_building_loose_parts(building_nodes_dict, osm_buildings)
last_time = time_logging('Time used in seconds for processing building loose parts', last_time)
# run a neighbour analysis -> building.refs_shared
_relate_neighbours(osm_buildings)
last_time = time_logging('Time used in seconds for relating neighbours', last_time)
# now we can calculate the roof ridge orientation
for building in osm_buildings:
building.calc_roof_mesh_orientation(building_nodes_dict, transformer)
last_time = time_logging('Time used in seconds for calculating the roof ridge orientation', last_time)
# FIXME: simplify stuff
# update the geometry a final time based on node references before we loose it
for building in osm_buildings:
building.update_geometry_from_refs(building_nodes_dict, transformer)
last_time = time_logging('Time used in seconds for calculating the roof ridge orientation', last_time)
# =========== FINALIZE Land-use PROCESSING =============================================
if parameters.DEBUG_PLOT_LANDUSE:
logging.info('Start of plotting zones')
......
......@@ -1110,7 +1110,7 @@ class GenBuilding(object):
self.shared_model.width / 2, self.shared_model.depth)
rotated = saf.rotate(floor_plan, -1 * self.angle, origin=(0, 0))
moved = saf.translate(rotated, self.x, self.y)
my_building = bl.Building(self.gen_id, self.shared_model.building_model.tags, moved.exterior, '',
my_building = bl.Building(self.gen_id, self.shared_model.building_model.tags, moved.exterior,
co.Vec2d(self.x, self.y),
street_angle=self.angle, is_owbb_model=True,
width=self.shared_model.width, depth=self.shared_model.depth)
......
......@@ -128,7 +128,7 @@ def separate_gable(ac_object, b, roof_mat_idx: int, facade_mat_idx: int, inward_
if osm_roof_orientation_exists:
if osm_roof_orientation == s.V_ACROSS:
i_side = i_small
elif b.roof_neighbour_orientation >= 0.: # only override if we have neighbours
elif b.roof_ridge_orientation >= 0.: # only override if we have neighbours
# calculate the angle of the "along"
along_angle = coord.calc_angle_of_line_local(b.pts_all[i_long % 4][0],
b.pts_all[i_long % 4][1],
......@@ -136,7 +136,7 @@ def separate_gable(ac_object, b, roof_mat_idx: int, facade_mat_idx: int, inward_
b.pts_all[(i_long + 1) % 4][1])
if along_angle >= 180.:
along_angle -= 180.
difference = fabs(b.roof_neighbour_orientation - along_angle)
difference = fabs(b.roof_ridge_orientation - along_angle)
# if the difference is closer to 90 than parallel, then change the orientation
if 45 < difference < 135:
i_side = i_small
......
......@@ -190,6 +190,18 @@ class Relation(OSMElement):
return 'Relation with osm_id: {}'.format(self.osm_id)
def refs_to_ring(coords_transform: Transformation, refs: List[int],
nodes_dict: Dict[int, Node]) -> shg.LinearRing:
"""Accept a list of OSM refs, return a linear ring."""
coords = []
for ref in refs:
c = nodes_dict[ref]
coords.append(coords_transform.to_local((c.lon, c.lat)))
ring = shg.polygon.LinearRing(coords)
return ring
def closed_ways_from_multiple_ways(way_parts: List[Way]) -> List[Way]:
"""Create closed ways from multiple not closed ways where possible.
See http://wiki.openstreetmap.org/wiki/Relation:multipolygon.
......
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