Commit 9118c561 authored by Rick Gruber-Riemer's avatar Rick Gruber-Riemer

Adding filter methods for textures as 4 new parameters TEXTURE_*.

parent e0b3ec10
......@@ -37,6 +37,8 @@ In most situations it is enough to call the following command once and then only
Alternatively `buildings.py` can be called with the ``-a`` option.
Chapter :ref:`Textures <chapter-parameters-textures>` has an overview of how roof and facade textures can be filtered.
====================
Overview of Programs
......
......@@ -172,6 +172,34 @@ LIGHTMAP_ENABLE Boolean True Creates sim
============================================= ======== ======= ==============================================================================
.. _chapter-parameters-textures:
--------
Textures
--------
============================================= ======== ======= ==============================================================================
Parameter Type Default Description / Example
============================================= ======== ======= ==============================================================================
ATLAS_SUFFIX_DATE Boolean False Add the current date as a suffix to the texture atlas in ``osm2city-data``.
TEXTURES_ROOFS_NAME_EXCLUDE List [] List of roof file names to exclude, e.g. ["roof_red3.png", "roof_orange.png"].
The file names must be relative paths to the ``tex.src`` directory within
``PATH_TO_OSM2CITY_DATA``.
Be aware the excluding roofs can lead to indirectly excluding facade textures,
which might be depending on provided roof types.
An empty list means that no filtering is done.
TEXTURES_FACADES_NAME_EXCLUDE List [] Same as ``TEXTURES_ROOFS_EXCLUDE`` but for facades — e.g.
["de/commercial/facade_modern_21x42m.jpg"].
TEXTURES_ROOFS_PROVIDE_EXCLUDE List [] List of provided features for roofs to exclude, e.g. ["colour:red"].
TEXTURES_FACADES_PROVIDE_EXCLUDE List [] Ditto for facades.
============================================= ======== ======= ==============================================================================
.. _chapter-parameters-clipping:
---------------
......
......@@ -28,9 +28,9 @@ from utils import vec2d as v
# The preceding line sets encoding of this file to utf-8. Needed for non-ascii
# object names. It must stay on the first or second line.
#=============================================================================
# =============================================================================
# PARAMETERS FOR ALL osm2city MODULES
#=============================================================================
# =============================================================================
LOGLEVEL = "INFO"
# -- Scenery folder, typically a geographic name or the ICAO code of the airport
......@@ -77,11 +77,9 @@ TELNET_PORT = 5501 # The port FlightGear listens to. Needed for ELEV_MODE = "Te
USE_NEW_STG_VERBS = False
#=============================================================================
# =============================================================================
# PARAMETERS RELATED TO BUILDINGS IN osm2city
#=============================================================================
ATLAS_SUFFIX_DATE = False # -- add timestamp to file name
# =============================================================================
# -- Check for static objects in the PATH_TO_SCENERY folder based on convex hull around all points
OVERLAP_CHECK_CONVEX_HULL = False
......@@ -161,15 +159,10 @@ OBSTRUCTION_LIGHT_MIN_LEVELS = 15 # -- put obstruction lights on buildings wit
CLUSTER_MIN_OBJECTS = 5 # -- discard cluster if too little objects
#=============================================================================
# EXPERIMENTAL PARAMETERS, work in progress, YMMV
#=============================================================================
#=============================================================================
# =============================================================================
# PARAMETERS RELATED TO PYLONS, POWERLINES, AERIALWAYS IN osm2pylons.py
#=============================================================================
# =============================================================================
C2P_PROCESS_POWERLINES = True
C2P_PROCESS_AERIALWAYS = True
......@@ -228,17 +221,17 @@ C2P_STREETLAMPS_RESIDENTIAL_DISTANCE = 40
C2P_STREETLAMPS_OTHER_DISTANCE = 70
C2P_STREETLAMPS_MIN_STREET_LENGTH = 20
#=============================================================================
# =============================================================================
# PARAMETERS RELATED TO landuse.py - might be replaced by another library
#=============================================================================
# =============================================================================
LU_LANDUSE_GENERATE_LANDUSE = True
LU_LANDUSE_BUILDING_BUFFER_DISTANCE = 25
LU_LANDUSE_BUILDING_BUFFER_DISTANCE_MAX = 50
LU_LANDUSE_MIN_AREA = 5000
#=============================================================================
# =============================================================================
# PARAMETERS RELATED TO roads.py
#=============================================================================
# =============================================================================
TRAFFIC_SHADER_ENABLE = False
MAX_SLOPE_RAILWAY = 0.04
......@@ -255,6 +248,18 @@ MIN_ABOVE_GROUND_LEVEL = 0.01 # how much a highway / railway is at least hove
HIGHWAY_TYPE_MIN = 4 # The lower the number, the more ways are added. See roads.HighwayType
POINTS_ON_LINE_DISTANCE_MAX = 1000 # the maximum distance between two points on a line. If longer, then new points are added
# =============================================================================
# PARAMETERS RELATED TO TEXTURES
# =============================================================================
ATLAS_SUFFIX_DATE = False # -- add timestamp to file name
TEXTURES_ROOFS_NAME_EXCLUDE = [] # list of roof file names to exclude, e.g. ["roof_red3.png", "roof_orange.png"]
TEXTURES_FACADES_NAME_EXCLUDE = [] # e.g. ["de/commercial/facade_modern_21x42m.jpg"]
TEXTURES_ROOFS_PROVIDE_EXCLUDE = [] # list of roof provides features to exclude, e.g. ["colour:red"]
TEXTURES_FACADES_PROVIDE_EXCLUDE = [] # ditto for facade provides features, e.g. ["age:modern"]
# default_args_end # DO NOT MODIFY THIS LINE
......
......@@ -22,6 +22,7 @@ import math
import os
import pickle
import sys
from typing import List
import img2np
import numpy as np
......@@ -41,8 +42,8 @@ def _next_pow2(value):
return 2**(int(math.log(value) / math.log(2)) + 1)
def _make_texture_atlas(texture_list, atlas_filename, ext, size_x=256, pad_y=0,
lightmap=False, ambient_occlusion=False):
def _make_texture_atlas(texture_list: List[Texture], atlas_filename: str, ext: str, size_x: int=256, pad_y: int=0,
lightmap: bool=False, ambient_occlusion: bool=False):
"""
Create texture atlas from all textures. Update all our item coordinates.
"""
......@@ -151,10 +152,10 @@ def _make_texture_atlas(texture_list, atlas_filename, ext, size_x=256, pad_y=0,
# -- create LM atlas, using the coordinates of the main atlas
if lightmap:
LM_atlas = atlas.Atlas(0, 0, atlas_sx, the_atlas.height_px, 'FacadesLM')
light_map_atlas = atlas.Atlas(0, 0, atlas_sx, the_atlas.height_px, 'FacadesLM')
for l in texture_list:
LM_atlas.pack_at(l, l.ax, l.ay)
LM_atlas.write(atlas_filename + '_LM' + ext, 'im_LM')
light_map_atlas.pack_at(l, l.ax, l.ay)
light_map_atlas.write(atlas_filename + '_LM' + ext, 'im_LM')
for l in texture_list:
logging.debug('%s (%4.2f, %4.2f) (%4.2f, %4.2f)' % (l.filename, l.x0, l.y0, l.x1, l.y1))
......@@ -163,7 +164,7 @@ def _make_texture_atlas(texture_list, atlas_filename, ext, size_x=256, pad_y=0,
del l.im_LM
def _check_missed_input_textures(tex_prefix, registered_textures):
def _check_missed_input_textures(tex_prefix: str, registered_textures: List[Texture]) -> None:
"""Find all .jpg and .png files in tex.src and compare with registered textures.
If not found in registered textures, then log a warning"""
......@@ -182,7 +183,7 @@ def _check_missed_input_textures(tex_prefix, registered_textures):
logging.warning("Texture %s has not been registered", my_path)
def _append_dynamic(my_facades, tex_prefix):
def _append_dynamic(facade_manager: FacadeManager, tex_prefix: str) -> None:
"""Dynamically runs .py files in tex.src and sub-directories to add facades.
For roofs see add_roofs(roofs)"""
......@@ -196,24 +197,27 @@ def _append_dynamic(my_facades, tex_prefix):
my_path = subdir + os.sep + filename
logging.info("Executing %s ", my_path)
try:
my_facades.current_registered_in = my_path
facade_manager.current_registered_in = my_path
exec(compile(open(my_path).read(), my_path, 'exec'))
except:
logging.exception("Error while running %s" % filename)
def _append_roofs(roofs, tex_prefix): # parameter roofs is used dynamically in execfile
"""Dynamically runs the content of a hard-coded file to fill the roofs texture list."""
def _append_roofs(roof_manager: RoofManager, tex_prefix: str) -> None:
"""Dynamically runs the content of a hard-coded file to fill the roofs texture list.
Argument roof_manager is used dynamically in execfile
."""
try:
file_name = tex_prefix + os.sep + ROOFS_DEFAULT_FILE_NAME
roofs.current_registered_in = file_name
roof_manager.current_registered_in = file_name
exec(compile(open(file_name).read(), file_name, 'exec'))
except Exception as e:
logging.exception("Unrecoverable error while loading roofs", e)
sys.exit(1)
def init(create_atlas=True):
def init(create_atlas: bool=True) -> None:
logging.debug("textures: init")
global facades
global roofs
......@@ -227,13 +231,13 @@ def init(create_atlas=True):
my_tex_prefix_src = my_tex_prefix + 'tex.src'
Texture.tex_prefix = my_tex_prefix_src # need to set static variable so managers get full path
pkl_fname = my_tex_prefix + "tex" + os.sep + "atlas_facades.pkl"
pkl_file_name = my_tex_prefix + "tex" + os.sep + "atlas_facades.pkl"
if create_atlas:
facades = FacadeManager('facade')
roofs = RoofManager('roof')
# read registration
# read registrations
_append_roofs(roofs, my_tex_prefix_src)
_append_dynamic(facades, my_tex_prefix_src)
......@@ -253,20 +257,20 @@ def init(create_atlas=True):
params = dict()
params['atlas_file_name'] = atlas_file_name
logging.info("Saving %s", pkl_fname)
fpickle = open(pkl_fname, 'wb')
pickle.dump(facades, fpickle, -1)
pickle.dump(roofs, fpickle, -1)
pickle.dump(params, fpickle, -1)
fpickle.close()
logging.info("Saving %s", pkl_file_name)
pickle_file = open(pkl_file_name, 'wb')
pickle.dump(facades, pickle_file, -1)
pickle.dump(roofs, pickle_file, -1)
pickle.dump(params, pickle_file, -1)
pickle_file.close()
else:
logging.info("Loading %s", pkl_fname)
fpickle = open(pkl_fname, 'rb')
facades = pickle.load(fpickle)
roofs = pickle.load(fpickle)
params = pickle.load(fpickle)
logging.info("Loading %s", pkl_file_name)
pickle_file = open(pkl_file_name, 'rb')
facades = pickle.load(pickle_file)
roofs = pickle.load(pickle_file)
params = pickle.load(pickle_file)
atlas_file_name = params['atlas_file_name']
fpickle.close()
pickle_file.close()
logging.debug(facades)
tools.stats.textures_total = dict((filename, 0) for filename in map((lambda x: x.filename), facades.get_list()))
......
import logging
import os
from PIL import Image
import random
import re
from typing import Dict
import numpy as np
import tools
from PIL import Image
import logging
import os
import parameters
class Texture(object):
......@@ -43,11 +45,11 @@ class Texture(object):
- shape:flat (pitched, ..)
"""
def __init__(self, filename:str,
def __init__(self, filename: str,
h_size_meters=None, h_cuts=list(), h_can_repeat=False,
v_size_meters=None, v_cuts=list(), v_can_repeat=False,
height_min=0, height_max=9999,
v_align_bottom=False,
v_align_bottom: bool=False,
provides=list(), requires=list(), levels=None) -> None:
self.filename = Texture.tex_prefix + os.sep + filename
self.x0 = self.x1 = self.y0 = self.y1 = 0
......@@ -193,6 +195,10 @@ class RoofManager(object):
texture.registered_in = self.current_registered_in
# check whether the texture should be excluded based on parameter for name
if not self._screen_exclude_texture_by_name(texture):
return False
# check whether the same texture already has been referenced in an existing entry
for existing in self.__l:
if existing.filename == texture.filename:
......@@ -201,25 +207,56 @@ class RoofManager(object):
return False
new_provides = list()
my_available_materials = list()
logging.debug("Based on registration file %s: added %s ", self.current_registered_in, texture.filename)
for item in texture.provides:
if item.split(':')[0] in ('age', 'region', 'compat'):
new_provides.append(screen_texture_tags_for_colour_spelling(item))
screened_item = screen_texture_tags_for_colour_spelling(item)
if not self._screen_exclude_texture_by_provides(screened_item):
return False
if screened_item.split(':')[0] in ('age', 'region', 'compat'):
new_provides.append(screened_item)
else:
if item.split(":")[0] == "material":
self.available_materials.add(item.split(":")[1])
new_provides.append(screen_texture_tags_for_colour_spelling(self.__cls + ':' + item))
if screened_item.split(":")[0] == "material":
my_available_materials.append(screened_item.split(":")[1])
new_provides.append(self.__cls + ':' + screened_item)
texture.provides = new_provides
new_requires = list()
for item in texture.requires:
new_requires.append(screen_texture_tags_for_colour_spelling(item))
texture.requires = new_requires
self.available_materials.update(my_available_materials)
texture.cls = self.__cls
tools.stats.textures_total[texture.filename] = None
self.__l.append(texture)
return True
def _screen_exclude_texture_by_name(self, texture: Texture) -> bool:
if isinstance(self, FacadeManager):
if len(parameters.TEXTURES_FACADES_NAME_EXCLUDE) > 0:
for a_facade_path in parameters.TEXTURES_FACADES_NAME_EXCLUDE:
if texture.filename.rfind(a_facade_path) >= 0:
return False
else:
if len(parameters.TEXTURES_ROOFS_NAME_EXCLUDE) > 0:
for a_roof_path in parameters.TEXTURES_ROOFS_NAME_EXCLUDE:
if texture.filename.rfind(a_roof_path) >= 0:
return False
return True
def _screen_exclude_texture_by_provides(self, provided_feature: str) -> bool:
if isinstance(self, FacadeManager):
if len(parameters.TEXTURES_FACADES_PROVIDE_EXCLUDE) > 0:
for a_feature in parameters.TEXTURES_FACADES_PROVIDE_EXCLUDE:
if screen_texture_tags_for_colour_spelling(a_feature) == provided_feature:
return False
else:
if len(parameters.TEXTURES_ROOFS_PROVIDE_EXCLUDE) > 0:
for a_feature in parameters.TEXTURES_ROOFS_PROVIDE_EXCLUDE:
if screen_texture_tags_for_colour_spelling(a_feature) == provided_feature:
return False
return True
def find_matching_roof(self, requires=[]):
candidates = self.find_candidates(requires)
logging.verbose("looking for texture" + str(requires)) # @UndefinedVariable
......
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