Commit eb7328da authored by Rick Gruber-Riemer's avatar Rick Gruber-Riemer

Removed possibility to read OSM information from files and introduced Details folder

parent 1fc59e4d
This diff is collapsed.
......@@ -48,11 +48,11 @@ class SceneryTile(object):
@unique
class Procedures(IntEnum):
all = 0
buildings = 1
piers = 2
platforms = 3
main = 1
buildings = 2
roads = 3
pylons = 4
roads = 5
details = 5
def _parse_exec_for_procedure(exec_argument: str) -> Procedures:
......@@ -92,24 +92,16 @@ def process_scenery_tile(scenery_tile: SceneryTile, params_file_name: str, log_l
my_airports)
# run programs
if exec_argument is Procedures.all:
buildings.process(the_coords_transform, my_fg_elev, my_blocked_areas, my_stg_entries, file_lock)
roads.process(the_coords_transform, my_fg_elev, my_blocked_areas, my_stg_entries, file_lock)
pylons.process(the_coords_transform, my_fg_elev, my_stg_entries, file_lock)
if not parameters.FLAG_2017_2:
platforms.process(the_coords_transform, my_fg_elev, file_lock)
piers.process(the_coords_transform, my_fg_elev, file_lock)
elif exec_argument is Procedures.buildings:
buildings.process(the_coords_transform, my_fg_elev, my_blocked_areas, my_stg_entries, file_lock)
elif exec_argument is Procedures.roads:
roads.process(the_coords_transform, my_fg_elev, my_blocked_areas, my_stg_entries, file_lock)
elif exec_argument is Procedures.pylons:
pylons.process(the_coords_transform, my_fg_elev, my_stg_entries, file_lock)
elif exec_argument is Procedures.platforms:
platforms.process(the_coords_transform, my_fg_elev, file_lock)
elif exec_argument is Procedures.piers:
piers.process(the_coords_transform, my_fg_elev, file_lock)
pass
if exec_argument in [Procedures.buildings, Procedures.main, Procedures.all]:
buildings.process_buildings(the_coords_transform, my_fg_elev, my_blocked_areas, my_stg_entries, file_lock)
if exec_argument in [Procedures.roads, Procedures.main, Procedures.all]:
roads.process_roads(the_coords_transform, my_fg_elev, my_blocked_areas, my_stg_entries, file_lock)
if exec_argument in [Procedures.pylons, Procedures.main, Procedures.all]:
pylons.process_pylons(the_coords_transform, my_fg_elev, my_stg_entries, file_lock)
if exec_argument in [Procedures.details, Procedures.all]:
pylons.process_details(the_coords_transform, my_fg_elev, my_stg_entries, file_lock)
platforms.process_details(the_coords_transform, my_fg_elev, file_lock)
piers.process_details(the_coords_transform, my_fg_elev, file_lock)
# clean-up
my_fg_elev.close()
......@@ -146,7 +138,7 @@ if __name__ == '__main__':
help="number of parallel processes (should not be more than number of cores/CPUs)",
required=True)
parser.add_argument("-e", "--execute", dest="exec",
help="execute only the given osm2city procedure (buildings, piers, platforms, pylons, roads)",
help="execute only the given procedure[s] (buildings, pylons, roads, details, main)",
required=False)
parser.add_argument("-l", "--loglevel", dest="loglevel",
help="set loglevel. Valid levels are VERBOSE, DEBUG, INFO, WARNING, ERROR, CRITICAL",
......@@ -235,7 +227,7 @@ if __name__ == '__main__':
pool.join()
# At the very end copy static data stuff in one process
if exec_procedure is Procedures.all:
if exec_procedure in [Procedures.all, Procedures.main]:
copy_data_stuff.process(utils.stg_io2.SceneryType.buildings)
copy_data_stuff.process(utils.stg_io2.SceneryType.roads)
copy_data_stuff.process(utils.stg_io2.SceneryType.pylons)
......@@ -243,7 +235,7 @@ if __name__ == '__main__':
copy_data_stuff.process(utils.stg_io2.SceneryType.pylons)
elif exec_procedure is Procedures.roads:
copy_data_stuff.process(utils.stg_io2.SceneryType.roads)
else:
elif exec_procedure is Procedures.buildings:
copy_data_stuff.process(utils.stg_io2.SceneryType.buildings)
logging.info("Total time used {}".format(time.time() - start_time))
......
......@@ -54,7 +54,6 @@ You should disable random buildings.
# - capitalize class names: class Interpolator(object):
# - comments: code # -- comment
import argparse
import logging
import multiprocessing as mp
import os
......@@ -72,7 +71,7 @@ import prepare_textures
import textures.texture as tex
import utils.stg_io2
import utils.vec2d as v
from utils import aptdat_io, osmparser, coordinates, stg_io2, utilities
from utils import osmparser, coordinates, stg_io2, utilities
OUR_MAGIC = "osm2city" # Used in e.g. stg files to mark edits by osm2city
......@@ -536,18 +535,14 @@ def _write_xml(path: str, file_name: str, the_buildings: List[building_lib.Build
xml.close()
def process(coords_transform: coordinates.Transformation, fg_elev: utilities.FGElev,
blocked_areas: List[shg.Polygon], stg_entries: List[utils.stg_io2.STGEntry],
file_lock: mp.Lock=None) -> None:
def process_buildings(coords_transform: coordinates.Transformation, fg_elev: utilities.FGElev,
blocked_areas: List[shg.Polygon], stg_entries: List[utils.stg_io2.STGEntry],
file_lock: mp.Lock=None) -> None:
random.seed(42)
stats = utilities.Stats()
if not parameters.USE_DATABASE:
osm_read_results = osmparser.fetch_osm_file_data(list(), ["building", "building:part"],
["building", "building:part"])
else:
osm_read_results = osmparser.fetch_osm_db_data_ways_keys(["building", "building:part"])
osm_read_results = osmparser.fetch_osm_db_data_relations_keys(["building", "building:part"], osm_read_results)
osm_read_results = osmparser.fetch_osm_db_data_ways_keys(["building", "building:part"])
osm_read_results = osmparser.fetch_osm_db_data_relations_keys(["building", "building:part"], osm_read_results)
osm_nodes_dict = osm_read_results.nodes_dict
osm_ways_dict = osm_read_results.ways_dict
osm_relations_dict = osm_read_results.relations_dict
......@@ -678,37 +673,3 @@ def process(coords_transform: coordinates.Transformation, fg_elev: utilities.FGE
stg_manager.write(file_lock)
stats.print_summary()
utilities.troubleshoot(stats)
if __name__ == "__main__":
# -- Parse arguments. Command line overrides config file.
parser = argparse.ArgumentParser(
description="buildings.py reads OSM data and creates buildings for use with FlightGear")
parser.add_argument("-f", "--file", dest="filename",
help="read parameters from FILE (e.g. params.ini)", metavar="FILE", required=True)
parser.add_argument("-l", "--loglevel",
help="set loglevel. Valid levels are VERBOSE, DEBUG, INFO, WARNING, ERROR, CRITICAL",
required=False)
parser.add_argument("-e", dest="skip_elev", action="store_true",
help="skip elevation interpolation", required=False)
args = parser.parse_args()
parameters.read_from_file(args.filename)
parameters.set_loglevel(args.loglevel) # -- must go after reading params file
if args.skip_elev:
parameters.NO_ELEV = True
parameters.show()
my_coords_transform = coordinates.Transformation(parameters.get_center_global())
my_fg_elev = utilities.FGElev(my_coords_transform)
my_blocked_areas = aptdat_io.get_apt_dat_blocked_areas(my_coords_transform,
parameters.BOUNDARY_WEST, parameters.BOUNDARY_SOUTH,
parameters.BOUNDARY_EAST, parameters.BOUNDARY_NORTH)
my_stg_entries = utils.stg_io2.read_stg_entries_in_boundary(True, my_coords_transform)
process(my_coords_transform, my_fg_elev, my_blocked_areas, my_stg_entries)
my_fg_elev.close()
logging.info("******* Finished *******")
......@@ -2,7 +2,6 @@
Copies texture related data in directory 'tex' into the scenery folders.
"""
import argparse
from distutils.dir_util import copy_tree
import logging
import os
......@@ -124,21 +123,3 @@ def process(scenery_type: stg.SceneryType) -> None:
else:
logging.info("ERROR: The scenery path must include a directory '%s' - maybe no objects written",
scenery_path)
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO)
parser = argparse.ArgumentParser(description="Copies texture and effects related data in directory 'tex' \
into the scenery folders.")
parser.add_argument("-f", "--file", dest="filename",
help="Mandatory: read parameters from FILE (e.g. params.ini)", metavar="FILE", required=True)
parser.add_argument("-t", "--type", dest="scenery_type",
help="Mandatory: Scenery type - typically 'Buildings', 'Roads', 'Pylons'",
metavar="STRING", required=True)
args = parser.parse_args()
parameters.read_from_file(args.filename)
try:
process(stg.parse_for_scenery_type(args.scenery_type))
except KeyError:
logging.error('Scenery type cannot be recognized: %s', args.scenery_type)
......@@ -31,7 +31,7 @@ import os
# ones.
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.pngmath',
'sphinx.ext.imgmath',
]
# Add any paths that contain templates here, relative to this directory.
......
This diff is collapsed.
......@@ -9,7 +9,7 @@ While the article on FlightGear's Wiki_ presents in general terms what ``osm2cit
.. _OpenStreetMap: http://www.osm.org/
Before you generate your own sceneries, you might want to get familiar with the output of ``osm2city`` by first deploying some of the downloadable osm2city sceneries and have a look at chapter :ref:`Using Generated Scenery <chapter-using-label>`. See amongst others `Areas populated with osm2city scenery <http://wiki.flightgear.org/Areas_populated_with_osm2city_scenery>`_ or look for announcements in the Sceneries_ part of the FlightGear Forums.
Before you generate your own sceneries, you might want to get familiar with the output of ``osm2city`` by first deploying some of the downloadable osm2city sceneries and have a look at chapter :ref:`Using Generated Scenery <chapter-using-label>`. See amongst others `Areas populated with osm2city scenery <http://wiki.flightgear.org/Areas_populated_with_osm2city_scenery>`_ or look for announcements in the Sceneries_ part of the FlightGear Forums.
.. _Sceneries: http://forum.flightgear.org/viewforum.php?f=5
......
......@@ -43,7 +43,7 @@ Please make sure to use Python 3.5+ compatible extensions. Often Python 3 compat
Installation of osm2city
========================
There is no installer package - neither on Windows nor Linux. ``osm2city`` consists of a set of Python programs "osm2city_" and the related data in "osm2city-data_". You need both.
There is no installer package - neither on Windows nor Linux. ``osm2city`` consists of a set of Python programs and the related data in "osm2city-data_". You need both.
.. _osm2city: https://gitlab.com/fg-radi/osm2city
.. _osm2city-data: https://gitlab.com/fg-radi/osm2city-data
......@@ -52,7 +52,7 @@ Do the following:
#. Download the packages either using Git_ or as a zip-package.
#. Add the ``osm2city`` directory to your ``PYTHONPATH`` (see :ref:`below <chapter-set-pythonpath-label>`).
#. Make sure that you have :ref:`set $FG_ROOT <chapter-set-fgroot-label>`
#. Make sure that you have :ref:`set $FG_ROOT <chapter-set-fgroot-label>`.
.. _chapter-set-pythonpath-label:
......@@ -90,8 +90,6 @@ You might have to restart Windows to be able to read the environment variable th
-----------------------------
Setting up a PostGIS Database
-----------------------------
At the moment using a database instead of reading directly from OSM-files is not yet mandatory. However it is strongly recommended to do so, as most development is done using a database as the data source.
Creating and populating a PostGIS database is described in :ref:`OSM Data in a PostGIS Database<chapter-osm-database-label>`.
......@@ -101,6 +99,6 @@ Creating and populating a PostGIS database is described in :ref:`OSM Data in a P
Other Tools
===========
You might want to check out Sławek Mikuła's scripts_ for osm2city parsing and generation, which make some of the repetitice manual tasks involved in generating a scenery a bit easier.
You might want to check out Sławek Mikuła's scripts_ for osm2city parsing and generation, which make some of the repetitive manual tasks involved in generating a scenery a bit easier.
.. _scripts: https://github.com/slawekmikula/scripts-osm2city
This diff is collapsed.
......@@ -80,23 +80,16 @@ Getting OpenStreetMap Data
The OpenStreetMap Wiki has comprehensive information_ about how to get OSM data. An easy way to start is using Geofabrik's extracts (http://download.geofabrik.de/).
Unless you are using a PostGIS database as input, then be aware that ``osm2city`` only accepts OSM data in xml-format, i.e. ``*.osm`` files. Therefore you might need to translate data from the binary ``*.pbf`` format using e.g. Osmosis_. It is highly recommend to limit the area covered as much as possible: it leads to faster processing and it is easier to experiment with smaller areas until you found suitable parameters. If you use Osmosis to cut the area with ``--bounding-box``, then you need to use ``completeWays=yes`` [#]_. E.g. on Windows it could look as follows:
It is highly recommend to limit the area covered as much as possible: it leads to faster processing and it is easier to experiment with smaller areas until you found suitable parameters. If you use Osmosis_ to cut the area with ``--bounding-box``, then you need to use ``completeWays=yes`` [#]_. E.g. on Windows it could look as follows:
::
c:\> "C:\FlightGear\osmosis-latest\bin\osmosis.bat" --read-pbf file="C:\FlightGear\fg_customscenery\raw_data\switzerland-latest.osm.pbf"
--bounding-box completeWays=yes top=46.7 left=9.75 bottom=46.4 right=10.0 --wx file="C:\FlightGear\fg_customscenery\projects\LSZS\lszs_wider.osm"
The exception to the requirement of using OSM data in xml-format is if you use batch processing with the optional ``-d`` command line argument (see :ref:`Calling build_tiles.py <chapter-build-tiles-label>`). In that situation you might want to consider using the pbf-format_.
Please be aware of the `Tile Index Schema`_ in FlightGear. It is advised to set boundaries, which do not cross tiles. Otherwise the scenery objects can jitter and disappear / re-appear due to the clusters of facades crossing tiles. Another reason to keep within boundaries is the sheer amount of data that needs to be kept in memory.
E.g. Switzerland is around 46 degrees of latitude, therefore the boundary can be set in increments of 0.125 degrees of latitude and 0.25 degrees of longitude. Smaller works fine. If you are using the recommended approach of :ref:`batch processing <chapter-batch-mode>`, then these details will be taken care of for you automatically.
.. _information: http://wiki.openstreetmap.org/wiki/Downloading_data
.. _Osmosis: http://wiki.openstreetmap.org/wiki/Osmosis
.. _`Tile Index Schema`: http://wiki.flightgear.org/Tile_Index_Scheme
.. _pbf-format: http://wiki.openstreetmap.org/wiki/PBF_Format
.. _chapter-setting-parameters-label:
......@@ -115,16 +108,17 @@ Create a ``params.ini`` file with your favorite text editor. In our example it w
PATH_TO_SCENERY = "/home/flightgear/fgfs_terrasync"
PATH_TO_OUTPUT = "/home/fg_customscenery/LSZS"
PATH_TO_OSM2CITY_DATA = "/home/user/osm2city-data"
OSM_FILE = "lszs_narrow.osm"
BOUNDARY_WEST = 9.81
BOUNDARY_SOUTH = 46.51
BOUNDARY_EAST = 9.90
BOUNDARY_NORTH = 46.54
NO_ELEV = False
FG_ELEV = '/home/pingu/bin/fgfs_git/next/install/flightgear/bin/fgelev'
DB_HOST = "localhost"
DB_PORT = 5433
DB_NAME = "osmgis"
DB_USER = "gisuser"
DB_USER_PASSWORD = "n/a"
A few comments on the parameters:
......@@ -137,14 +131,12 @@ PATH_TO_SCENERY
PATH_TO_OUTPUT
The generated scenery files (.stg, .ac) will be written to this path — specified without trailing slash. If empty then the correct location in PATH_TO_SCENERY is used. Note that if you use TerraSync for PATH_TO_SCENERY, you MUST choose a different path here. Otherwise, TerraSync will overwrite the generated scenery. Unless you know what you are doing, there is no reason not to specify a dedicated path here. While not absolutely needed, it is good practice to name the output folder the same as ``PREFIX``.
OSM_FILE
The file containing OpenStreetMap data. See previous chapter :ref:`Getting OpenStreetMap Data <chapter-getting-data-label>`. The file should reside in $PREFIX and no path components are allowed (i.e. pure file name). If you have your data in PostGIS, then instead you need to specify the :ref:`database parameters <chapter-parameters-database>`.
BOUNDARY_*
The longitude and latitude of the boundaries of the generated scenery. The boundaries should correspond to the boundaries in the ``OSM_FILE`` (open the \*.osm file in a text editor and check the data in ca. line 3) respectively the data in PostGIS. The boundaries can be different, but then you might either miss data (if the OSM boundaries are larger) or do more processing than necessary (if the OSM boundaries are more narrow and you use a fiel based approach — not an issue when using a database).
NO_ELEV
Set this to ``False``. The only reason to set this to ``True`` would be for builders to check generated scenery objects a bit faster not caring about the vertical position in the scenery.
FG_ELEV
Set parameter ``FG_ELEV`` to point to the full path of the fgelev executable. On Linux it could be something like ``FG_ELEV = '/home/pingu/bin/fgfs_git/next/install/flightgear/bin/fgelev'``. On Windows you might have to put quotes around the path due to whitespace e.g. ``FG_ELEV = '"D:/Program Files/FlightGear/bin/Win64/fgelev.exe"'`` (yes, both single and double quotes).
DB_*
Connection settings for PostGIS: see :ref:`database parameters <chapter-parameters-database>`.
.. _chapter-generating-elevation-data-label:
......
......@@ -76,7 +76,7 @@ Use the FlightGear menu ``View``, menu item ``Rendering Options``.
* Buildings: Choose ``OpenStreetMap Data`` (i.e. ``Randomly Generated`` is turned off)
* Pylons and power lines: not only used for electrical power pylons and cables, but also e.g. wind turbines
* Detailed Roads and Railways: draped over the grey roads and railways lines in the default scenery.
* If you also enable ``Atmospheric Light Scattering (ALS)`` you also get better effects during the night as well as moving cars.
* If you also enable ``Atmospheric Light Scattering (ALS)`` you also get better effects during day and night as well as moving cars. Not using ALS might give odd graphical effects.
.. image:: fgfs_rendering_options.png
......@@ -85,6 +85,11 @@ In the same dialog press the ``Shader Options`` button and set the slider for ``
.. image:: fgfs_shader_options.png
========================
Showing Detailed Objects
========================
Some of the generated sceneries might contain a sub-folder ``Details`` apart from e.g. ``Buildings``. If you want to show more scenery details (and accept that this might drain some system resources), then rename the folder to ``Objects``.
.. _chapter-hide-urban-textures-label:
......
# -*- coding: utf-8 -*-
"""
Script part of osm2city which takes OpenStreetMap data as input and generates data to be used in FlightGear
* isolated trees
@author: rogue-spectre
"""
import argparse
import logging
import math
import xml.sax
import parameters
from utils import osmparser, vec2d, coordinates, stg_io2
from utils.utilities import FGElev
OUR_MAGIC = "osm2nature" # Used in e.g. stg files to mark edits by osm2nature.py
SCENERY_TYPE = "Objects" # yes, not "Nature"
class TreeNode(object):
def __init__(self, osm_id):
self.osm_id = osm_id
self.switch = False
self.buffer_stop = False
self.lon = 0.0 # longitude coordinate in decimal as a float
self.lat = 0.0 # latitude coordinate in decimal as a float
self.x = 0.0 # local position x
self.y = 0.0 # local position y
self.elevation = 500.0 # elevation above sea level in meters
self.tree_model = "Models/Trees/platanus_acerifolia_15m.xml"
def calc_global_coordinates(self, fg_elev: FGElev, my_coord_transformator):
self.lon, self.lat = my_coord_transformator.toGlobal((self.x, self.y))
self.elevation = fg_elev.probe_elev(vec2d.Vec2d(self.lon, self.lat), True)
def make_stg_entry(self, my_stg_mgr):
"""
Returns a stg entry for this tree.
E.g. OBJECT_SHARED Models/Airport/ils.xml 5.313108 45.364122 374.49 268.92
"""
my_stg_mgr.add_object_shared(self.tree_model, vec2d.Vec2d(self.lon, self.lat)
, self.elevation
, stg_angle(0)) # 90 less because arms are in x-direction in ac-file
def process_osm_tree(nodes_dict, fg_elev: FGElev, my_coord_transformator):
my_trees = {}
for node in list(nodes_dict.values()):
for key in node.tags :
if node.tags[key] == "tree":
my_node = node
my_tree_node = TreeNode(my_node.osm_id)
my_tree_node.lat = my_node.lat
my_tree_node.lon = my_node.lon
# try to get a suitable model
print((node.tags))
try:
if "type" in node.tags:
if node.tags["type"] == "conifer":
print("found conifer")
my_tree_node.tree_model = "Models/Trees/coniferous-tree.xml"
if node.tags["type"] == "palm":
print("found palm")
my_tree_node.tree_model = "Models/Trees/palm02.xml"
except:
my_tree_node.tree_model = "Models/Trees/platanus_acerifolia_15m.xml"
my_tree_node.tree_model = "Models/Trees/egkk_woods.xml"
my_tree_node.x, my_tree_node.y = my_coord_transformator.toLocal((my_tree_node.lon, my_tree_node.lat))
my_tree_node.elevation = fg_elev.probe_elev(vec2d.Vec2d(my_tree_node.lon, my_tree_node.lat), True)
print(("adding entry to trees", my_node.osm_id, " ", my_tree_node.x, " ", my_tree_node.y, " ", my_tree_node.elevation))
my_trees[my_tree_node.osm_id] = my_tree_node
return my_trees
def process_osm_forest(nodes_dict, ways_dict, my_elev_interpolator, my_coord_transformator):
""" fist stage put trees on contour """
my_trees = {}
for way in list(ways_dict.values()):
for key in way.tags:
if way.tags[key] == "forest":
print("found forest")
for ref in way.refs:
if ref in nodes_dict:
my_node = nodes_dict[ref]
my_tree_node = TreeNode(my_node.osm_id)
my_tree_node.lat = my_node.lat
my_tree_node.lon = my_node.lon
my_tree_node.x, my_tree_node.y = my_coord_transformator.toLocal((my_tree_node.lon, my_tree_node.lat))
my_tree_node.elevation = my_elev_interpolator(vec2d.Vec2d(my_tree_node.lon, my_tree_node.lat), True)
print(("adding entry to trees", my_tree_node.x, my_tree_node.y, my_tree_node.elevation))
my_trees[my_tree_node.osm_id] = my_tree_node
return my_trees
def write_stg_entries(my_stg_mgr, my_files_to_remove, lines_dict, wayname, cluster_max_length):
line_index = 0
for line in list(lines_dict.values()):
line_index += 1
line.make_shared_pylons_stg_entries(my_stg_mgr)
if None is not wayname:
line.make_cables_ac_xml_stg_entries(my_stg_mgr, line_index, wayname, cluster_max_length, my_files_to_remove)
def stg_angle(angle_normal):
"""Returns the input angle in degrees to an angle for the stg-file in degrees.
stg-files use angles counter-clockwise starting with 0 in North."""
if 0 == angle_normal:
return 0
else:
return 360 - angle_normal
def calc_distance(x1, y1, x2, y2):
return math.sqrt(math.pow(x1 - x2, 2) + math.pow(y1 - y2, 2))
def main():
# Handling arguments and parameters
parser = argparse.ArgumentParser(
description="osm2nature reads OSM data and creates single trees for use with FlightGear")
parser.add_argument("-f", "--file", dest="filename",
help="read parameters from FILE (e.g. params.ini)", metavar="FILE")
parser.add_argument("-e", dest="e", action="store_true", help="skip elevation interpolation")
parser.add_argument("-l", "--loglevel", help="set loglevel. Valid levels are VERBOSE, DEBUG, INFO, WARNING, ERROR, CRITICAL")
args = parser.parse_args()
if args.filename is not None:
parameters.read_from_file(args.filename)
parameters.set_loglevel(args.loglevel) # -- must go after reading params file
if args.e:
parameters.NO_ELEV = True
# Initializing tools for global/local coordinate transformations
center_global = parameters.get_center_global()
osm_fname = parameters.get_OSM_file_name()
coords_transform = coordinates.Transformation(center_global, hdg=0)
# Reading elevation data
logging.info("Reading ground elevation data might take some time ...")
fg_elev = FGElev(coords_transform)
# Transform to real objects
logging.info("Transforming OSM data to Line and Pylon objects")
valid_node_keys = ["natural", "landuse", "type"]
valid_way_keys = ["landuse"]
valid_relation_keys = []
req_relation_keys = []
req_way_keys = ["natural", "landuse"]
handler = osmparser.OSMContentHandlerOld(valid_node_keys, valid_way_keys, req_way_keys, valid_relation_keys,
req_relation_keys)
source = open(osm_fname, encoding="utf8")
xml.sax.parse(source, handler)
trees = {}
forest_trees = {}
if True : # parameters.PROCESS_TREES :
trees = process_osm_tree(handler.nodes_dict, fg_elev, coords_transform)
logging.info('Number of trees to process: %s', len(trees))
#if True :
# forest_trees = process_osm_forest(handler.nodes_dict, handler.ways_dict, elev_interpolator
# , coords_transform)
# logging.info('Number of forest to process: %s', len(trees))
# # -- initialize STGManager
path_to_output = parameters.get_output_path()
stg_manager = stg_io2.STGManager(path_to_output, TERRASYNC_DIR_NATURE, OUR_MAGIC, parameters.get_repl_prefix())
#write_stg_entries(stg_manager, files_to_remove, trees, "trees", 2000)
for tree in list(trees.values()) :
print((tree.elevation))
tree.make_stg_entry(stg_manager)
#write_stg_entries(stg_manager, files_to_remove, trees, "trees", 2000)
for forest_tree in list(forest_trees.values()) :
print((forest_tree.elevation))
forest_tree.make_stg_entry(stg_manager)
stg_manager.write()
fg_elev.close()
logging.info("******* Finished *******")
if __name__ == "__main__":
main()
......@@ -14,7 +14,6 @@ Ludomotico contributed a cleaner version of read_from_file().
import argparse
import logging
import os
import re
import sys
import traceback
......@@ -38,13 +37,12 @@ LOGLEVEL = "INFO"
PREFIX = "LSZR"
# -- Boundary of the scenery in degrees (use "." not ","). The example below is from LSZR.
# The values are set dynamically during program execution - no need to set them manually.
BOUNDARY_WEST = 9.54
BOUNDARY_SOUTH = 47.48
BOUNDARY_EAST = 9.58
BOUNDARY_NORTH = 47.50
OSM_FILE = "buildings.osm" # -- file name of file with OSM data. Should reside in $PREFIX. No path components allowed.
# -- Full path to the scenery folder without trailing slash. This is where we
# will probe elevation and check for overlap with static objects. Most
# likely you'll want to use your TerraSync path here.
......@@ -61,10 +59,7 @@ PATH_TO_SCENERY_OPT = None # if not none, then needs to be list of strings
# Also make sure PATH_TO_OUTPUT is included in your $FG_SCENERY.
PATH_TO_OUTPUT = "/home/user/fgfs/scenery/osm2city"
# OSM DATA is either stored in a file pointed to by PATH_TO_OSM2CITY_DATA (USE_DATABASE = False) or in a database.
# If using the database then set USE_DATABASE = True and set the DB_* parameters according to your PostGIS instance.
PATH_TO_OSM2CITY_DATA = "/home/user/osm2city-data"
USE_DATABASE = False # If True then the OSM data is read from a database instead of PATH_TO_OSM2CITY_DATA.
DB_HOST = "localhost" # The host name of the computer running PostGIS.
DB_PORT = 5432 # The port used to connect to the host
DB_NAME = "osmgis" # The name of the database.
......@@ -89,7 +84,7 @@ FLAG_2017_2 = True # Feature flag for 2017.2 version of FG
# =============================================================================
# -- Check for static objects in the PATH_TO_SCENERY folder based on convex hull around all points
OVERLAP_CHECK_CONVEX_HULL = False
OVERLAP_CHECK_CONVEX_HULL = True
OVERLAP_CHECK_CH_BUFFER_STATIC = 0.0
OVERLAP_CHECK_CH_BUFFER_SHARED = 0.0
......@@ -168,13 +163,15 @@ CLUSTER_MIN_OBJECTS = 5 # -- discard cluster if too few objects
BUILDING_TOLERANCE_MATCH_NODE = 0.5 # when searching for a OSM node based on distance: what is the allowed tolerance
DETAILS_PROCESS_PIERS = True
DETAILS_PROCESS_PLATFORMS = True
# =============================================================================
# PARAMETERS RELATED TO PYLONS, POWERLINES, AERIALWAYS IN osm2pylons.py
# PARAMETERS RELATED TO PYLONS, POWERLINES, AERIALWAYS IN pylons.py
# =============================================================================
C2P_PROCESS_POWERLINES = True
C2P_PROCESS_POWERLINES_MINOR = False # only considered of C2P_PROCESS_POWERLINES is True
C2P_PROCESS_POWERLINES_MINOR = False # only considered if C2P_PROCESS_POWERLINES is True
C2P_PROCESS_AERIALWAYS = False
C2P_PROCESS_OVERHEAD_LINES = False
C2P_PROCESS_WIND_TURBINES = True
......@@ -289,13 +286,6 @@ def get_output_path():
return PATH_TO_SCENERY
def get_OSM_file_name():
"""
Returns the path to the OSM File
"""
return os.path.join(PREFIX, OSM_FILE)
def get_repl_prefix():
"""If the PREFIX contains '/' or '\' characters due to batch processing, then they get replaced with underscore."""
return re.sub('[\/]', '_', PREFIX)
......
......@@ -7,7 +7,6 @@ Created on Sun Sep 29 10:42:12 2013
@author: Portree Kid
"""
import argparse
import logging
import math
import multiprocessing as mp
......@@ -24,7 +23,7 @@ from shapely.geometry.linestring import LineString
from utils import osmparser, coordinates, ac3d, stg_io2, utilities
from utils.vec2d import Vec2d
OUR_MAGIC = "osm2piers" # Used in e.g. stg files to mark edits by osm2Piers
OUR_MAGIC = "piers" # Used in e.g. stg files to mark edits by osm2Piers
class Pier(object):
......@@ -314,7 +313,8 @@ def _write_pier_line(pier, obj, offset):
obj.face(sideface)
def process(coords_transform: coordinates.Transformation, fg_elev: utilities.FGElev, file_lock: mp.Lock=None) -> None:
def process_details(coords_transform: coordinates.Transformation, fg_elev: utilities.FGElev,
file_lock: mp.Lock=None) -> None:
stats = utilities.Stats()
# -- prepare transformation to local coordinates
cmin, cmax = parameters.get_extent_global()
......@@ -324,10 +324,7 @@ def process(coords_transform: coordinates.Transformation, fg_elev: utilities.FGE
lmax = Vec2d(coords_transform.toLocal(cmax))
clusters = ClusterContainer(lmin, lmax)
if not parameters.USE_DATABASE:
osm_way_result = osmparser.fetch_osm_file_data(["man_made", "area"], ["man_made"])
else:
osm_way_result = osmparser.fetch_osm_db_data_ways_key_values(["man_made=>pier"])
osm_way_result = osmparser.fetch_osm_db_data_ways_key_values(["man_made=>pier"])
osm_nodes_dict = osm_way_result.nodes_dict
osm_ways_dict = osm_way_result.ways_dict
......@@ -346,32 +343,10 @@ def process(coords_transform: coordinates.Transformation, fg_elev: utilities.FGE
# -- initialize STGManager
path_to_output = parameters.get_output_path()
replacement_prefix = parameters.get_repl_prefix()
stg_manager = stg_io2.STGManager(path_to_output, stg_io2.SceneryType.buildings, OUR_MAGIC, replacement_prefix)
stg_manager = stg_io2.STGManager(path_to_output, stg_io2.SceneryType.details, OUR_MAGIC, replacement_prefix)
_write_piers(stg_manager, replacement_prefix, clusters, coords_transform, stats)
_write_boats(stg_manager, piers, coords_transform)
# -- write stg
stg_manager.write(file_lock)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="piers.py reads OSM data and creates Pier models for use with FlightGear")
parser.add_argument("-f", "--file", dest="filename",
help="read parameters from FILE (e.g. params.ini)", metavar="FILE", required=True)
parser.add_argument("-l", "--loglevel", dest="loglevel",
help="set loglevel. Valid levels are VERBOSE, DEBUG, INFO, WARNING, ERROR, CRITICAL",
required=False)
args = parser.parse_args()
parameters.read_from_file(args.filename)
parameters.set_loglevel(args.loglevel) # -- must go after reading params file
parameters.show()
my_coords_transform = coordinates.Transformation(parameters.get_center_global())
my_fg_elev = utilities.FGElev(my_coords_transform)
process(my_coords_transform, my_fg_elev)
my_fg_elev.close()
logging.info("******* Finished *******")
......@@ -6,7 +6,6 @@ Created on Sun Sep 29 10:42:12 2013
@author: Portree Kid
"""
import argparse
import logging
import multiprocessing as mp
import numpy as np
......@@ -21,7 +20,7 @@ from utils import osmparser, coordinates, ac3d, stg_io2, utilities
from utils.vec2d import Vec2d
OUR_MAGIC = "osm2platforms" # Used in e.g. stg files to mark edits by osm2platforms
OUR_MAGIC = "platforms" # Used in e.g. stg files to mark edits by osm2platforms
class Platform(object):
......@@ -205,7 +204,7 @@ def _write_line(platform, fg_elev: utilities.FGElev, obj, offset) -> None:
obj.face(sideface)
def process(coords_transform: coordinates.Transformation, fg_elev: utilities.FGElev, file_lock: mp.Lock=None) -> None:
def process_details(coords_transform: coordinates.Transformation, fg_elev: utilities.FGElev, file_lock: mp.Lock=None) -> None:
stats = utilities.Stats()
# -- prepare transformation to local coordinates
cmin, cmax = parameters.get_extent_global()
......@@ -215,10 +214,7 @@ def process(coords_transform: coordinates.Transformation, fg_elev: utilities.FGE
lmax = Vec2d(coords_transform.toLocal(cmax))
clusters = ClusterContainer(lmin, lmax)
if not parameters.USE_DATABASE:
osm_way_result = osmparser.fetch_osm_file_data(['railway', 'area', 'layer'], ["railway"])
else:
osm_way_result = osmparser.fetch_osm_db_data_ways_key_values(["railway=>platform"])
osm_way_result = osmparser.fetch_osm_db_data_ways_key_values(["railway=>platform"])
osm_nodes_dict = osm_way_result.nodes_dict
osm_ways_dict = osm_way_result.ways_dict
......@@ -234,31 +230,9 @@ def process(coords_transform: coordinates.Transformation, fg_elev: utilities.FGE
# -- initialize STGManager
path_to_output = parameters.get_output_path()
replacement_prefix = parameters.get_repl_prefix()
stg_manager = stg_io2.STGManager(path_to_output, stg_io2.SceneryType.buildings, OUR_MAGIC, replacement_prefix)
stg_manager = stg_io2.STGManager(path_to_output, stg_io2.SceneryType.details, OUR_MAGIC, replacement_prefix)
_write(fg_elev, stg_manager, replacement_prefix, clusters, coords_transform, stats)
# -- write stg
stg_manager.write(file_lock)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="platforms.py reads OSM data and creates platform models for use with FlightGear")
parser.add_argument("-f", "--file", dest="filename",
help="read parameters from FILE (e.g. params.ini)", metavar="FILE", required=True)
parser.add_argument("-l", "--loglevel", dest="loglevel",
help="set loglevel. Valid levels are VERBOSE, DEBUG, INFO, WARNING, ERROR, CRITICAL",
required=False)
args = parser.parse_args()
parameters.read_from_file(args.filename)
parameters.set_loglevel(args.loglevel) # -- must go after reading params file
parameters.show()
my_coords_transform = coordinates.Transformation(parameters.get_center_global())
my_fg_elev = utilities.FGElev(my_coords_transform)
process(my_coords_transform, my_fg_elev)
my_fg_elev.close()